📄 geometrystructure.java
字号:
/* * $RCSfile: GeometryStructure.java,v $ * * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. * * Use is subject to license terms. * * $Revision: 1.8 $ * $Date: 2007/04/12 17:34:05 $ * $State: Exp $ */package javax.media.j3d;import javax.vecmath.*;import java.util.ArrayList;import java.util.Arrays;/** * A geometry structure is a object that organizes geometries * and bounds. */class GeometryStructure extends J3dStructure { /** * used during Transform Processing */ UpdateTargets targets = null; /** * A multiple read single write Lock to sychronize access into this * GeometryStructure. * To prevent deadlock a call to read/write lock must end with a read/write * unlock respectively. */ private MRSWLock lock = null; /** * A lock object to prevent concurrent getVisibleBHTree query. */ private Object visLock = new Object(); /** * A lock object to prevent concurrent collideEntryList, * collideExitList using toArray() in BehaviorStructure buildTree() * while clearMirror() is invoked in GeometryStructure removeNode() */ private Object collideListLock = new Object(); /** * Binary Hull Tree structure for handling geometry atoms. * Do not change the following private variables to public, their access * need to synchronize via lock. */ private BHTree[] bhTreeArr = null; private int bhTreeCount; private int bhTreeMax; private int bhTreeBlockSize = 5; /** * The array of BHNode, a data pool, for passing data between GS and BHTrees. * Do not change the following private variables to public, their access * need to synchronize via lock. */ private BHNode[] bhNodeArr = null; private int bhNodeCount, bhNodeMax; private int bhNodeBlockSize = 50; // Support for multi-locale. private Vector3d localeTrans = new Vector3d(); //The lists of wakeupCriterion object currently in collision. WakeupIndexedList collideEntryList; WakeupIndexedList collideExitList; WakeupIndexedList collideMovementList; // The lists of wakeupCriterion objects that GeometryStructure keeps WakeupIndexedList wakeupOnCollisionEntry; WakeupIndexedList wakeupOnCollisionExit; WakeupIndexedList wakeupOnCollisionMovement; // When Shape insert/remove for WakeupOnCollisionxxx() using // Group node and USE_GEOMETRY, we need to reevaluate the // cache geometryAtoms list. boolean reEvaluateWakeupCollisionGAs; private boolean transformMsg = false; /** * Constructor. */ GeometryStructure(VirtualUniverse u) { super(u, J3dThread.UPDATE_GEOMETRY); bhNodeCount = 0; bhNodeMax = bhNodeBlockSize; bhNodeArr = new BHNode[bhNodeMax]; bhTreeMax = 1; bhTreeArr = new BHTree[bhTreeMax]; bhTreeCount=0; lock = new MRSWLock(); collideEntryList = new WakeupIndexedList(WakeupOnCollisionEntry.class, WakeupOnCollisionEntry.COLLIDEENTRY_IN_BS_LIST, u); collideExitList = new WakeupIndexedList(WakeupOnCollisionExit.class, WakeupOnCollisionExit.COLLIDEEXIT_IN_BS_LIST, u); collideMovementList = new WakeupIndexedList(WakeupOnCollisionMovement.class, WakeupOnCollisionMovement.COLLIDEMOVE_IN_BS_LIST, u); wakeupOnCollisionEntry = new WakeupIndexedList(WakeupOnCollisionEntry.class, WakeupOnCollisionEntry.COND_IN_GS_LIST, u); wakeupOnCollisionExit = new WakeupIndexedList(WakeupOnCollisionExit.class, WakeupOnCollisionExit.COND_IN_GS_LIST, u); wakeupOnCollisionMovement = new WakeupIndexedList(WakeupOnCollisionMovement.class, WakeupOnCollisionMovement.COND_IN_GS_LIST, u); } void processMessages(long referenceTime) { J3dMessage m; J3dMessage[] messages = getMessages(referenceTime); int nMsg = getNumMessage(); if (nMsg > 0) { reEvaluateWakeupCollisionGAs = false; for (int i=0; i < nMsg; i++) { lock.writeLock(); m = messages[i]; switch (m.type) { case J3dMessage.TRANSFORM_CHANGED: transformMsg = true; break; case J3dMessage.SWITCH_CHANGED: processSwitchChanged(m); // may need to process dirty switched-on transform if (universe.transformStructure.getLazyUpdate()) { transformMsg = true; } break; case J3dMessage.INSERT_NODES: insertNodes((Object[])m.args[0]); reEvaluateWakeupCollisionGAs = true; break; case J3dMessage.REMOVE_NODES: removeNodes(m); reEvaluateWakeupCollisionGAs = true; break; case J3dMessage.SHAPE3D_CHANGED: { int comp = ((Integer)m.args[1]).intValue(); if (comp == Shape3DRetained.GEOMETRY_CHANGED) { m.args[0] = m.args[2]; removeNodes(m); insertNodes((Object[])m.args[3]); reEvaluateWakeupCollisionGAs = true; } else if (comp == Shape3DRetained.APPEARANCE_CHANGED) { processVisibleChanged(m.args[2], ((GeometryAtom[]) m.args[3])); } break; } case J3dMessage.TEXT3D_DATA_CHANGED: removeNodes(m); insertNodes((Object[])m.args[1]); break; case J3dMessage.TEXT3D_TRANSFORM_CHANGED: processBoundsChanged((Object []) m.args[0], false); break; case J3dMessage.MORPH_CHANGED: { int comp = ((Integer)m.args[1]).intValue(); if (comp == MorphRetained.GEOMETRY_CHANGED) { processBoundsChanged((Object []) m.args[3], false); } else if (comp == MorphRetained.APPEARANCE_CHANGED) { processVisibleChanged(m.args[2], ((GeometryAtom[]) m.args[3])); } break; } case J3dMessage.REGION_BOUND_CHANGED: case J3dMessage.BOUNDS_AUTO_COMPUTE_CHANGED: // Only set this flag, when bounds might be empty. processBoundsChanged((Object [])m.args[0], false); break; case J3dMessage.GEOMETRY_CHANGED: // System.err.println("J3dMessage.GEOMETRY_CHANGED"); processBoundsChanged((Object []) m.args[0], false); break; case J3dMessage.RENDERINGATTRIBUTES_CHANGED: processVisibleChanged(m.args[2], ((GeometryAtom[]) m.args[3])); break; } lock.writeUnlock(); m.decRefcount(); } if (transformMsg) { targets = universe.transformStructure.getTargetList(); lock.writeLock(); processTransformChanged(targets); lock.writeUnlock(); transformMsg = false; targets = null; } Arrays.fill(messages, 0, nMsg, null); } processCollisionDetection(); } private int getBHTreeIndex(Locale locale) { int i; for (i=0; i< bhTreeCount; i++) { if (bhTreeArr[i].locale == locale) return i; } // Can't find will return -1 so that other // program know this return -1; } private int getOrAddBHTreeIndex(Locale locale) { int i; for (i=0; i< bhTreeCount; i++) { if (bhTreeArr[i].locale == locale) return i; } if (bhTreeCount >= bhTreeMax) { // allocate a bigger array here.... if (J3dDebug.devPhase) J3dDebug.doDebug(J3dDebug.geometryStructure, J3dDebug.LEVEL_2, "Expanding bhTreeArr array ...\n"); bhTreeMax += bhTreeBlockSize; BHTree[] oldBhTreeArr = bhTreeArr; bhTreeArr = new BHTree[bhTreeMax]; System.arraycopy(oldBhTreeArr, 0, bhTreeArr, 0, oldBhTreeArr.length); } bhTreeArr[bhTreeCount] = new BHTree(locale); bhTreeCount++; return i; } private void clearBhNodeArr() { // Issue 353: set all elements to null so we don't leak // NOTE: we really should change this to be an ArrayList, but that // would be a less localized change. Consider for 1.6.0. for (int i = 0; i < bhNodeCount; i++) { bhNodeArr[i] = null; } bhNodeCount = 0; } private void addToBhNodeArr(BHNode bhNode) { // Add to bhNodeArr. if (bhNodeCount >= bhNodeMax) { bhNodeMax += bhNodeBlockSize; BHNode[] oldbhNodeArr = bhNodeArr; bhNodeArr = new BHNode[bhNodeMax]; System.arraycopy(oldbhNodeArr, 0, bhNodeArr, 0, oldbhNodeArr.length); } bhNodeArr[bhNodeCount] = bhNode; bhNodeCount++; } private void processVisibleChanged(Object valueObj, GeometryAtom[] gaArr) { boolean visible = true; // Default is true. int i, treeIndex; if ((gaArr == null) || (gaArr.length < 1)) return; treeIndex = getBHTreeIndex(gaArr[0].locale); visible = ((Boolean)valueObj).booleanValue(); for ( i=gaArr.length-1; i>=0; i--) { gaArr[i].visible = visible; } } private void insertNodes(Object[] nodes) { Object node; GeometryAtom geomAtom; BHTree currTree = null; clearBhNodeArr(); // System.err.println("GS : nodes.length is " + nodes.length); for (int i=0; i<nodes.length; i++) { node = nodes[i]; if (node instanceof GeometryAtom) { synchronized (node) { geomAtom = (GeometryAtom) node; if (geomAtom.source.inBackgroundGroup) { geomAtom.source.geometryBackground. addBgGeometryAtomList(geomAtom); continue; } BHLeafNode bhLeafNode = new BHLeafNode(); bhLeafNode.leafIF = geomAtom; geomAtom.bhLeafNode = bhLeafNode; bhLeafNode.computeBoundingHull(); // System.err.println("bhLeafNode.bHull is " + bhLeafNode.bHull); addToBhNodeArr(bhLeafNode); } } else if (node instanceof GroupRetained) { synchronized (node) { GroupRetained group = (GroupRetained) node; BHLeafNode bhLeafNode = new BHLeafNode(); bhLeafNode.leafIF = group; group.bhLeafNode = bhLeafNode; bhLeafNode.computeBoundingHull(); addToBhNodeArr(bhLeafNode); } } } if (bhNodeCount < 1) { return; } // Look for the right BHTree to insert to. if (currTree == null) { // We must separate the following two calls // since the first Call will allocate storage bhTreeArr // for the second index operation. (see bug 4361998) int idx = getOrAddBHTreeIndex(((BHLeafNode)bhNodeArr[0]).getLocale()); currTree = bhTreeArr[idx]; } currTree.insert(bhNodeArr, bhNodeCount); // Issue 353: must clear array after we are done with it clearBhNodeArr(); // currTree.gatherTreeStatistics(); } void removeNodes(J3dMessage m) { Object[] nodes = (Object[]) m.args[0]; BHTree currTree = null; Object node; int index; clearBhNodeArr(); for (int i=0; i<nodes.length; i++) { node = nodes[i]; if (node instanceof GeometryAtom) { synchronized (node) { GeometryAtom geomAtom = (GeometryAtom) node; if ((geomAtom.source != null) && (geomAtom.source.inBackgroundGroup)) { geomAtom.source.geometryBackground. removeBgGeometryAtomList(geomAtom); continue; } if (geomAtom.bhLeafNode != null) { addToBhNodeArr(geomAtom.bhLeafNode); // Dereference BHLeafNode in GeometryAtom. geomAtom.bhLeafNode = null; } } } else if (node instanceof GroupRetained) { if (((NodeRetained)node).nodeType != NodeRetained.ORDEREDGROUP) { synchronized (node) { GroupRetained group = (GroupRetained) node; if (group.bhLeafNode != null) { addToBhNodeArr(group.bhLeafNode); // Dereference BHLeafNode in GroupRetained group.bhLeafNode = null; } } } } else if (node instanceof BehaviorRetained) { synchronized (node) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -