1 /*******************************************************************************
\r
2 * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.
\r
3 * All rights reserved. This program and the accompanying materials
\r
4 * are made available under the terms of the Eclipse Public License v1.0
\r
5 * which accompanies this distribution, and is available at
\r
6 * http://www.eclipse.org/legal/epl-v10.html
\r
9 * VTT Technical Research Centre of Finland - initial API and implementation
\r
10 *******************************************************************************/
\r
11 package org.simantics.proconf.g3d.scenegraph;
\r
13 import java.util.ArrayList;
\r
14 import java.util.Collection;
\r
15 import java.util.List;
\r
17 import javax.vecmath.AxisAngle4d;
\r
18 import javax.vecmath.Quat4d;
\r
20 import org.simantics.g2d.stubs.anim.Interpolator;
\r
21 import org.simantics.animation.curve.SlerpCurve;
\r
22 import org.simantics.animation.curve.TCBCurve;
\r
23 import org.simantics.proconf.g3d.Resources;
\r
24 import org.simantics.proconf.g3d.animation.Animatable;
\r
25 import org.simantics.proconf.g3d.animation.Animation;
\r
26 import org.simantics.proconf.g3d.animation.ChanneledColorInterpolator;
\r
27 import org.simantics.proconf.g3d.animation.ChanneledPositionInterpolator;
\r
28 import org.simantics.proconf.g3d.animation.ConstantInterpolator;
\r
29 import org.simantics.proconf.g3d.animation.ScalarInterpolator;
\r
30 import org.simantics.proconf.g3d.animation.SlerpInterpolator;
\r
31 import org.simantics.proconf.g3d.animation.TCBInterpolator;
\r
32 import org.simantics.proconf.g3d.base.AppearanceTools;
\r
33 import org.simantics.proconf.g3d.base.G3DTools;
\r
34 import org.simantics.proconf.g3d.base.GeometryProvider;
\r
35 import org.simantics.proconf.g3d.base.GeometryProviderRegistry;
\r
36 import org.simantics.proconf.g3d.base.ThreeDimensionalEditorBase;
\r
37 import org.simantics.proconf.g3d.stubs.Appearance;
\r
38 import org.simantics.proconf.g3d.stubs.Color;
\r
39 import org.simantics.proconf.g3d.stubs.G3DModel;
\r
40 import org.simantics.proconf.g3d.stubs.G3DNode;
\r
41 import org.simantics.proconf.g3d.stubs.Orientation;
\r
42 import org.simantics.utils.ErrorLogger;
\r
44 import com.jme.bounding.BoundingBox;
\r
45 import com.jme.bounding.CollisionTreeManager;
\r
46 import com.jme.intersection.PickResults;
\r
47 import com.jme.math.Ray;
\r
48 import com.jme.renderer.ColorRGBA;
\r
49 import com.jme.renderer.Renderer;
\r
50 import com.jme.scene.Geometry;
\r
51 import com.jme.scene.Node;
\r
52 import com.jme.scene.SharedMesh;
\r
53 import com.jme.scene.TriMesh;
\r
54 import com.jme.scene.state.AlphaState;
\r
55 import com.jme.scene.state.MaterialState;
\r
56 import com.jme.scene.state.RenderState;
\r
57 import com.jme.scene.state.WireframeState;
\r
58 import com.jme.scene.state.ZBufferState;
\r
60 import org.simantics.db.Builtins;
\r
61 import org.simantics.db.ContextGraph;
\r
62 import org.simantics.db.Graph;
\r
63 import org.simantics.db.Resource;
\r
64 import org.simantics.layer0.utils.IEntity;
\r
66 public class ShapeNode extends AbstractGraphicsNode implements Animatable, IGeometryNode{
\r
68 public static final int NORMAL = 0;
\r
69 public static final int TRANSPARENT = 1;
\r
70 public static final int SELECTED_EDGE = 2;
\r
71 public static final int HIGHLIGHTED_EDGE = 3;
\r
73 private boolean highlighted = false;
\r
75 protected Geometry mesh = null;
\r
76 protected Geometry lines = null;
\r
77 protected Geometry[] geometry = null;
\r
79 private boolean visible[] = new boolean[4];
\r
82 private Node transparent;
\r
85 private MaterialState selectedEdgeState;
\r
86 private MaterialState highlightedEdgeState;
\r
88 private Collection<RenderState> renderStates;
\r
89 private boolean isTransparent;
\r
92 public ShapeNode(ThreeDimensionalEditorBase editor,IGraphicsNode parent, Graph graph, Resource shapeResource) {
\r
93 super(editor,parent, graph, shapeResource);
\r
94 for (int i = 0; i < visible.length; i++)
\r
102 transparent = new Node() {
\r
103 private static final long serialVersionUID = 1L;
\r
105 public void calculatePick(Ray ray, PickResults results) {
\r
110 // transparent.setRenderQueueMode(Renderer.QUEUE_TRANSPARENT);
\r
113 private static final long serialVersionUID = 1L;
\r
115 public void calculatePick(Ray ray, PickResults results) {
\r
119 transparent.setIsCollidable(false);
\r
120 edge.setIsCollidable(false);
\r
122 MaterialState ms = editor.getRenderingComponent().getDisplaySystem().getRenderer().createMaterialState();
\r
123 ms.setDiffuse(new ColorRGBA(0.0f, 0.75f, 0.0f,0.3f));
\r
124 ms.setEmissive(new ColorRGBA(0f, 0f, 0f,0.3f));
\r
125 ms.setSpecular(new ColorRGBA(0.5f, 0.5f, 0.5f,0.3f));
\r
126 ms.setAmbient(new ColorRGBA(0.0f, 0.75f, 0.0f,0.3f));
\r
127 ms.setShininess(128.f);
\r
128 ms.setMaterialFace(MaterialState.MF_FRONT_AND_BACK);
\r
129 transparent.setRenderState(ms);
\r
131 AlphaState as = editor.getRenderingComponent().getDisplaySystem().getRenderer().createAlphaState();
\r
132 as.setBlendEnabled(true);
\r
133 as.setDstFunction(AlphaState.DB_ONE_MINUS_SRC_ALPHA);
\r
134 as.setSrcFunction(AlphaState.DB_SRC_ALPHA);
\r
135 transparent.setRenderState(as);
\r
137 ms = editor.getRenderingComponent().getDisplaySystem().getRenderer().createMaterialState();
\r
138 ms.setDiffuse(new ColorRGBA(1.f, 1.f, 1.f, 1.f));
\r
139 ms.setEmissive(new ColorRGBA(1.f, 1.f, 1.f, 1.f));
\r
140 ms.setSpecular(new ColorRGBA(1.f, 1.f, 1.f, 1.f));
\r
141 ms.setAmbient(new ColorRGBA(1.f, 1.f, 1.f, 1.f));
\r
142 ms.setShininess(128.f);
\r
143 selectedEdgeState = ms;
\r
145 ms = editor.getRenderingComponent().getDisplaySystem().getRenderer().createMaterialState();
\r
146 ms.setDiffuse(new ColorRGBA(1.f, 0.f, 1.f, 1.f));
\r
147 ms.setEmissive(new ColorRGBA(1.f, 0.f, 1.f, 1.f));
\r
148 ms.setSpecular(new ColorRGBA(1.f, 0.f, 1.f, 1.f));
\r
149 ms.setAmbient(new ColorRGBA(1.f, 0.f, 1.f, 1.f));
\r
150 ms.setShininess(128.f);
\r
152 highlightedEdgeState = ms;
\r
159 * This method is used to get implementation specific geometry.
\r
160 * Arrays first element is a mesh, second contains edges.
\r
163 public Geometry[] getGeometry(Graph graph, boolean update) {
\r
164 G3DNode shape = getG3DNode(graph);
\r
165 final GeometryProvider provider = GeometryProviderRegistry.getGeometryProvider(shape);
\r
167 return provider.getGeometryFromResource(shape, false);
\r
169 if (geometry == null) {
\r
170 geometry = provider.getGeometryFromResource(shape, false);
\r
172 provider.reconstructGeometry(shape, false, geometry);
\r
179 * Updates shapes and it's ancestors geometry
\r
181 public void updateGeometry(Graph graph) {
\r
182 updateTransform(graph);
\r
183 // cleanAnimation();
\r
184 //System.out.println("ShapeNode.updateGeometry() " + name);
\r
185 if (geometry == null) {
\r
186 Geometry g[] = getGeometry(graph,true);
\r
191 mesh.setModelBound(new BoundingBox());
\r
192 if (g.length > 1) {
\r
197 body.attachChild(mesh);
\r
198 transparent.detachAllChildren();
\r
199 SharedMesh m = new SharedMesh("",(TriMesh)mesh);
\r
200 m.setRenderQueueMode(Renderer.QUEUE_TRANSPARENT);
\r
201 m.getBatch(0).setCastsShadows(false);
\r
202 transparent.attachChild(m);
\r
205 if (lines == null) {
\r
206 WireframeState ws = editor.getRenderingComponent().getDisplaySystem().getRenderer().createWireframeState();
\r
207 edge.attachChild(new SharedMesh("",(TriMesh)mesh));
\r
208 edge.setRenderState(ws);
\r
210 ZBufferState zs = editor.getRenderingComponent().getDisplaySystem().getRenderer().createZBufferState();
\r
211 zs.setFunction(ZBufferState.CF_ALWAYS);
\r
212 AlphaState as = editor.getRenderingComponent().getDisplaySystem().getRenderer().createAlphaState();
\r
213 as.setBlendEnabled(true);
\r
214 as.setDstFunction(AlphaState.DB_ONE_MINUS_SRC_ALPHA);
\r
215 as.setSrcFunction(AlphaState.DB_SRC_ALPHA);
\r
216 lines.setRenderState(zs);
\r
217 lines.setRenderState(as);
\r
218 lines.setRenderQueueMode(Renderer.QUEUE_TRANSPARENT);
\r
219 edge.attachChild(lines);
\r
224 if (geometry != null) {
\r
225 getGeometry(graph,true);
\r
228 G3DNode shape = getG3DNode(graph);
\r
229 if (renderStates == null)
\r
230 updateAppearance(shape);
\r
233 getGroup().attachChild(body);
\r
235 body.removeFromParent();
\r
237 if (isTransparentVisible()) {
\r
238 getGroup().attachChild(transparent);
\r
239 //setVisible(TRANSPARENT, true);
\r
241 transparent.removeFromParent();
\r
244 if (isSelectedVisible() || isHighlightedVisible()) {
\r
245 getGroup().attachChild(edge);
\r
246 //setVisible(SELECTED_EDGE, true);
\r
248 edge.removeFromParent();
\r
249 //setVisible(SELECTED_EDGE,false);
\r
253 mesh.updateModelBound();
\r
254 CollisionTreeManager.getInstance().updateCollisionTree(mesh);
\r
255 //mesh.updateCollisionTree();
\r
260 protected void updateAppearance(IEntity shape) {
\r
261 Collection<IEntity> appearanceResource;
\r
262 if ((appearanceResource = shape.getRelatedObjects(Resources.g3dResource.HasAppearance)) != null && appearanceResource.size() > 0) {
\r
263 renderStates = AppearanceTools.getAppearance(new Appearance(shape.getGraph(),appearanceResource.iterator().next().getResource()), editor.getRenderingComponent().getDisplaySystem().getRenderer());
\r
265 renderStates = getMaterial();
\r
268 isTransparent = false;
\r
269 for (RenderState s : renderStates) {
\r
270 if (s instanceof AlphaState)
\r
271 isTransparent = true;
\r
276 protected void setAppearance() {
\r
277 if (mesh == null || renderStates == null) {
\r
280 for (RenderState s : renderStates)
\r
281 mesh.setRenderState(s);
\r
283 mesh.setRenderQueueMode(Renderer.QUEUE_TRANSPARENT);
\r
285 mesh.setRenderQueueMode(Renderer.QUEUE_OPAQUE);
\r
288 public void setSelected(boolean selected) {
\r
289 if (this.selected == selected)
\r
291 this.selected = selected;
\r
294 setSelectedVisible(true);
\r
295 setTransparentVisible(true);
\r
297 setSelectedVisible(false);
\r
298 setTransparentVisible(false);
\r
302 public boolean isSelected() {
\r
308 public boolean isHighlighted() {
\r
309 return highlighted;
\r
312 public void setHighlighted(boolean highlighted) {
\r
313 if (this.highlighted == highlighted)
\r
315 this.highlighted = highlighted;
\r
317 setHighlightedVisible(true);
\r
319 setHighlightedVisible(false);
\r
323 public boolean isVisible(int shape) {
\r
324 return visible[shape];
\r
327 public void setVisible(int shape, boolean visible) {
\r
328 if (this.visible[shape] == visible)
\r
330 this.visible[shape] = visible;
\r
331 if (mesh == null) {
\r
334 if (this.visible[NORMAL]){
\r
335 getGroup().attachChild(body);
\r
337 body.removeFromParent();
\r
339 if (this.visible[TRANSPARENT]) {
\r
340 getGroup().attachChild(transparent);
\r
342 transparent.removeFromParent();
\r
344 if (this.visible[SELECTED_EDGE] || this.visible[HIGHLIGHTED_EDGE]) {
\r
345 if (this.visible[HIGHLIGHTED_EDGE])
\r
346 edge.setRenderState(highlightedEdgeState);
\r
348 edge.setRenderState(selectedEdgeState);
\r
349 getGroup().attachChild(edge);
\r
350 edge.updateRenderState();
\r
352 edge.removeFromParent();
\r
356 public boolean isVisible() {
\r
357 return isVisible(NORMAL);
\r
360 public void setVisible(boolean visible) {
\r
361 setVisible(NORMAL, visible);
\r
364 public boolean isSelectedVisible() {
\r
365 return isVisible(SELECTED_EDGE);
\r
368 public void setSelectedVisible(boolean visible) {
\r
369 setVisible(SELECTED_EDGE, visible);
\r
372 public boolean isHighlightedVisible() {
\r
373 return isVisible(HIGHLIGHTED_EDGE);
\r
376 public void setHighlightedVisible(boolean visible) {
\r
377 setVisible(HIGHLIGHTED_EDGE, visible);
\r
383 public boolean isTransparentVisible() {
\r
384 return isVisible(TRANSPARENT);
\r
387 public void setTransparentVisible(boolean visible) {
\r
388 setVisible(TRANSPARENT, visible);
\r
391 public void setPickable(boolean pickable) {
\r
392 body.setIsCollidable(pickable);
\r
395 public Collection<RenderState> getMaterial() {
\r
396 List<RenderState> states = new ArrayList<RenderState>();
\r
397 MaterialState ms = editor.getRenderingComponent().getDisplaySystem().getRenderer().createMaterialState();
\r
398 ms.setEmissive(new ColorRGBA(0.f,0.f,0.f,0.f));
\r
399 ms.setSpecular(new ColorRGBA(1.f,1.f,1.f,1.f));
\r
400 ms.setDiffuse(new ColorRGBA(0.75f,0.f,0.f,0.f));
\r
401 ms.setAmbient(new ColorRGBA(0.75f,0.f,0.f,0.f));
\r
402 ms.setEnabled(true);
\r
403 ms.setShininess(128.f);
\r
409 private Animation animation;
\r
410 private static int preCalcSteps = 9;
\r
411 private Geometry[] preCalc = null;
\r
412 private int currentPreCalc = 0;
\r
414 public void animate(double delta,double frameTime) {
\r
415 if (animation != null)
\r
416 animation.interpolate(delta);
\r
417 if (preCalc != null) {
\r
418 int newPreCalc = (int)Math.round(delta*(preCalc.length-1));
\r
419 if (currentPreCalc != newPreCalc) {
\r
421 preCalc[currentPreCalc].removeFromParent();
\r
422 currentPreCalc = newPreCalc;
\r
424 body.attachChild(preCalc[currentPreCalc]);
\r
429 private void cleanAnimation() {
\r
430 this.animation = null;
\r
431 if (preCalc != null) {
\r
432 for (Geometry g : preCalc) {
\r
434 g.removeFromParent();
\r
443 * Sets shape's animation
\r
444 * TODO : multiple animations at the same time! (must check common animatable properties)
\r
445 * TODO : initial values (material, ..) (requires changes in the ontology)
\r
446 * TODO : messy code, refactor!
\r
447 * TODO : calculate number of required pre-calculated geometries
\r
450 public boolean setAnimation(Graph g, Resource res) {
\r
451 ContextGraph graph;
\r
452 if (g instanceof ContextGraph) {
\r
453 graph = (ContextGraph)g;
\r
455 graph = new ContextGraph(g);
\r
456 graph.setContext(shapeResource);
\r
461 body.attachChild(mesh);
\r
464 org.simantics.g2d.stubs.anim.Animation animation = new org.simantics.g2d.stubs.anim.Animation(graph,res);
\r
465 G3DNode shape = getG3DNode(graph);
\r
466 G3DNode modelResource = G3DTools.getModelFromResource(graph,shape.getResource());
\r
467 assert (modelResource != null);
\r
468 G3DModel model = new G3DModel(graph,modelResource.getResource());
\r
469 Collection<org.simantics.g2d.stubs.anim.Animation> animations = model.getAnimation();
\r
470 boolean found = false;
\r
471 for (org.simantics.g2d.stubs.anim.Animation a : animations) {
\r
472 if (a.getResource().equals(animation.getResource())) {
\r
478 ErrorLogger.getDefault().logWarning("Shape " + shape.getResource() + " cannot handle animation " + animation.getResource() + " because it isn't model's animation", null);
\r
481 Collection<org.simantics.g2d.stubs.anim.Interpolator> interpolators = animation.getInterpolator();
\r
482 List<org.simantics.g2d.stubs.anim.Interpolator> handled = new ArrayList<org.simantics.g2d.stubs.anim.Interpolator>();
\r
483 List<org.simantics.g2d.stubs.anim.Interpolator> precalculated = new ArrayList<org.simantics.g2d.stubs.anim.Interpolator>();
\r
484 for (org.simantics.g2d.stubs.anim.Interpolator i : interpolators) {
\r
485 IEntity target = i.getTarget();
\r
486 if (G3DTools.hasProperty(graph,shape.getResource(),target.getResource()))
\r
488 else if (G3DTools.hasSubProperty(graph,shape.getResource(),target.getResource())) {
\r
489 precalculated.add(i);
\r
492 if (handled.size() == 0 && precalculated.size() == 0) {
\r
493 ErrorLogger.getDefault().logWarning("Shape " + shape.getResource() + " cannot handle animation " + animation.getResource() + " since it doesn't change any of shape's properties", null);
\r
498 this.animation = new Animation();
\r
500 org.simantics.g2d.stubs.anim.Interpolator[] pos = new org.simantics.g2d.stubs.anim.Interpolator[3];
\r
501 org.simantics.g2d.stubs.anim.Interpolator[] ambient = new org.simantics.g2d.stubs.anim.Interpolator[3];
\r
502 org.simantics.g2d.stubs.anim.Interpolator[] diffuse = new org.simantics.g2d.stubs.anim.Interpolator[3];
\r
503 org.simantics.g2d.stubs.anim.Interpolator[] specular = new org.simantics.g2d.stubs.anim.Interpolator[3];
\r
504 org.simantics.g2d.stubs.anim.Interpolator[] emissive = new org.simantics.g2d.stubs.anim.Interpolator[3];
\r
506 Builtins builtins = graph.getBuiltins();
\r
509 for (org.simantics.g2d.stubs.anim.Interpolator i : handled) {
\r
510 IEntity target = i.getTarget();
\r
511 //if (target.isInstanceOf(Resources.g3dResource.LocalOrientation)) {
\r
512 if (target.isInstanceOf(Resources.g3dResource.Orientation) && target.getRelatedObjects(Resources.g3dResource.LocalOrientationOf).size() == 1) {
\r
513 SlerpInterpolator si = new SlerpInterpolator((SlerpCurve)Resources.curveBuilder.loadInterpolator(i));
\r
514 si.setTarget(transform);
\r
515 this.animation.addInterpolator(si);
\r
516 } else if (target.isInstanceOf(builtins.Double)) {
\r
517 Resource targetResource = target.getResource();
\r
518 Collection<IEntity> p = target.getRelatedObjects(builtins.PropertyOf);
\r
519 if (p.size() == 1) {
\r
520 IEntity parent = p.iterator().next();
\r
521 //if (parent.isInstanceOf(Resources.g3dResource.LocalPosition)) {
\r
522 if (parent.isInstanceOf(Resources.g3dResource.Position) && parent.getRelatedObjects(Resources.g3dResource.LocalPositionOf).size() == 1) {
\r
523 if (parent.getSingleRelatedObject(Resources.g3dResource.HasX).getResource().equals(targetResource)) {
\r
525 } else if (parent.getSingleRelatedObject(Resources.g3dResource.HasY).getResource().equals(targetResource)) {
\r
527 } else if (parent.getSingleRelatedObject(Resources.g3dResource.HasZ).getResource().equals(targetResource)) {
\r
530 ErrorLogger.getDefault().logWarning("Cannot map animation interpolator " + i.getResource() + " to target (Position ?)" + target.getResource(), null);
\r
532 } else if (parent.isInstanceOf(Resources.g3dResource.Color)) {
\r
533 org.simantics.g2d.stubs.anim.Interpolator[] color = null;
\r
534 if (parent.isInstanceOf(Resources.g3dResource.Color) && parent.getRelatedObjects(Resources.g3dResource.AmbientColorOf).size() > 0) {
\r
536 } else if (parent.isInstanceOf(Resources.g3dResource.Color)&& parent.getRelatedObjects(Resources.g3dResource.DiffuseColorOf).size() > 0) {
\r
538 } else if (parent.isInstanceOf(Resources.g3dResource.Color) && parent.getRelatedObjects(Resources.g3dResource.SpecularColorOf).size() > 0) {
\r
540 } else if (parent.isInstanceOf(Resources.g3dResource.Color) && parent.getRelatedObjects(Resources.g3dResource.EmissiveColorOf).size() > 0) {
\r
543 ErrorLogger.getDefault().logWarning("Cannot map animation interpolator " + i.getResource() + " to target (Color)" + target.getResource() + " unknown color type", null);
\r
545 if (color != null) {
\r
546 if (parent.getSingleRelatedObject(Resources.g3dResource.HasRed).getResource().equals(targetResource)) {
\r
548 } else if (parent.getSingleRelatedObject(Resources.g3dResource.HasGreen).getResource().equals(targetResource)) {
\r
550 } else if (parent.getSingleRelatedObject(Resources.g3dResource.HasBlue).getResource().equals(targetResource)) {
\r
553 ErrorLogger.getDefault().logWarning(
\r
554 "Cannot map animation interpolator " + i.getResource()
\r
555 + " to target (Color ?)" + target.getResource(), null);
\r
558 } else if (parent.isInstanceOf(Resources.g3dResource.Material)) {
\r
559 // TODO : transparency or shininess
\r
561 ErrorLogger.getDefault().logWarning("Cannot map animation interpolator " + i.getResource() + " to target" + target.getResource() + " adding it to precalculated interpolators", null);
\r
562 precalculated.add(i);
\r
565 if (p.size() == 0) {
\r
566 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
568 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
572 ErrorLogger.getDefault().logWarning("Cannot map animation interpolator " + i.getResource() + " to target" + target.getResource(), null);
\r
576 if (pos[0] != null || pos[1] != null || pos[2] != null) {
\r
577 ScalarInterpolator xIp;
\r
578 ScalarInterpolator yIp;
\r
579 ScalarInterpolator zIp;
\r
580 if (pos[0] != null) {
\r
581 xIp = new TCBInterpolator((TCBCurve)Resources.curveBuilder.loadInterpolator(pos[0]));
\r
583 xIp = new ConstantInterpolator(shape.getLocalPosition().getX()[0]);
\r
585 if (pos[1] != null) {
\r
586 yIp = new TCBInterpolator((TCBCurve)Resources.curveBuilder.loadInterpolator(pos[1]));
\r
588 yIp = new ConstantInterpolator(shape.getLocalPosition().getY()[0]);
\r
590 if (pos[2] != null) {
\r
591 zIp = new TCBInterpolator((TCBCurve)Resources.curveBuilder.loadInterpolator(pos[2]));
\r
593 zIp = new ConstantInterpolator(shape.getLocalPosition().getZ()[0]);
\r
595 ChanneledPositionInterpolator ip = new ChanneledPositionInterpolator(xIp,yIp,zIp);
\r
596 ip.setTarget(transform);
\r
597 this.animation.addInterpolator(ip);
\r
600 addColorInterpolator(shape, ambient, ChanneledColorInterpolator.AMBIENT);
\r
601 addColorInterpolator(shape, diffuse, ChanneledColorInterpolator.DIFFUSE);
\r
602 addColorInterpolator(shape, emissive, ChanneledColorInterpolator.EMISSIVE);
\r
603 addColorInterpolator(shape, specular, ChanneledColorInterpolator.SPECULAR);
\r
605 if (precalculated.size() == 0) {
\r
608 preCalc = new Geometry[preCalcSteps+1];
\r
609 for (int i = 0; i <= preCalcSteps; i++) {
\r
610 double delta = ((double)i / (double)preCalcSteps);
\r
611 // TODO : copy-paste from CSGAnimatorView
\r
612 // FIXME : does not update transformations (since ContextGraph does not support queries for context dependent values)
\r
613 for (Interpolator ip : precalculated) {
\r
614 if (ip.isInstanceOf(Resources.animationResource.ScalarInterpolator)) {
\r
615 // TODO : creating curve each time when time is set is slow.
\r
616 // Curve should be cached
\r
617 TCBCurve c = (TCBCurve)Resources.curveBuilder.loadInterpolator(ip);
\r
618 double out = c.evaluate(delta);
\r
619 //Double d = DoubleFactory.create(ip.getTarget());
\r
620 //d.setValue(new double[]{out});
\r
621 IEntity d = ip.getTarget();
\r
622 d.toProperty().setDoubleArray(new double[]{out});
\r
623 } else if (ip.isInstanceOf(Resources.animationResource.SlerpInterpolator)) {
\r
624 // TODO : creating curve each time when time is set is slow.
\r
625 // Curve should be cached
\r
626 SlerpCurve c = (SlerpCurve)Resources.curveBuilder.loadInterpolator(ip);
\r
627 Quat4d out = c.evaluate(delta);
\r
628 Orientation r = new Orientation(ip.getTarget());
\r
629 AxisAngle4d aa = new AxisAngle4d();
\r
631 G3DTools.setOrientation(r, aa);
\r
634 preCalc[i] = getGeometry(graph,false)[0];
\r
635 preCalc[i].setIsCollidable(false);
\r
636 AppearanceTools.copyMaterial(mesh, preCalc[i]);
\r
639 // We'll have to remove original (non-animated) shape from the node
\r
640 mesh.removeFromParent();
\r
641 body.attachChild(preCalc[0]);
\r
647 private void addColorInterpolator(G3DNode shape, org.simantics.g2d.stubs.anim.Interpolator[] color, int type) {
\r
648 if (color[0] != null || color[1] != null || color[2] != null) {
\r
649 ScalarInterpolator xIp;
\r
650 ScalarInterpolator yIp;
\r
651 ScalarInterpolator zIp;
\r
653 Collection<IEntity> appearanceResource = shape.getRelatedObjects(Resources.g3dResource.HasAppearance);
\r
654 if (appearanceResource.size() == 0) {
\r
655 ErrorLogger.getDefault().logWarning("Cannot create interpolator for color because shape " + shape.getResource() + " has no appearance", null);
\r
657 Appearance a = new Appearance(shape.getGraph(),appearanceResource.iterator().next().getResource());
\r
659 case ChanneledColorInterpolator.AMBIENT:
\r
660 col = a.getMaterial().getAmbientColor();
\r
662 case ChanneledColorInterpolator.DIFFUSE:
\r
663 col = a.getMaterial().getDiffuseColor();
\r
665 case ChanneledColorInterpolator.EMISSIVE:
\r
666 col = a.getMaterial().getEmissiveColor();
\r
668 case ChanneledColorInterpolator.SPECULAR:
\r
669 col = a.getMaterial().getSpecularColor();
\r
672 ErrorLogger.defaultLogError("Unknown color type", null);
\r
676 if (color[0] != null) {
\r
677 xIp = new TCBInterpolator((TCBCurve)Resources.curveBuilder.loadInterpolator(color[0]));//CurveUtils.loadCurve(color[0].getResource()));
\r
679 xIp = new ConstantInterpolator(col.getRed()[0]);
\r
681 if (color[1] != null) {
\r
682 yIp = new TCBInterpolator((TCBCurve)Resources.curveBuilder.loadInterpolator(color[1]));//CurveUtils.loadCurve(color[1].getResource()));
\r
684 yIp = new ConstantInterpolator(col.getGreen()[0]);
\r
686 if (color[1] != null) {
\r
687 zIp = new TCBInterpolator((TCBCurve)Resources.curveBuilder.loadInterpolator(color[2]));//CurveUtils.loadCurve(color[2].getResource()));
\r
689 zIp = new ConstantInterpolator(col.getBlue()[0]);
\r
691 ChanneledColorInterpolator ip = new ChanneledColorInterpolator(xIp,yIp,zIp);
\r
693 ip.setTarget(mesh.getRenderState(RenderState.RS_MATERIAL));
\r
694 this.animation.addInterpolator(ip);
\r
698 public boolean setRandomAnimation(Graph graph) {
\r
702 public void dispose() {
\r
703 // mesh.clearBuffers();
\r
704 // mesh.clearBatches();
\r
705 // lines.clearBuffers();
\r
706 // lines.clearBatches();
\r
707 if (mesh != null) {
\r
708 mesh.removeFromParent();
\r
712 if (lines != null) {
\r
713 lines.removeFromParent();
\r