📄 pickinfo.java
字号:
do { if (nodeR.source.getCapability(Node.ENABLE_PICK_REPORTING)){ path.add(nodeR); } nodeR = nodeR.parent; } while (nodeR != null); // reach Locale return path; } static private Node[] createPath(NodeRetained srcNode, BranchGroupRetained bgRetained, GeometryAtom geomAtom, ArrayList initpath) { ArrayList path = retrievePath(srcNode, bgRetained, geomAtom.source.key); assert(path != null); return mergePath(path, initpath); } /** * Return true if bg is inside cachedBG or bg is null */ static private boolean inside(BranchGroupRetained bgArr[], BranchGroupRetained bg) { if ((bg == null) || (bgArr == null)) { return true; } for (int i=0; i < bgArr.length; i++) { if (bgArr[i] == bg) { return true; } } return false; } /** * search the full path from the bottom of the scene graph - * startNode, up to the Locale if endNode is null. * If endNode is not null, the path is found up to, but not * including, endNode or return null if endNode not hit * during the search. */ static private ArrayList retrievePath(NodeRetained startNode, NodeRetained endNode, HashKey key) { ArrayList path = new ArrayList(5); NodeRetained nodeR = startNode; if (nodeR.inSharedGroup) { // getlastNodeId() will destroy this key key = new HashKey(key); } do { if (nodeR == endNode) { // we found it ! return path; } if (nodeR.source.getCapability(Node.ENABLE_PICK_REPORTING)) { path.add(nodeR); } if (nodeR instanceof SharedGroupRetained) { // retrieve the last node ID String nodeId = key.getLastNodeId(); Vector parents = ((SharedGroupRetained) nodeR).parents; int sz = parents.size(); NodeRetained prevNodeR = nodeR; for(int i=0; i< sz; i++) { NodeRetained linkR = (NodeRetained) parents.elementAt(i); if (linkR.nodeId.equals(nodeId)) { nodeR = linkR; // Need to add Link to the path report path.add(nodeR); // since !(endNode instanceof Link), we // can skip the check (nodeR == endNode) and // proceed to parent of link below break; } } if (nodeR == prevNodeR) { // branch is already detach return null; } } nodeR = nodeR.parent; } while (nodeR != null); // reach Locale if (endNode == null) { // user call pickxxx(Locale locale, PickShape shape) return path; } // user call pickxxx(BranchGroup endNode, PickShape shape) // if locale is reached and endNode not hit, this is not // the path user want to select return null; } /** * copy p1, (follow by) p2 into a new array, p2 can be null * The path is then reverse before return. */ static private Node[] mergePath(ArrayList p1, ArrayList p2) { int s = p1.size(); int len; int i; int l; if (p2 == null) { len = s; } else { len = s + p2.size(); } Node nodes[] = new Node[len]; l = len-1; for (i=0; i < s; i++) { nodes[l-i] = (Node) ((NodeRetained) p1.get(i)).source; } for (int j=0; i< len; i++, j++) { nodes[l-i] = (Node) ((NodeRetained) p2.get(j)).source; } return nodes; } /** * Sort the GeometryAtoms distance from shape in ascending order * geomAtoms.length must be >= 1 */ static void sortGeomAtoms(GeometryAtom geomAtoms[], PickShape shape) { final double distance[] = new double[geomAtoms.length]; Point4d pickPos = new Point4d(); for (int i=0; i < geomAtoms.length; i++) { shape.intersect(geomAtoms[i].source.vwcBounds, pickPos); distance[i] = pickPos.w; } class Sort { GeometryAtom atoms[]; Sort(GeometryAtom[] atoms) { this.atoms = atoms; } void sorting() { if (atoms.length < 7) { insertSort(); } else { quicksort(0, atoms.length-1); } } // Insertion sort on smallest arrays final void insertSort() { for (int i=0; i<atoms.length; i++) { for (int j=i; j>0 && (distance[j-1] > distance[j]); j--) { double t = distance[j]; distance[j] = distance[j-1]; distance[j-1] = t; GeometryAtom p = atoms[j]; atoms[j] = atoms[j-1]; atoms[j-1] = p; } } } final void quicksort( int l, int r ) { int i = l; int j = r; double k = distance[(l+r) / 2]; do { while (distance[i]<k) i++; while (k<distance[j]) j--; if (i<=j) { double tmp = distance[i]; distance[i] =distance[j]; distance[j] = tmp; GeometryAtom p=atoms[i]; atoms[i]=atoms[j]; atoms[j]=p; i++; j--; } } while (i<=j); if (l<j) quicksort(l,j); if (l<r) quicksort(i,r); } } (new Sort(geomAtoms)).sorting(); } /** * return all PickInfo[] of the geomAtoms. * If initpath is null, the path is search from * geomAtom Shape3D/Morph Node up to Locale * (assume the same locale). * Otherwise, the path is search up to node or * null is return if it is not hit. */ static ArrayList getPickInfos(ArrayList initpath, BranchGroupRetained bgRetained, GeometryAtom geomAtoms[], Locale locale, int flags, int pickType) { ArrayList pickInfoList = new ArrayList(5); NodeRetained srcNode; ArrayList text3dList = null; if ((geomAtoms == null) || (geomAtoms.length == 0)) { return null; } for (int i=0; i < geomAtoms.length; i++) { assert((geomAtoms[i] != null) && (geomAtoms[i].source != null)); PickInfo pickInfo = null; Shape3DRetained shape = geomAtoms[i].source; srcNode = shape.sourceNode; // Fix to Issue 274 : NPE With Simultaneous View and Content Side PickingBehaviors // This node isn't under the selected BG for pick operation. if (!inside(shape.branchGroupPath,bgRetained)) { continue; } if (srcNode == null) { // The node is just detach from branch so sourceNode = null continue; } // Special case, for Text3DRetained, it is possible // for different geomAtoms pointing to the same // source Text3DRetained. So we need to combine // those cases and report only once. if (srcNode instanceof Shape3DRetained) { Shape3DRetained s3dR = (Shape3DRetained) srcNode; GeometryRetained geomR = null; for(int cnt=0; cnt<s3dR.geometryList.size(); cnt++) { geomR = (GeometryRetained) s3dR.geometryList.get(cnt); if(geomR != null) break; } if (geomR == null) continue; if (geomR instanceof Text3DRetained) { // assume this case is not frequent, we allocate // ArrayList only when necessary and we use ArrayList // instead of HashMap since the case of when large // number of distingish Text3DRetained node hit is // rare. if (text3dList == null) { text3dList = new ArrayList(3); } else { int size = text3dList.size(); boolean found = false; for (int j=0; j < size; j++) { if (text3dList.get(j) == srcNode) { found = true; break; } } if (found) { continue; // try next geomAtom } } text3dList.add(srcNode); } } // If srcNode is instance of compile retained, then loop thru // the entire source list and add it to the scene graph path if (srcNode instanceof Shape3DCompileRetained) { Shape3DCompileRetained s3dCR = (Shape3DCompileRetained)srcNode; Node[] mpath = null; boolean first = true; for (int n = 0; n < s3dCR.srcList.length; n++) { pickInfo = null; // PickInfo.SCENEGRAPHPATH - request for computed SceneGraphPath. if ((flags & SCENEGRAPHPATH) != 0){ if(first) { mpath = createPath(srcNode, bgRetained, geomAtoms[i], initpath); first = false; } if(mpath != null) { SceneGraphPath sgpath = new SceneGraphPath(locale, mpath, (Node) s3dCR.srcList[n]); sgpath.setTransform(shape.getCurrentLocalToVworld(0)); if(pickInfo == null) pickInfo = new PickInfo(); pickInfo.setSceneGraphPath(sgpath); } } // PickInfo.NODE - request for computed intersected Node. if ((flags & NODE) != 0) { if(pickInfo == null) pickInfo = new PickInfo(); pickInfo.setNode((Node) s3dCR.srcList[n]); } // PickInfo.LOCAL_TO_VWORLD // - request for computed local to virtual world transform. if ((flags & LOCAL_TO_VWORLD) != 0) { Transform3D l2vw = geomAtoms[i].source.getCurrentLocalToVworld(); if(pickInfo == null) pickInfo = new PickInfo(); pickInfo.setLocalToVWorld( new Transform3D(l2vw)); } // NOTE : Piggy bag for geometry computation by caller. if (((flags & CLOSEST_DISTANCE) != 0) || ((flags & CLOSEST_GEOM_INFO) != 0) || ((flags & CLOSEST_INTERSECTION_POINT) != 0) || ((flags & ALL_GEOM_INFO) != 0)) { if(pickInfo == null) pickInfo = new PickInfo(); pickInfo.setNodeRef((Node) s3dCR.srcList[n]); Transform3D l2vw = geomAtoms[i].source.getCurrentLocalToVworld(); pickInfo.setLocalToVWorldRef(l2vw); } if(pickInfo != null) pickInfoList.add(pickInfo); if(pickType == PICK_ANY) { return pickInfoList; } } } else { Node[] mpath = null;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -