/* ========================
* 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:
* EADS Corporate Research Center
* Individual:
* Nicolas Brodu
*
* $Id: SceneNodeXith3D.java,v 1.10 2005/09/02 11:57:31 ogor Exp $
*
* Changes
* -------
* 19-Mar-2004 : Creation date (NB);
*
*/
package syn3d.nodes.xith3d;
import java.util.ArrayList;
import java.util.List;
import javax.vecmath.Color3f;
import javax.vecmath.Vector3f;
import syn3d.base.ActiveNode;
import syn3d.nodes.SceneChangeListener;
import syn3d.nodes.SceneNode;
import syn3d.util.AxisMaker;
import syn3d.ui.xith3d.Frame3DXith3D;
import com.xith3d.scenegraph.AmbientLight;
import com.xith3d.scenegraph.Appearance;
import com.xith3d.scenegraph.BranchGroup;
import com.xith3d.scenegraph.ColoringAttributes;
import com.xith3d.scenegraph.DirectionalLight;
import com.xith3d.scenegraph.LineArray;
import com.xith3d.scenegraph.Locale;
import com.xith3d.scenegraph.PolygonAttributes;
import com.xith3d.scenegraph.Shape3D;
import com.xith3d.scenegraph.VirtualUniverse;
import syn3d.base.PluginManager;
/**
*
*/
public class SceneNodeXith3D extends SceneNode implements SceneChangeListener {
protected VirtualUniverse universe;
protected Locale locale;
protected BranchGroup rootGroup, branchgroup;
protected Frame3DXith3D frame;
protected DirectionalLight[] lights;
protected Shape3D lightVector = null;
// -1 : rotate view, >=0 : rotate light[rotationMode]
protected int lightRotationMode = -1;
protected PluginManager pluginManager;
public SceneNodeXith3D(ActiveNode parent, PluginManager pm) {
super(parent);
pluginManager = pm;
universe = new VirtualUniverse();
locale = new Locale();
locale.setName(name);
//locale.setPickable(true);
//locale.setUserData(this);
universe.addLocale(locale);
branchgroup = new BranchGroup();
branchgroup.setName(name);
branchgroup.setUserData(this);
branchgroup.setPickable(true);
rootGroup = new BranchGroup();
rootGroup.setName(name);
rootGroup.setUserData(this);
rootGroup.setPickable(true);
AmbientLight alight = new AmbientLight(true,new Color3f(0.5f,0.5f,0.5f));
rootGroup.addChild(alight);
lights = new DirectionalLight[1];
for (int i=0; i<lights.length; ++i) {
// TODO : position lights around the object
lights[i] = new DirectionalLight(true,new Color3f(1.0f,1.0f,1.0f),new Vector3f(-1,-1,-1));
rootGroup.addChild(lights[i]);
}
rootGroup.addChild(branchgroup);
locale.addBranchGraph(rootGroup);
// X axis in blue
float[] axis = AxisMaker.makeAxis(0);
LineArray la = new LineArray(axis.length/3, LineArray.COORDINATES);
la.setCoordinates(0,axis);
Appearance a = new Appearance();
a.setPolygonAttributes(new PolygonAttributes(PolygonAttributes.POLYGON_LINE, PolygonAttributes.CULL_NONE, 0));
ColoringAttributes ca = new ColoringAttributes();
ca.setColor(0.0f,0.0f,1.0f);
a.setColoringAttributes(ca);
Shape3D saxis = new Shape3D(la, a);
saxis.setName("X axis");
rootGroup.addChild(saxis);
// Y axis in green
axis = AxisMaker.makeAxis(1);
la = new LineArray(axis.length/3, LineArray.COORDINATES);
la.setCoordinates(0,axis);
a = new Appearance();
a.setPolygonAttributes(new PolygonAttributes(PolygonAttributes.POLYGON_LINE, PolygonAttributes.CULL_NONE, 0));
ca = new ColoringAttributes();
ca.setColor(0.0f,1.0f,0.0f);
a.setColoringAttributes(ca);
saxis = new Shape3D(la, a);
saxis.setName("Y axis");
rootGroup.addChild(saxis);
// Z axis in purple
axis = AxisMaker.makeAxis(2);
la = new LineArray(axis.length/3, LineArray.COORDINATES);
la.setCoordinates(0,axis);
a = new Appearance();
a.setPolygonAttributes(new PolygonAttributes(PolygonAttributes.POLYGON_LINE, PolygonAttributes.CULL_NONE, 0));
ca = new ColoringAttributes();
ca.setColor(1.0f,0.0f,1.0f);
a.setColoringAttributes(ca);
saxis = new Shape3D(la, a);
saxis.setName("Z axis");
rootGroup.addChild(saxis);
frame = null; // lazy creation
}
// don't know how or why the scene would be removed, but let's do it cleanly
public void remove() {
if (frame!=null) frame.getPeerWindow().dispose();
// cleanup. Not strictly necessary now that listeners help the garbage collector,
// but still good practice so let's do it.
removeListener(this);
super.remove();
}
public Object get3DObject() {
return branchgroup; // this is a group node, directly usable for other nodes
}
public List getActions() {
List l = super.getActions();
for (int i=0; i<lights.length; ++i) {
if (i!=lightRotationMode) l.add("Rotate Light "+(i+1));
}
if (lightRotationMode!=-1) l.add("Rotate View");
return l;
}
public void doAction(Object action) {
if (action.toString().startsWith("Rotate Light ")) {
lightRotationMode = Integer.parseInt(action.toString().substring("Rotate Light ".length())) - 1;
Vector3f direction = lights[lightRotationMode].getDirection();
showLightVector(direction.x,direction.y,direction.z);
if (isVisible()) frame.getView().renderOnce();
}
if (action.equals("Rotate View")) {
lightRotationMode = -1;
if (lightVector!=null) {
rootGroup.removeChild(lightVector);
lightVector = null;
if (isVisible()) frame.getView().renderOnce();
}
}
super.doAction(action);
}
/* (non-Javadoc)
* @see syn3d.nodes.SceneNode#isVisible()
*/
public boolean isVisible() {
if (frame==null) return false;
return frame.getPeerWindow().isVisible();
}
/* (non-Javadoc)
* @see syn3d.nodes.SceneNode#setVisible(boolean)
*/
public void setVisible(boolean status) {
if (frame==null) {
frame = new Frame3DXith3D(this, null, "Xith3D frame",-1,-1,400,400, pluginManager);
frame.getView().setName(name);
getUniverse().addView(frame.getView());
addListener(this);
}
else frame.getPeerWindow().setVisible(status);
}
/**
* @return Returns the branchgroup.
*/
public BranchGroup getBranchgroup() {
return branchgroup;
}
/**
* @return Returns the locale.
*/
public Locale getLocale() {
return locale;
}
/**
* @return Returns the universe.
*/
public VirtualUniverse getUniverse() {
return universe;
}
/**
* @return Returns the lights.
*/
public DirectionalLight[] getLights() {
return lights;
}
/**
* @return Returns the rotationMode.
*/
public int getLightRotationMode() {
return lightRotationMode;
}
/* (non-Javadoc)
* @see syn3d.nodes.SceneChangeListener#sceneChanged(syn3d.nodes.SceneNode)
*/
public void sceneChanged(SceneNode scene) {
if (isVisible()) {
frame.getView().renderOnce();
}
}
public void showLightVector(float x, float y, float z) {
if (lightVector!=null) rootGroup.removeChild(lightVector);
float[] vectorCoords = new float[] {
0,0,0, x,y,z
};
LineArray la = new LineArray(2, LineArray.COORDINATES);
la.setCoordinates(0,vectorCoords);
Appearance a = new Appearance();
a.setPolygonAttributes(new PolygonAttributes(PolygonAttributes.POLYGON_LINE, PolygonAttributes.CULL_NONE, 0));
ColoringAttributes ca = new ColoringAttributes();
ca.setColor(1.0f,1.0f,0.0f);
a.setColoringAttributes(ca);
lightVector = new Shape3D(la, a);
lightVector.setName("Light vector");
rootGroup.addChild(lightVector);
}
// Parent overloads => redirect to the frame
public void init2DPosition(int posX, int posY) {
frame.init2DPosition(posX, posY);
}
public void rotate2D(int newX, int newY) {
frame.rotate2D(newX, newY);
}
public void translate2D(int newX, int newY) {
frame.translate2D(newX, newY);
}
public void zoom(int zoomIncrement) {
frame.zoom(zoomIncrement);
}
public void zoom2D(int newX, int newY) {
frame.zoom2D(newX, newY);
}
public void changeProjection() {
frame.changeProjection();
}
public void reset() {
frame.reset();
}
public void autoZoom() {
frame.autoZoom();
}
public ArrayList toggleSinglePick(int posX, int posY) {
return frame.toggleSinglePick(posX,posY);
}
public ArrayList toggleAllPicks(int posX, int posY) {
return frame.toggleAllPicks(posX,posY);
}
public ActiveNode pick(int posX, int posY) {
return frame.pick(posX,posY);
}
}