Package syn3d.ui.java3d

Source Code of syn3d.ui.java3d.Frame3DJava3D

/* ========================
* JSynoptic : a free Synoptic editor
* ========================
*
* Project Info:  http://jsynoptic.sourceforge.net/index.html
*
* This program is free software; you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Foundation;
* either version 2.1 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* (C) Copyright 2001-2004, by :
*     Corporate:
*         Astrium SAS
*     Individual:
*         Claude Cazenave
*
* $Id: Frame3DJava3D.java,v 1.13 2006/11/23 15:45:31 ogor Exp $
*
* Changes
* -------
* 9-Dec-2003 : Creation date (CC);
*
*/
package syn3d.ui.java3d;

import java.awt.BorderLayout;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;

import javax.media.j3d.AmbientLight;
import javax.media.j3d.Appearance;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.Bounds;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.Canvas3D;
import javax.media.j3d.DirectionalLight;
import javax.media.j3d.Node;
import javax.media.j3d.PolygonAttributes;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.media.j3d.View;
import javax.swing.JFrame;
import javax.vecmath.AxisAngle4f;
import javax.vecmath.Color3f;
import javax.vecmath.Matrix4f;
import javax.vecmath.Vector3f;

import syn3d.base.ActiveNode;
import syn3d.base.PluginManager;
import syn3d.nodes.SceneNode;
import syn3d.nodes.java3d.SceneNodeJava3D;
import syn3d.ui.Frame3DBase;

import com.sun.j3d.utils.geometry.Sphere;
import com.sun.j3d.utils.picking.PickCanvas;
import com.sun.j3d.utils.picking.PickResult;
import com.sun.j3d.utils.picking.PickTool;
import com.sun.j3d.utils.universe.SimpleUniverse;
import com.sun.j3d.utils.universe.Viewer;
import com.sun.j3d.utils.universe.ViewingPlatform;

import syn3d.base.java3d.Java3DPluginManager;

/**
* Class description ...
*
* @author Claude CAZENAVE
*
*/
public class Frame3DJava3D extends Frame3DBase {

  protected JFrame frame;
  protected View view;
  protected Viewer viewer;
  protected ViewingPlatform viewingPlatform;
  protected Canvas3D canvas;
  protected SceneNodeJava3D scene;
  protected ArrayList lastPickSelection = new ArrayList();
  protected int lastMouseX = -1, lastMouseY = -1;
 
  protected Transform3D transform;
  protected Transform3D tempTransform;
 
  public SceneNode getScene() {
    return scene;
  }

    /**
     * @return Returns the viewer.
     */
    public Viewer getViewer() {
        return viewer;
    }

    /**
   * @return the view
   */
  public View getView() {
    return view;
  }
   
  /**
   * @param owner
   * @param x
   * @param y
   * @param width
   * @param height
   */
  public Frame3DJava3D(SceneNodeJava3D scene, String t, int x, int y, int width, int height, PluginManager pm) {
    super(scene, t, x, y, width, height,pm);
    this.scene = scene;
  }
   
  protected void createPeer(Object owner){
      SceneNodeJava3D scene = (SceneNodeJava3D)owner;
    canvas = scene.getCanvas3D();

    frame=new JFrame(SimpleUniverse.getPreferredConfiguration());
    frame.getContentPane().setLayout(new BorderLayout());
    frame.setLocation(x, y);
    frame.setSize(width,height);
    frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
    frame.getContentPane().add("Center", canvas);
   
    peerComponent=frame;
    peerWindow=frame; 

    transform=new Transform3D();
    // avoids cumulative rounding errors
    // This should avoid "non-congruent transform above view transform" exception
    // Warning: In some cases, this exception still appears. This is a known J3D bug, that
    // should hopefully be corrected in J3D v1.4
    transform.setAutoNormalize(true);
    tempTransform=new Transform3D();
   
    viewingPlatform = scene.getUniverse().getViewingPlatform();
   
    viewer = viewingPlatform.getViewers()[0];
    view = viewer.getView();
    // Use J3D recommendation to set this between 100 and 1000
    // default is a factor of 100 (front=0.1, back=10)
    // Make this 1000 to have more space
    view.setBackClipDistance(view.getFrontClipDistance() * 1000);
   
    canvas.addMouseListener(this);
    canvas.addMouseMotionListener(this);
    canvas.addMouseWheelListener(this);
    canvas.addKeyListener(this);
   
    frame.show();
  }
 
  public void setPerspective(boolean p){
    super.setPerspective(p);
    if (perspective)
      view.setProjectionPolicy(View.PERSPECTIVE_PROJECTION);
    else
      view.setProjectionPolicy(View.PARALLEL_PROJECTION);
  }

 
  public void rotate2D(int newX, int newY, boolean inverse) {
   
    int lightRotationMode;
   
    if (scene!=null) lightRotationMode = scene.getLightRotationMode();
    else lightRotationMode = -1;
   
    // rotate only one light, view is fixed
    if (lightRotationMode != -1) {
      float dx=(float)(newX-pos2DX)/wsize;
      float dy=(float)(newY-pos2DY)/wsize;
     
      // Cancels the rotation for the scene => use inverse of inverse...
      if (!inverse) {
        dx = -dx;
        dy = -dy;
      }
          drotX.rotX(dy * 2 * (float)Math.PI);
      drotY.rotY(dx * 2 * (float)Math.PI);

      Matrix4f transform = new Matrix4f(rot);
      transform.mul(drotX);
      transform.mul(drotY);
      Matrix4f tmp = new Matrix4f(rot);
      tmp.invert();
      transform.mul(tmp);

      DirectionalLight light = scene.getLights()[lightRotationMode];
      Vector3f direction = new Vector3f();
      light.getDirection(direction);
      transform.transform(direction);
      light.setDirection(direction);
      // this calls detach/attach => more flicker
      //scene.showLightVector(direction.x,direction.y,direction.z);
     
      // update pos, don't move view
          pos2DX = newX;
          pos2DY = newY;
          peerWindow.repaint();
          return;
    }

    // rotate all lights together with view
    if (scene!=null) {
     
      float dx=(float)(newX-pos2DX)/wsize;
      float dy=(float)(newY-pos2DY)/wsize;
      if (inverse) {
        dx = -dx;
        dy = -dy;
      }
          drotX.rotX(dy * 2 * (float)Math.PI);
      drotY.rotY(dx * 2 * (float)Math.PI);
     
      Matrix4f transform = new Matrix4f(rot);
      transform.mul(drotX);
      transform.mul(drotY);
      Matrix4f tmp = new Matrix4f(rot);
      tmp.invert();
      transform.mul(tmp);

      DirectionalLight[] lights = scene.getLights();
      Vector3f direction = new Vector3f();
      for (int i=0; i<lights.length; ++i) {
        lights[i].getDirection(direction);
        transform.transform(direction);
        lights[i].setDirection(direction);
      }
      // don't update pos for super implementation call

    }
   
    super.rotate2D(newX,newY,inverse);
   
  }

  protected Timer zoomAccumulator = null;
  protected int accumulator = 0;
 
  /* (non-Javadoc)
   * @see syn3d.ui.Transformator#zoom(int)
   */
  public void zoom(int zoomIncrement) {

    if (scene.getViewingMode() == SceneNode.ROTATION_MODE) {
      super.zoom(zoomIncrement*5);
      return;
    }

    synchronized (this) {
      accumulator+=zoomIncrement;
      if (zoomAccumulator!=null) return;
      zoomAccumulator = new Timer();
      zoomAccumulator.schedule(new TimerTask() {
        public void run() {
          int accuCopy;
          synchronized (Frame3DJava3D.this) {
            accuCopy = accumulator;
            accumulator = 0;
            zoomAccumulator = null;
          }
          Vector3f view = new Vector3f(0,0,-1);
          rot.transform(view);
          float scale = (float)Math.pow(2.0, Math.abs(accuCopy))*getSceneSize()/200.0f;
          if (accuCopy<0) scale = -scale;
          view.scale(scale);
          trans.m03 += view.x;
          trans.m13 += view.y;
          trans.m23 += view.z;
          applyTransform();
        }
      },200);
    }


  }

 
 
 
  /* (non-Javadoc)
   * @see syn3d.ui.Transformator#zoom2D(int, int)
   */
  public void zoom2D(int newX, int newY) {
    if (scene.getViewingMode() == SceneNode.ROTATION_MODE) {
      super.zoom2D(newX, newY);
      return;
    }

    float dx=(float)(newX-pos2DX)/wsize;
    float dy=-(float)(newY-pos2DY)/wsize;
    pos2DX = newX;
    pos2DY = newY;

    Vector3f viewX = new Vector3f(1,0,0);
    rot.transform(viewX);
    viewX.scale(dx/5.0f);
    Vector3f viewY = new Vector3f(0,1,0);
    rot.transform(viewY);
    viewY.scale(dy/5.0f);
    trans.m03 += viewX.x + viewY.x;
    trans.m13 += viewX.y + viewY.y;
    trans.m23 += viewX.z + viewY.z;
    applyTransform();
  }
 
 
  /* (non-Javadoc)
   * @see syn3d.ui.Transformator#translate2D(int, int)
   */
  public void translate2D(int newX, int newY) {
    if (scene.getViewingMode() == SceneNode.ROTATION_MODE) {
      super.translate2D(newX, newY);
      return;
    }
   
    // rotation around view vector
    Vector3f view = new Vector3f(0,0,-1);
    rot.transform(view);
    float dx = (float)(newX-pos2DX)/wsize;
    float dy = (float)(newY-pos2DY)/wsize;
    pos2DX = newX;
    pos2DY = newY;
    AxisAngle4f aa = new AxisAngle4f(view, (dx-dy) * (float)Math.PI);
   
    Matrix4f mat = new Matrix4f();
    mat.setIdentity();
    mat.setRotation(aa);
    mat.mul(rot);
    rot = mat;
    applyTransform();
  }
 
  public void applyTransform(){
    super.applyTransform();

    if ((scene==null) || (scene.getViewingMode() == SceneNode.ROTATION_MODE)) {
       transform.set(rot);
      tempTransform.set(trans);
    } else {
      transform.set(trans);
      tempTransform.set(rot);
    }
    transform.mul(tempTransform);
    tempTransform.set(zoom);
    transform.mul(tempTransform);

    viewingPlatform.getViewPlatformTransform().setTransform(transform);
  }


    /**
     * Adds or removes a single pick at the given position to the selected objects.
     * @param posX the 2D X position where to do the picking  
     * @param posY the 2D Y position where to do the picking
     * @return Returns the current selection, possibly an empy array
     * @see ActiveNode.higlight(boolean,Object) 
     */
    public ArrayList toggleSinglePick(int posX, int posY) {
      lastMouseX = posX;
      lastMouseY = posY;

    PickCanvas pickCanvas = new PickCanvas(canvas, scene.getBranchgroup());
      pickCanvas.setMode(PickTool.GEOMETRY_INTERSECT_INFO);
      pickCanvas.setTolerance(2.0f);
      pickCanvas.setShapeLocation(posX, posY);
      PickResult result = pickCanvas.pickClosest();

      if (result!=null) {
      Node node = result.getObject();
            Object o = node.getUserData();
            if (o instanceof ActiveNode) {
              ((ActiveNode)o).highlight(true,result);
                lastPickSelection.add(o);
                // pass full info to the active node so it can find which point is
                // picked if necessary
                lastPickSelection.add(result);
            }
    }
     
      return lastPickSelection;
    }

    /**
     * Adds or removes all picks between the given position and the last position,
     * to the selected objects.
     * @param posX the 2D X position defining a region with the last position. All objects in this region should be picked.    
     * @param posX the 2D Y position defining a region with the last position. All objects in this region should be picked.    
     * @return Returns the current selection, possibly an empy array 
     * @see ActiveNode.higlight(boolean,Object) 
     */
    public ArrayList toggleAllPicks(int posX, int posY) {
      // do not update last mouse XY position, so user can refine selection from the same point

      int dx = Math.abs(posX - lastMouseX) / 2;
      int dy = Math.abs(posY - lastMouseY) / 2;

      PickCanvas pickCanvas = new PickCanvas(canvas, scene.getBranchgroup());
      pickCanvas.setMode(PickTool.GEOMETRY_INTERSECT_INFO);
      pickCanvas.setTolerance(Math.max(dx,dy));
      pickCanvas.setShapeLocation(posX, posY);

      // TODO : don't do pick closest, loop on all results
      PickResult result = pickCanvas.pickClosest();
      if (result!=null) {
      Node node = result.getObject();
            Object o = node.getUserData();
            if (o instanceof ActiveNode) {
              ((ActiveNode)o).highlight(true,result);
                lastPickSelection.add(o);
                // pass full info to the active node so it can find which point is
                // picked if necessary
                lastPickSelection.add(result);
            }
    }
     
      return lastPickSelection;
    }

    /**
     * Selects a single pick at the given position.
     * @param posX the 2D X position where to do the picking  
     * @param posY the 2D Y position where to do the picking  
     * @return Returns the picked node or possibly a null object if there was nothing to pick at this position 
     * @see ActiveNode.higlight(boolean,Object) 
     */
    public ActiveNode pick(int posX, int posY) {
        int s = lastPickSelection.size();
        for (int i=0; i<s; i+=2) {
            ActiveNode node = (ActiveNode)lastPickSelection.get(i);
            node.highlight(false,lastPickSelection.get(i+1));
        }
        lastPickSelection.clear();
        toggleSinglePick(posX,posY);
        if (lastPickSelection.size()>0) return (ActiveNode)lastPickSelection.get(0);
        return null;
    }
   
    /*
     *
     */
  protected float getSceneSize() {
    BranchGroup bg = scene.getBranchgroup();
    boolean autocompute = bg.getBoundsAutoCompute();
    scene.getBranchgroup().setBoundsAutoCompute(true);
    Bounds bounds = scene.getBranchgroup().getBounds();
    scene.getBranchgroup().setBoundsAutoCompute(autocompute);
    if (bounds instanceof BoundingSphere) {
      return (float)((BoundingSphere)bounds).getRadius();
    }
    // else, include this bounds object in a bounding sphere and get radius
    return 0;
  }
 
 
 
  /**
   * Main function to test navigation
   * @param args
   */
  public static void main(String[] args) {
     
   
    PluginManager pluginManager = (PluginManager) new Java3DPluginManager();
      SceneNodeJava3D scene = new SceneNodeJava3D(null, pluginManager);
     
   
    //BoundingSphere bs = new BoundingSphere(//universe bounds
    //        new Point3d(0.0, 0.0, 0.0), 1000.0);
    //PlatformGeometry pg = new PlatformGeometry();
    //Color3f ac = new Color3f(0.2f, 0.2f, 0.2f);
    //AmbientLight al = new AmbientLight(ac);
    //al.setInfluencingBounds(bs);
    //pg.addChild(al);
    //f1.viewingPlatform.setPlatformGeometry(pg);
    // TODO check where to add the light
    //f1.viewingPlatform.setNominalViewingTransform();

    BranchGroup objRoot = scene.getBranchgroup();

    Appearance a = new Appearance();
    a.setPolygonAttributes(new PolygonAttributes(PolygonAttributes.POLYGON_LINE, PolygonAttributes.CULL_NONE, 0));
    TransformGroup sphereTrans = new TransformGroup();
    sphereTrans.addChild(new Sphere(1.f, Sphere.GENERATE_NORMALS,40, a));

    scene.detach();
    objRoot.setCapability(BranchGroup.ALLOW_CHILDREN_EXTEND);
    objRoot.addChild(sphereTrans);

    AmbientLight aLgt = new AmbientLight(new Color3f(0.2f, 0.2f, 0.2f));
    objRoot.addChild(aLgt);
   
    scene.attach();
  }

}
TOP

Related Classes of syn3d.ui.java3d.Frame3DJava3D

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.