Source Code Cross Referenced for PickInfo.java in  » 6.0-JDK-Modules » java-3d » javax » media » j3d » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » 6.0 JDK Modules » java 3d » javax.media.j3d 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * $RCSfile: PickInfo.java,v $
0003:         *
0004:         * Copyright 2005-2008 Sun Microsystems, Inc.  All Rights Reserved.
0005:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0006:         *
0007:         * This code is free software; you can redistribute it and/or modify it
0008:         * under the terms of the GNU General Public License version 2 only, as
0009:         * published by the Free Software Foundation.  Sun designates this
0010:         * particular file as subject to the "Classpath" exception as provided
0011:         * by Sun in the LICENSE file that accompanied this code.
0012:         *
0013:         * This code is distributed in the hope that it will be useful, but WITHOUT
0014:         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0015:         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
0016:         * version 2 for more details (a copy is included in the LICENSE file that
0017:         * accompanied this code).
0018:         *
0019:         * You should have received a copy of the GNU General Public License version
0020:         * 2 along with this work; if not, write to the Free Software Foundation,
0021:         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0022:         *
0023:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0024:         * CA 95054 USA or visit www.sun.com if you need additional information or
0025:         * have any questions.
0026:         *
0027:         * $Revision: 1.12 $
0028:         * $Date: 2008/02/28 20:17:27 $
0029:         * $State: Exp $
0030:         */
0031:
0032:        package javax.media.j3d;
0033:
0034:        import javax.vecmath.*;
0035:        import java.util.*;
0036:
0037:        /**
0038:         * The PickInfo object contains the computed information about a pick hit.  
0039:         * The detailed information about each intersection of the PickShape 
0040:         * with the picked Node can be inquired.  The PickInfo object is constructed with
0041:         * basic information and more detailed information can be generated by setting the
0042:         * appropriate mask to the flag argument in the pick methods of BranchGroup and 
0043:         * Locale.
0044:         * <p>
0045:         *
0046:         * @see Locale
0047:         * @see BranchGroup 
0048:         *
0049:         * @since Java 3D 1.4
0050:         */
0051:
0052:        public class PickInfo extends Object {
0053:
0054:            static final int PICK_ALL = 1;
0055:
0056:            static final int PICK_ANY = 2;
0057:
0058:            /* The SceneGraphPath of the intersected pickable item */
0059:            private SceneGraphPath sgp;
0060:
0061:            /* The intersected pickable node object */
0062:            private Node node;
0063:
0064:            /* A copy of LocalToVworld transform of the pickable node */
0065:            private Transform3D l2vw;
0066:
0067:            /* The closest intersection point */
0068:            private Point3d closestIntersectionPoint;
0069:
0070:            /* Distance between start point of pickShape and closest intersection point */
0071:            private double closestDistance;
0072:
0073:            /* An array to store intersection results */
0074:            private IntersectionInfo[] intersectionInfoArr;
0075:
0076:            /* The following references are for internal geometry computation use only */
0077:            private ArrayList intersectionInfoList = new ArrayList();
0078:            private boolean intersectionInfoListSorted = false;
0079:            private Transform3D l2vwRef;
0080:            private Node nodeRef;
0081:
0082:            /**
0083:             * Specifies a Pick using the bounds of the pickable nodes.
0084:             */
0085:            public static final int PICK_BOUNDS = 1;
0086:
0087:            /**
0088:             * Specifies a Pick using the geometry of the pickable nodes.
0089:             */
0090:            public static final int PICK_GEOMETRY = 2;
0091:
0092:            /**
0093:             * Specifies that this PickInfo returns the computed SceneGraphPath object.
0094:             */
0095:            public static final int SCENEGRAPHPATH = 0x01;
0096:
0097:            /**
0098:             * Specifies that this PickInfo returns the computed intersected Node object.
0099:             */
0100:            public static final int NODE = 0x02;
0101:
0102:            /**
0103:             * Specifies that this PickInfo returns the computed local to vworld transform.
0104:             */
0105:            public static final int LOCAL_TO_VWORLD = 0x04;
0106:
0107:            /**
0108:             * Specifies that this PickInfo returns the closest intersection point.
0109:             */
0110:            public static final int CLOSEST_INTERSECTION_POINT = 0x08;
0111:
0112:            /**
0113:             * Specifies that this PickInfo returns the closest intersection distance.
0114:             */
0115:            public static final int CLOSEST_DISTANCE = 0x10;
0116:
0117:            /**
0118:             * Specifies that this PickInfo returns only the closest intersection 
0119:             * geometry information.
0120:             */
0121:            public static final int CLOSEST_GEOM_INFO = 0x20;
0122:
0123:            /**
0124:             * Specifies that this PickInfo returns all the closest intersection 
0125:             * geometry informations.
0126:             */
0127:            public static final int ALL_GEOM_INFO = 0x40;
0128:
0129:            /** PickInfo Constructor */
0130:            PickInfo() {
0131:
0132:            }
0133:
0134:            void setSceneGraphPath(SceneGraphPath sgp) {
0135:                this .sgp = sgp;
0136:            }
0137:
0138:            void setNode(Node node) {
0139:                this .node = node;
0140:            }
0141:
0142:            void setLocalToVWorld(Transform3D l2vw) {
0143:                this .l2vw = l2vw;
0144:            }
0145:
0146:            void setClosestIntersectionPoint(Point3d cIPt) {
0147:                this .closestIntersectionPoint = cIPt;
0148:            }
0149:
0150:            void setClosestDistance(double cDist) {
0151:                this .closestDistance = cDist;
0152:            }
0153:
0154:            void setLocalToVWorldRef(Transform3D l2vwRef) {
0155:                this .l2vwRef = l2vwRef;
0156:            }
0157:
0158:            void setNodeRef(Node nodeRef) {
0159:                this .nodeRef = nodeRef;
0160:            }
0161:
0162:            IntersectionInfo createIntersectionInfo() {
0163:                return new IntersectionInfo();
0164:            }
0165:
0166:            void insertIntersectionInfo(IntersectionInfo iInfo) {
0167:                intersectionInfoList.add(iInfo);
0168:                intersectionInfoListSorted = false;
0169:            }
0170:
0171:            void sortIntersectionInfoArray(IntersectionInfo[] iInfoArr) {
0172:
0173:                class Sort {
0174:
0175:                    IntersectionInfo iInfoArr[];
0176:
0177:                    Sort(IntersectionInfo[] iInfoArr) {
0178:                        // System.err.println("Sort IntersectionInfo ...");
0179:                        this .iInfoArr = iInfoArr;
0180:                    }
0181:
0182:                    void sorting() {
0183:                        if (iInfoArr.length < 7) {
0184:                            // System.err.println(" -- insertSort.");
0185:                            insertSort();
0186:                        } else {
0187:                            // System.err.println(" -- quicksort.");                    
0188:                            quicksort(0, iInfoArr.length - 1);
0189:                        }
0190:                    }
0191:
0192:                    // Insertion sort on smallest arrays
0193:                    final void insertSort() {
0194:                        for (int i = 0; i < iInfoArr.length; i++) {
0195:                            for (int j = i; j > 0
0196:                                    && (iInfoArr[j - 1].distance > iInfoArr[j].distance); j--) {
0197:                                IntersectionInfo iInfo = iInfoArr[j];
0198:                                iInfoArr[j] = iInfoArr[j - 1];
0199:                                iInfoArr[j - 1] = iInfo;
0200:                            }
0201:                        }
0202:                    }
0203:
0204:                    final void quicksort(int l, int r) {
0205:                        int i = l;
0206:                        int j = r;
0207:                        double k = iInfoArr[(l + r) / 2].distance;
0208:
0209:                        do {
0210:                            while (iInfoArr[i].distance < k)
0211:                                i++;
0212:                            while (k < iInfoArr[j].distance)
0213:                                j--;
0214:                            if (i <= j) {
0215:                                IntersectionInfo iInfo = iInfoArr[i];
0216:                                iInfoArr[i] = iInfoArr[j];
0217:                                iInfoArr[j] = iInfo;
0218:                                i++;
0219:                                j--;
0220:                            }
0221:                        } while (i <= j);
0222:
0223:                        if (l < j)
0224:                            quicksort(l, j);
0225:                        if (l < r)
0226:                            quicksort(i, r);
0227:                    }
0228:                }
0229:
0230:                (new Sort(iInfoArr)).sorting();
0231:                intersectionInfoListSorted = true;
0232:            }
0233:
0234:            static void sortPickInfoArray(PickInfo[] pickInfoArr) {
0235:
0236:                class Sort {
0237:
0238:                    PickInfo pIArr[];
0239:
0240:                    Sort(PickInfo[] pIArr) {
0241:                        // System.err.println("Sort PickInfo ...");
0242:                        this .pIArr = pIArr;
0243:                    }
0244:
0245:                    void sorting() {
0246:                        if (pIArr.length < 7) {
0247:                            // System.err.println(" -- insertSort.");
0248:                            insertSort();
0249:                        } else {
0250:                            // System.err.println(" -- quicksort.");                    
0251:                            quicksort(0, pIArr.length - 1);
0252:                        }
0253:                    }
0254:
0255:                    // Insertion sort on smallest arrays
0256:                    final void insertSort() {
0257:                        for (int i = 0; i < pIArr.length; i++) {
0258:                            for (int j = i; j > 0
0259:                                    && (pIArr[j - 1].closestDistance > pIArr[j].closestDistance); j--) {
0260:                                PickInfo pI = pIArr[j];
0261:                                pIArr[j] = pIArr[j - 1];
0262:                                pIArr[j - 1] = pI;
0263:                            }
0264:                        }
0265:                    }
0266:
0267:                    final void quicksort(int l, int r) {
0268:                        int i = l;
0269:                        int j = r;
0270:                        double k = pIArr[(l + r) / 2].closestDistance;
0271:
0272:                        do {
0273:                            while (pIArr[i].closestDistance < k)
0274:                                i++;
0275:                            while (k < pIArr[j].closestDistance)
0276:                                j--;
0277:                            if (i <= j) {
0278:                                PickInfo pI = pIArr[i];
0279:                                pIArr[i] = pIArr[j];
0280:                                pIArr[j] = pI;
0281:                                i++;
0282:                                j--;
0283:                            }
0284:                        } while (i <= j);
0285:
0286:                        if (l < j)
0287:                            quicksort(l, j);
0288:                        if (l < r)
0289:                            quicksort(i, r);
0290:                    }
0291:                }
0292:
0293:                (new Sort(pickInfoArr)).sorting();
0294:
0295:            }
0296:
0297:            /**
0298:             * Retrieves the reference to the SceneGraphPath in this PickInfo object.
0299:             * @return the SceneGraphPath object, or null if  flag is not set with SCENEGRAPHPATH.
0300:             * @see Locale
0301:             * @see BranchGroup
0302:             */
0303:            public SceneGraphPath getSceneGraphPath() {
0304:                return sgp;
0305:            }
0306:
0307:            /**
0308:             * Retrieves the reference to the picked node, either a Shape3D or a Morph, in this PickInfo object.
0309:             * @return the picked leaf node object, or null if  flag is not set with NODE.
0310:             * @see Locale
0311:             * @see BranchGroup
0312:             */
0313:            public Node getNode() {
0314:                return node;
0315:            }
0316:
0317:            /**
0318:             * Retrieves the reference to the LocalToVworld transform of the picked node in this PickInfo object.
0319:             * @return the local to vworld transform, or null if  flag is not set with LOCAL_TO_VWORLD.
0320:             * @see Locale
0321:             * @see BranchGroup
0322:             */
0323:            public Transform3D getLocalToVWorld() {
0324:                return l2vw;
0325:            }
0326:
0327:            /**
0328:             * Retrieves the reference to the closest intersection point in this PickInfo object.
0329:             * @return the closest intersection point, or null if  flag is not set with CLOSEST_INTERSECTION_POINT.
0330:             * @see Locale
0331:             * @see BranchGroup
0332:             */
0333:            public Point3d getClosestIntersectionPoint() {
0334:                return closestIntersectionPoint;
0335:            }
0336:
0337:            /**
0338:             * Retrieves the distance between the start point of the pickShape and the closest intersection point.
0339:             * @return the closest distance in double, or NaN if  flag is not set with CLOSEST_INTERSECTION_POINT.
0340:             * Note : If this PickInfo object is returned by either pickClosest or pickAllSorted method, the return
0341:             * value is the closest distance in double even if flag is not set with CLOSET_INTERSECTION_POINT.
0342:             * @see Locale
0343:             * @see BranchGroup
0344:             */
0345:            public double getClosestDistance() {
0346:                return closestDistance;
0347:            }
0348:
0349:            Transform3D getLocalToVWorldRef() {
0350:                return l2vwRef;
0351:            }
0352:
0353:            Node getNodeRef() {
0354:                return nodeRef;
0355:            }
0356:
0357:            /**
0358:             * Retrieves the reference to the array of intersection results in this PickInfo object.
0359:             * @return an array of 1 IntersectionInfo object if flag is to set  CLOSEST_GEOM_INFO,
0360:             * or an array of <i>N</i> IntersectionInfo objects containing all intersections of 
0361:             * the picked node in sorted order if flag is to set ALL_GEOM_INFO, or null if neither 
0362:             * bit is set.
0363:             * @see Locale
0364:             * @see BranchGroup
0365:             */
0366:            public IntersectionInfo[] getIntersectionInfos() {
0367:                if (intersectionInfoListSorted == false) {
0368:                    intersectionInfoArr = new IntersectionInfo[intersectionInfoList
0369:                            .size()];
0370:                    intersectionInfoArr = (IntersectionInfo[]) intersectionInfoList
0371:                            .toArray(intersectionInfoArr);
0372:
0373:                    sortIntersectionInfoArray(intersectionInfoArr);
0374:                }
0375:
0376:                return intersectionInfoArr;
0377:            }
0378:
0379:            /**
0380:             * Search the path from nodeR up to Locale.
0381:             * Return the search path as ArrayList if found.
0382:             * Note that the locale will not insert into path.
0383:             */
0384:            static ArrayList initSceneGraphPath(NodeRetained nodeR) {
0385:                ArrayList path = new ArrayList(5);
0386:
0387:                do {
0388:                    if (nodeR.source.getCapability(Node.ENABLE_PICK_REPORTING)) {
0389:                        path.add(nodeR);
0390:                    }
0391:                    nodeR = nodeR.parent;
0392:                } while (nodeR != null); // reach Locale
0393:
0394:                return path;
0395:            }
0396:
0397:            static private Node[] createPath(NodeRetained srcNode,
0398:                    BranchGroupRetained bgRetained, GeometryAtom geomAtom,
0399:                    ArrayList initpath) {
0400:
0401:                ArrayList path = retrievePath(srcNode, bgRetained,
0402:                        geomAtom.source.key);
0403:                assert (path != null);
0404:
0405:                return mergePath(path, initpath);
0406:
0407:            }
0408:
0409:            /**
0410:             * Return true if bg is inside cachedBG or bg is null
0411:             */
0412:            static private boolean inside(BranchGroupRetained bgArr[],
0413:                    BranchGroupRetained bg) {
0414:
0415:                if ((bg == null) || (bgArr == null)) {
0416:                    return true;
0417:                }
0418:
0419:                for (int i = 0; i < bgArr.length; i++) {
0420:                    if (bgArr[i] == bg) {
0421:                        return true;
0422:                    }
0423:                }
0424:                return false;
0425:            }
0426:
0427:            /**
0428:             * search the full path from the bottom of the scene graph -
0429:             * startNode, up to the Locale if endNode is null.
0430:             * If endNode is not null, the path is found up to, but not
0431:             * including, endNode or return null if endNode not hit 
0432:             * during the search.
0433:             */
0434:            static private ArrayList retrievePath(NodeRetained startNode,
0435:                    NodeRetained endNode, HashKey key) {
0436:
0437:                ArrayList path = new ArrayList(5);
0438:                NodeRetained nodeR = startNode;
0439:
0440:                if (nodeR.inSharedGroup) {
0441:                    // getlastNodeId() will destroy this key
0442:                    key = new HashKey(key);
0443:                }
0444:
0445:                do {
0446:                    if (nodeR == endNode) { // we found it !
0447:                        return path;
0448:                    }
0449:
0450:                    if (nodeR.source.getCapability(Node.ENABLE_PICK_REPORTING)) {
0451:                        path.add(nodeR);
0452:                    }
0453:
0454:                    if (nodeR instanceof  SharedGroupRetained) {
0455:                        // retrieve the last node ID
0456:                        String nodeId = key.getLastNodeId();
0457:                        Vector parents = ((SharedGroupRetained) nodeR).parents;
0458:                        int sz = parents.size();
0459:                        NodeRetained prevNodeR = nodeR;
0460:                        for (int i = 0; i < sz; i++) {
0461:                            NodeRetained linkR = (NodeRetained) parents
0462:                                    .elementAt(i);
0463:                            if (linkR.nodeId.equals(nodeId)) {
0464:                                nodeR = linkR;
0465:                                // Need to add Link to the path report
0466:                                path.add(nodeR);
0467:                                // since !(endNode instanceof Link), we 
0468:                                // can skip the check (nodeR == endNode) and
0469:                                // proceed to parent of link below
0470:                                break;
0471:                            }
0472:                        }
0473:                        if (nodeR == prevNodeR) {
0474:                            // branch is already detach
0475:                            return null;
0476:                        }
0477:                    }
0478:                    nodeR = nodeR.parent;
0479:                } while (nodeR != null); // reach Locale
0480:
0481:                if (endNode == null) {
0482:                    // user call pickxxx(Locale locale, PickShape shape)
0483:                    return path;
0484:                }
0485:
0486:                // user call pickxxx(BranchGroup endNode, PickShape shape)
0487:                // if locale is reached and endNode not hit, this is not
0488:                // the path user want to select 
0489:                return null;
0490:            }
0491:
0492:            /**
0493:             * copy p1, (follow by) p2 into a new array, p2 can be null
0494:             * The path is then reverse before return.
0495:             */
0496:            static private Node[] mergePath(ArrayList p1, ArrayList p2) {
0497:                int s = p1.size();
0498:                int len;
0499:                int i;
0500:                int l;
0501:                if (p2 == null) {
0502:                    len = s;
0503:                } else {
0504:                    len = s + p2.size();
0505:                }
0506:
0507:                Node nodes[] = new Node[len];
0508:                l = len - 1;
0509:                for (i = 0; i < s; i++) {
0510:                    nodes[l - i] = (Node) ((NodeRetained) p1.get(i)).source;
0511:                }
0512:                for (int j = 0; i < len; i++, j++) {
0513:                    nodes[l - i] = (Node) ((NodeRetained) p2.get(j)).source;
0514:                }
0515:                return nodes;
0516:            }
0517:
0518:            /**
0519:             * Sort the GeometryAtoms distance from shape in ascending order
0520:             * geomAtoms.length must be >= 1
0521:             */
0522:            static void sortGeomAtoms(GeometryAtom geomAtoms[], PickShape shape) {
0523:
0524:                final double distance[] = new double[geomAtoms.length];
0525:                Point4d pickPos = new Point4d();
0526:
0527:                for (int i = 0; i < geomAtoms.length; i++) {
0528:                    shape.intersect(geomAtoms[i].source.vwcBounds, pickPos);
0529:                    distance[i] = pickPos.w;
0530:                }
0531:
0532:                class Sort {
0533:
0534:                    GeometryAtom atoms[];
0535:
0536:                    Sort(GeometryAtom[] atoms) {
0537:                        this .atoms = atoms;
0538:                    }
0539:
0540:                    void sorting() {
0541:                        if (atoms.length < 7) {
0542:                            insertSort();
0543:                        } else {
0544:                            quicksort(0, atoms.length - 1);
0545:                        }
0546:                    }
0547:
0548:                    // Insertion sort on smallest arrays
0549:                    final void insertSort() {
0550:                        for (int i = 0; i < atoms.length; i++) {
0551:                            for (int j = i; j > 0
0552:                                    && (distance[j - 1] > distance[j]); j--) {
0553:                                double t = distance[j];
0554:                                distance[j] = distance[j - 1];
0555:                                distance[j - 1] = t;
0556:                                GeometryAtom p = atoms[j];
0557:                                atoms[j] = atoms[j - 1];
0558:                                atoms[j - 1] = p;
0559:                            }
0560:                        }
0561:                    }
0562:
0563:                    final void quicksort(int l, int r) {
0564:                        int i = l;
0565:                        int j = r;
0566:                        double k = distance[(l + r) / 2];
0567:
0568:                        do {
0569:                            while (distance[i] < k)
0570:                                i++;
0571:                            while (k < distance[j])
0572:                                j--;
0573:                            if (i <= j) {
0574:                                double tmp = distance[i];
0575:                                distance[i] = distance[j];
0576:                                distance[j] = tmp;
0577:
0578:                                GeometryAtom p = atoms[i];
0579:                                atoms[i] = atoms[j];
0580:                                atoms[j] = p;
0581:                                i++;
0582:                                j--;
0583:                            }
0584:                        } while (i <= j);
0585:
0586:                        if (l < j)
0587:                            quicksort(l, j);
0588:                        if (l < r)
0589:                            quicksort(i, r);
0590:                    }
0591:                }
0592:
0593:                (new Sort(geomAtoms)).sorting();
0594:            }
0595:
0596:            /**
0597:             * return all PickInfo[] of the geomAtoms.
0598:             * If initpath is null, the path is search from 
0599:             * geomAtom Shape3D/Morph Node up to Locale
0600:             * (assume the same locale).
0601:             * Otherwise, the path is search up to node or 
0602:             * null is return if it is not hit.
0603:             */
0604:            static ArrayList getPickInfos(ArrayList initpath,
0605:                    BranchGroupRetained bgRetained, GeometryAtom geomAtoms[],
0606:                    Locale locale, int flags, int pickType) {
0607:
0608:                ArrayList pickInfoList = new ArrayList(5);
0609:                NodeRetained srcNode;
0610:                ArrayList text3dList = null;
0611:
0612:                if ((geomAtoms == null) || (geomAtoms.length == 0)) {
0613:                    return null;
0614:                }
0615:
0616:                for (int i = 0; i < geomAtoms.length; i++) {
0617:                    assert ((geomAtoms[i] != null) && (geomAtoms[i].source != null));
0618:
0619:                    PickInfo pickInfo = null;
0620:                    Shape3DRetained shape = geomAtoms[i].source;
0621:                    srcNode = shape.sourceNode;
0622:
0623:                    // Fix to Issue 274 : NPE With Simultaneous View and Content Side PickingBehaviors
0624:                    // This node isn't under the selected BG for pick operation.
0625:                    if (!inside(shape.branchGroupPath, bgRetained)) {
0626:                        continue;
0627:                    }
0628:
0629:                    if (srcNode == null) {
0630:                        // The node is just detach from branch so sourceNode = null
0631:                        continue;
0632:                    }
0633:
0634:                    // Special case, for Text3DRetained, it is possible
0635:                    // for different geomAtoms pointing to the same
0636:                    // source Text3DRetained. So we need to combine
0637:                    // those cases and report only once.
0638:                    if (srcNode instanceof  Shape3DRetained) {
0639:                        Shape3DRetained s3dR = (Shape3DRetained) srcNode;
0640:                        GeometryRetained geomR = null;
0641:                        for (int cnt = 0; cnt < s3dR.geometryList.size(); cnt++) {
0642:                            geomR = (GeometryRetained) s3dR.geometryList
0643:                                    .get(cnt);
0644:                            if (geomR != null)
0645:                                break;
0646:                        }
0647:
0648:                        if (geomR == null)
0649:                            continue;
0650:
0651:                        if (geomR instanceof  Text3DRetained) {
0652:                            // assume this case is not frequent, we allocate
0653:                            // ArrayList only when necessary and we use ArrayList
0654:                            // instead of HashMap since the case of when large
0655:                            // number of distingish Text3DRetained node hit is
0656:                            // rare.
0657:                            if (text3dList == null) {
0658:                                text3dList = new ArrayList(3);
0659:                            } else {
0660:                                int size = text3dList.size();
0661:                                boolean found = false;
0662:                                for (int j = 0; j < size; j++) {
0663:                                    if (text3dList.get(j) == srcNode) {
0664:                                        found = true;
0665:                                        break;
0666:                                    }
0667:                                }
0668:                                if (found) {
0669:                                    continue; // try next geomAtom
0670:                                }
0671:                            }
0672:                            text3dList.add(srcNode);
0673:                        }
0674:                    }
0675:
0676:                    // If srcNode is instance of compile retained, then loop thru
0677:                    // the entire source list and add it to the scene graph path
0678:                    if (srcNode instanceof  Shape3DCompileRetained) {
0679:
0680:                        Shape3DCompileRetained s3dCR = (Shape3DCompileRetained) srcNode;
0681:
0682:                        Node[] mpath = null;
0683:                        boolean first = true;
0684:
0685:                        for (int n = 0; n < s3dCR.srcList.length; n++) {
0686:
0687:                            pickInfo = null;
0688:
0689:                            // PickInfo.SCENEGRAPHPATH - request for computed SceneGraphPath.
0690:                            if ((flags & SCENEGRAPHPATH) != 0) {
0691:
0692:                                if (first) {
0693:                                    mpath = createPath(srcNode, bgRetained,
0694:                                            geomAtoms[i], initpath);
0695:                                    first = false;
0696:                                }
0697:
0698:                                if (mpath != null) {
0699:                                    SceneGraphPath sgpath = new SceneGraphPath(
0700:                                            locale, mpath,
0701:                                            (Node) s3dCR.srcList[n]);
0702:                                    sgpath.setTransform(shape
0703:                                            .getCurrentLocalToVworld(0));
0704:                                    if (pickInfo == null)
0705:                                        pickInfo = new PickInfo();
0706:                                    pickInfo.setSceneGraphPath(sgpath);
0707:                                }
0708:                            }
0709:
0710:                            // PickInfo.NODE - request for computed intersected Node.
0711:                            if ((flags & NODE) != 0) {
0712:                                if (pickInfo == null)
0713:                                    pickInfo = new PickInfo();
0714:                                pickInfo.setNode((Node) s3dCR.srcList[n]);
0715:                            }
0716:
0717:                            // PickInfo.LOCAL_TO_VWORLD
0718:                            //    - request for computed local to virtual world transform.
0719:                            if ((flags & LOCAL_TO_VWORLD) != 0) {
0720:                                Transform3D l2vw = geomAtoms[i].source
0721:                                        .getCurrentLocalToVworld();
0722:                                if (pickInfo == null)
0723:                                    pickInfo = new PickInfo();
0724:                                pickInfo
0725:                                        .setLocalToVWorld(new Transform3D(l2vw));
0726:                            }
0727:
0728:                            // NOTE : Piggy bag for geometry computation by caller.
0729:                            if (((flags & CLOSEST_DISTANCE) != 0)
0730:                                    || ((flags & CLOSEST_GEOM_INFO) != 0)
0731:                                    || ((flags & CLOSEST_INTERSECTION_POINT) != 0)
0732:                                    || ((flags & ALL_GEOM_INFO) != 0)) {
0733:                                if (pickInfo == null)
0734:                                    pickInfo = new PickInfo();
0735:                                pickInfo.setNodeRef((Node) s3dCR.srcList[n]);
0736:                                Transform3D l2vw = geomAtoms[i].source
0737:                                        .getCurrentLocalToVworld();
0738:                                pickInfo.setLocalToVWorldRef(l2vw);
0739:                            }
0740:
0741:                            if (pickInfo != null)
0742:                                pickInfoList.add(pickInfo);
0743:                            if (pickType == PICK_ANY) {
0744:                                return pickInfoList;
0745:                            }
0746:                        }
0747:                    } else {
0748:                        Node[] mpath = null;
0749:
0750:                        // PickInfo.SCENEGRAPHPATH - request for computed SceneGraphPath.
0751:                        if ((flags & SCENEGRAPHPATH) != 0) {
0752:
0753:                            mpath = createPath(srcNode, bgRetained,
0754:                                    geomAtoms[i], initpath);
0755:
0756:                            if (mpath != null) {
0757:                                SceneGraphPath sgpath = new SceneGraphPath(
0758:                                        locale, mpath, (Node) srcNode.source);
0759:                                sgpath.setTransform(shape
0760:                                        .getCurrentLocalToVworld(0));
0761:                                if (pickInfo == null)
0762:                                    pickInfo = new PickInfo();
0763:                                pickInfo.setSceneGraphPath(sgpath);
0764:                            }
0765:                        }
0766:
0767:                        // PickInfo.NODE - request for computed intersected Node.
0768:                        if ((flags & NODE) != 0) {
0769:                            if (pickInfo == null)
0770:                                pickInfo = new PickInfo();
0771:                            pickInfo.setNode((Node) srcNode.source);
0772:                        }
0773:
0774:                        // PickInfo.LOCAL_TO_VWORLD
0775:                        //    - request for computed local to virtual world transform.
0776:                        if ((flags & LOCAL_TO_VWORLD) != 0) {
0777:                            Transform3D l2vw = geomAtoms[i].source
0778:                                    .getCurrentLocalToVworld();
0779:                            if (pickInfo == null)
0780:                                pickInfo = new PickInfo();
0781:                            pickInfo.setLocalToVWorld(new Transform3D(l2vw));
0782:                        }
0783:
0784:                        // NOTE : Piggy bag for geometry computation by caller.
0785:                        if (((flags & CLOSEST_DISTANCE) != 0)
0786:                                || ((flags & CLOSEST_GEOM_INFO) != 0)
0787:                                || ((flags & CLOSEST_INTERSECTION_POINT) != 0)
0788:                                || ((flags & ALL_GEOM_INFO) != 0)) {
0789:                            if (pickInfo == null)
0790:                                pickInfo = new PickInfo();
0791:                            pickInfo.setNodeRef((Node) srcNode.source);
0792:                            Transform3D l2vw = geomAtoms[i].source
0793:                                    .getCurrentLocalToVworld();
0794:                            pickInfo.setLocalToVWorldRef(l2vw);
0795:                        }
0796:
0797:                        if (pickInfo != null)
0798:                            pickInfoList.add(pickInfo);
0799:                        if (pickType == PICK_ANY) {
0800:                            return pickInfoList;
0801:                        }
0802:                    }
0803:                }
0804:
0805:                return pickInfoList;
0806:            }
0807:
0808:            static PickInfo[] pick(Object node, GeometryAtom[] geomAtoms,
0809:                    int mode, int flags, PickShape pickShape, int pickType) {
0810:
0811:                int pickInfoListSize;
0812:                PickInfo[] pickInfoArr = null;
0813:                Locale locale = null;
0814:                BranchGroupRetained bgRetained = null;
0815:                ArrayList initPath = null;
0816:                ArrayList pickInfoList = null;
0817:
0818:                if (node instanceof  Locale) {
0819:                    locale = (Locale) node;
0820:                } else if (node instanceof  BranchGroupRetained) {
0821:                    bgRetained = (BranchGroupRetained) node;
0822:                    locale = bgRetained.locale;
0823:                }
0824:                synchronized (locale.universe.sceneGraphLock) {
0825:                    if (bgRetained != null) {
0826:                        initPath = initSceneGraphPath(bgRetained);
0827:                    }
0828:                    pickInfoList = getPickInfos(initPath, bgRetained,
0829:                            geomAtoms, locale, flags, pickType);
0830:                }
0831:
0832:                // We're done with PICK_BOUNDS case, but there is still more work for PICK_GEOMETRY case.
0833:                if ((mode == PICK_GEOMETRY) && (pickInfoList != null)
0834:                        && ((pickInfoListSize = pickInfoList.size()) > 0)) {
0835:
0836:                    //System.err.println("PickInfo.pick() - In geometry case : pickInfoList.size() is " + pickInfoListSize);
0837:                    PickInfo pickInfo = null;
0838:                    Node pickNode = null;
0839:
0840:                    // Order is impt. Need to do in reverse order.    
0841:                    for (int i = pickInfoListSize - 1; i >= 0; i--) {
0842:                        pickInfo = (PickInfo) pickInfoList.get(i);
0843:
0844:                        pickNode = pickInfo.getNode();
0845:                        if (pickNode == null) {
0846:                            // Use the piggy reference from getPickInfos()
0847:                            pickNode = pickInfo.getNodeRef();
0848:                        }
0849:
0850:                        if (pickNode instanceof  Shape3D) {
0851:
0852:                            /*
0853:                             * @exception CapabilityNotSetException if the mode is
0854:                             * PICK_GEOMETRY and the Geometry.ALLOW_INTERSECT capability bit
0855:                             * is not set in any Geometry objects referred to by any shape
0856:                             * node whose bounds intersects the PickShape.
0857:                             *
0858:                             * @exception CapabilityNotSetException if flags contains any of
0859:                             * CLOSEST_INTERSECTION_POINT, CLOSEST_DISTANCE, CLOSEST_GEOM_INFO
0860:                             * or ALL_GEOM_INFO, and the capability bits that control reading of
0861:                             * coordinate data are not set in any GeometryArray object referred
0862:                             * to by any shape node that intersects the PickShape.
0863:                             * The capability bits that must be set to avoid this exception are 
0864:                             * as follows :
0865:                             * 
0866:                             * By-copy geometry : GeometryArray.ALLOW_COORDINATE_READ
0867:                             * By-reference geometry : GeometryArray.ALLOW_REF_DATA_READ
0868:                             * Indexed geometry : IndexedGeometryArray.ALLOW_COORDINATE_INDEX_READ
0869:                             * (in addition to one of the above)
0870:                             *     
0871:                             */
0872:
0873:                            if (!pickNode
0874:                                    .getCapability(Shape3D.ALLOW_GEOMETRY_READ)) {
0875:                                throw new CapabilityNotSetException(J3dI18N
0876:                                        .getString("PickInfo0"));
0877:                            }
0878:
0879:                            for (int j = 0; j < ((Shape3D) pickNode)
0880:                                    .numGeometries(); j++) {
0881:                                Geometry geo = ((Shape3D) pickNode)
0882:                                        .getGeometry(j);
0883:
0884:                                if (geo == null) {
0885:                                    continue;
0886:                                }
0887:
0888:                                if (!geo
0889:                                        .getCapability(Geometry.ALLOW_INTERSECT)) {
0890:                                    throw new CapabilityNotSetException(J3dI18N
0891:                                            .getString("PickInfo1"));
0892:                                }
0893:
0894:                                if (geo instanceof  GeometryArray) {
0895:                                    if (!geo
0896:                                            .getCapability(GeometryArray.ALLOW_COORDINATE_READ))
0897:                                        throw new CapabilityNotSetException(
0898:                                                J3dI18N.getString("PickInfo2"));
0899:                                    if (!geo
0900:                                            .getCapability(GeometryArray.ALLOW_COUNT_READ))
0901:                                        throw new CapabilityNotSetException(
0902:                                                J3dI18N.getString("PickInfo3"));
0903:                                    if (!geo
0904:                                            .getCapability(GeometryArray.ALLOW_FORMAT_READ))
0905:                                        throw new CapabilityNotSetException(
0906:                                                J3dI18N.getString("PickInfo4"));
0907:                                    if (geo instanceof  IndexedGeometryArray) {
0908:                                        if (!geo
0909:                                                .getCapability(IndexedGeometryArray.ALLOW_COORDINATE_INDEX_READ))
0910:                                            throw new CapabilityNotSetException(
0911:                                                    J3dI18N
0912:                                                            .getString("PickInfo5"));
0913:                                    }
0914:                                } else if (geo instanceof  CompressedGeometry) {
0915:                                    if (!geo
0916:                                            .getCapability(CompressedGeometry.ALLOW_GEOMETRY_READ))
0917:                                        throw new CapabilityNotSetException(
0918:                                                J3dI18N.getString("PickInfo0"));
0919:                                }
0920:                            }
0921:
0922:                            if (((Shape3DRetained) (pickNode.retained))
0923:                                    .intersect(pickInfo, pickShape, flags) == false) {
0924:                                // System.err.println("  ---- geom " + i + " not intersected");
0925:
0926:                                pickInfoList.remove(i);
0927:
0928:                            } else if (pickType == PICK_ANY) {
0929:                                pickInfoArr = new PickInfo[1];
0930:                                pickInfoArr[0] = pickInfo;
0931:                                return pickInfoArr;
0932:                            }
0933:                        } else if (pickNode instanceof  Morph) {
0934:
0935:                            /*
0936:                             * @exception CapabilityNotSetException if the mode is
0937:                             * PICK_GEOMETRY and the Geometry.ALLOW_INTERSECT capability bit
0938:                             * is not set in any Geometry objects referred to by any shape
0939:                             * node whose bounds intersects the PickShape.
0940:                             *
0941:                             * @exception CapabilityNotSetException if flags contains any of
0942:                             * CLOSEST_INTERSECTION_POINT, CLOSEST_DISTANCE, CLOSEST_GEOM_INFO
0943:                             * or ALL_GEOM_INFO, and the capability bits that control reading of
0944:                             * coordinate data are not set in any GeometryArray object referred
0945:                             * to by any shape node that intersects the PickShape.
0946:                             * The capability bits that must be set to avoid this exception are 
0947:                             * as follows :
0948:                             * 
0949:                             * By-copy geometry : GeometryArray.ALLOW_COORDINATE_READ
0950:                             * By-reference geometry : GeometryArray.ALLOW_REF_DATA_READ
0951:                             * Indexed geometry : IndexedGeometryArray.ALLOW_COORDINATE_INDEX_READ
0952:                             * (in addition to one of the above)
0953:                             *     
0954:                             */
0955:
0956:                            if (!pickNode
0957:                                    .getCapability(Morph.ALLOW_GEOMETRY_ARRAY_READ)) {
0958:                                throw new CapabilityNotSetException(J3dI18N
0959:                                        .getString("PickInfo6"));
0960:                            }
0961:
0962:                            int numGeo = ((MorphRetained) (pickNode.retained))
0963:                                    .getNumGeometryArrays();
0964:                            for (int j = 0; j < numGeo; j++) {
0965:                                GeometryArray geo = ((Morph) pickNode)
0966:                                        .getGeometryArray(j);
0967:
0968:                                if (geo == null) {
0969:                                    continue;
0970:                                }
0971:
0972:                                if (!geo
0973:                                        .getCapability(Geometry.ALLOW_INTERSECT)) {
0974:                                    throw new CapabilityNotSetException(J3dI18N
0975:                                            .getString("PickInfo1"));
0976:                                }
0977:
0978:                                if (!geo
0979:                                        .getCapability(GeometryArray.ALLOW_COORDINATE_READ))
0980:                                    throw new CapabilityNotSetException(J3dI18N
0981:                                            .getString("PickInfo2"));
0982:                                if (!geo
0983:                                        .getCapability(GeometryArray.ALLOW_COUNT_READ))
0984:                                    throw new CapabilityNotSetException(J3dI18N
0985:                                            .getString("PickInfo3"));
0986:                                if (!geo
0987:                                        .getCapability(GeometryArray.ALLOW_FORMAT_READ))
0988:                                    throw new CapabilityNotSetException(J3dI18N
0989:                                            .getString("PickInfo4"));
0990:
0991:                                if (geo instanceof  IndexedGeometryArray) {
0992:                                    if (!geo
0993:                                            .getCapability(IndexedGeometryArray.ALLOW_COORDINATE_INDEX_READ))
0994:                                        throw new CapabilityNotSetException(
0995:                                                J3dI18N.getString("PickInfo5"));
0996:                                }
0997:                            }
0998:
0999:                            if (((MorphRetained) (pickNode.retained))
1000:                                    .intersect(pickInfo, pickShape, flags) == false) {
1001:                                pickInfoList.remove(i);
1002:                            } else if (pickType == PICK_ANY) {
1003:                                pickInfoArr = new PickInfo[1];
1004:                                pickInfoArr[0] = pickInfo;
1005:                                return pickInfoArr;
1006:                            }
1007:                        }
1008:                    }
1009:                }
1010:
1011:                // System.err.println("PickInfo : pickInfoList " + pickInfoList);
1012:
1013:                if ((pickInfoList != null) && (pickInfoList.size() > 0)) {
1014:                    // System.err.println("   ---  : pickInfoList.size() " + pickInfoList.size());
1015:                    // System.err.println("   ---  : pickInfoList's sgp " + 
1016:                    // ((PickInfo)(pickInfoList.get(0))).getSceneGraphPath());
1017:                    pickInfoArr = new PickInfo[pickInfoList.size()];
1018:                    return (PickInfo[]) pickInfoList.toArray(pickInfoArr);
1019:                }
1020:
1021:                return null;
1022:
1023:            }
1024:
1025:            /**
1026:             * The IntersectionInfo object holds extra information about an intersection 
1027:             * of a PickShape with a Node as part of a PickInfo. Information such as 
1028:             * the intersected geometry, the intersected point, and the vertex indices 
1029:             * can be inquired.  
1030:             * The local coordinates, normal, color and texture coordiantes of at the
1031:             * intersection can be computed, if they are present and readable, using the 
1032:             * interpolation weights and vertex indices.
1033:             * <p>
1034:             * If the Shape3D being picked has multiple geometry arrays, the possible arrays
1035:             * of IntersectionInfo are stored in the PickInfo and referred to by a geometry 
1036:             * index. If the picked geometry is of type, Text3D or CompressGeometry, 
1037:             * getVertexIndices is invalid. If the picked Node is an Morph 
1038:             * object, the geometry used in pick computation is alway at index 0.
1039:             * <p>
1040:             *
1041:             * @since Java 3D 1.4
1042:             */
1043:
1044:            public class IntersectionInfo extends Object {
1045:
1046:                /* The index to the intersected geometry in the pickable node */
1047:                private int geomIndex;
1048:
1049:                /* The reference to the intersected geometry in the pickable object */
1050:                private Geometry geom;
1051:
1052:                /* The intersection point */
1053:                private Point3d intersectionPoint;
1054:
1055:                /* Distance between start point of pickShape and intersection point */
1056:                private double distance;
1057:
1058:                /* The vertex indices of the intersected primitive in the geometry */
1059:                private int[] vertexIndices;
1060:
1061:                /* The interpolation weights for each of the verticies of the primitive */
1062:                // private float[] weights;  Not supported. Should be done in util. package  
1063:                /** IntersectionInfo Constructor */
1064:                IntersectionInfo() {
1065:
1066:                }
1067:
1068:                void setGeometryIndex(int geomIndex) {
1069:                    this .geomIndex = geomIndex;
1070:                }
1071:
1072:                void setGeometry(Geometry geom) {
1073:                    this .geom = geom;
1074:                }
1075:
1076:                void setIntersectionPoint(Point3d intersectionPoint) {
1077:                    assert (intersectionPoint != null);
1078:                    this .intersectionPoint = new Point3d(intersectionPoint);
1079:                }
1080:
1081:                void setDistance(double distance) {
1082:                    this .distance = distance;
1083:                }
1084:
1085:                void setVertexIndices(int[] vertexIndices) {
1086:                    assert (vertexIndices != null);
1087:                    this .vertexIndices = new int[vertexIndices.length];
1088:                    for (int i = 0; i < vertexIndices.length; i++) {
1089:                        this .vertexIndices[i] = vertexIndices[i];
1090:                    }
1091:                }
1092:
1093:                /**
1094:                 * Retrieves the index to the intersected geometry in the picked node, either a Shape3D or Morph.
1095:                 * @return the index of the intersected geometry in the pickable node.
1096:                 */
1097:                public int getGeometryIndex() {
1098:                    return geomIndex;
1099:                }
1100:
1101:                /**
1102:                 * Retrieves the reference to the intersected geometry in the picked object, either a Shape3D or Morph.
1103:                 * @return the intersected geometry in the pickable node.
1104:                 */
1105:                public Geometry getGeometry() {
1106:                    return geom;
1107:                }
1108:
1109:                /**
1110:                 * Retrieves the reference to the intersection point in the pickable node.
1111:                 * @return the intersected point in the pickable node.
1112:                 */
1113:                public Point3d getIntersectionPoint() {
1114:                    return intersectionPoint;
1115:                }
1116:
1117:                /**
1118:                 * Retrieves the distance between the start point of the pickShape and the 
1119:                 * intersection point.
1120:                 * @return distance between the start point of the pickShape and the 
1121:                 * intersection point.
1122:                 */
1123:                public double getDistance() {
1124:                    return distance;
1125:                }
1126:
1127:                /**
1128:                 * Retrieves the vertex indices of the intersected primitive in the geometry.
1129:                 * @return the vertex indices of the intersected primitive.
1130:                 */
1131:                public int[] getVertexIndices() {
1132:                    return vertexIndices;
1133:                }
1134:
1135:            }
1136:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.