📄 objectgridportrayal3d.java
字号:
package sim.portrayal3d.grid;import sim.portrayal3d.*;import sim.portrayal.*;import sim.field.grid.*;import sim.util.*;import java.util.*;import javax.media.j3d.*;import javax.vecmath.*;import com.sun.j3d.utils.picking.*;/** Portrays ObjectGrid2D and ObjectGrid3D in 3D space. A (0,0) or (0,0,0) object is centered * on the origin. 2D fields are spread through the XY plane and are presumed to have Z=0. * * <p>You should be aware that ObjectGrid3DPortrayal3D is slow, especially if objects change * a lot at given locations. This is because it has to update * all the objects on a <i>per location</i> basis rather than on a <i>per object</i> basis. * This is a worst-case scenario for Java3D. * * <p>Note for Java3D users: We experimented with a number of approaches to dealing with this. * One approach was to use shared groups and only portray an object once, then use links to draw * it in many locations. This has two subapproaches: you can wrap the link in a BranchGroup and * replace it and the BranchGroup when the object changes at that location; or you can just change * the link directly. The first approach is very slow (building BranchGroups isn't efficient). * The second approach has promise, but there are grievous bugs in Java3D's handling of links * which generate all sorts of race conditions with array bounds exceptions and null pointer exceptions * etc. internal to Java3D when you change the SharedGroup that a link is pointing to. Ultimately * we just gave up and used BranchGroups wrapping whole new submodels, entire copies for each * location. Memory inefficient, but it's the fastest method we have figured out which doesn't * break with stupid Sun bugs. It's also fairly simple to grok. Sorry. */ public class ObjectGridPortrayal3D extends FieldPortrayal3D { protected TransformGroup createModel() { Vector3d locationV3d = new Vector3d(); TransformGroup globalTG = new TransformGroup(); globalTG.setCapability(TransformGroup.ALLOW_CHILDREN_READ); // we need a group to stick stuff into, so we create a Group here Group global = new Group(); global.setCapability(Group.ALLOW_CHILDREN_READ); global.setCapability(Group.ALLOW_CHILDREN_WRITE); global.setCapability(Group.ALLOW_CHILDREN_EXTEND); global.setUserData(this); // a sufficient tag -- a Group containing me. See LocationWrapper // this is set so he'll be in the scenegraph path global.setCapability(Group.ENABLE_PICK_REPORTING); globalTG.addChild(global); if (field==null) return globalTG; Transform3D tmpLocalT = new Transform3D(); if (field instanceof ObjectGrid2D) { Object[][] grid = ((ObjectGrid2D)field).field; for(int x=0;x<grid.length;x++) { Object[] gridx = grid[x]; for(int y=0;y<gridx.length;y++) { Object o = gridx[y]; // get the child model -- it doesn't exist yet Portrayal p = getPortrayalForObject(o); if(! (p instanceof SimplePortrayal3D)) throw new RuntimeException("Unexpected Portrayal " + p + " for object " + o + " -- expecting a SimplePortrayal3D"); SimplePortrayal3D p3d = (SimplePortrayal3D)p; p3d.setParentPortrayal(this); TransformGroup newTransformGroup = p3d.getModel(o, null); newTransformGroup.setCapability(TransformGroup.ALLOW_CHILDREN_READ); newTransformGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE); newTransformGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_READ); // this is set so he'll be in the scenegraph path newTransformGroup.setCapability(TransformGroup.ENABLE_PICK_REPORTING); tmpLocalT.setTranslation(new Vector3d(x,y,0)); newTransformGroup.setTransform(tmpLocalT); newTransformGroup.setUserData(new Int2D(x,y)); BranchGroup bg = new BranchGroup(); bg.setCapability(BranchGroup.ALLOW_CHILDREN_READ); bg.setCapability(BranchGroup.ALLOW_DETACH); // this is set so he'll be in the scenegraph path bg.setCapability(BranchGroup.ENABLE_PICK_REPORTING); bg.addChild(newTransformGroup); bg.setUserData(o); global.addChild(bg); } } } else // field instanceof ObjectGrid3D { Object[][][] grid = ((ObjectGrid3D)field).field; for(int x=0;x<grid.length;x++) { Object[][] gridx = grid[x]; for(int y=0;y<gridx.length;y++) { Object[] gridy = gridx[y]; for(int z=0;z<gridy.length;z++) { Object o = gridy[z]; // get the child model -- it doesn't exist yet Portrayal p = getPortrayalForObject(o); if(! (p instanceof SimplePortrayal3D)) throw new RuntimeException("Unexpected Portrayal " + p + " for object " + o + " -- expecting a SimplePortrayal3D"); SimplePortrayal3D p3d = (SimplePortrayal3D)p; p3d.setParentPortrayal(this); TransformGroup newTransformGroup = p3d.getModel(o, null); newTransformGroup.setCapability(TransformGroup.ALLOW_CHILDREN_READ); newTransformGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE); newTransformGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_READ); // this is set so he'll be in the scenegraph path newTransformGroup.setCapability(TransformGroup.ENABLE_PICK_REPORTING); tmpLocalT.setTranslation(new Vector3d(x,y,z)); newTransformGroup.setUserData(new Int3D(x,y,z)); newTransformGroup.setTransform(tmpLocalT); BranchGroup bg = new BranchGroup(); bg.setCapability(BranchGroup.ALLOW_CHILDREN_READ); bg.setCapability(BranchGroup.ALLOW_DETACH); // this is set so he'll be in the scenegraph path bg.setCapability(BranchGroup.ENABLE_PICK_REPORTING); bg.addChild(newTransformGroup); bg.setUserData(o); global.addChild(bg); } } } } return globalTG; } protected void updateModel(TransformGroup globalTG) { Group global = (Group)(globalTG.getChild(0)); Vector3d locationV3d = new Vector3d(); if (field==null) return; int count = 0; // first, let's pass through the field to see who is DEFINITELY going to have their // models removed. If so, we hash those models by the object, making them available // for others. This is more efficient than lots of recreation. We hope! HashMap models = new HashMap(); Transform3D tmpLocalT = new Transform3D(); count = 0; if (field instanceof ObjectGrid2D) { Object[][] grid = ((ObjectGrid2D)field).field; for(int x=0;x<grid.length;x++) { Object[] gridx = grid[x]; for(int y=0;y<gridx.length;y++) { Object o = gridx[y]; // get the child model -- it doesn't exist yet Portrayal p = getPortrayalForObject(o); if(! (p instanceof SimplePortrayal3D)) throw new RuntimeException("Unexpected Portrayal " + p + " for object " + o + " -- expecting a SimplePortrayal3D"); SimplePortrayal3D p3d = (SimplePortrayal3D)p; p3d.setParentPortrayal(this); BranchGroup bg = (BranchGroup)(global.getChild(count++)); TransformGroup originalTransformGroup = null; if (bg.numChildren() > 0) originalTransformGroup = (TransformGroup)(bg.getChild(0)); // could be null if we've stubbed TransformGroup newTransformGroup = null; Object originalData = bg.getUserData(); if (originalData == o) newTransformGroup = p3d.getModel(o, originalTransformGroup); else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -