1 /*******************************************************************************
\r
2 * Copyright (c) 2007- VTT Technical Research Centre of Finland.
\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.animation.stubs.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.AppearanceProvider;
\r
33 import org.simantics.proconf.g3d.base.AppearanceProviderRegistry;
\r
34 import org.simantics.proconf.g3d.base.AppearanceTools;
\r
35 import org.simantics.proconf.g3d.base.G3DTools;
\r
36 import org.simantics.proconf.g3d.base.GeometryProvider;
\r
37 import org.simantics.proconf.g3d.base.GeometryProviderRegistry;
\r
38 import org.simantics.proconf.g3d.base.ThreeDimensionalEditorBase;
\r
39 import org.simantics.proconf.g3d.stubs.Appearance;
\r
40 import org.simantics.proconf.g3d.stubs.Color;
\r
41 import org.simantics.proconf.g3d.stubs.G3DModel;
\r
42 import org.simantics.proconf.g3d.stubs.G3DNode;
\r
43 import org.simantics.proconf.g3d.stubs.Orientation;
\r
44 import org.simantics.utils.ui.ErrorLogger;
\r
46 import com.jme.bounding.BoundingBox;
\r
47 import com.jme.bounding.CollisionTreeManager;
\r
48 import com.jme.intersection.PickResults;
\r
49 import com.jme.math.Ray;
\r
50 import com.jme.renderer.ColorRGBA;
\r
51 import com.jme.renderer.Renderer;
\r
52 import com.jme.scene.Geometry;
\r
53 import com.jme.scene.Node;
\r
54 import com.jme.scene.SharedMesh;
\r
55 import com.jme.scene.TriMesh;
\r
56 import com.jme.scene.state.AlphaState;
\r
57 import com.jme.scene.state.MaterialState;
\r
58 import com.jme.scene.state.RenderState;
\r
59 import com.jme.scene.state.WireframeState;
\r
60 import com.jme.scene.state.ZBufferState;
\r
62 import org.simantics.db.Builtins;
\r
63 import org.simantics.db.ContextGraph;
\r
64 import org.simantics.db.Graph;
\r
65 import org.simantics.db.Resource;
\r
66 import org.simantics.layer0.utils.IEntity;
\r
68 public class ShapeNode extends AbstractGraphicsNode implements Animatable, IGeometryNode{
\r
70 public static final int NORMAL = 0;
\r
71 public static final int TRANSPARENT = 1;
\r
72 public static final int SELECTED_EDGE = 2;
\r
73 public static final int HIGHLIGHTED_EDGE = 3;
\r
75 private boolean highlighted = false;
\r
77 protected Geometry mesh = null;
\r
78 protected Geometry lines = null;
\r
79 protected Geometry[] geometry = null;
\r
81 private boolean visible[] = new boolean[4];
\r
84 private Node transparent;
\r
87 private MaterialState selectedEdgeState;
\r
88 private MaterialState highlightedEdgeState;
\r
90 private Collection<RenderState> renderStates;
\r
91 private boolean isTransparent;
\r
94 public ShapeNode(ThreeDimensionalEditorBase editor,IGraphicsNode parent, Graph graph, Resource shapeResource) {
\r
95 super(editor,parent, graph, shapeResource);
\r
96 for (int i = 0; i < visible.length; i++)
\r
104 transparent = new Node() {
\r
105 private static final long serialVersionUID = 1L;
\r
107 public void calculatePick(Ray ray, PickResults results) {
\r
112 // transparent.setRenderQueueMode(Renderer.QUEUE_TRANSPARENT);
\r
115 private static final long serialVersionUID = 1L;
\r
117 public void calculatePick(Ray ray, PickResults results) {
\r
121 transparent.setIsCollidable(false);
\r
122 edge.setIsCollidable(false);
\r
124 MaterialState ms = editor.getRenderingComponent().getDisplaySystem().getRenderer().createMaterialState();
\r
125 ms.setDiffuse(new ColorRGBA(0.0f, 0.75f, 0.0f,0.3f));
\r
126 ms.setEmissive(new ColorRGBA(0f, 0f, 0f,0.3f));
\r
127 ms.setSpecular(new ColorRGBA(0.5f, 0.5f, 0.5f,0.3f));
\r
128 ms.setAmbient(new ColorRGBA(0.0f, 0.75f, 0.0f,0.3f));
\r
129 ms.setShininess(128.f);
\r
130 ms.setMaterialFace(MaterialState.MF_FRONT_AND_BACK);
\r
131 transparent.setRenderState(ms);
\r
133 AlphaState as = editor.getRenderingComponent().getDisplaySystem().getRenderer().createAlphaState();
\r
134 as.setBlendEnabled(true);
\r
135 as.setDstFunction(AlphaState.DB_ONE_MINUS_SRC_ALPHA);
\r
136 as.setSrcFunction(AlphaState.DB_SRC_ALPHA);
\r
137 transparent.setRenderState(as);
\r
139 ms = editor.getRenderingComponent().getDisplaySystem().getRenderer().createMaterialState();
\r
140 ms.setDiffuse(new ColorRGBA(1.f, 1.f, 1.f, 1.f));
\r
141 ms.setEmissive(new ColorRGBA(1.f, 1.f, 1.f, 1.f));
\r
142 ms.setSpecular(new ColorRGBA(1.f, 1.f, 1.f, 1.f));
\r
143 ms.setAmbient(new ColorRGBA(1.f, 1.f, 1.f, 1.f));
\r
144 ms.setShininess(128.f);
\r
145 selectedEdgeState = ms;
\r
147 ms = editor.getRenderingComponent().getDisplaySystem().getRenderer().createMaterialState();
\r
148 ms.setDiffuse(new ColorRGBA(1.f, 0.f, 1.f, 1.f));
\r
149 ms.setEmissive(new ColorRGBA(1.f, 0.f, 1.f, 1.f));
\r
150 ms.setSpecular(new ColorRGBA(1.f, 0.f, 1.f, 1.f));
\r
151 ms.setAmbient(new ColorRGBA(1.f, 0.f, 1.f, 1.f));
\r
152 ms.setShininess(128.f);
\r
154 highlightedEdgeState = ms;
\r
161 * This method is used to get implementation specific geometry.
\r
162 * Arrays first element is a mesh, second contains edges.
\r
165 public Geometry[] getGeometry(Graph graph, boolean update) {
\r
166 G3DNode shape = getG3DNode(graph);
\r
167 final GeometryProvider provider = GeometryProviderRegistry.getGeometryProvider(shape);
\r
169 return provider.getGeometryFromResource(shape, false);
\r
171 if (geometry == null) {
\r
172 geometry = provider.getGeometryFromResource(shape, false);
\r
174 provider.reconstructGeometry(shape, false, geometry);
\r
181 * Updates shapes and it's ancestors geometry
\r
183 public void updateGeometry(Graph graph) {
\r
184 updateTransform(graph);
\r
185 // cleanAnimation();
\r
186 //System.out.println("ShapeNode.updateGeometry() " + name);
\r
187 if (geometry == null) {
\r
188 Geometry g[] = getGeometry(graph,true);
\r
193 mesh.setModelBound(new BoundingBox());
\r
194 if (g.length > 1) {
\r
199 body.attachChild(mesh);
\r
200 transparent.detachAllChildren();
\r
201 SharedMesh m = new SharedMesh("",(TriMesh)mesh);
\r
202 m.setRenderQueueMode(Renderer.QUEUE_TRANSPARENT);
\r
203 m.getBatch(0).setCastsShadows(false);
\r
204 transparent.attachChild(m);
\r
207 if (lines == null) {
\r
208 WireframeState ws = editor.getRenderingComponent().getDisplaySystem().getRenderer().createWireframeState();
\r
209 edge.attachChild(new SharedMesh("",(TriMesh)mesh));
\r
210 edge.setRenderState(ws);
\r
212 ZBufferState zs = editor.getRenderingComponent().getDisplaySystem().getRenderer().createZBufferState();
\r
213 zs.setFunction(ZBufferState.CF_ALWAYS);
\r
214 AlphaState as = editor.getRenderingComponent().getDisplaySystem().getRenderer().createAlphaState();
\r
215 as.setBlendEnabled(true);
\r
216 as.setDstFunction(AlphaState.DB_ONE_MINUS_SRC_ALPHA);
\r
217 as.setSrcFunction(AlphaState.DB_SRC_ALPHA);
\r
218 lines.setRenderState(zs);
\r
219 lines.setRenderState(as);
\r
220 lines.setRenderQueueMode(Renderer.QUEUE_TRANSPARENT);
\r
221 edge.attachChild(lines);
\r
226 if (geometry != null) {
\r
227 getGeometry(graph,true);
\r
230 G3DNode shape = getG3DNode(graph);
\r
231 //if (renderStates == null)
\r
232 updateAppearance(shape);
\r
235 getGroup().attachChild(body);
\r
237 body.removeFromParent();
\r
239 if (isTransparentVisible()) {
\r
240 getGroup().attachChild(transparent);
\r
241 //setVisible(TRANSPARENT, true);
\r
243 transparent.removeFromParent();
\r
246 if (isSelectedVisible() || isHighlightedVisible()) {
\r
247 getGroup().attachChild(edge);
\r
248 //setVisible(SELECTED_EDGE, true);
\r
250 edge.removeFromParent();
\r
251 //setVisible(SELECTED_EDGE,false);
\r
255 mesh.updateModelBound();
\r
256 CollisionTreeManager.getInstance().updateCollisionTree(mesh);
\r
257 //mesh.updateCollisionTree();
\r
262 protected void updateAppearance(IEntity shape) {
\r
263 AppearanceProvider provider = AppearanceProviderRegistry.getAppearanceProvider(shape);
\r
264 if (provider != null) {
\r
265 renderStates = provider.getAppearanceFromResource(shape, editor.getRenderingComponent().getDisplaySystem().getRenderer());
\r
267 renderStates = getMaterial();
\r
270 isTransparent = false;
\r
271 for (RenderState s : renderStates) {
\r
272 if (s instanceof AlphaState)
\r
273 isTransparent = true;
\r
278 protected void setAppearance() {
\r
279 if (mesh == null || renderStates == null) {
\r
282 for (RenderState s : renderStates)
\r
283 mesh.setRenderState(s);
\r
285 mesh.setRenderQueueMode(Renderer.QUEUE_TRANSPARENT);
\r
287 mesh.setRenderQueueMode(Renderer.QUEUE_OPAQUE);
\r
290 public void setSelected(boolean selected) {
\r
291 if (this.selected == selected)
\r
293 this.selected = selected;
\r
296 setSelectedVisible(true);
\r
297 setTransparentVisible(true);
\r
299 setSelectedVisible(false);
\r
300 setTransparentVisible(false);
\r
304 public boolean isSelected() {
\r
310 public boolean isHighlighted() {
\r
311 return highlighted;
\r
314 public void setHighlighted(boolean highlighted) {
\r
315 if (this.highlighted == highlighted)
\r
317 this.highlighted = highlighted;
\r
319 setHighlightedVisible(true);
\r
321 setHighlightedVisible(false);
\r
325 public boolean isVisible(int shape) {
\r
326 return visible[shape];
\r
329 public void setVisible(int shape, boolean visible) {
\r
330 if (this.visible[shape] == visible)
\r
332 this.visible[shape] = visible;
\r
333 if (mesh == null) {
\r
336 if (this.visible[NORMAL]){
\r
337 getGroup().attachChild(body);
\r
339 body.removeFromParent();
\r
341 if (this.visible[TRANSPARENT]) {
\r
342 getGroup().attachChild(transparent);
\r
344 transparent.removeFromParent();
\r
346 if (this.visible[SELECTED_EDGE] || this.visible[HIGHLIGHTED_EDGE]) {
\r
347 if (this.visible[HIGHLIGHTED_EDGE])
\r
348 edge.setRenderState(highlightedEdgeState);
\r
350 edge.setRenderState(selectedEdgeState);
\r
351 getGroup().attachChild(edge);
\r
352 edge.updateRenderState();
\r
354 edge.removeFromParent();
\r
358 public boolean isVisible() {
\r
359 return isVisible(NORMAL);
\r
362 public void setVisible(boolean visible) {
\r
363 setVisible(NORMAL, visible);
\r
366 public boolean isSelectedVisible() {
\r
367 return isVisible(SELECTED_EDGE);
\r
370 public void setSelectedVisible(boolean visible) {
\r
371 setVisible(SELECTED_EDGE, visible);
\r
374 public boolean isHighlightedVisible() {
\r
375 return isVisible(HIGHLIGHTED_EDGE);
\r
378 public void setHighlightedVisible(boolean visible) {
\r
379 setVisible(HIGHLIGHTED_EDGE, visible);
\r
385 public boolean isTransparentVisible() {
\r
386 return isVisible(TRANSPARENT);
\r
389 public void setTransparentVisible(boolean visible) {
\r
390 setVisible(TRANSPARENT, visible);
\r
393 public void setPickable(boolean pickable) {
\r
394 body.setIsCollidable(pickable);
\r
397 public Collection<RenderState> getMaterial() {
\r
398 List<RenderState> states = new ArrayList<RenderState>();
\r
399 MaterialState ms = editor.getRenderingComponent().getDisplaySystem().getRenderer().createMaterialState();
\r
400 ms.setEmissive(new ColorRGBA(0.f,0.f,0.f,0.f));
\r
401 ms.setSpecular(new ColorRGBA(1.f,1.f,1.f,1.f));
\r
402 ms.setDiffuse(new ColorRGBA(0.75f,0.f,0.f,0.f));
\r
403 ms.setAmbient(new ColorRGBA(0.75f,0.f,0.f,0.f));
\r
404 ms.setEnabled(true);
\r
405 ms.setShininess(128.f);
\r
411 private Animation animation;
\r
412 private static int preCalcSteps = 9;
\r
413 private Geometry[] preCalc = null;
\r
414 private int currentPreCalc = 0;
\r
416 public void animate(double delta,double frameTime) {
\r
417 if (animation != null)
\r
418 animation.interpolate(delta);
\r
419 if (preCalc != null) {
\r
420 int newPreCalc = (int)Math.round(delta*(preCalc.length-1));
\r
421 if (currentPreCalc != newPreCalc) {
\r
423 preCalc[currentPreCalc].removeFromParent();
\r
424 currentPreCalc = newPreCalc;
\r
426 body.attachChild(preCalc[currentPreCalc]);
\r
431 private void cleanAnimation() {
\r
432 this.animation = null;
\r
433 if (preCalc != null) {
\r
434 for (Geometry g : preCalc) {
\r
436 g.removeFromParent();
\r
445 * Sets shape's animation
\r
446 * TODO : multiple animations at the same time! (must check common animatable properties)
\r
447 * TODO : initial values (material, ..) (requires changes in the ontology)
\r
448 * TODO : messy code, refactor!
\r
449 * TODO : calculate number of required pre-calculated geometries
\r
452 public boolean setAnimation(Graph g, Resource res) {
\r
453 ContextGraph graph;
\r
454 if (g instanceof ContextGraph) {
\r
455 graph = (ContextGraph)g;
\r
457 graph = new ContextGraph(g);
\r
458 graph.setContext(shapeResource);
\r
463 body.attachChild(mesh);
\r
466 org.simantics.animation.stubs.Animation animation = new org.simantics.animation.stubs.Animation(graph,res);
\r
467 G3DNode shape = getG3DNode(graph);
\r
468 G3DNode modelResource = G3DTools.getModelFromResource(graph,shape.getResource());
\r
469 assert (modelResource != null);
\r
470 G3DModel model = new G3DModel(graph,modelResource.getResource());
\r
471 Collection<org.simantics.animation.stubs.Animation> animations = model.getAnimation();
\r
472 boolean found = false;
\r
473 for (org.simantics.animation.stubs.Animation a : animations) {
\r
474 if (a.getResource().equals(animation.getResource())) {
\r
480 ErrorLogger.getDefault().logWarning("Shape " + shape.getResource() + " cannot handle animation " + animation.getResource() + " because it isn't model's animation", null);
\r
483 Collection<org.simantics.animation.stubs.Interpolator> interpolators = animation.getInterpolator();
\r
484 List<org.simantics.animation.stubs.Interpolator> handled = new ArrayList<org.simantics.animation.stubs.Interpolator>();
\r
485 List<org.simantics.animation.stubs.Interpolator> precalculated = new ArrayList<org.simantics.animation.stubs.Interpolator>();
\r
486 for (org.simantics.animation.stubs.Interpolator i : interpolators) {
\r
487 IEntity target = i.getTarget();
\r
488 if (G3DTools.hasProperty(graph,shape.getResource(),target.getResource()))
\r
490 else if (G3DTools.hasSubProperty(graph,shape.getResource(),target.getResource())) {
\r
491 precalculated.add(i);
\r
494 if (handled.size() == 0 && precalculated.size() == 0) {
\r
495 ErrorLogger.getDefault().logWarning("Shape " + shape.getResource() + " cannot handle animation " + animation.getResource() + " since it doesn't change any of shape's properties", null);
\r
500 this.animation = new Animation();
\r
502 org.simantics.animation.stubs.Interpolator[] pos = new org.simantics.animation.stubs.Interpolator[3];
\r
503 org.simantics.animation.stubs.Interpolator[] ambient = new org.simantics.animation.stubs.Interpolator[3];
\r
504 org.simantics.animation.stubs.Interpolator[] diffuse = new org.simantics.animation.stubs.Interpolator[3];
\r
505 org.simantics.animation.stubs.Interpolator[] specular = new org.simantics.animation.stubs.Interpolator[3];
\r
506 org.simantics.animation.stubs.Interpolator[] emissive = new org.simantics.animation.stubs.Interpolator[3];
\r
508 Builtins builtins = graph.getBuiltins();
\r
511 for (org.simantics.animation.stubs.Interpolator i : handled) {
\r
512 IEntity target = i.getTarget();
\r
513 //if (target.isInstanceOf(Resources.g3dResource.LocalOrientation)) {
\r
514 if (target.isInstanceOf(Resources.g3dResource.Orientation) && target.getRelatedObjects(Resources.g3dResource.LocalOrientationOf).size() == 1) {
\r
515 SlerpInterpolator si = new SlerpInterpolator((SlerpCurve)Resources.curveBuilder.loadInterpolator(i));
\r
516 si.setTarget(transform);
\r
517 this.animation.addInterpolator(si);
\r
518 } else if (target.isInstanceOf(builtins.Double)) {
\r
519 Resource targetResource = target.getResource();
\r
520 Collection<IEntity> p = target.getRelatedObjects(builtins.PropertyOf);
\r
521 if (p.size() == 1) {
\r
522 IEntity parent = p.iterator().next();
\r
523 //if (parent.isInstanceOf(Resources.g3dResource.LocalPosition)) {
\r
524 if (parent.isInstanceOf(Resources.g3dResource.Position) && parent.getRelatedObjects(Resources.g3dResource.LocalPositionOf).size() == 1) {
\r
525 if (parent.getSingleRelatedObject(Resources.g3dResource.HasX).getResource().equals(targetResource)) {
\r
527 } else if (parent.getSingleRelatedObject(Resources.g3dResource.HasY).getResource().equals(targetResource)) {
\r
529 } else if (parent.getSingleRelatedObject(Resources.g3dResource.HasZ).getResource().equals(targetResource)) {
\r
532 ErrorLogger.getDefault().logWarning("Cannot map animation interpolator " + i.getResource() + " to target (Position ?)" + target.getResource(), null);
\r
534 } else if (parent.isInstanceOf(Resources.g3dResource.Color)) {
\r
535 org.simantics.animation.stubs.Interpolator[] color = null;
\r
536 if (parent.isInstanceOf(Resources.g3dResource.Color) && parent.getRelatedObjects(Resources.g3dResource.AmbientColorOf).size() > 0) {
\r
538 } else if (parent.isInstanceOf(Resources.g3dResource.Color)&& parent.getRelatedObjects(Resources.g3dResource.DiffuseColorOf).size() > 0) {
\r
540 } else if (parent.isInstanceOf(Resources.g3dResource.Color) && parent.getRelatedObjects(Resources.g3dResource.SpecularColorOf).size() > 0) {
\r
542 } else if (parent.isInstanceOf(Resources.g3dResource.Color) && parent.getRelatedObjects(Resources.g3dResource.EmissiveColorOf).size() > 0) {
\r
545 ErrorLogger.getDefault().logWarning("Cannot map animation interpolator " + i.getResource() + " to target (Color)" + target.getResource() + " unknown color type", null);
\r
547 if (color != null) {
\r
548 if (parent.getSingleRelatedObject(Resources.g3dResource.HasRed).getResource().equals(targetResource)) {
\r
550 } else if (parent.getSingleRelatedObject(Resources.g3dResource.HasGreen).getResource().equals(targetResource)) {
\r
552 } else if (parent.getSingleRelatedObject(Resources.g3dResource.HasBlue).getResource().equals(targetResource)) {
\r
555 ErrorLogger.getDefault().logWarning(
\r
556 "Cannot map animation interpolator " + i.getResource()
\r
557 + " to target (Color ?)" + target.getResource(), null);
\r
560 } else if (parent.isInstanceOf(Resources.g3dResource.Material)) {
\r
561 // TODO : transparency or shininess
\r
563 ErrorLogger.getDefault().logWarning("Cannot map animation interpolator " + i.getResource() + " to target" + target.getResource() + " adding it to precalculated interpolators", null);
\r
564 precalculated.add(i);
\r
567 if (p.size() == 0) {
\r
568 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
570 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
574 ErrorLogger.getDefault().logWarning("Cannot map animation interpolator " + i.getResource() + " to target" + target.getResource(), null);
\r
578 if (pos[0] != null || pos[1] != null || pos[2] != null) {
\r
579 ScalarInterpolator xIp;
\r
580 ScalarInterpolator yIp;
\r
581 ScalarInterpolator zIp;
\r
582 if (pos[0] != null) {
\r
583 xIp = new TCBInterpolator((TCBCurve)Resources.curveBuilder.loadInterpolator(pos[0]));
\r
585 xIp = new ConstantInterpolator(shape.getLocalPosition().getX()[0]);
\r
587 if (pos[1] != null) {
\r
588 yIp = new TCBInterpolator((TCBCurve)Resources.curveBuilder.loadInterpolator(pos[1]));
\r
590 yIp = new ConstantInterpolator(shape.getLocalPosition().getY()[0]);
\r
592 if (pos[2] != null) {
\r
593 zIp = new TCBInterpolator((TCBCurve)Resources.curveBuilder.loadInterpolator(pos[2]));
\r
595 zIp = new ConstantInterpolator(shape.getLocalPosition().getZ()[0]);
\r
597 ChanneledPositionInterpolator ip = new ChanneledPositionInterpolator(xIp,yIp,zIp);
\r
598 ip.setTarget(transform);
\r
599 this.animation.addInterpolator(ip);
\r
602 addColorInterpolator(shape, ambient, ChanneledColorInterpolator.AMBIENT);
\r
603 addColorInterpolator(shape, diffuse, ChanneledColorInterpolator.DIFFUSE);
\r
604 addColorInterpolator(shape, emissive, ChanneledColorInterpolator.EMISSIVE);
\r
605 addColorInterpolator(shape, specular, ChanneledColorInterpolator.SPECULAR);
\r
607 if (precalculated.size() == 0) {
\r
610 preCalc = new Geometry[preCalcSteps+1];
\r
611 for (int i = 0; i <= preCalcSteps; i++) {
\r
612 double delta = ((double)i / (double)preCalcSteps);
\r
613 // TODO : copy-paste from CSGAnimatorView
\r
614 // FIXME : does not update transformations (since ContextGraph does not support queries for context dependent values)
\r
615 for (Interpolator ip : precalculated) {
\r
616 if (ip.isInstanceOf(Resources.animationResource.ScalarInterpolator)) {
\r
617 // TODO : creating curve each time when time is set is slow.
\r
618 // Curve should be cached
\r
619 TCBCurve c = (TCBCurve)Resources.curveBuilder.loadInterpolator(ip);
\r
620 double out = c.evaluate(delta);
\r
621 //Double d = DoubleFactory.create(ip.getTarget());
\r
622 //d.setValue(new double[]{out});
\r
623 IEntity d = ip.getTarget();
\r
624 d.toProperty().setDoubleArray(new double[]{out});
\r
625 } else if (ip.isInstanceOf(Resources.animationResource.SlerpInterpolator)) {
\r
626 // TODO : creating curve each time when time is set is slow.
\r
627 // Curve should be cached
\r
628 SlerpCurve c = (SlerpCurve)Resources.curveBuilder.loadInterpolator(ip);
\r
629 Quat4d out = c.evaluate(delta);
\r
630 Orientation r = new Orientation(ip.getTarget());
\r
631 AxisAngle4d aa = new AxisAngle4d();
\r
633 G3DTools.setOrientation(r, aa);
\r
636 preCalc[i] = getGeometry(graph,false)[0];
\r
637 preCalc[i].setIsCollidable(false);
\r
638 AppearanceTools.copyMaterial(mesh, preCalc[i]);
\r
641 // We'll have to remove original (non-animated) shape from the node
\r
642 mesh.removeFromParent();
\r
643 body.attachChild(preCalc[0]);
\r
649 private void addColorInterpolator(G3DNode shape, org.simantics.animation.stubs.Interpolator[] color, int type) {
\r
650 if (color[0] != null || color[1] != null || color[2] != null) {
\r
651 ScalarInterpolator xIp;
\r
652 ScalarInterpolator yIp;
\r
653 ScalarInterpolator zIp;
\r
655 Collection<IEntity> appearanceResource = shape.getRelatedObjects(Resources.g3dResource.HasAppearance);
\r
656 if (appearanceResource.size() == 0) {
\r
657 ErrorLogger.getDefault().logWarning("Cannot create interpolator for color because shape " + shape.getResource() + " has no appearance", null);
\r
659 Appearance a = new Appearance(shape.getGraph(),appearanceResource.iterator().next().getResource());
\r
661 case ChanneledColorInterpolator.AMBIENT:
\r
662 col = a.getMaterial().getAmbientColor();
\r
664 case ChanneledColorInterpolator.DIFFUSE:
\r
665 col = a.getMaterial().getDiffuseColor();
\r
667 case ChanneledColorInterpolator.EMISSIVE:
\r
668 col = a.getMaterial().getEmissiveColor();
\r
670 case ChanneledColorInterpolator.SPECULAR:
\r
671 col = a.getMaterial().getSpecularColor();
\r
674 ErrorLogger.defaultLogError("Unknown color type", null);
\r
678 if (color[0] != null) {
\r
679 xIp = new TCBInterpolator((TCBCurve)Resources.curveBuilder.loadInterpolator(color[0]));//CurveUtils.loadCurve(color[0].getResource()));
\r
681 xIp = new ConstantInterpolator(col.getRed()[0]);
\r
683 if (color[1] != null) {
\r
684 yIp = new TCBInterpolator((TCBCurve)Resources.curveBuilder.loadInterpolator(color[1]));//CurveUtils.loadCurve(color[1].getResource()));
\r
686 yIp = new ConstantInterpolator(col.getGreen()[0]);
\r
688 if (color[1] != null) {
\r
689 zIp = new TCBInterpolator((TCBCurve)Resources.curveBuilder.loadInterpolator(color[2]));//CurveUtils.loadCurve(color[2].getResource()));
\r
691 zIp = new ConstantInterpolator(col.getBlue()[0]);
\r
693 ChanneledColorInterpolator ip = new ChanneledColorInterpolator(xIp,yIp,zIp);
\r
695 ip.setTarget(mesh.getRenderState(RenderState.RS_MATERIAL));
\r
696 this.animation.addInterpolator(ip);
\r
700 public boolean setRandomAnimation(Graph graph) {
\r
704 public void dispose() {
\r
705 // mesh.clearBuffers();
\r
706 // mesh.clearBatches();
\r
707 // lines.clearBuffers();
\r
708 // lines.clearBatches();
\r
709 if (mesh != null) {
\r
710 mesh.removeFromParent();
\r
714 if (lines != null) {
\r
715 lines.removeFromParent();
\r