/* ========================
* 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: ShapeNodeJava3D.java,v 1.11 2006/06/08 09:50:21 ogor Exp $
*
* Changes
* -------
* 01-04-2004 : Creation date (NB);
*
*/
package syn3d.nodes.java3d;
import java.awt.Color;
import java.io.Serializable;
import javax.media.j3d.Appearance;
import javax.media.j3d.ColoringAttributes;
import javax.media.j3d.Group;
import javax.media.j3d.Material;
import javax.media.j3d.PolygonAttributes;
import javax.media.j3d.Shape3D;
import syn3d.base.ActiveNode;
import syn3d.nodes.ShapeNode;
import com.sun.j3d.utils.picking.PickTool;
/**
* Base class for Java3D shapes. Make cube and sphere from this, useful for plugins too
*/
public class ShapeNodeJava3D extends ShapeNode implements Serializable{
static final long serialVersionUID = -5754480233994820530L;
protected transient Shape3D shape;
protected float polygonOffset, polygonOffsetFactor;
public ShapeNodeJava3D(ActiveNode parent) {
this(parent,null);
polygonOffset = 0;
}
public ShapeNodeJava3D(ActiveNode parent, Shape3D shape3d) {
super(parent);
shape = shape3d;
if (shape==null) shape = createShape();
shape.setUserData(this);
shape.setPickable(true);
PickTool.setCapabilities(shape,PickTool.INTERSECT_FULL);
shape.setCapability(Shape3D.ALLOW_APPEARANCE_READ);
shape.setCapability(Shape3D.ALLOW_APPEARANCE_WRITE);
setAppearanceForHighlight(false);
if (parent!=null) SceneNodeJava3D.addChildToParentGroup((Group)getParent().get3DObject(), shape);
}
/**
* Subclasses API when using the constructor without a shape specified
* @return a newly created Shape3D.
*/
protected Shape3D createShape() {
return null;
}
public void remove() {
if (shape!=null) SceneNodeJava3D.removeChildFromParentGroup(shape);
super.remove();
}
public Object get3DObject() {
return shape;
}
protected void setAppearanceForHighlight(boolean on) {
if (shape==null) return;
Appearance a=new Appearance();
a.setCapability(Appearance.ALLOW_COLORING_ATTRIBUTES_READ);
a.setCapability(Appearance.ALLOW_COLORING_ATTRIBUTES_WRITE);
a.setCapability(Appearance.ALLOW_LINE_ATTRIBUTES_READ);
a.setCapability(Appearance.ALLOW_LINE_ATTRIBUTES_WRITE);
a.setCapability(Appearance.ALLOW_MATERIAL_READ);
a.setCapability(Appearance.ALLOW_MATERIAL_WRITE);
a.setCapability(Appearance.ALLOW_POINT_ATTRIBUTES_READ);
a.setCapability(Appearance.ALLOW_POINT_ATTRIBUTES_WRITE);
a.setCapability(Appearance.ALLOW_POLYGON_ATTRIBUTES_READ);
a.setCapability(Appearance.ALLOW_POLYGON_ATTRIBUTES_WRITE);
a.setCapability(Appearance.ALLOW_RENDERING_ATTRIBUTES_READ);
a.setCapability(Appearance.ALLOW_RENDERING_ATTRIBUTES_WRITE);
a.setCapability(Appearance.ALLOW_TEXGEN_READ);
a.setCapability(Appearance.ALLOW_TEXGEN_WRITE);
a.setCapability(Appearance.ALLOW_TEXTURE_ATTRIBUTES_READ);
a.setCapability(Appearance.ALLOW_TEXTURE_ATTRIBUTES_WRITE);
a.setCapability(Appearance.ALLOW_TEXTURE_READ);
a.setCapability(Appearance.ALLOW_TEXTURE_WRITE);
a.setCapability(Appearance.ALLOW_TEXTURE_UNIT_STATE_READ);
a.setCapability(Appearance.ALLOW_TEXTURE_UNIT_STATE_WRITE);
a.setCapability(Appearance.ALLOW_TRANSPARENCY_ATTRIBUTES_READ);
a.setCapability(Appearance.ALLOW_TRANSPARENCY_ATTRIBUTES_WRITE);
ColoringAttributes ca = new ColoringAttributes();
// don't use light
if ((mode==WIREFRAME_MODE) || (mode==FILLED_MODE)) {
int attribute = (mode==FILLED_MODE) ? PolygonAttributes.POLYGON_FILL : PolygonAttributes.POLYGON_LINE;
PolygonAttributes pa = new PolygonAttributes(attribute, PolygonAttributes.CULL_NONE, 0);
unlockPolygonAttributes(pa);
pa.setPolygonOffset(polygonOffset);
pa.setPolygonOffsetFactor(polygonOffsetFactor);
a.setPolygonAttributes(pa);
Color selectedColor;
if (on) selectedColor = highlightColor;
else selectedColor = baseColor;
float[] colors = selectedColor.getRGBColorComponents(null);
ca.setColor(colors[0], colors[1], colors[2]);
a.setColoringAttributes(ca);
}
// use light
if ((mode==SHADING_MODE) || (mode==FLAT_MODE)) {
if (mode==SHADING_MODE) ca.setShadeModel(ColoringAttributes.SHADE_GOURAUD);
if (mode==FLAT_MODE) ca.setShadeModel(ColoringAttributes.SHADE_FLAT);
a.setColoringAttributes(ca);
PolygonAttributes pa = new PolygonAttributes(PolygonAttributes.POLYGON_FILL, PolygonAttributes.CULL_NONE, 0);
unlockPolygonAttributes(pa);
pa.setPolygonOffset(polygonOffset);
pa.setPolygonOffsetFactor(polygonOffsetFactor);
pa.setBackFaceNormalFlip(true);
a.setPolygonAttributes(pa);
Material m = new Material();
Color selectedColor;
if (on) selectedColor = highlightColor;
else selectedColor = baseColor;
float[] colors = selectedColor.getRGBColorComponents(null);
m.setAmbientColor(colors[0], colors[1], colors[2]);
// Squash specular toward white => keep only hue
float[] hsb = Color.RGBtoHSB(selectedColor.getRed(), selectedColor.getGreen(), selectedColor.getBlue(), null);
Color.getHSBColor(hsb[0],hsb[1]/10,1.0f).getRGBColorComponents(colors);
m.setSpecularColor(colors[0], colors[1], colors[2]);
// diffuse is same hue and saturation but darker
Color.getHSBColor(hsb[0],hsb[1],hsb[2]/2).getRGBColorComponents(colors);
m.setDiffuseColor(colors[0], colors[1], colors[2]);
// no emissive color
m.setEmissiveColor(0f,0f,0f);
m.setLightingEnable(true);
a.setMaterial(m);
}
shape.setAppearance(a);
}
protected PolygonAttributes unlockPolygonAttributes(PolygonAttributes pa) {
pa.setCapability(PolygonAttributes.ALLOW_CULL_FACE_READ);
pa.setCapability(PolygonAttributes.ALLOW_CULL_FACE_WRITE);
pa.setCapability(PolygonAttributes.ALLOW_MODE_READ);
pa.setCapability(PolygonAttributes.ALLOW_MODE_WRITE);
pa.setCapability(PolygonAttributes.ALLOW_NORMAL_FLIP_READ);
pa.setCapability(PolygonAttributes.ALLOW_NORMAL_FLIP_WRITE);
pa.setCapability(PolygonAttributes.ALLOW_OFFSET_READ);
pa.setCapability(PolygonAttributes.ALLOW_OFFSET_WRITE);
return pa;
}
public void highlight(boolean on, Object parameter) {
setAppearanceForHighlight(on);
super.highlight(on,parameter);
}
protected PropertiesPanel createPanel(boolean showName) {
return new J3DPropertiesPanel(showName);
}
protected class J3DPropertiesPanel extends PropertiesPanel {
public J3DPropertiesPanel(boolean showName) {
super(showName);
}
public void apply() {
super.apply();
// change display to take mode into account
ShapeNodeJava3D.this.notifyInternalChange();
}
}
/* (non-Javadoc)
* @see syn3d.base.ActiveNode#notifyInternalChange()
*/
public void notifyInternalChange() {
setAppearanceForHighlight(highlighted);
super.notifyInternalChange();
}
/**
* @return Returns the polygonOffset.
*/
public float getPolygonOffset() {
return polygonOffset;
}
/**
* @param polygonOffset The polygonOffset to set.
*/
public void setPolygonOffset(float polygonOffset) {
this.polygonOffset = polygonOffset;
}
/**
* @return Returns the polygonOffsetFactor.
*/
public float getPolygonOffsetFactor() {
return polygonOffsetFactor;
}
/**
* @param polygonOffsetFactor The polygonOffsetFactor to set.
*/
public void setPolygonOffsetFactor(float polygonOffsetFactor) {
this.polygonOffsetFactor = polygonOffsetFactor;
}
public void restoreReferences(ActiveNode parent) {
super.restoreReferences(parent);
if (parent!=null) SceneNodeJava3D.addChildToParentGroup((Group)getParent().get3DObject(), shape);
}
private void readObject(java.io.ObjectInputStream in) throws java.lang.ClassNotFoundException, java.io.IOException {
in.defaultReadObject();
shape = createShape();
shape.setUserData(this);
shape.setPickable(true);
PickTool.setCapabilities(shape,PickTool.INTERSECT_FULL);
shape.setCapability(Shape3D.ALLOW_APPEARANCE_READ);
shape.setCapability(Shape3D.ALLOW_APPEARANCE_WRITE);
setAppearanceForHighlight(false);
}
}