--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007- VTT Technical Research Centre of Finland.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.scenegraph;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.List;\r
+\r
+import javax.vecmath.AxisAngle4d;\r
+import javax.vecmath.Quat4d;\r
+\r
+import org.simantics.animation.stubs.Interpolator;\r
+import org.simantics.animation.curve.SlerpCurve;\r
+import org.simantics.animation.curve.TCBCurve;\r
+import org.simantics.proconf.g3d.Resources;\r
+import org.simantics.proconf.g3d.animation.Animatable;\r
+import org.simantics.proconf.g3d.animation.Animation;\r
+import org.simantics.proconf.g3d.animation.ChanneledColorInterpolator;\r
+import org.simantics.proconf.g3d.animation.ChanneledPositionInterpolator;\r
+import org.simantics.proconf.g3d.animation.ConstantInterpolator;\r
+import org.simantics.proconf.g3d.animation.ScalarInterpolator;\r
+import org.simantics.proconf.g3d.animation.SlerpInterpolator;\r
+import org.simantics.proconf.g3d.animation.TCBInterpolator;\r
+import org.simantics.proconf.g3d.base.AppearanceProvider;\r
+import org.simantics.proconf.g3d.base.AppearanceProviderRegistry;\r
+import org.simantics.proconf.g3d.base.AppearanceTools;\r
+import org.simantics.proconf.g3d.base.G3DTools;\r
+import org.simantics.proconf.g3d.base.GeometryProvider;\r
+import org.simantics.proconf.g3d.base.GeometryProviderRegistry;\r
+import org.simantics.proconf.g3d.base.ThreeDimensionalEditorBase;\r
+import org.simantics.proconf.g3d.stubs.Appearance;\r
+import org.simantics.proconf.g3d.stubs.Color;\r
+import org.simantics.proconf.g3d.stubs.G3DModel;\r
+import org.simantics.proconf.g3d.stubs.G3DNode;\r
+import org.simantics.proconf.g3d.stubs.Orientation;\r
+import org.simantics.utils.ui.ErrorLogger;\r
+\r
+import com.jme.bounding.BoundingBox;\r
+import com.jme.bounding.CollisionTreeManager;\r
+import com.jme.intersection.PickResults;\r
+import com.jme.math.Ray;\r
+import com.jme.renderer.ColorRGBA;\r
+import com.jme.renderer.Renderer;\r
+import com.jme.scene.Geometry;\r
+import com.jme.scene.Node;\r
+import com.jme.scene.SharedMesh;\r
+import com.jme.scene.TriMesh;\r
+import com.jme.scene.state.AlphaState;\r
+import com.jme.scene.state.MaterialState;\r
+import com.jme.scene.state.RenderState;\r
+import com.jme.scene.state.WireframeState;\r
+import com.jme.scene.state.ZBufferState;\r
+\r
+import org.simantics.db.Builtins;\r
+import org.simantics.db.ContextGraph;\r
+import org.simantics.db.Graph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.layer0.utils.IEntity;\r
+\r
+public class ShapeNode extends AbstractGraphicsNode implements Animatable, IGeometryNode{\r
+\r
+ public static final int NORMAL = 0;\r
+ public static final int TRANSPARENT = 1;\r
+ public static final int SELECTED_EDGE = 2;\r
+ public static final int HIGHLIGHTED_EDGE = 3;\r
+ \r
+ private boolean highlighted = false;\r
+\r
+ protected Geometry mesh = null;\r
+ protected Geometry lines = null;\r
+ protected Geometry[] geometry = null;\r
+\r
+ private boolean visible[] = new boolean[4];\r
+ \r
+ private Node body;\r
+ private Node transparent;\r
+ private Node edge;\r
+\r
+ private MaterialState selectedEdgeState;\r
+ private MaterialState highlightedEdgeState;\r
+ \r
+ private Collection<RenderState> renderStates;\r
+ private boolean isTransparent;\r
+ \r
+\r
+ public ShapeNode(ThreeDimensionalEditorBase editor,IGraphicsNode parent, Graph graph, Resource shapeResource) {\r
+ super(editor,parent, graph, shapeResource);\r
+ for (int i = 0; i < visible.length; i++)\r
+ visible[i] = false;\r
+ \r
+ body = new Node();\r
+\r
+ body.setName(id); \r
+ \r
+ \r
+ transparent = new Node() {\r
+ private static final long serialVersionUID = 1L;\r
+ @Override\r
+ public void calculatePick(Ray ray, PickResults results) {\r
+ \r
+ }\r
+ };\r
+ \r
+ // transparent.setRenderQueueMode(Renderer.QUEUE_TRANSPARENT);\r
+ \r
+ edge = new Node(){\r
+ private static final long serialVersionUID = 1L;\r
+ @Override\r
+ public void calculatePick(Ray ray, PickResults results) {\r
+ \r
+ }\r
+ };\r
+ transparent.setIsCollidable(false);\r
+ edge.setIsCollidable(false);\r
+ \r
+ MaterialState ms = editor.getRenderingComponent().getDisplaySystem().getRenderer().createMaterialState();\r
+ ms.setDiffuse(new ColorRGBA(0.0f, 0.75f, 0.0f,0.3f));\r
+ ms.setEmissive(new ColorRGBA(0f, 0f, 0f,0.3f));\r
+ ms.setSpecular(new ColorRGBA(0.5f, 0.5f, 0.5f,0.3f));\r
+ ms.setAmbient(new ColorRGBA(0.0f, 0.75f, 0.0f,0.3f));\r
+ ms.setShininess(128.f);\r
+ ms.setMaterialFace(MaterialState.MF_FRONT_AND_BACK);\r
+ transparent.setRenderState(ms);\r
+ \r
+ AlphaState as = editor.getRenderingComponent().getDisplaySystem().getRenderer().createAlphaState();\r
+ as.setBlendEnabled(true);\r
+ as.setDstFunction(AlphaState.DB_ONE_MINUS_SRC_ALPHA);\r
+ as.setSrcFunction(AlphaState.DB_SRC_ALPHA);\r
+ transparent.setRenderState(as);\r
+ \r
+ ms = editor.getRenderingComponent().getDisplaySystem().getRenderer().createMaterialState();\r
+ ms.setDiffuse(new ColorRGBA(1.f, 1.f, 1.f, 1.f));\r
+ ms.setEmissive(new ColorRGBA(1.f, 1.f, 1.f, 1.f));\r
+ ms.setSpecular(new ColorRGBA(1.f, 1.f, 1.f, 1.f));\r
+ ms.setAmbient(new ColorRGBA(1.f, 1.f, 1.f, 1.f));\r
+ ms.setShininess(128.f);\r
+ selectedEdgeState = ms;\r
+ \r
+ ms = editor.getRenderingComponent().getDisplaySystem().getRenderer().createMaterialState();\r
+ ms.setDiffuse(new ColorRGBA(1.f, 0.f, 1.f, 1.f));\r
+ ms.setEmissive(new ColorRGBA(1.f, 0.f, 1.f, 1.f));\r
+ ms.setSpecular(new ColorRGBA(1.f, 0.f, 1.f, 1.f));\r
+ ms.setAmbient(new ColorRGBA(1.f, 0.f, 1.f, 1.f));\r
+ ms.setShininess(128.f);\r
+ \r
+ highlightedEdgeState = ms;\r
+\r
+ \r
+ }\r
+\r
+\r
+ /**\r
+ * This method is used to get implementation specific geometry.\r
+ * Arrays first element is a mesh, second contains edges.\r
+ * @return\r
+ */\r
+ public Geometry[] getGeometry(Graph graph, boolean update) {\r
+ G3DNode shape = getG3DNode(graph);\r
+ final GeometryProvider provider = GeometryProviderRegistry.getGeometryProvider(shape);\r
+ if (!update) {\r
+ return provider.getGeometryFromResource(shape, false);\r
+ } else {\r
+ if (geometry == null) {\r
+ geometry = provider.getGeometryFromResource(shape, false);\r
+ } else {\r
+ provider.reconstructGeometry(shape, false, geometry);\r
+ }\r
+ return geometry;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Updates shapes and it's ancestors geometry\r
+ */\r
+ public void updateGeometry(Graph graph) {\r
+ updateTransform(graph);\r
+ // cleanAnimation();\r
+ //System.out.println("ShapeNode.updateGeometry() " + name);\r
+ if (geometry == null) {\r
+ Geometry g[] = getGeometry(graph,true);\r
+ if (g != null) {\r
+ mesh = g[0];\r
+ //TODO : uid\r
+ mesh.setName(id); \r
+ mesh.setModelBound(new BoundingBox());\r
+ if (g.length > 1) {\r
+ lines = g[1];\r
+ } else {\r
+ lines = null;\r
+ }\r
+ body.attachChild(mesh);\r
+ transparent.detachAllChildren();\r
+ SharedMesh m = new SharedMesh("",(TriMesh)mesh);\r
+ m.setRenderQueueMode(Renderer.QUEUE_TRANSPARENT);\r
+ m.getBatch(0).setCastsShadows(false);\r
+ transparent.attachChild(m);\r
+ \r
+ \r
+ if (lines == null) {\r
+ WireframeState ws = editor.getRenderingComponent().getDisplaySystem().getRenderer().createWireframeState();\r
+ edge.attachChild(new SharedMesh("",(TriMesh)mesh));\r
+ edge.setRenderState(ws);\r
+ } else {\r
+ ZBufferState zs = editor.getRenderingComponent().getDisplaySystem().getRenderer().createZBufferState();\r
+ zs.setFunction(ZBufferState.CF_ALWAYS);\r
+ AlphaState as = editor.getRenderingComponent().getDisplaySystem().getRenderer().createAlphaState();\r
+ as.setBlendEnabled(true);\r
+ as.setDstFunction(AlphaState.DB_ONE_MINUS_SRC_ALPHA);\r
+ as.setSrcFunction(AlphaState.DB_SRC_ALPHA);\r
+ lines.setRenderState(zs);\r
+ lines.setRenderState(as);\r
+ lines.setRenderQueueMode(Renderer.QUEUE_TRANSPARENT);\r
+ edge.attachChild(lines);\r
+ }\r
+\r
+ }\r
+ }\r
+ if (geometry != null) {\r
+ getGeometry(graph,true);\r
+\r
+ \r
+ G3DNode shape = getG3DNode(graph);\r
+ //if (renderStates == null)\r
+ updateAppearance(shape);\r
+\r
+ if (isVisible()) {\r
+ getGroup().attachChild(body);\r
+ } else {\r
+ body.removeFromParent();\r
+ }\r
+ if (isTransparentVisible()) {\r
+ getGroup().attachChild(transparent);\r
+ //setVisible(TRANSPARENT, true);\r
+ } else {\r
+ transparent.removeFromParent();\r
+ }\r
+\r
+ if (isSelectedVisible() || isHighlightedVisible()) {\r
+ getGroup().attachChild(edge);\r
+ //setVisible(SELECTED_EDGE, true);\r
+ } else {\r
+ edge.removeFromParent();\r
+ //setVisible(SELECTED_EDGE,false);\r
+ }\r
+ \r
+ \r
+ mesh.updateModelBound();\r
+ CollisionTreeManager.getInstance().updateCollisionTree(mesh);\r
+ //mesh.updateCollisionTree();\r
+ \r
+ }\r
+ }\r
+ \r
+ protected void updateAppearance(IEntity shape) {\r
+ AppearanceProvider provider = AppearanceProviderRegistry.getAppearanceProvider(shape);\r
+ if (provider != null) {\r
+ renderStates = provider.getAppearanceFromResource(shape, editor.getRenderingComponent().getDisplaySystem().getRenderer());\r
+ } else {\r
+ renderStates = getMaterial();\r
+ }\r
+ \r
+ isTransparent = false;\r
+ for (RenderState s : renderStates) {\r
+ if (s instanceof AlphaState)\r
+ isTransparent = true;\r
+ }\r
+ setAppearance();\r
+ }\r
+ \r
+ protected void setAppearance() {\r
+ if (mesh == null || renderStates == null) {\r
+ return;\r
+ }\r
+ for (RenderState s : renderStates)\r
+ mesh.setRenderState(s);\r
+ if (isTransparent)\r
+ mesh.setRenderQueueMode(Renderer.QUEUE_TRANSPARENT);\r
+ else\r
+ mesh.setRenderQueueMode(Renderer.QUEUE_OPAQUE);\r
+ }\r
+\r
+ public void setSelected(boolean selected) {\r
+ if (this.selected == selected)\r
+ return;\r
+ this.selected = selected;\r
+ if (selected) {\r
+\r
+ setSelectedVisible(true);\r
+ setTransparentVisible(true);\r
+ } else {\r
+ setSelectedVisible(false);\r
+ setTransparentVisible(false);\r
+ }\r
+ }\r
+\r
+ public boolean isSelected() {\r
+ return selected;\r
+ }\r
+ \r
+ \r
+\r
+ public boolean isHighlighted() {\r
+ return highlighted;\r
+ }\r
+\r
+ public void setHighlighted(boolean highlighted) {\r
+ if (this.highlighted == highlighted)\r
+ return;\r
+ this.highlighted = highlighted;\r
+ if (highlighted) {\r
+ setHighlightedVisible(true);\r
+ } else {\r
+ setHighlightedVisible(false);\r
+ }\r
+ }\r
+ \r
+ public boolean isVisible(int shape) {\r
+ return visible[shape];\r
+ }\r
+ \r
+ public void setVisible(int shape, boolean visible) {\r
+ if (this.visible[shape] == visible)\r
+ return; \r
+ this.visible[shape] = visible;\r
+ if (mesh == null) {\r
+ return;\r
+ }\r
+ if (this.visible[NORMAL]){\r
+ getGroup().attachChild(body);\r
+ } else {\r
+ body.removeFromParent();\r
+ }\r
+ if (this.visible[TRANSPARENT]) {\r
+ getGroup().attachChild(transparent);\r
+ } else {\r
+ transparent.removeFromParent();\r
+ }\r
+ if (this.visible[SELECTED_EDGE] || this.visible[HIGHLIGHTED_EDGE]) {\r
+ if (this.visible[HIGHLIGHTED_EDGE])\r
+ edge.setRenderState(highlightedEdgeState);\r
+ else\r
+ edge.setRenderState(selectedEdgeState);\r
+ getGroup().attachChild(edge);\r
+ edge.updateRenderState();\r
+ } else {\r
+ edge.removeFromParent();\r
+ } \r
+ }\r
+\r
+ public boolean isVisible() {\r
+ return isVisible(NORMAL);\r
+ }\r
+\r
+ public void setVisible(boolean visible) {\r
+ setVisible(NORMAL, visible);\r
+ }\r
+\r
+ public boolean isSelectedVisible() {\r
+ return isVisible(SELECTED_EDGE);\r
+ }\r
+\r
+ public void setSelectedVisible(boolean visible) {\r
+ setVisible(SELECTED_EDGE, visible);\r
+ }\r
+\r
+ public boolean isHighlightedVisible() {\r
+ return isVisible(HIGHLIGHTED_EDGE);\r
+ }\r
+\r
+ public void setHighlightedVisible(boolean visible) {\r
+ setVisible(HIGHLIGHTED_EDGE, visible);\r
+ \r
+ }\r
+\r
+ \r
+\r
+ public boolean isTransparentVisible() {\r
+ return isVisible(TRANSPARENT);\r
+ }\r
+\r
+ public void setTransparentVisible(boolean visible) {\r
+ setVisible(TRANSPARENT, visible);\r
+ }\r
+\r
+ public void setPickable(boolean pickable) {\r
+ body.setIsCollidable(pickable);\r
+ }\r
+ \r
+ public Collection<RenderState> getMaterial() {\r
+ List<RenderState> states = new ArrayList<RenderState>();\r
+ MaterialState ms = editor.getRenderingComponent().getDisplaySystem().getRenderer().createMaterialState();\r
+ ms.setEmissive(new ColorRGBA(0.f,0.f,0.f,0.f));\r
+ ms.setSpecular(new ColorRGBA(1.f,1.f,1.f,1.f));\r
+ ms.setDiffuse(new ColorRGBA(0.75f,0.f,0.f,0.f));\r
+ ms.setAmbient(new ColorRGBA(0.75f,0.f,0.f,0.f));\r
+ ms.setEnabled(true);\r
+ ms.setShininess(128.f);\r
+ states.add(ms);\r
+\r
+ return states; \r
+ }\r
+ \r
+ private Animation animation;\r
+ private static int preCalcSteps = 9;\r
+ private Geometry[] preCalc = null;\r
+ private int currentPreCalc = 0;\r
+ \r
+ public void animate(double delta,double frameTime) {\r
+ if (animation != null)\r
+ animation.interpolate(delta);\r
+ if (preCalc != null) {\r
+ int newPreCalc = (int)Math.round(delta*(preCalc.length-1));\r
+ if (currentPreCalc != newPreCalc) {\r
+\r
+ preCalc[currentPreCalc].removeFromParent();\r
+ currentPreCalc = newPreCalc;\r
+ \r
+ body.attachChild(preCalc[currentPreCalc]);\r
+ }\r
+ }\r
+ }\r
+ \r
+ private void cleanAnimation() {\r
+ this.animation = null;\r
+ if (preCalc != null) {\r
+ for (Geometry g : preCalc) {\r
+ if (g != null) {\r
+ g.removeFromParent();\r
+ g.clearBuffers();\r
+ }\r
+ }\r
+ preCalc = null;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Sets shape's animation\r
+ * TODO : multiple animations at the same time! (must check common animatable properties)\r
+ * TODO : initial values (material, ..) (requires changes in the ontology)\r
+ * TODO : messy code, refactor!\r
+ * TODO : calculate number of required pre-calculated geometries \r
+ * @param animation\r
+ */\r
+ public boolean setAnimation(Graph g, Resource res) {\r
+ ContextGraph graph;\r
+ if (g instanceof ContextGraph) {\r
+ graph = (ContextGraph)g;\r
+ } else {\r
+ graph = new ContextGraph(g);\r
+ graph.setContext(shapeResource);\r
+ }\r
+ cleanAnimation();\r
+ if (res == null) {\r
+ if (isVisible())\r
+ body.attachChild(mesh);\r
+ return false;\r
+ }\r
+ org.simantics.animation.stubs.Animation animation = new org.simantics.animation.stubs.Animation(graph,res);\r
+ G3DNode shape = getG3DNode(graph);\r
+ G3DNode modelResource = G3DTools.getModelFromResource(graph,shape.getResource());\r
+ assert (modelResource != null);\r
+ G3DModel model = new G3DModel(graph,modelResource.getResource());\r
+ Collection<org.simantics.animation.stubs.Animation> animations = model.getAnimation();\r
+ boolean found = false;\r
+ for (org.simantics.animation.stubs.Animation a : animations) {\r
+ if (a.getResource().equals(animation.getResource())) {\r
+ found = true;\r
+ break;\r
+ }\r
+ }\r
+ if (!found) {\r
+ ErrorLogger.getDefault().logWarning("Shape " + shape.getResource() + " cannot handle animation " + animation.getResource() + " because it isn't model's animation", null);\r
+ return false;\r
+ }\r
+ Collection<org.simantics.animation.stubs.Interpolator> interpolators = animation.getInterpolator();\r
+ List<org.simantics.animation.stubs.Interpolator> handled = new ArrayList<org.simantics.animation.stubs.Interpolator>();\r
+ List<org.simantics.animation.stubs.Interpolator> precalculated = new ArrayList<org.simantics.animation.stubs.Interpolator>();\r
+ for (org.simantics.animation.stubs.Interpolator i : interpolators) {\r
+ IEntity target = i.getTarget();\r
+ if (G3DTools.hasProperty(graph,shape.getResource(),target.getResource()))\r
+ handled.add(i);\r
+ else if (G3DTools.hasSubProperty(graph,shape.getResource(),target.getResource())) {\r
+ precalculated.add(i);\r
+ }\r
+ }\r
+ if (handled.size() == 0 && precalculated.size() == 0) {\r
+ ErrorLogger.getDefault().logWarning("Shape " + shape.getResource() + " cannot handle animation " + animation.getResource() + " since it doesn't change any of shape's properties", null);\r
+ return false;\r
+ }\r
+ \r
+ \r
+ this.animation = new Animation();\r
+ \r
+ org.simantics.animation.stubs.Interpolator[] pos = new org.simantics.animation.stubs.Interpolator[3];\r
+ org.simantics.animation.stubs.Interpolator[] ambient = new org.simantics.animation.stubs.Interpolator[3];\r
+ org.simantics.animation.stubs.Interpolator[] diffuse = new org.simantics.animation.stubs.Interpolator[3];\r
+ org.simantics.animation.stubs.Interpolator[] specular = new org.simantics.animation.stubs.Interpolator[3];\r
+ org.simantics.animation.stubs.Interpolator[] emissive = new org.simantics.animation.stubs.Interpolator[3];\r
+\r
+ Builtins builtins = graph.getBuiltins();\r
+\r
+ \r
+ for (org.simantics.animation.stubs.Interpolator i : handled) {\r
+ IEntity target = i.getTarget();\r
+ //if (target.isInstanceOf(Resources.g3dResource.LocalOrientation)) {\r
+ if (target.isInstanceOf(Resources.g3dResource.Orientation) && target.getRelatedObjects(Resources.g3dResource.LocalOrientationOf).size() == 1) {\r
+ SlerpInterpolator si = new SlerpInterpolator((SlerpCurve)Resources.curveBuilder.loadInterpolator(i));\r
+ si.setTarget(transform);\r
+ this.animation.addInterpolator(si);\r
+ } else if (target.isInstanceOf(builtins.Double)) {\r
+ Resource targetResource = target.getResource();\r
+ Collection<IEntity> p = target.getRelatedObjects(builtins.PropertyOf);\r
+ if (p.size() == 1) {\r
+ IEntity parent = p.iterator().next();\r
+ //if (parent.isInstanceOf(Resources.g3dResource.LocalPosition)) {\r
+ if (parent.isInstanceOf(Resources.g3dResource.Position) && parent.getRelatedObjects(Resources.g3dResource.LocalPositionOf).size() == 1) {\r
+ if (parent.getSingleRelatedObject(Resources.g3dResource.HasX).getResource().equals(targetResource)) {\r
+ pos[0] = i;\r
+ } else if (parent.getSingleRelatedObject(Resources.g3dResource.HasY).getResource().equals(targetResource)) {\r
+ pos[1] = i;\r
+ } else if (parent.getSingleRelatedObject(Resources.g3dResource.HasZ).getResource().equals(targetResource)) {\r
+ pos[2] = i;\r
+ } else {\r
+ ErrorLogger.getDefault().logWarning("Cannot map animation interpolator " + i.getResource() + " to target (Position ?)" + target.getResource(), null);\r
+ }\r
+ } else if (parent.isInstanceOf(Resources.g3dResource.Color)) {\r
+ org.simantics.animation.stubs.Interpolator[] color = null;\r
+ if (parent.isInstanceOf(Resources.g3dResource.Color) && parent.getRelatedObjects(Resources.g3dResource.AmbientColorOf).size() > 0) {\r
+ color = ambient;\r
+ } else if (parent.isInstanceOf(Resources.g3dResource.Color)&& parent.getRelatedObjects(Resources.g3dResource.DiffuseColorOf).size() > 0) {\r
+ color = diffuse;\r
+ } else if (parent.isInstanceOf(Resources.g3dResource.Color) && parent.getRelatedObjects(Resources.g3dResource.SpecularColorOf).size() > 0) {\r
+ color = specular;\r
+ } else if (parent.isInstanceOf(Resources.g3dResource.Color) && parent.getRelatedObjects(Resources.g3dResource.EmissiveColorOf).size() > 0) {\r
+ color = emissive;\r
+ } else {\r
+ ErrorLogger.getDefault().logWarning("Cannot map animation interpolator " + i.getResource() + " to target (Color)" + target.getResource() + " unknown color type", null);\r
+ }\r
+ if (color != null) {\r
+ if (parent.getSingleRelatedObject(Resources.g3dResource.HasRed).getResource().equals(targetResource)) {\r
+ color[0] = i;\r
+ } else if (parent.getSingleRelatedObject(Resources.g3dResource.HasGreen).getResource().equals(targetResource)) {\r
+ color[1] = i;\r
+ } else if (parent.getSingleRelatedObject(Resources.g3dResource.HasBlue).getResource().equals(targetResource)) {\r
+ color[2] = i;\r
+ } else {\r
+ ErrorLogger.getDefault().logWarning(\r
+ "Cannot map animation interpolator " + i.getResource()\r
+ + " to target (Color ?)" + target.getResource(), null);\r
+ }\r
+ }\r
+ } else if (parent.isInstanceOf(Resources.g3dResource.Material)) {\r
+ // TODO : transparency or shininess \r
+ } else {\r
+ ErrorLogger.getDefault().logWarning("Cannot map animation interpolator " + i.getResource() + " to target" + target.getResource() + " adding it to precalculated interpolators", null);\r
+ precalculated.add(i);\r
+ }\r
+ } else {\r
+ if (p.size() == 0) {\r
+ ErrorLogger.getDefault().logWarning("Cannot map animation interpolator " + i.getResource() + " to target (Double)" + target.getResource() + " since it is not a part of a property", null);\r
+ } else {\r
+ ErrorLogger.getDefault().logWarning("Cannot map animation interpolator " + i.getResource() + " to target (Double)" + target.getResource() + " since it acts as a property to more than one entity", null); \r
+ }\r
+ }\r
+ } else {\r
+ ErrorLogger.getDefault().logWarning("Cannot map animation interpolator " + i.getResource() + " to target" + target.getResource(), null);\r
+ }\r
+ }\r
+ \r
+ if (pos[0] != null || pos[1] != null || pos[2] != null) {\r
+ ScalarInterpolator xIp;\r
+ ScalarInterpolator yIp;\r
+ ScalarInterpolator zIp;\r
+ if (pos[0] != null) {\r
+ xIp = new TCBInterpolator((TCBCurve)Resources.curveBuilder.loadInterpolator(pos[0]));\r
+ } else {\r
+ xIp = new ConstantInterpolator(shape.getLocalPosition().getX()[0]);\r
+ }\r
+ if (pos[1] != null) {\r
+ yIp = new TCBInterpolator((TCBCurve)Resources.curveBuilder.loadInterpolator(pos[1]));\r
+ } else {\r
+ yIp = new ConstantInterpolator(shape.getLocalPosition().getY()[0]);\r
+ }\r
+ if (pos[2] != null) {\r
+ zIp = new TCBInterpolator((TCBCurve)Resources.curveBuilder.loadInterpolator(pos[2]));\r
+ } else {\r
+ zIp = new ConstantInterpolator(shape.getLocalPosition().getZ()[0]);\r
+ }\r
+ ChanneledPositionInterpolator ip = new ChanneledPositionInterpolator(xIp,yIp,zIp);\r
+ ip.setTarget(transform);\r
+ this.animation.addInterpolator(ip);\r
+ \r
+ } \r
+ addColorInterpolator(shape, ambient, ChanneledColorInterpolator.AMBIENT);\r
+ addColorInterpolator(shape, diffuse, ChanneledColorInterpolator.DIFFUSE);\r
+ addColorInterpolator(shape, emissive, ChanneledColorInterpolator.EMISSIVE);\r
+ addColorInterpolator(shape, specular, ChanneledColorInterpolator.SPECULAR);\r
+ \r
+ if (precalculated.size() == 0) {\r
+ preCalc = null;\r
+ } else {\r
+ preCalc = new Geometry[preCalcSteps+1];\r
+ for (int i = 0; i <= preCalcSteps; i++) {\r
+ double delta = ((double)i / (double)preCalcSteps);\r
+ // TODO : copy-paste from CSGAnimatorView\r
+ // FIXME : does not update transformations (since ContextGraph does not support queries for context dependent values)\r
+ for (Interpolator ip : precalculated) {\r
+ if (ip.isInstanceOf(Resources.animationResource.ScalarInterpolator)) {\r
+ // TODO : creating curve each time when time is set is slow.\r
+ // Curve should be cached\r
+ TCBCurve c = (TCBCurve)Resources.curveBuilder.loadInterpolator(ip);\r
+ double out = c.evaluate(delta);\r
+ //Double d = DoubleFactory.create(ip.getTarget());\r
+ //d.setValue(new double[]{out});\r
+ IEntity d = ip.getTarget();\r
+ d.toProperty().setDoubleArray(new double[]{out});\r
+ } else if (ip.isInstanceOf(Resources.animationResource.SlerpInterpolator)) {\r
+ // TODO : creating curve each time when time is set is slow.\r
+ // Curve should be cached\r
+ SlerpCurve c = (SlerpCurve)Resources.curveBuilder.loadInterpolator(ip);\r
+ Quat4d out = c.evaluate(delta);\r
+ Orientation r = new Orientation(ip.getTarget());\r
+ AxisAngle4d aa = new AxisAngle4d();\r
+ aa.set(out);\r
+ G3DTools.setOrientation(r, aa);\r
+ }\r
+ }\r
+ preCalc[i] = getGeometry(graph,false)[0];\r
+ preCalc[i].setIsCollidable(false);\r
+ AppearanceTools.copyMaterial(mesh, preCalc[i]);\r
+ }\r
+ \r
+ // We'll have to remove original (non-animated) shape from the node\r
+ mesh.removeFromParent();\r
+ body.attachChild(preCalc[0]);\r
+ \r
+ }\r
+ return true;\r
+ }\r
+ \r
+ private void addColorInterpolator(G3DNode shape, org.simantics.animation.stubs.Interpolator[] color, int type) {\r
+ if (color[0] != null || color[1] != null || color[2] != null) {\r
+ ScalarInterpolator xIp;\r
+ ScalarInterpolator yIp;\r
+ ScalarInterpolator zIp;\r
+ Color col = null;\r
+ Collection<IEntity> appearanceResource = shape.getRelatedObjects(Resources.g3dResource.HasAppearance);\r
+ if (appearanceResource.size() == 0) {\r
+ ErrorLogger.getDefault().logWarning("Cannot create interpolator for color because shape " + shape.getResource() + " has no appearance", null);\r
+ }\r
+ Appearance a = new Appearance(shape.getGraph(),appearanceResource.iterator().next().getResource());\r
+ switch (type) {\r
+ case ChanneledColorInterpolator.AMBIENT:\r
+ col = a.getMaterial().getAmbientColor();\r
+ break;\r
+ case ChanneledColorInterpolator.DIFFUSE:\r
+ col = a.getMaterial().getDiffuseColor();\r
+ break;\r
+ case ChanneledColorInterpolator.EMISSIVE:\r
+ col = a.getMaterial().getEmissiveColor();\r
+ break;\r
+ case ChanneledColorInterpolator.SPECULAR:\r
+ col = a.getMaterial().getSpecularColor();\r
+ break;\r
+ default:\r
+ ErrorLogger.defaultLogError("Unknown color type", null);\r
+ return;\r
+ }\r
+\r
+ if (color[0] != null) {\r
+ xIp = new TCBInterpolator((TCBCurve)Resources.curveBuilder.loadInterpolator(color[0]));//CurveUtils.loadCurve(color[0].getResource()));\r
+ } else {\r
+ xIp = new ConstantInterpolator(col.getRed()[0]);\r
+ }\r
+ if (color[1] != null) {\r
+ yIp = new TCBInterpolator((TCBCurve)Resources.curveBuilder.loadInterpolator(color[1]));//CurveUtils.loadCurve(color[1].getResource()));\r
+ } else {\r
+ yIp = new ConstantInterpolator(col.getGreen()[0]);\r
+ }\r
+ if (color[1] != null) {\r
+ zIp = new TCBInterpolator((TCBCurve)Resources.curveBuilder.loadInterpolator(color[2]));//CurveUtils.loadCurve(color[2].getResource()));\r
+ } else {\r
+ zIp = new ConstantInterpolator(col.getBlue()[0]);\r
+ }\r
+ ChanneledColorInterpolator ip = new ChanneledColorInterpolator(xIp,yIp,zIp);\r
+ ip.setType(type);\r
+ ip.setTarget(mesh.getRenderState(RenderState.RS_MATERIAL));\r
+ this.animation.addInterpolator(ip);\r
+ } \r
+ }\r
+ \r
+ public boolean setRandomAnimation(Graph graph) {\r
+ return false;\r
+ }\r
+ \r
+ public void dispose() {\r
+// mesh.clearBuffers();\r
+// mesh.clearBatches();\r
+// lines.clearBuffers();\r
+// lines.clearBatches();\r
+ if (mesh != null) {\r
+ mesh.removeFromParent();\r
+ mesh.dispose();\r
+ mesh = null;\r
+ }\r
+ if (lines != null) {\r
+ lines.removeFromParent();\r
+ lines.dispose();\r
+ lines = null;\r
+ }\r
+ super.dispose();\r
+ }\r
+}
\ No newline at end of file