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