diff options
Diffstat (limited to 'src/javax/media/j3d/Locale.java')
-rw-r--r-- | src/javax/media/j3d/Locale.java | 1088 |
1 files changed, 1088 insertions, 0 deletions
diff --git a/src/javax/media/j3d/Locale.java b/src/javax/media/j3d/Locale.java new file mode 100644 index 0000000..4da6c4a --- /dev/null +++ b/src/javax/media/j3d/Locale.java @@ -0,0 +1,1088 @@ +/* + * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package javax.media.j3d; + +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.Vector; + +/** + * A Locale object defines a high-resolution position within a + * VirtualUniverse, and serves as a container for a collection of + * BranchGroup-rooted subgraphs (branch graphs), at that position. + * Objects within a Locale are defined using standard double-precision + * coordinates, relative to the origin of the Locale. This origin + * defines the Virtual World coordinate system for that Locale. + * <p> + * A Locale object defines methods to set and get its high-resolution + * coordinates, and methods to add, remove, and enumerate the branch + * graphs. + * + * <p> + * For more information, see the + * <a href="doc-files/intro.html">Introduction to the Java 3D API</a> and + * <a href="doc-files/VirtualUniverse.html">Scene Graph Superstructure</a> + * documents. + * + * @see VirtualUniverse + * @see HiResCoord + * @see BranchGroup + */ + +public class Locale extends Object { + + /** + * The virtual universe that this Locale object is contained within. + */ + VirtualUniverse universe; + + /** + * The high resolution coordinate associated with this Locale object. + */ + HiResCoord hiRes; + +/** + * List of BranchGroup objects included in this Locale + */ +Vector<BranchGroup> branchGroups = new Vector<BranchGroup>(); + + // locale's identifier + String nodeId = null; + + /** + * Constructs and initializes a new high resolution Locale object + * located at (0, 0, 0). + * @param universe the virtual universe that will contain this + * Locale object + */ + public Locale(VirtualUniverse universe) { + this.universe = universe; + this.universe.addLocale(this); + this.hiRes = new HiResCoord(); + nodeId = universe.getNodeId(); + } + + /** + * Constructs and initializes a new high resolution Locale object + * from the parameters provided. + * @param universe the virtual universe that will contain this + * Locale object + * @param x an eight element array specifying the x position + * @param y an eight element array specifying the y position + * @param z an eight element array specifying the z position + */ + public Locale(VirtualUniverse universe, int[] x, int[] y, int[] z) { + this.universe = universe; + this.universe.addLocale(this); + this.hiRes = new HiResCoord(x, y, z); + nodeId = universe.getNodeId(); + } + + /** + * Constructs and initializes a new high resolution Locale object + * at the location specified by the HiResCoord argument. + * @param universe the virtual universe that will contain this + * Locale object + * @param hiRes the HiRes coordinate to use in creating this Locale + */ + public Locale(VirtualUniverse universe, HiResCoord hiRes) { + this.universe = universe; + this.universe.addLocale(this); + this.hiRes = new HiResCoord(hiRes); + nodeId = universe.getNodeId(); + } + + /** + * Retrieves the virtual universe within which this Locale object + * is contained. A null reference indicates that this + * Locale has been removed from its VirtualUniverse. + * @return the virtual universe within which this Locale object + * is contained. + */ + public VirtualUniverse getVirtualUniverse() { + return universe; + } + + /** + * Sets the HiRes coordinate of this Locale to the location + * specified by the parameters provided. + * @param x an eight element array specifying the x position + * @param y an eight element array specifying the y position + * @param z an eight element array specifying the z position + */ + public void setHiRes(int[] x, int[] y, int[] z) { + this.hiRes.setHiResCoord(x, y, z); + } + + /** + * Sets the HiRes coordinate of this Locale + * to the location specified by the HiRes argument. + * @param hiRes the HiRes coordinate specifying this node's new location + */ + public void setHiRes(HiResCoord hiRes) { + this.hiRes.setHiResCoord(hiRes); + } + + /** + * Returns this node's HiResCoord. + * @param hiRes a HiResCoord object that will receive the + * HiRes coordinate of this Locale node + */ + public void getHiRes(HiResCoord hiRes) { + this.hiRes.getHiResCoord(hiRes); + } + + /** + * Add a new branch graph rooted at BranchGroup to + * the list of branch graphs. + * @param branchGroup root of the branch graph to be added + * @exception IllegalStateException if this Locale has been + * removed from its VirtualUniverse. + * @exception MultipleParentException if the specified BranchGroup node + * is already live. + */ + public void addBranchGraph(BranchGroup branchGroup){ + if (universe == null) { + throw new IllegalStateException(J3dI18N.getString("Locale4")); + } + + // if the BranchGroup already has a parent, or has already been + // added to a locale, throw MultipleParentException + if ((((BranchGroupRetained)branchGroup.retained).parent != null) || + (branchGroup.isLive())) { + throw new MultipleParentException(J3dI18N.getString("Locale0")); + } + + universe.notifyStructureChangeListeners(true, this, branchGroup); + universe.resetWaitMCFlag(); + synchronized (universe.sceneGraphLock) { + doAddBranchGraph(branchGroup); + universe.setLiveState.reset(this); + } + universe.waitForMC(); + } + + // The method that does the work once the lock is acquired. + void doAddBranchGraph(BranchGroup branchGroup) { + BranchGroupRetained bgr = (BranchGroupRetained)branchGroup.retained; + J3dMessage createMessage; + SetLiveState s = universe.setLiveState; + + // bgr.setLocale(this); + + // addElement needs to precede setLive or else any liveness checks + // in the initialize() call of a user behavior (ie, calling collision + // or picking constructor with a SceneGraphPath) will fail + // when SceneGraphPath.validate() attempts to verify that + // the proper Locale is associated with that SceneGraphPath + bgr.attachedToLocale = true; + branchGroups.addElement(branchGroup); + s.reset(this); + s.currentTransforms[0] = new Transform3D[2]; + s.currentTransforms[0][0] = new Transform3D(); + s.currentTransforms[0][1] = new Transform3D(); + s.currentTransformsIndex[0] = new int[2]; + s.currentTransformsIndex[0][0] = 0; + s.currentTransformsIndex[0][1] = 0; + + s.localToVworld = s.currentTransforms; + s.localToVworldIndex = s.currentTransformsIndex; + + s.branchGroupPaths = new ArrayList<BranchGroupRetained[]>(); + s.branchGroupPaths.add(new BranchGroupRetained[0]); + + s.orderedPaths = new ArrayList<OrderedPath>(1); + s.orderedPaths.add(new OrderedPath()); + + s.switchStates = new ArrayList<SwitchState>(1); + s.switchStates.add(new SwitchState(false)); + + bgr.setLive(s); + + createMessage = new J3dMessage(); + createMessage.threads = J3dThread.UPDATE_RENDER| J3dThread.UPDATE_RENDERING_ENVIRONMENT; + createMessage.type = J3dMessage.ORDERED_GROUP_INSERTED; + createMessage.universe = universe; + createMessage.args[0] = s.ogList.toArray(); + createMessage.args[1] = s.ogChildIdList.toArray(); + createMessage.args[2] = s.ogOrderedIdList.toArray(); + createMessage.args[3] = s.ogCIOList.toArray(); + createMessage.args[4] = s.ogCIOTableList.toArray(); + + VirtualUniverse.mc.processMessage(createMessage); + + createMessage = new J3dMessage(); + createMessage.threads = J3dThread.UPDATE_RENDERING_ENVIRONMENT; + createMessage.type = J3dMessage.VIEWSPECIFICGROUP_INIT; + createMessage.universe = universe; + createMessage.args[0] = s.changedViewGroup; + createMessage.args[1] = s.changedViewList; + createMessage.args[2] = s.keyList; + VirtualUniverse.mc.processMessage(createMessage); + + + createMessage = new J3dMessage(); + createMessage.threads = s.notifyThreads; + createMessage.type = J3dMessage.INSERT_NODES; + createMessage.universe = universe; + createMessage.args[0] = s.nodeList.toArray(); + createMessage.args[1] = null; + createMessage.args[2] = null; + if (s.viewScopedNodeList != null) { + createMessage.args[3] = s.viewScopedNodeList; + createMessage.args[4] = s.scopedNodesViewList; + } + VirtualUniverse.mc.processMessage(createMessage); + + int sz = s.behaviorNodes.size(); + for (int i=0; i< sz; i++) { + BehaviorRetained b = s.behaviorNodes.get(i); + b.executeInitialize(); + } + + createMessage = new J3dMessage(); + createMessage.threads = J3dThread.UPDATE_BEHAVIOR; + createMessage.type = J3dMessage.BEHAVIOR_ACTIVATE; + createMessage.universe = universe; + VirtualUniverse.mc.processMessage(createMessage); + + // Free up memory. + s.reset(null); + } + + /** + * Removes a branch graph rooted at BranchGroup from + * the list of branch graphs. + * @param branchGroup root of the branch graph to be removed + * @exception IllegalStateException if this Locale has been + * removed from its VirtualUniverse. + * @exception CapabilityNotSetException if the ALLOW_DETACH capability is + * not set in the specified BranchGroup node. + */ + public void removeBranchGraph(BranchGroup branchGroup){ + if (universe == null) { + throw new IllegalStateException(J3dI18N.getString("Locale4")); + } + + if (! branchGroup.getCapability(BranchGroup.ALLOW_DETACH)) { + throw new CapabilityNotSetException(J3dI18N.getString("Locale1")); + } + universe.resetWaitMCFlag(); + synchronized (universe.sceneGraphLock) { + doRemoveBranchGraph(branchGroup, null, 0); + universe.setLiveState.reset(this); + } + universe.waitForMC(); + } + + + // Method to remove all branch graphs from this Locale and remove + // this Locale from the VirtualUniverse + void removeFromUniverse() { + if (branchGroups.size() > 0) { + universe.resetWaitMCFlag(); + synchronized (universe.sceneGraphLock) { + // Make a copy of the branchGroups list so that we can safely + // iterate over it. + Object[] bg = branchGroups.toArray(); + for (int i = 0; i < bg.length; i++) { + doRemoveBranchGraph((BranchGroup)bg[i], null, 0); + } + } + // Put after sceneGraphLock to prevent deadlock + universe.waitForMC(); + } + + // free nodeId + if (nodeId != null) { + universe.nodeIdFreeList.addElement(nodeId); + nodeId = null; + } + + // Set universe pointer to null, indicating that this Locale + // has been removed from its universe + universe = null; + } + + + // The method that does the work once the lock is acquired. + void doRemoveBranchGraph(BranchGroup branchGroup, + J3dMessage messages[], int startIndex) { + + BranchGroupRetained bgr = (BranchGroupRetained)branchGroup.retained; + J3dMessage destroyMessage; + + if (!branchGroup.isLive()) + return; + bgr.attachedToLocale = false; + branchGroups.removeElement(branchGroup); + universe.setLiveState.reset(this); + bgr.clearLive(universe.setLiveState); + bgr.setParent(null); + bgr.setLocale(null); + + if (messages == null) { + destroyMessage = new J3dMessage(); + } else { + destroyMessage = messages[startIndex++]; + } + destroyMessage.threads = J3dThread.UPDATE_RENDER| J3dThread.UPDATE_RENDERING_ENVIRONMENT; + destroyMessage.type = J3dMessage.ORDERED_GROUP_REMOVED; + destroyMessage.universe = universe; + destroyMessage.args[0] = universe.setLiveState.ogList.toArray(); + destroyMessage.args[1] = universe.setLiveState.ogChildIdList.toArray(); + destroyMessage.args[3] = universe.setLiveState.ogCIOList.toArray(); + destroyMessage.args[4] = universe.setLiveState.ogCIOTableList.toArray(); + + // Issue 312: We need to send the REMOVE_NODES message to the + // RenderingEnvironmentStructure before we send VIEWSPECIFICGROUP_CLEAR, + // since the latter clears the list of views that is referred to by + // scopedNodesViewList and used by removeNodes. + if (messages == null) { + VirtualUniverse.mc.processMessage(destroyMessage); + destroyMessage = new J3dMessage(); + } else { + destroyMessage = messages[startIndex++]; + } + destroyMessage.threads = universe.setLiveState.notifyThreads; + destroyMessage.type = J3dMessage.REMOVE_NODES; + destroyMessage.universe = universe; + destroyMessage.args[0] = universe.setLiveState.nodeList.toArray(); + if (universe.setLiveState.viewScopedNodeList != null) { + destroyMessage.args[3] = universe.setLiveState.viewScopedNodeList; + destroyMessage.args[4] = universe.setLiveState.scopedNodesViewList; + } + + if (messages == null) { + VirtualUniverse.mc.processMessage(destroyMessage); + destroyMessage = new J3dMessage(); + } else { + destroyMessage = messages[startIndex++]; + } + destroyMessage.threads = J3dThread.UPDATE_RENDERING_ENVIRONMENT; + destroyMessage.type = J3dMessage.VIEWSPECIFICGROUP_CLEAR; + destroyMessage.universe = universe; + destroyMessage.args[0] = universe.setLiveState.changedViewGroup; + destroyMessage.args[1] = universe.setLiveState.keyList; + + if (messages == null) { + VirtualUniverse.mc.processMessage(destroyMessage); + } else { + destroyMessage = messages[startIndex++]; + } + + if (universe.isEmpty()) { + VirtualUniverse.mc.postRequest(MasterControl.EMPTY_UNIVERSE, + universe); + } + universe.setLiveState.reset(null); // cleanup memory + universe.notifyStructureChangeListeners(false, this, branchGroup); + } + + /** + * Replaces the branch graph rooted at oldGroup in the list of + * branch graphs with the branch graph rooted at + * newGroup. + * @param oldGroup root of the branch graph to be replaced. + * @param newGroup root of the branch graph that will replace the old + * branch graph. + * @exception IllegalStateException if this Locale has been + * removed from its VirtualUniverse. + * @exception CapabilityNotSetException if the ALLOW_DETACH capability is + * not set in the old BranchGroup node. + * @exception MultipleParentException if the new BranchGroup node + * is already live. + */ + public void replaceBranchGraph(BranchGroup oldGroup, + BranchGroup newGroup){ + + if (universe == null) { + throw new IllegalStateException(J3dI18N.getString("Locale4")); + } + + if (! oldGroup.getCapability(BranchGroup.ALLOW_DETACH)) { + throw new CapabilityNotSetException(J3dI18N.getString("Locale1")); + } + + if (((BranchGroupRetained)newGroup.retained).parent != null) { + throw new MultipleParentException(J3dI18N.getString("Locale3")); + } + universe.resetWaitMCFlag(); + universe.notifyStructureChangeListeners(true, this, newGroup); + synchronized (universe.sceneGraphLock) { + doReplaceBranchGraph(oldGroup, newGroup); + universe.setLiveState.reset(this); + } + universe.notifyStructureChangeListeners(false, this, oldGroup); + universe.waitForMC(); + } + + // The method that does the work once the lock is acquired. + void doReplaceBranchGraph(BranchGroup oldGroup, + BranchGroup newGroup){ + BranchGroupRetained obgr = (BranchGroupRetained)oldGroup.retained; + BranchGroupRetained nbgr = (BranchGroupRetained)newGroup.retained; + J3dMessage createMessage; + J3dMessage destroyMessage; + + + branchGroups.removeElement(oldGroup); + obgr.attachedToLocale = false; + universe.setLiveState.reset(this); + obgr.clearLive(universe.setLiveState); + + destroyMessage = new J3dMessage(); + + destroyMessage.threads = J3dThread.UPDATE_RENDER| J3dThread.UPDATE_RENDERING_ENVIRONMENT; + destroyMessage.type = J3dMessage.ORDERED_GROUP_REMOVED; + destroyMessage.universe = universe; + destroyMessage.args[0] = universe.setLiveState.ogList.toArray(); + destroyMessage.args[1] = universe.setLiveState.ogChildIdList.toArray(); + destroyMessage.args[3] = universe.setLiveState.ogCIOList.toArray(); + destroyMessage.args[4] = universe.setLiveState.ogCIOTableList.toArray(); + VirtualUniverse.mc.processMessage(destroyMessage); + + destroyMessage = new J3dMessage(); + destroyMessage.threads = J3dThread.UPDATE_RENDERING_ENVIRONMENT; + destroyMessage.type = J3dMessage.VIEWSPECIFICGROUP_CLEAR; + destroyMessage.universe = universe; + destroyMessage.args[0] = universe.setLiveState.changedViewGroup; + destroyMessage.args[1] = universe.setLiveState.keyList; + VirtualUniverse.mc.processMessage(destroyMessage); + + + destroyMessage = new J3dMessage(); + destroyMessage.threads = universe.setLiveState.notifyThreads; + destroyMessage.type = J3dMessage.REMOVE_NODES; + destroyMessage.universe = universe; + destroyMessage.args[0] = universe.setLiveState.nodeList.toArray(); + VirtualUniverse.mc.processMessage(destroyMessage); + + branchGroups.addElement(newGroup); + nbgr.attachedToLocale = true; + universe.setLiveState.reset(this); + universe.setLiveState.currentTransforms[0] = new Transform3D[2]; + universe.setLiveState.currentTransforms[0][0] = new Transform3D(); + universe.setLiveState.currentTransforms[0][1] = new Transform3D(); + universe.setLiveState.currentTransformsIndex[0] = new int[2]; + universe.setLiveState.currentTransformsIndex[0][0] = 0; + universe.setLiveState.currentTransformsIndex[0][1] = 0; + + universe.setLiveState.localToVworld = + universe.setLiveState.currentTransforms; + universe.setLiveState.localToVworldIndex = + universe.setLiveState.currentTransformsIndex; + + universe.setLiveState.branchGroupPaths = new ArrayList<BranchGroupRetained[]>(); + universe.setLiveState.branchGroupPaths.add(new BranchGroupRetained[0]); + + universe.setLiveState.orderedPaths = new ArrayList<OrderedPath>(1); + universe.setLiveState.orderedPaths.add(new OrderedPath()); + + universe.setLiveState.switchStates = new ArrayList<SwitchState>(1); + universe.setLiveState.switchStates.add(new SwitchState(false)); + + nbgr.setLive(universe.setLiveState); + + + createMessage = new J3dMessage(); + createMessage.threads = J3dThread.UPDATE_RENDER| J3dThread.UPDATE_RENDERING_ENVIRONMENT; + createMessage.type = J3dMessage.ORDERED_GROUP_INSERTED; + createMessage.universe = universe; + createMessage.args[0] = universe.setLiveState.ogList.toArray(); + createMessage.args[1] = universe.setLiveState.ogChildIdList.toArray(); + createMessage.args[2] = universe.setLiveState.ogOrderedIdList.toArray(); + createMessage.args[3] = universe.setLiveState.ogCIOList.toArray(); + createMessage.args[4] = universe.setLiveState.ogCIOTableList.toArray(); + VirtualUniverse.mc.processMessage(createMessage); + + // XXXX: make these two into one message + createMessage = new J3dMessage(); + createMessage.threads = universe.setLiveState.notifyThreads; + createMessage.type = J3dMessage.INSERT_NODES; + createMessage.universe = universe; + createMessage.args[0] = universe.setLiveState.nodeList.toArray(); + createMessage.args[1] = null; + createMessage.args[2] = null; + if (universe.setLiveState.viewScopedNodeList != null) { + createMessage.args[3] = universe.setLiveState.viewScopedNodeList; + createMessage.args[4] = universe.setLiveState.scopedNodesViewList; + } + VirtualUniverse.mc.processMessage(createMessage); + + BehaviorRetained[] behavNodes = new BehaviorRetained[universe.setLiveState.behaviorNodes.size()]; + behavNodes = universe.setLiveState.behaviorNodes.toArray(behavNodes); + + if (universe.isEmpty()) { + VirtualUniverse.mc.postRequest(MasterControl.EMPTY_UNIVERSE, + universe); + } + + for (int i=0; i< behavNodes.length; i++) { + behavNodes[i].executeInitialize(); + } + + createMessage = new J3dMessage(); + createMessage.threads = J3dThread.UPDATE_BEHAVIOR; + createMessage.type = J3dMessage.BEHAVIOR_ACTIVATE; + createMessage.universe = universe; + VirtualUniverse.mc.processMessage(createMessage); + + // Free up memory. + universe.setLiveState.reset(null); + } + + /** + * Get number of branch graphs in this Locale. + * @return number of branch graphs in this Locale. + */ + public int numBranchGraphs(){ + return branchGroups.size(); + } + + /** + * Gets an Enumeration object of all branch graphs in this Locale. + * @return an Enumeration object of all branch graphs. + * @exception IllegalStateException if this Locale has been + * removed from its VirtualUniverse. + */ + public Enumeration getAllBranchGraphs(){ + if (universe == null) { + throw new IllegalStateException(J3dI18N.getString("Locale4")); + } + + return branchGroups.elements(); + } + + + void validateModeFlagAndPickShape(int mode, int flags, PickShape pickShape) { + + if (universe == null) { + throw new IllegalStateException(J3dI18N.getString("Locale4")); + } + + if((mode != PickInfo.PICK_BOUNDS) && (mode != PickInfo.PICK_GEOMETRY)) { + + throw new IllegalArgumentException(J3dI18N.getString("Locale5")); + } + + if((pickShape instanceof PickPoint) && (mode == PickInfo.PICK_GEOMETRY)) { + throw new IllegalArgumentException(J3dI18N.getString("Locale6")); + } + + if(((flags & PickInfo.CLOSEST_GEOM_INFO) != 0) && + ((flags & PickInfo.ALL_GEOM_INFO) != 0)) { + throw new IllegalArgumentException(J3dI18N.getString("Locale7")); + } + + if((mode == PickInfo.PICK_BOUNDS) && + (((flags & (PickInfo.CLOSEST_GEOM_INFO | + PickInfo.ALL_GEOM_INFO | + PickInfo.CLOSEST_DISTANCE | + PickInfo.CLOSEST_INTERSECTION_POINT)) != 0))) { + + throw new IllegalArgumentException(J3dI18N.getString("Locale8")); + } + + if((pickShape instanceof PickBounds) && + (((flags & (PickInfo.CLOSEST_GEOM_INFO | + PickInfo.ALL_GEOM_INFO | + PickInfo.CLOSEST_DISTANCE | + PickInfo.CLOSEST_INTERSECTION_POINT)) != 0))) { + + throw new IllegalArgumentException(J3dI18N.getString("Locale9")); + } + } + + /** + * Returns an array referencing all the items that are pickable below this + * <code>Locale</code> that intersect with PickShape. + * The resultant array is unordered. + * + * @param pickShape the description of this picking volume or area. + * + * @exception IllegalStateException if this Locale has been + * removed from its VirtualUniverse. + * + * @see BranchGroup#pickAll + */ + public SceneGraphPath[] pickAll( PickShape pickShape ) { + if (universe == null) { + throw new IllegalStateException(J3dI18N.getString("Locale4")); + } + + PickInfo[] pickInfoArr = pickAll( PickInfo.PICK_BOUNDS, + PickInfo.SCENEGRAPHPATH, pickShape); + + if(pickInfoArr == null) { + return null; + } + SceneGraphPath[] sgpArr = new SceneGraphPath[pickInfoArr.length]; + for( int i=0; i<sgpArr.length; i++) { + sgpArr[i] = pickInfoArr[i].getSceneGraphPath(); + } + + return sgpArr; + + } + + + /** + * Returns an array unsorted references to all the PickInfo objects that are pickable + * below this <code>Locale</code> that intersect with PickShape. + * The accuracy of the pick is set by the pick mode. The mode include : + * PickInfo.PICK_BOUNDS and PickInfo.PICK_GEOMETRY. The amount of information returned + * is specified via a masked variable, flags, indicating which components are + * present in each returned PickInfo object. + * + * @param mode picking mode, one of <code>PickInfo.PICK_BOUNDS</code> or <code>PickInfo.PICK_GEOMETRY</code>. + * + * @param flags a mask indicating which components are present in each PickInfo object. + * This is specified as one or more individual bits that are bitwise "OR"ed together to + * describe the PickInfo data. The flags include : + * <ul> + * <code>PickInfo.SCENEGRAPHPATH</code> - request for computed SceneGraphPath.<br> + * <code>PickInfo.NODE</code> - request for computed intersected Node.<br> + * <code>PickInfo.LOCAL_TO_VWORLD</code> - request for computed local to virtual world transform.<br> + * <code>PickInfo.CLOSEST_INTERSECTION_POINT</code> - request for closest intersection point.<br> + * <code>PickInfo.CLOSEST_DISTANCE</code> - request for the distance of closest intersection.<br> + * <code>PickInfo.CLOSEST_GEOM_INFO</code> - request for only the closest intersection geometry information.<br> + * <code>PickInfo.ALL_GEOM_INFO</code> - request for all intersection geometry information.<br> + * </ul> + * + * @param pickShape the description of this picking volume or area. + * + * @exception IllegalArgumentException if flags contains both CLOSEST_GEOM_INFO and + * ALL_GEOM_INFO. + * + * @exception IllegalArgumentException if pickShape is a PickPoint and pick mode + * is set to PICK_GEOMETRY. + * + * @exception IllegalArgumentException if pick mode is neither PICK_BOUNDS + * nor PICK_GEOMETRY. + * + * @exception IllegalArgumentException if pick mode is PICK_BOUNDS + * and flags includes any of CLOSEST_INTERSECTION_POINT, CLOSEST_DISTANCE, + * CLOSEST_GEOM_INFO or ALL_GEOM_INFO. + * + * @exception IllegalArgumentException if pickShape is PickBounds + * and flags includes any of CLOSEST_INTERSECTION_POINT, CLOSEST_DISTANCE, + * CLOSEST_GEOM_INFO or ALL_GEOM_INFO. + * + * @exception IllegalStateException if this Locale has been + * removed from its VirtualUniverse. + * + * @exception CapabilityNotSetException if the mode is + * PICK_GEOMETRY and the Geometry.ALLOW_INTERSECT capability bit + * is not set in any Geometry objects referred to by any shape + * node whose bounds intersects the PickShape. + * + * @exception CapabilityNotSetException if flags contains any of + * CLOSEST_INTERSECTION_POINT, CLOSEST_DISTANCE, CLOSEST_GEOM_INFO + * or ALL_GEOM_INFO, and the capability bits that control reading of + * coordinate data are not set in any GeometryArray object referred + * to by any shape node that intersects the PickShape. + * The capability bits that must be set to avoid this exception are as follows : + * <ul> + * <li>By-copy geometry : GeometryArray.ALLOW_COORDINATE_READ</li> + * <li>By-reference geometry : GeometryArray.ALLOW_REF_DATA_READ</li> + * <li>Indexed geometry : IndexedGeometryArray.ALLOW_COORDINATE_INDEX_READ + * (in addition to one of the above)</li> + * </ul> + * + * @see BranchGroup#pickAll(int,int,javax.media.j3d.PickShape) + * @see PickInfo + * + * @since Java 3D 1.4 + * + */ + public PickInfo[] pickAll( int mode, int flags, PickShape pickShape ) { + + validateModeFlagAndPickShape(mode, flags, pickShape); + + GeometryAtom geomAtoms[] = universe.geometryStructure.pickAll(this, pickShape); + + return PickInfo.pick(this, geomAtoms, mode, flags, pickShape, PickInfo.PICK_ALL); + + } + + /** + * Returns a sorted array of references to all the pickable items + * that intersect with the pickShape. Element [0] references the + * item closest to <i>origin</i> of PickShape successive array + * elements are further from the <i>origin</i> + * <br> + * NOTE: If pickShape is of type PickBounds, the resulting array + * is unordered. + * + * @param pickShape the description of this picking volume or area. + * + * @exception IllegalStateException if this Locale has been + * removed from its VirtualUniverse. + * + * @see BranchGroup#pickAllSorted + */ + public SceneGraphPath[] pickAllSorted( PickShape pickShape ) { + if (universe == null) { + throw new IllegalStateException(J3dI18N.getString("Locale4")); + } + + PickInfo[] pickInfoArr = pickAllSorted( PickInfo.PICK_BOUNDS, + PickInfo.SCENEGRAPHPATH, pickShape); + + if(pickInfoArr == null) { + return null; + } + SceneGraphPath[] sgpArr = new SceneGraphPath[pickInfoArr.length]; + for( int i=0; i<sgpArr.length; i++) { + sgpArr[i] = pickInfoArr[i].getSceneGraphPath(); + } + + return sgpArr; + + } + + /** + * Returns a sorted array of PickInfo references to all the pickable + * items that intersect with the pickShape. Element [0] references + * the item closest to <i>origin</i> of PickShape successive array + * elements are further from the <i>origin</i> + * The accuracy of the pick is set by the pick mode. The mode include : + * PickInfo.PICK_BOUNDS and PickInfo.PICK_GEOMETRY. The amount of information returned + * is specified via a masked variable, flags, indicating which components are + * present in each returned PickInfo object. + * + * @param mode picking mode, one of <code>PickInfo.PICK_BOUNDS</code> or <code>PickInfo.PICK_GEOMETRY</code>. + * + * @param flags a mask indicating which components are present in each PickInfo object. + * This is specified as one or more individual bits that are bitwise "OR"ed together to + * describe the PickInfo data. The flags include : + * <ul> + * <code>PickInfo.SCENEGRAPHPATH</code> - request for computed SceneGraphPath.<br> + * <code>PickInfo.NODE</code> - request for computed intersected Node.<br> + * <code>PickInfo.LOCAL_TO_VWORLD</code> - request for computed local to virtual world transform.<br> + * <code>PickInfo.CLOSEST_INTERSECTION_POINT</code> - request for closest intersection point.<br> + * <code>PickInfo.CLOSEST_DISTANCE</code> - request for the distance of closest intersection.<br> + * <code>PickInfo.CLOSEST_GEOM_INFO</code> - request for only the closest intersection geometry information.<br> + * <code>PickInfo.ALL_GEOM_INFO</code> - request for all intersection geometry information.<br> + * </ul> + * + * @param pickShape the description of this picking volume or area. + * + * @exception IllegalArgumentException if flags contains both CLOSEST_GEOM_INFO and + * ALL_GEOM_INFO. + * + * @exception IllegalArgumentException if pickShape is a PickPoint and pick mode + * is set to PICK_GEOMETRY. + * + * @exception IllegalArgumentException if pick mode is neither PICK_BOUNDS + * nor PICK_GEOMETRY. + * + * @exception IllegalArgumentException if pick mode is PICK_BOUNDS + * and flags includes any of CLOSEST_INTERSECTION_POINT, CLOSEST_DISTANCE, + * CLOSEST_GEOM_INFO or ALL_GEOM_INFO. + * + * @exception IllegalArgumentException if pickShape is PickBounds + * and flags includes any of CLOSEST_INTERSECTION_POINT, CLOSEST_DISTANCE, + * CLOSEST_GEOM_INFO or ALL_GEOM_INFO. + * + * @exception IllegalStateException if this Locale has been + * removed from its VirtualUniverse. + * + * @exception CapabilityNotSetException if the mode is + * PICK_GEOMETRY and the Geometry.ALLOW_INTERSECT capability bit + * is not set in any Geometry objects referred to by any shape + * node whose bounds intersects the PickShape. + * + * @exception CapabilityNotSetException if flags contains any of + * CLOSEST_INTERSECTION_POINT, CLOSEST_DISTANCE, CLOSEST_GEOM_INFO + * or ALL_GEOM_INFO, and the capability bits that control reading of + * coordinate data are not set in any GeometryArray object referred + * to by any shape node that intersects the PickShape. + * The capability bits that must be set to avoid this exception are as follows : + * <ul> + * <li>By-copy geometry : GeometryArray.ALLOW_COORDINATE_READ</li> + * <li>By-reference geometry : GeometryArray.ALLOW_REF_DATA_READ</li> + * <li>Indexed geometry : IndexedGeometryArray.ALLOW_COORDINATE_INDEX_READ + * (in addition to one of the above)</li> + * </ul> + * + * @see BranchGroup#pickAllSorted(int,int,javax.media.j3d.PickShape) + * @see PickInfo + * + * @since Java 3D 1.4 + * + */ + public PickInfo[] pickAllSorted( int mode, int flags, PickShape pickShape ) { + + validateModeFlagAndPickShape(mode, flags, pickShape); + GeometryAtom geomAtoms[] = universe.geometryStructure.pickAll(this, pickShape); + + if ((geomAtoms == null) || (geomAtoms.length == 0)) { + return null; + } + + PickInfo[] pickInfoArr = null; + + if (mode == PickInfo.PICK_GEOMETRY) { + // Need to have closestDistance set + flags |= PickInfo.CLOSEST_DISTANCE; + pickInfoArr= PickInfo.pick(this, geomAtoms, mode, flags, pickShape, PickInfo.PICK_ALL); + if (pickInfoArr != null) { + PickInfo.sortPickInfoArray(pickInfoArr); + } + } + else { + PickInfo.sortGeomAtoms(geomAtoms, pickShape); + pickInfoArr= PickInfo.pick(this, geomAtoms, mode, flags, pickShape, PickInfo.PICK_ALL); + } + + return pickInfoArr; + } + + /** + * Returns a SceneGraphPath which references the pickable item + * which is closest to the origin of <code>pickShape</code>. + * <br> + * NOTE: If pickShape is of type PickBounds, the return is any + * pickable node below this Locale. + * + * @param pickShape the description of this picking volume or area. + * + * @exception IllegalStateException if this Locale has been + * removed from its VirtualUniverse. + * + * @see BranchGroup#pickClosest + */ + public SceneGraphPath pickClosest( PickShape pickShape ) { + if (universe == null) { + throw new IllegalStateException(J3dI18N.getString("Locale4")); + } + + PickInfo pickInfo = pickClosest( PickInfo.PICK_BOUNDS, + PickInfo.SCENEGRAPHPATH, pickShape); + + if(pickInfo == null) { + return null; + } + return pickInfo.getSceneGraphPath(); + } + + /** + * Returns a PickInfo which references the pickable item + * which is closest to the origin of <code>pickShape</code>. + * The accuracy of the pick is set by the pick mode. The mode include : + * PickInfo.PICK_BOUNDS and PickInfo.PICK_GEOMETRY. The amount of information returned + * is specified via a masked variable, flags, indicating which components are + * present in each returned PickInfo object. + * + * @param mode picking mode, one of <code>PickInfo.PICK_BOUNDS</code> or <code>PickInfo.PICK_GEOMETRY</code>. + * + * @param flags a mask indicating which components are present in each PickInfo object. + * This is specified as one or more individual bits that are bitwise "OR"ed together to + * describe the PickInfo data. The flags include : + * <ul> + * <code>PickInfo.SCENEGRAPHPATH</code> - request for computed SceneGraphPath.<br> + * <code>PickInfo.NODE</code> - request for computed intersected Node.<br> + * <code>PickInfo.LOCAL_TO_VWORLD</code> - request for computed local to virtual world transform.<br> + * <code>PickInfo.CLOSEST_INTERSECTION_POINT</code> - request for closest intersection point.<br> + * <code>PickInfo.CLOSEST_DISTANCE</code> - request for the distance of closest intersection.<br> + * <code>PickInfo.CLOSEST_GEOM_INFO</code> - request for only the closest intersection geometry information.<br> + * <code>PickInfo.ALL_GEOM_INFO</code> - request for all intersection geometry information.<br> + * </ul> + * + * @param pickShape the description of this picking volume or area. + * + * @exception IllegalArgumentException if flags contains both CLOSEST_GEOM_INFO and + * ALL_GEOM_INFO. + * + * @exception IllegalArgumentException if pickShape is a PickPoint and pick mode + * is set to PICK_GEOMETRY. + * + * @exception IllegalArgumentException if pick mode is neither PICK_BOUNDS + * nor PICK_GEOMETRY. + * + * @exception IllegalArgumentException if pick mode is PICK_BOUNDS + * and flags includes any of CLOSEST_INTERSECTION_POINT, CLOSEST_DISTANCE, + * CLOSEST_GEOM_INFO or ALL_GEOM_INFO. + * + * @exception IllegalArgumentException if pickShape is PickBounds + * and flags includes any of CLOSEST_INTERSECTION_POINT, CLOSEST_DISTANCE, + * CLOSEST_GEOM_INFO or ALL_GEOM_INFO. + * + * @exception IllegalStateException if this Locale has been + * removed from its VirtualUniverse. + * + * @exception CapabilityNotSetException if the mode is + * PICK_GEOMETRY and the Geometry.ALLOW_INTERSECT capability bit + * is not set in any Geometry objects referred to by any shape + * node whose bounds intersects the PickShape. + * + * @exception CapabilityNotSetException if flags contains any of + * CLOSEST_INTERSECTION_POINT, CLOSEST_DISTANCE, CLOSEST_GEOM_INFO + * or ALL_GEOM_INFO, and the capability bits that control reading of + * coordinate data are not set in any GeometryArray object referred + * to by any shape node that intersects the PickShape. + * The capability bits that must be set to avoid this exception are as follows : + * <ul> + * <li>By-copy geometry : GeometryArray.ALLOW_COORDINATE_READ</li> + * <li>By-reference geometry : GeometryArray.ALLOW_REF_DATA_READ</li> + * <li>Indexed geometry : IndexedGeometryArray.ALLOW_COORDINATE_INDEX_READ + * (in addition to one of the above)</li> + * </ul> + * + * @see BranchGroup#pickClosest(int,int,javax.media.j3d.PickShape) + * @see PickInfo + * + * @since Java 3D 1.4 + * + */ + public PickInfo pickClosest( int mode, int flags, PickShape pickShape ) { + + PickInfo[] pickInfoArr = null; + + pickInfoArr = pickAllSorted( mode, flags, pickShape ); + + if(pickInfoArr == null) { + return null; + } + + return pickInfoArr[0]; + + } + + /** + * Returns a reference to any item that is Pickable below this + * Locale which intersects with <code>pickShape</code>. + * + * @param pickShape the description of this picking volume or area. + * + * @exception IllegalStateException if this Locale has been + * removed from its VirtualUniverse. + * + * @see BranchGroup#pickAny + */ + public SceneGraphPath pickAny( PickShape pickShape ) { + if (universe == null) { + throw new IllegalStateException(J3dI18N.getString("Locale4")); + } + + PickInfo pickInfo = pickAny( PickInfo.PICK_BOUNDS, + PickInfo.SCENEGRAPHPATH, pickShape); + + if(pickInfo == null) { + return null; + } + return pickInfo.getSceneGraphPath(); + + } + + /** + * Returns a PickInfo which references the pickable item below this + * Locale which intersects with <code>pickShape</code>. + * The accuracy of the pick is set by the pick mode. The mode include : + * PickInfo.PICK_BOUNDS and PickInfo.PICK_GEOMETRY. The amount of information returned + * is specified via a masked variable, flags, indicating which components are + * present in each returned PickInfo object. + * + * @param mode picking mode, one of <code>PickInfo.PICK_BOUNDS</code> or <code>PickInfo.PICK_GEOMETRY</code>. + * + * @param flags a mask indicating which components are present in each PickInfo object. + * This is specified as one or more individual bits that are bitwise "OR"ed together to + * describe the PickInfo data. The flags include : + * <ul> + * <code>PickInfo.SCENEGRAPHPATH</code> - request for computed SceneGraphPath.<br> + * <code>PickInfo.NODE</code> - request for computed intersected Node.<br> + * <code>PickInfo.LOCAL_TO_VWORLD</code> - request for computed local to virtual world transform.<br> + * <code>PickInfo.CLOSEST_INTERSECTION_POINT</code> - request for closest intersection point.<br> + * <code>PickInfo.CLOSEST_DISTANCE</code> - request for the distance of closest intersection.<br> + * <code>PickInfo.CLOSEST_GEOM_INFO</code> - request for only the closest intersection geometry information.<br> + * <code>PickInfo.ALL_GEOM_INFO</code> - request for all intersection geometry information.<br> + * </ul> + * + * @param pickShape the description of this picking volume or area. + * + * @exception IllegalArgumentException if flags contains both CLOSEST_GEOM_INFO and + * ALL_GEOM_INFO. + * + * @exception IllegalArgumentException if pickShape is a PickPoint and pick mode + * is set to PICK_GEOMETRY. + * + * @exception IllegalArgumentException if pick mode is neither PICK_BOUNDS + * nor PICK_GEOMETRY. + * + * @exception IllegalArgumentException if pick mode is PICK_BOUNDS + * and flags includes any of CLOSEST_INTERSECTION_POINT, CLOSEST_DISTANCE, + * CLOSEST_GEOM_INFO or ALL_GEOM_INFO. + * + * @exception IllegalArgumentException if pickShape is PickBounds + * and flags includes any of CLOSEST_INTERSECTION_POINT, CLOSEST_DISTANCE, + * CLOSEST_GEOM_INFO or ALL_GEOM_INFO. + * + * @exception IllegalStateException if this Locale has been + * removed from its VirtualUniverse. + * + * @exception CapabilityNotSetException if the mode is + * PICK_GEOMETRY and the Geometry.ALLOW_INTERSECT capability bit + * is not set in any Geometry objects referred to by any shape + * node whose bounds intersects the PickShape. + * + * @exception CapabilityNotSetException if flags contains any of + * CLOSEST_INTERSECTION_POINT, CLOSEST_DISTANCE, CLOSEST_GEOM_INFO + * or ALL_GEOM_INFO, and the capability bits that control reading of + * coordinate data are not set in any GeometryArray object referred + * to by any shape node that intersects the PickShape. + * The capability bits that must be set to avoid this exception are as follows : + * <ul> + * <li>By-copy geometry : GeometryArray.ALLOW_COORDINATE_READ</li> + * <li>By-reference geometry : GeometryArray.ALLOW_REF_DATA_READ</li> + * <li>Indexed geometry : IndexedGeometryArray.ALLOW_COORDINATE_INDEX_READ + * (in addition to one of the above)</li> + * </ul> + * + * @see BranchGroup#pickAny(int,int,javax.media.j3d.PickShape) + * @see PickInfo + * + * @since Java 3D 1.4 + * + */ + public PickInfo pickAny( int mode, int flags, PickShape pickShape ) { + + validateModeFlagAndPickShape(mode, flags, pickShape); + GeometryAtom geomAtoms[] = universe.geometryStructure.pickAll(this, pickShape); + + PickInfo[] pickInfoArr = PickInfo.pick(this, geomAtoms, mode, flags, pickShape, PickInfo.PICK_ANY); + + if(pickInfoArr == null) { + return null; + } + + return pickInfoArr[0]; + + } + +} |