Source Code Cross Referenced for Shape3DRetained.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: Shape3DRetained.java,v $
0003:         *
0004:         * Copyright 1996-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:30 $
0029:         * $State: Exp $
0030:         */
0031:
0032:        package javax.media.j3d;
0033:
0034:        import javax.vecmath.*;
0035:        import java.util.ArrayList;
0036:        import java.util.Enumeration;
0037:        import java.util.Vector;
0038:
0039:        /**
0040:         * A shape leaf node consisting of geometry and appearance properties.
0041:         */
0042:
0043:        class Shape3DRetained extends LeafRetained {
0044:
0045:            static final int GEOMETRY_CHANGED = 0x00001;
0046:            static final int APPEARANCE_CHANGED = 0x00002;
0047:            static final int COLLISION_CHANGED = 0x00004;
0048:            static final int BOUNDS_CHANGED = 0x00008;
0049:            static final int APPEARANCEOVERRIDE_CHANGED = 0x00010;
0050:            static final int LAST_DEFINED_BIT = 0x00010;
0051:
0052:            // Target threads to be notified when light changes
0053:            static final int targetThreads = J3dThread.UPDATE_RENDERING_ENVIRONMENT
0054:                    | J3dThread.UPDATE_RENDER;
0055:
0056:            /**
0057:             * The appearance component of the shape node.
0058:             */
0059:            AppearanceRetained appearance = null;
0060:
0061:            /**
0062:             * The arraylist of geometry component of the shape node.
0063:             */
0064:            ArrayList geometryList = null;
0065:
0066:            /**
0067:             * A 2D storage of all geometry atoms associated with this shape node.  
0068:             * There may be more than one geometry for a Shape3D node. 
0069:             * Do not change the following private variables to public, its access need to synchronize
0070:             * via mirrorShape3DLock.
0071:             */
0072:
0073:            // geomAtomArr should always be a 1 element array, unless S3D contains multiple Text3Ds.
0074:            private GeometryAtom geomAtom = null;
0075:
0076:            /**
0077:             * To sychronize access of the mirrorShape3D's geomAtomArray*. 
0078:             * A multiple read single write Lock to sychronize access into mirrorShape3D.
0079:             * To prevent deadlock a call to read/write lock must end with a read/write unlock
0080:             * respectively.
0081:             */
0082:            private MRSWLock mirrorShape3DLock = null;
0083:
0084:            /**
0085:             * The mirror Shape3DRetained nodes for this object.  There is one
0086:             * mirror for each instance of this Shape3D node.  If it is not in
0087:             * a SharedGroup, only index 0 is valid.
0088:             * Do not change the following private variables to public, its access need to synchronize
0089:             * via mirrorShape3DLock.
0090:             */
0091:            ArrayList mirrorShape3D = new ArrayList(1);
0092:
0093:            /**
0094:             * This field is used for mirror Shape3D nodes accessing their
0095:             * original nodes.  It is a NodeRetained because the original 
0096:             * node may be a Shape3DRetained or a MorphRetained node.
0097:             */
0098:            NodeRetained sourceNode = null;
0099:
0100:            /**
0101:             * The hashkey for this Shape3DRetained mirror object
0102:             */
0103:            HashKey key = null;
0104:
0105:            // This is true when this geometry is referenced in an IMM mode context
0106:            boolean inImmCtx = false;
0107:
0108:            // A bitmask to indicate when something has changed
0109:            int isDirty = 0xffff;
0110:
0111:            // The list of lights that are scoped to this node
0112:            LightRetained[] lights = null;
0113:
0114:            // The number of lights in the above array, may be less than lights.length
0115:            int numlights = 0;
0116:
0117:            // The list of fogs that are scoped to this node
0118:            FogRetained[] fogs = null;
0119:
0120:            // The number of fogs in the above array, may be less than fogs.length
0121:            int numfogs = 0;
0122:
0123:            // The list of modelClips that are scoped to this node
0124:            ModelClipRetained[] modelClips = null;
0125:
0126:            // The number of modelClips in the above array, may be less than modelClips.length
0127:            int numModelClips = 0;
0128:
0129:            // The list of alt app that are scoped to this node
0130:            AlternateAppearanceRetained[] altApps = null;
0131:
0132:            //The number of alt app in the above array, may be less than alt app.length
0133:            int numAltApps = 0;
0134:
0135:            /**
0136:             * Reference to the  BranchGroup path of this mirror shape
0137:             * This is used for picking and GeometryStructure only.
0138:             */
0139:            BranchGroupRetained branchGroupPath[];
0140:
0141:            // cache value for picking in mirror shape. 
0142:            // True if all the node of the path from this to root are all pickable
0143:            boolean isPickable = true;
0144:
0145:            // cache value for collidable in mirror shape. 
0146:            // True if all the node of the path from this to root are all collidable
0147:            boolean isCollidable = true;
0148:
0149:            // closest switch parent
0150:            SwitchRetained closestSwitchParent = null;
0151:
0152:            // the child index from the closest switch parent
0153:            int closestSwitchIndex = -1;
0154:
0155:            // Is this S3D visible ? The default is true.  
0156:            boolean visible = true;
0157:
0158:            // Whether the normal appearance is overrided by the alternate app
0159:            boolean appearanceOverrideEnable = false;
0160:
0161:            // AlternateAppearance retained that is applicable to this
0162:            // mirror shape when the override flag is true
0163:            AppearanceRetained otherAppearance = null;
0164:
0165:            // geometry Bounds in local coordinate
0166:            Bounds bounds = null;
0167:
0168:            // geometry Bounds in virtual world coordinate
0169:            BoundingBox vwcBounds = null;
0170:
0171:            // collision Bounds in local coordinate
0172:            Bounds collisionBound = null;
0173:
0174:            // collision Bounds in virtual world coordinate
0175:            Bounds collisionVwcBound = null;
0176:
0177:            // a path of OrderedGroup, childrenId pairs which leads to this node
0178:            OrderedPath orderedPath = null;
0179:
0180:            // List of views that a mirror object is scoped to
0181:            ArrayList viewList = null;
0182:
0183:            int changedFrequent = 0;
0184:
0185:            Shape3DRetained() {
0186:                super ();
0187:                this .nodeType = NodeRetained.SHAPE;
0188:                numlights = 0;
0189:                numfogs = 0;
0190:                numModelClips = 0;
0191:                numAltApps = 0;
0192:                localBounds = new BoundingBox((BoundingBox) null);
0193:
0194:                mirrorShape3DLock = new MRSWLock();
0195:                geometryList = new ArrayList(1);
0196:                geometryList.add(null);
0197:            }
0198:
0199:            /**
0200:             * Sets the collision bounds of a node.
0201:             * @param bounds the bounding object for the node
0202:             */
0203:            void setCollisionBounds(Bounds bounds) {
0204:                if (bounds == null) {
0205:                    this .collisionBound = null;
0206:                } else {
0207:                    this .collisionBound = (Bounds) bounds.clone();
0208:                }
0209:
0210:                if (source.isLive()) {
0211:                    // Notify Geometry Structure to check for collision
0212:                    J3dMessage message = new J3dMessage();
0213:                    message.type = J3dMessage.COLLISION_BOUND_CHANGED;
0214:                    message.threads = J3dThread.UPDATE_TRANSFORM;
0215:                    message.universe = universe;
0216:                    message.args[0] = getGeomAtomsArray(mirrorShape3D);
0217:                    // no need to clone collisionBound
0218:                    message.args[1] = collisionBound;
0219:                    VirtualUniverse.mc.processMessage(message);
0220:                }
0221:            }
0222:
0223:            Bounds getLocalBounds(Bounds bounds) {
0224:                if (localBounds != null) {
0225:                    localBounds.set(bounds);
0226:                } else {
0227:                    localBounds = new BoundingBox(bounds);
0228:                }
0229:                return localBounds;
0230:            }
0231:
0232:            /**
0233:             * Sets the geometric bounds of a node.
0234:             * @param bounds the bounding object for the node
0235:             */
0236:            void setBounds(Bounds bounds) {
0237:                super .setBounds(bounds);
0238:
0239:                if (source.isLive() && !boundsAutoCompute) {
0240:                    J3dMessage message = new J3dMessage();
0241:                    message.type = J3dMessage.REGION_BOUND_CHANGED;
0242:                    message.threads = J3dThread.UPDATE_TRANSFORM
0243:                            | J3dThread.UPDATE_GEOMETRY
0244:                            | J3dThread.UPDATE_RENDER;
0245:
0246:                    message.universe = universe;
0247:                    message.args[0] = getGeomAtomsArray(mirrorShape3D);
0248:                    // no need to clone localBounds
0249:                    message.args[1] = localBounds;
0250:                    VirtualUniverse.mc.processMessage(message);
0251:                }
0252:            }
0253:
0254:            /**
0255:             * Gets the collision bounds of a node.
0256:             * @return the node's bounding object
0257:             */
0258:            Bounds getCollisionBounds(int id) {
0259:                return (collisionBound == null ? null : (Bounds) collisionBound
0260:                        .clone());
0261:            }
0262:
0263:            /**
0264:             * Appends the specified geometry component to this Shape3D
0265:             * node's list of geometry components.
0266:             * If there are existing geometry components in the list, the new
0267:             * geometry component must be of the same equivalence class
0268:             * (point, line, polygon, CompressedGeometry, Raster, Text3D) as
0269:             * the others.
0270:             * @param geometry the geometry component to be appended.
0271:             * @exception IllegalArgumentException if the new geometry
0272:             * component is not of of the same equivalence class as the
0273:             * existing geometry components.
0274:             *
0275:             * @since Java 3D 1.2
0276:             */
0277:            void addGeometry(Geometry geometry) {
0278:                int i;
0279:                Shape3DRetained s;
0280:                GeometryRetained newGeom = null;
0281:
0282:                checkEquivalenceClass(geometry, -1);
0283:
0284:                if (((Shape3D) this .source).isLive()) {
0285:                    if (geometry != null) {
0286:
0287:                        newGeom = ((GeometryRetained) geometry.retained);
0288:                        newGeom.setLive(inBackgroundGroup, refCount);
0289:
0290:                        geometryList.add(newGeom);
0291:
0292:                    } else {
0293:                        geometryList.add(null);
0294:                        newGeom = null;
0295:                    }
0296:                    sendDataChangedMessage(newGeom);
0297:
0298:                } else {
0299:                    if (geometry != null) {
0300:                        geometryList.add((GeometryRetained) geometry.retained);
0301:                    } else {
0302:                        geometryList.add(null);
0303:                    }
0304:                }
0305:                dirtyBoundsCache();
0306:            }
0307:
0308:            /**
0309:             * Replaces the geometry component at the specified index in this
0310:             * Shape3D node's list of geometry components with the specified
0311:             * geometry component.
0312:             * If there are existing geometry components in the list (besides
0313:             * the one being replaced), the new geometry component must be of
0314:             * the same equivalence class (point, line, polygon, CompressedGeometry,
0315:             * Raster, Text3D) as the others.
0316:             * @param geometry the geometry component to be stored at the
0317:             * specified index.
0318:             * @param index the index of the geometry component to be replaced.
0319:             * @exception IllegalArgumentException if the new geometry
0320:             * component is not of of the same equivalence class as the
0321:             * existing geometry components.
0322:             *
0323:             * @since Java 3D 1.2
0324:             */
0325:            void setGeometry(Geometry geometry, int index) {
0326:                int i;
0327:                Shape3DRetained mShape;
0328:                GeometryRetained newGeom = null;
0329:                GeometryRetained oldGeom = null;
0330:
0331:                checkEquivalenceClass(geometry, index);
0332:
0333:                if (((Shape3D) this .source).isLive()) {
0334:
0335:                    oldGeom = (GeometryRetained) (geometryList.get(index));
0336:                    if (oldGeom != null) {
0337:                        oldGeom.clearLive(refCount);
0338:                        for (i = 0; i < mirrorShape3D.size(); i++) {
0339:                            mShape = (Shape3DRetained) mirrorShape3D.get(i);
0340:                            oldGeom.removeUser(mShape);
0341:                        }
0342:                        oldGeom.decRefCnt();
0343:                    }
0344:
0345:                    if (geometry != null) {
0346:                        newGeom = (GeometryRetained) geometry.retained;
0347:                        newGeom.incRefCnt();
0348:                        newGeom.setLive(inBackgroundGroup, refCount);
0349:                        geometryList.set(index, newGeom);
0350:                        sendDataChangedMessage(newGeom);
0351:                    } else {
0352:                        geometryList.set(index, null);
0353:                        sendDataChangedMessage(null);
0354:                    }
0355:
0356:                } else {
0357:
0358:                    oldGeom = (GeometryRetained) (geometryList.get(index));
0359:                    if (oldGeom != null) {
0360:                        oldGeom.decRefCnt();
0361:                    }
0362:                    if (geometry != null) {
0363:                        geometryList.set(index,
0364:                                (GeometryRetained) geometry.retained);
0365:                        ((GeometryRetained) geometry.retained).incRefCnt();
0366:                    } else {
0367:                        geometryList.set(index, null);
0368:                    }
0369:                }
0370:                dirtyBoundsCache();
0371:            }
0372:
0373:            /**
0374:             * Inserts the specified geometry component into this Shape3D
0375:             * node's list of geometry components at the specified index.
0376:             * If there are existing geometry components in the list, the new
0377:             * geometry component must be of the same equivalence class
0378:             * (point, line, polygon, CompressedGeometry, Raster, Text3D) as
0379:             * the others.
0380:             * @param geometry the geometry component to be inserted at the
0381:             * specified index.
0382:             * @param index the index at which the geometry component is inserted.
0383:             *
0384:             * @since Java 3D 1.2
0385:             */
0386:            void insertGeometry(Geometry geometry, int index) {
0387:                int i;
0388:                Shape3DRetained mShape;
0389:                GeometryRetained newGeom = null;
0390:                GeometryRetained oldGeom = null;
0391:
0392:                checkEquivalenceClass(geometry, -1);
0393:
0394:                if (((Shape3D) this .source).isLive()) {
0395:
0396:                    if (geometry != null) {
0397:                        // Note : The order of the statements in important. Want ArrayList class to do index bounds
0398:                        // check before creating internal object.
0399:                        newGeom = (GeometryRetained) geometry.retained;
0400:                        newGeom.incRefCnt();
0401:                        geometryList.add(index, newGeom);
0402:                        newGeom.setLive(inBackgroundGroup, refCount);
0403:                        sendDataChangedMessage(newGeom);
0404:                    } else {
0405:                        geometryList.add(index, null);
0406:                        sendDataChangedMessage(null);
0407:                    }
0408:
0409:                } else {
0410:
0411:                    if (geometry != null) {
0412:                        geometryList.add(index,
0413:                                (GeometryRetained) geometry.retained);
0414:                        ((GeometryRetained) geometry.retained).incRefCnt();
0415:                    } else {
0416:                        geometryList.add(index, null);
0417:                    }
0418:                }
0419:                dirtyBoundsCache();
0420:            }
0421:
0422:            /**
0423:             * Removes the geometry component at the specified index from
0424:             * this Shape3D node's list of geometry components.
0425:             * @param index the index of the geometry component to be removed.
0426:             *
0427:             * @since Java 3D 1.2
0428:             */
0429:            void removeGeometry(int index) {
0430:                int i;
0431:                Shape3DRetained mShape;
0432:                GeometryRetained oldGeom = null;
0433:
0434:                if (((Shape3D) this .source).isLive()) {
0435:
0436:                    oldGeom = (GeometryRetained) (geometryList.get(index));
0437:                    if (oldGeom != null) {
0438:                        oldGeom.clearLive(refCount);
0439:                        oldGeom.decRefCnt();
0440:                        for (i = 0; i < mirrorShape3D.size(); i++) {
0441:                            mShape = (Shape3DRetained) mirrorShape3D.get(i);
0442:                            oldGeom.removeUser(mShape);
0443:
0444:                        }
0445:                    }
0446:
0447:                    geometryList.remove(index);
0448:                    sendDataChangedMessage(null);
0449:
0450:                } else {
0451:                    oldGeom = (GeometryRetained) (geometryList.get(index));
0452:                    if (oldGeom != null) {
0453:                        oldGeom.decRefCnt();
0454:                    }
0455:                    geometryList.remove(index);
0456:                }
0457:
0458:                dirtyBoundsCache();
0459:
0460:            }
0461:
0462:            /**
0463:             * Retrieves the geometry component of this Shape3D node.
0464:             * @return the geometry component of this shape node
0465:             *
0466:             * @since Java 3D 1.2
0467:             */
0468:            Geometry getGeometry(int index, int id) {
0469:                GeometryRetained ga = (GeometryRetained) geometryList
0470:                        .get(index);
0471:                return (ga == null ? null : (Geometry) ga.source);
0472:            }
0473:
0474:            /**
0475:             * Returns an enumeration of this Shape3D node's list of geometry
0476:             * components.
0477:             * @return an Enumeration object containing all geometry components in
0478:             * this Shape3D node's list of geometry components.
0479:             *
0480:             * @since Java 3D 1.2
0481:             */
0482:            Enumeration getAllGeometries(int id) {
0483:                GeometryRetained ga = null;
0484:                Vector geomList = new Vector(geometryList.size());
0485:
0486:                for (int i = 0; i < geometryList.size(); i++) {
0487:                    ga = (GeometryRetained) geometryList.get(i);
0488:                    if (ga != null)
0489:                        geomList.add((Geometry) ga.source);
0490:                    else
0491:                        geomList.add(null);
0492:                }
0493:
0494:                return geomList.elements();
0495:            }
0496:
0497:            /**
0498:             * Returns the number of geometry components in this Shape3D node's
0499:             * list of geometry components.
0500:             * @return the number of geometry components in this Shape3D node's
0501:             * list of geometry components.
0502:             *
0503:             * @since Java 3D 1.2
0504:             */
0505:            int numGeometries(int id) {
0506:
0507:                return geometryList.size();
0508:            }
0509:
0510:            /**
0511:             * Sets the appearance component of this Shape3D node.
0512:             * @param appearance the new apearance component for this shape node
0513:             */
0514:            void setAppearance(Appearance newAppearance) {
0515:
0516:                Shape3DRetained s;
0517:                boolean visibleIsDirty = false;
0518:
0519:                if (((Shape3D) this .source).isLive()) {
0520:                    if (appearance != null) {
0521:                        appearance.clearLive(refCount);
0522:                        for (int i = 0; i < mirrorShape3D.size(); i++) {
0523:                            s = (Shape3DRetained) mirrorShape3D.get(i);
0524:                            appearance.removeAMirrorUser(s);
0525:                        }
0526:                    }
0527:
0528:                    if (newAppearance != null) {
0529:                        ((AppearanceRetained) newAppearance.retained).setLive(
0530:                                inBackgroundGroup, refCount);
0531:                        appearance = ((AppearanceRetained) newAppearance.retained);
0532:                        for (int i = 0; i < mirrorShape3D.size(); i++) {
0533:                            s = (Shape3DRetained) mirrorShape3D.get(i);
0534:                            appearance.addAMirrorUser(s);
0535:                        }
0536:                        if ((appearance.renderingAttributes != null)
0537:                                && (visible != appearance.renderingAttributes.visible)) {
0538:                            visible = appearance.renderingAttributes.visible;
0539:                            visibleIsDirty = true;
0540:                        }
0541:                    } else {
0542:                        if (visible == false) {
0543:                            visible = true;
0544:                            visibleIsDirty = true;
0545:                        }
0546:                    }
0547:                    int size = 0;
0548:                    if (visibleIsDirty)
0549:                        size = 2;
0550:                    else
0551:                        size = 1;
0552:                    J3dMessage[] createMessage = new J3dMessage[size];
0553:                    // Send a message
0554:                    createMessage[0] = new J3dMessage();
0555:                    createMessage[0].threads = targetThreads;
0556:                    createMessage[0].type = J3dMessage.SHAPE3D_CHANGED;
0557:                    createMessage[0].universe = universe;
0558:                    createMessage[0].args[0] = this ;
0559:                    createMessage[0].args[1] = new Integer(APPEARANCE_CHANGED);
0560:                    Shape3DRetained[] s3dArr = new Shape3DRetained[mirrorShape3D
0561:                            .size()];
0562:                    mirrorShape3D.toArray(s3dArr);
0563:                    createMessage[0].args[2] = s3dArr;
0564:                    Object[] obj = new Object[2];
0565:                    if (newAppearance == null) {
0566:                        obj[0] = null;
0567:                    } else {
0568:                        obj[0] = appearance.mirror;
0569:                    }
0570:                    obj[1] = new Integer(changedFrequent);
0571:                    createMessage[0].args[3] = obj;
0572:                    createMessage[0].args[4] = getGeomAtomsArray(mirrorShape3D);
0573:                    if (visibleIsDirty) {
0574:                        createMessage[1] = new J3dMessage();
0575:                        createMessage[1].threads = J3dThread.UPDATE_GEOMETRY;
0576:                        createMessage[1].type = J3dMessage.SHAPE3D_CHANGED;
0577:                        createMessage[1].universe = universe;
0578:                        createMessage[1].args[0] = this ;
0579:                        createMessage[1].args[1] = new Integer(
0580:                                APPEARANCE_CHANGED);
0581:                        createMessage[1].args[2] = visible ? Boolean.TRUE
0582:                                : Boolean.FALSE;
0583:                        createMessage[1].args[3] = createMessage[0].args[4];
0584:                    }
0585:                    VirtualUniverse.mc.processMessage(createMessage);
0586:
0587:                } else { // not live.
0588:                    if (newAppearance == null) {
0589:                        appearance = null;
0590:                    } else {
0591:                        appearance = (AppearanceRetained) newAppearance.retained;
0592:                    }
0593:                }
0594:            }
0595:
0596:            /**
0597:             * Retrieves the shape node's appearance component.
0598:             * @return the shape node's appearance
0599:             */
0600:            Appearance getAppearance() {
0601:                return (appearance == null ? null
0602:                        : (Appearance) appearance.source);
0603:            }
0604:
0605:            void setAppearanceOverrideEnable(boolean flag) {
0606:                if (((Shape3D) this .source).isLive()) {
0607:
0608:                    // Send a message
0609:                    J3dMessage createMessage = new J3dMessage();
0610:                    createMessage.threads = targetThreads;
0611:                    createMessage.type = J3dMessage.SHAPE3D_CHANGED;
0612:                    createMessage.universe = universe;
0613:                    createMessage.args[0] = this ;
0614:                    createMessage.args[1] = new Integer(
0615:                            APPEARANCEOVERRIDE_CHANGED);
0616:                    Shape3DRetained[] s3dArr = new Shape3DRetained[mirrorShape3D
0617:                            .size()];
0618:                    mirrorShape3D.toArray(s3dArr);
0619:                    createMessage.args[2] = s3dArr;
0620:                    Object[] obj = new Object[2];
0621:                    if (flag) {
0622:                        obj[0] = Boolean.TRUE;
0623:                    } else {
0624:                        obj[0] = Boolean.FALSE;
0625:                    }
0626:                    obj[1] = new Integer(changedFrequent);
0627:                    createMessage.args[3] = obj;
0628:                    createMessage.args[4] = getGeomAtomsArray(mirrorShape3D);
0629:
0630:                    VirtualUniverse.mc.processMessage(createMessage);
0631:                }
0632:                appearanceOverrideEnable = flag;
0633:            }
0634:
0635:            boolean getAppearanceOverrideEnable() {
0636:                return appearanceOverrideEnable;
0637:            }
0638:
0639:            boolean intersect(PickInfo pickInfo, PickShape pickShape, int flags) {
0640:
0641:                Transform3D localToVworld = pickInfo.getLocalToVWorldRef();
0642:
0643:                // Support OrientedShape3D here.
0644:                // Note - BugId : 4363899 - APIs issue : OrientedShape3D's intersect needs view
0645:                //                          info. temp. fix use the primary view.
0646:                if (this  instanceof  OrientedShape3DRetained) {
0647:                    Transform3D orientedTransform = ((OrientedShape3DRetained) this )
0648:                            .getOrientedTransform(getPrimaryViewIdx());
0649:                    localToVworld.mul(orientedTransform);
0650:                }
0651:
0652:                Transform3D t3d = new Transform3D();
0653:                t3d.invert(localToVworld);
0654:                PickShape newPS = pickShape.transform(t3d);
0655:
0656:                // Note: For optimization - Should do a geobounds check of
0657:                // each geometry first. But this doesn't work for
0658:                // OrientedShape3D case...
0659:                int geomListSize = geometryList.size();
0660:                GeometryRetained geometry;
0661:
0662:                if (((flags & PickInfo.CLOSEST_INTERSECTION_POINT) == 0)
0663:                        && ((flags & PickInfo.CLOSEST_DISTANCE) == 0)
0664:                        && ((flags & PickInfo.CLOSEST_GEOM_INFO) == 0)
0665:                        && ((flags & PickInfo.ALL_GEOM_INFO) == 0)) {
0666:
0667:                    for (int i = 0; i < geomListSize; i++) {
0668:                        geometry = (GeometryRetained) geometryList.get(i);
0669:                        if (geometry != null) {
0670:                            if (geometry.mirrorGeometry != null) {
0671:                                geometry = geometry.mirrorGeometry;
0672:                            }
0673:                            if (geometry.intersect(newPS, null, 0, null, null,
0674:                                    0)) {
0675:                                return true;
0676:                            }
0677:                        }
0678:                    }
0679:                } else {
0680:                    double distance;
0681:                    double minDist = Double.POSITIVE_INFINITY;
0682:                    Point3d closestIPnt = new Point3d();
0683:                    Point3d iPnt = new Point3d();
0684:                    Point3d iPntVW = new Point3d();
0685:
0686:                    for (int i = 0; i < geomListSize; i++) {
0687:                        geometry = (GeometryRetained) geometryList.get(i);
0688:                        if (geometry != null) {
0689:                            if (geometry.mirrorGeometry != null) {
0690:                                geometry = geometry.mirrorGeometry;
0691:                            }
0692:                            //if (geometry.intersect(newPS, intersectionInfo, flags, iPnt)) {
0693:                            if (geometry.intersect(newPS, pickInfo, flags,
0694:                                    iPnt, geometry, i)) {
0695:
0696:                                iPntVW.set(iPnt);
0697:                                localToVworld.transform(iPntVW);
0698:                                distance = pickShape.distance(iPntVW);
0699:
0700:                                if (minDist > distance) {
0701:                                    minDist = distance;
0702:                                    closestIPnt.set(iPnt);
0703:                                }
0704:                            }
0705:                        }
0706:                    }
0707:
0708:                    if (minDist < Double.POSITIVE_INFINITY) {
0709:                        if ((flags & PickInfo.CLOSEST_DISTANCE) != 0) {
0710:                            pickInfo.setClosestDistance(minDist);
0711:                        }
0712:                        if ((flags & PickInfo.CLOSEST_INTERSECTION_POINT) != 0) {
0713:                            pickInfo.setClosestIntersectionPoint(closestIPnt);
0714:                        }
0715:                        return true;
0716:                    }
0717:                }
0718:
0719:                return false;
0720:
0721:            }
0722:
0723:            /**
0724:             * Check if the geometry component of this shape node under path
0725:             * intersects with the pickShape.
0726:             * This is an expensive method. It should only be called if and only
0727:             * if the path's bound intersects pickShape.  
0728:             * @exception IllegalArgumentException if <code>path</code> is
0729:             * invalid.
0730:             */
0731:
0732:            boolean intersect(SceneGraphPath path, PickShape pickShape,
0733:                    double[] dist) {
0734:
0735:                int flags;
0736:                PickInfo pickInfo = new PickInfo();
0737:
0738:                Transform3D localToVworld = path.getTransform();
0739:                if (localToVworld == null) {
0740:                    throw new IllegalArgumentException(J3dI18N
0741:                            .getString("Shape3DRetained3"));
0742:                }
0743:                pickInfo.setLocalToVWorldRef(localToVworld);
0744:                //System.err.println("Shape3DRetained.intersect() : ");
0745:                if (dist == null) {
0746:                    //System.err.println("      no dist request ....");
0747:                    return intersect(pickInfo, pickShape, 0);
0748:                }
0749:
0750:                flags = PickInfo.CLOSEST_DISTANCE;
0751:                if (intersect(pickInfo, pickShape, flags)) {
0752:                    dist[0] = pickInfo.getClosestDistance();
0753:                    return true;
0754:                }
0755:
0756:                return false;
0757:
0758:            }
0759:
0760:            /**
0761:             * This sets the immedate mode context flag
0762:             */
0763:            void setInImmCtx(boolean inCtx) {
0764:                inImmCtx = inCtx;
0765:            }
0766:
0767:            /**
0768:             * This gets the immedate mode context flag
0769:             */
0770:            boolean getInImmCtx() {
0771:                return (inImmCtx);
0772:            }
0773:
0774:            /**
0775:             * This updates the mirror shape to reflect the state of the
0776:             * real shape3d.
0777:             */
0778:            private void initMirrorShape3D(SetLiveState s, Shape3DRetained ms,
0779:                    int index) {
0780:
0781:                // New 1.2.1 code
0782:
0783:                ms.inBackgroundGroup = inBackgroundGroup;
0784:                ms.geometryBackground = geometryBackground;
0785:                ms.source = source;
0786:                ms.universe = universe;
0787:                // Has to be false. We have a instance of mirror for every link to the shape3d.
0788:                ms.inSharedGroup = false;
0789:                ms.locale = locale;
0790:                ms.parent = parent;
0791:
0792:                // New 1.3.2
0793:                // Used when user supplied their own bounds for transparency sorting
0794:                // GeometryAtom uses this to change how it computes the centroid
0795:                ms.boundsAutoCompute = boundsAutoCompute;
0796:                ms.localBounds = localBounds;
0797:                // End new 1.3.2
0798:
0799:                OrderedPath op = (OrderedPath) s.orderedPaths.get(index);
0800:                if (op.pathElements.size() == 0) {
0801:                    ms.orderedPath = null;
0802:                } else {
0803:                    ms.orderedPath = op;
0804:                    /*
0805:                     System.err.println("initMirrorShape3D ms.orderedPath ");
0806:                     ms.orderedPath.printPath();
0807:                     */
0808:                }
0809:
0810:                // all mirror shapes point to the same transformGroupRetained
0811:                // for the static transform
0812:                ms.staticTransform = staticTransform;
0813:
0814:                ms.appearanceOverrideEnable = appearanceOverrideEnable;
0815:
0816:                ms.geometryList = geometryList;
0817:
0818:                // Assign the parent of this mirror shape node
0819:                ms.sourceNode = this ;
0820:
0821:                if (this  instanceof  OrientedShape3DRetained) {
0822:                    OrientedShape3DRetained os = (OrientedShape3DRetained) this ;
0823:                    OrientedShape3DRetained oms = (OrientedShape3DRetained) ms;
0824:                    oms.initAlignmentMode(os.mode);
0825:                    oms.initAlignmentAxis(os.axis);
0826:                    oms.initRotationPoint(os.rotationPoint);
0827:                    oms.initConstantScaleEnable(os.constantScale);
0828:                    oms.initScale(os.scaleFactor);
0829:                }
0830:
0831:            }
0832:
0833:            void updateImmediateMirrorObject(Object[] objs) {
0834:                int component = ((Integer) objs[1]).intValue();
0835:                GeometryArrayRetained ga;
0836:
0837:                Shape3DRetained[] msArr = (Shape3DRetained[]) objs[2];
0838:                int i, j;
0839:                if ((component & APPEARANCE_CHANGED) != 0) {
0840:                    Object[] arg = (Object[]) objs[3];
0841:                    int val = ((Integer) arg[1]).intValue();
0842:                    for (i = msArr.length - 1; i >= 0; i--) {
0843:                        msArr[i].appearance = (AppearanceRetained) arg[0];
0844:                        msArr[i].changedFrequent = val;
0845:                    }
0846:                }
0847:                if ((component & APPEARANCEOVERRIDE_CHANGED) != 0) {
0848:                    Object[] arg = (Object[]) objs[3];
0849:                    int val = ((Integer) arg[1]).intValue();
0850:                    for (i = msArr.length - 1; i >= 0; i--) {
0851:                        msArr[i].appearanceOverrideEnable = ((Boolean) arg[0])
0852:                                .booleanValue();
0853:                        msArr[i].changedFrequent = val;
0854:                    }
0855:                }
0856:            }
0857:
0858:            /**
0859:             * Gets the bounding object of a node.
0860:             * @return the node's bounding object
0861:             */
0862:
0863:            Bounds getBounds() {
0864:
0865:                if (boundsAutoCompute) {
0866:                    // System.err.println("getBounds ---- localBounds is " + localBounds);
0867:                    // Issue 514 : NPE in Wonderland : triggered in cached bounds computation
0868:                    if (validCachedBounds) {
0869:                        return (Bounds) cachedBounds.clone();
0870:                    }
0871:
0872:                    if (geometryList != null) {
0873:                        BoundingBox bbox = new BoundingBox((Bounds) null);
0874:                        GeometryRetained geometry;
0875:                        for (int i = 0; i < geometryList.size(); i++) {
0876:                            geometry = (GeometryRetained) geometryList.get(i);
0877:                            if ((geometry != null)
0878:                                    && (geometry.geoType != GeometryRetained.GEO_TYPE_NONE)) {
0879:                                geometry.computeBoundingBox();
0880:                                synchronized (geometry.geoBounds) {
0881:                                    bbox.combine(geometry.geoBounds);
0882:                                }
0883:                            }
0884:                        }
0885:                        return (Bounds) bbox;
0886:
0887:                    } else {
0888:                        return null;
0889:                    }
0890:
0891:                } else {
0892:                    return super .getBounds();
0893:                }
0894:            }
0895:
0896:            Bounds getEffectiveBounds() {
0897:                if (boundsAutoCompute) {
0898:                    return getBounds();
0899:                } else {
0900:                    return super .getEffectiveBounds();
0901:                }
0902:            }
0903:
0904:            /**
0905:             * ONLY needed for SHAPE, MORPH, and LINK node type.
0906:             * Compute the combine bounds of bounds and its localBounds.
0907:             */
0908:            void computeCombineBounds(Bounds bounds) {
0909:
0910:                if (boundsAutoCompute) {
0911:                    if (geometryList != null) {
0912:                        GeometryRetained geometry;
0913:                        BoundingBox bbox = null;
0914:
0915:                        if (staticTransform != null) {
0916:                            bbox = new BoundingBox((BoundingBox) null);
0917:                        }
0918:
0919:                        if (!VirtualUniverse.mc.cacheAutoComputedBounds) {
0920:                            for (int i = 0; i < geometryList.size(); i++) {
0921:                                geometry = (GeometryRetained) geometryList
0922:                                        .get(i);
0923:                                if ((geometry != null)
0924:                                        && (geometry.geoType != GeometryRetained.GEO_TYPE_NONE)) {
0925:                                    geometry.computeBoundingBox();
0926:                                    // Should this be lock too ? ( MT safe  ? )
0927:                                    synchronized (geometry.geoBounds) {
0928:                                        if (staticTransform != null) {
0929:                                            bbox.set(geometry.geoBounds);
0930:                                            bbox
0931:                                                    .transform(staticTransform.transform);
0932:                                            bounds.combine((Bounds) bbox);
0933:                                        } else {
0934:                                            bounds
0935:                                                    .combine((Bounds) geometry.geoBounds);
0936:                                        }
0937:                                    }
0938:                                }
0939:                            }
0940:                        } else {
0941:                            // Issue 514 : NPE in Wonderland : triggered in cached bounds computation
0942:                            if (!validCachedBounds) {
0943:                                validCachedBounds = true;
0944:                                cachedBounds = new BoundingBox(
0945:                                        (BoundingBox) null);
0946:
0947:                                for (int i = 0; i < geometryList.size(); i++) {
0948:                                    geometry = (GeometryRetained) geometryList
0949:                                            .get(i);
0950:                                    if ((geometry != null)
0951:                                            && (geometry.geoType != GeometryRetained.GEO_TYPE_NONE)) {
0952:                                        geometry.computeBoundingBox();
0953:                                        // Should this be lock too ? ( MT safe  ? )
0954:                                        synchronized (geometry.geoBounds) {
0955:                                            if (staticTransform != null) {
0956:                                                bbox.set(geometry.geoBounds);
0957:                                                bbox
0958:                                                        .transform(staticTransform.transform);
0959:                                                cachedBounds
0960:                                                        .combine((Bounds) bbox);
0961:                                            } else {
0962:                                                cachedBounds
0963:                                                        .combine((Bounds) geometry.geoBounds);
0964:                                            }
0965:                                        }
0966:                                    }
0967:                                }
0968:                            }
0969:                            bounds.combine(cachedBounds);
0970:                        }
0971:                    }
0972:                } else {
0973:
0974:                    // Should this be lock too ? ( MT safe  ? )
0975:                    synchronized (localBounds) {
0976:                        bounds.combine((Bounds) localBounds);
0977:                    }
0978:                }
0979:            }
0980:
0981:            /**
0982:             * assign a name to this node when it is made live.
0983:             */
0984:
0985:            void setLive(SetLiveState s) {
0986:                doSetLive(s);
0987:                markAsLive();
0988:            }
0989:
0990:            void doSetLive(SetLiveState s) {
0991:                // System.err.println("S3DRetained : setLive " + s);
0992:                Shape3DRetained shape;
0993:                GeometryRetained geometry;
0994:                int i, j, k, gaCnt;
0995:                ArrayList msList = new ArrayList();
0996:
0997:                super .doSetLive(s);
0998:
0999:                nodeId = universe.getNodeId();
1000:
1001:                if (inSharedGroup) {
1002:                    for (i = 0; i < s.keys.length; i++) {
1003:                        if (this  instanceof  OrientedShape3DRetained) {
1004:                            shape = new OrientedShape3DRetained();
1005:                        } else {
1006:                            shape = new Shape3DRetained();
1007:                        }
1008:                        shape.key = s.keys[i];
1009:                        shape.localToVworld = new Transform3D[1][];
1010:                        shape.localToVworldIndex = new int[1][];
1011:
1012:                        j = s.keys[i].equals(localToVworldKeys, 0,
1013:                                localToVworldKeys.length);
1014:                        /*
1015:                            System.err.print("s.keys[i] = "+s.keys[i]+" j = "+j);
1016:                            if(j < 0) {
1017:                            System.err.println("Shape3dRetained : Can't find hashKey"); 
1018:                            }
1019:                         */
1020:                        shape.localToVworld[0] = localToVworld[j];
1021:                        shape.localToVworldIndex[0] = localToVworldIndex[j];
1022:                        shape.branchGroupPath = (BranchGroupRetained[]) branchGroupPaths
1023:                                .get(j);
1024:                        shape.isPickable = s.pickable[i];
1025:                        shape.isCollidable = s.collidable[i];
1026:
1027:                        initMirrorShape3D(s, shape, j);
1028:
1029:                        if (s.switchTargets != null
1030:                                && s.switchTargets[i] != null) {
1031:                            s.switchTargets[i].addNode(shape,
1032:                                    Targets.GEO_TARGETS);
1033:                            shape.closestSwitchParent = s.closestSwitchParents[i];
1034:                            shape.closestSwitchIndex = s.closestSwitchIndices[i];
1035:                        }
1036:                        shape.switchState = (SwitchState) s.switchStates.get(j);
1037:
1038:                        // Add any scoped lights to the mirror shape
1039:                        if (s.lights != null) {
1040:                            ArrayList l = (ArrayList) s.lights.get(j);
1041:                            if (l != null) {
1042:                                for (int m = 0; m < l.size(); m++) {
1043:                                    shape.addLight((LightRetained) l.get(m));
1044:                                }
1045:                            }
1046:                        }
1047:
1048:                        // Add any scoped fog
1049:                        if (s.fogs != null) {
1050:                            ArrayList l = (ArrayList) s.fogs.get(j);
1051:                            if (l != null) {
1052:                                for (int m = 0; m < l.size(); m++) {
1053:                                    shape.addFog((FogRetained) l.get(m));
1054:                                }
1055:                            }
1056:                        }
1057:
1058:                        // Add any scoped modelClip
1059:                        if (s.modelClips != null) {
1060:                            ArrayList l = (ArrayList) s.modelClips.get(j);
1061:                            if (l != null) {
1062:                                for (int m = 0; m < l.size(); m++) {
1063:                                    shape.addModelClip((ModelClipRetained) l
1064:                                            .get(m));
1065:                                }
1066:                            }
1067:                        }
1068:
1069:                        // Add any scoped alt app
1070:                        if (s.altAppearances != null) {
1071:                            ArrayList l = (ArrayList) s.altAppearances.get(j);
1072:                            if (l != null) {
1073:                                for (int m = 0; m < l.size(); m++) {
1074:                                    shape
1075:                                            .addAltApp((AlternateAppearanceRetained) l
1076:                                                    .get(m));
1077:                                }
1078:                            }
1079:                        }
1080:                        synchronized (mirrorShape3D) {
1081:                            mirrorShape3D.add(j, shape);
1082:                        }
1083:
1084:                        msList.add(shape);
1085:                        if (s.viewLists != null) {
1086:                            shape.viewList = (ArrayList) s.viewLists.get(j);
1087:                        } else {
1088:                            shape.viewList = null;
1089:                        }
1090:                    }
1091:                } else {
1092:                    if (this  instanceof  OrientedShape3DRetained) {
1093:                        shape = new OrientedShape3DRetained();
1094:                    } else {
1095:                        shape = new Shape3DRetained();
1096:                    }
1097:
1098:                    shape.localToVworld = new Transform3D[1][];
1099:                    shape.localToVworldIndex = new int[1][];
1100:                    shape.localToVworld[0] = localToVworld[0];
1101:                    shape.localToVworldIndex[0] = localToVworldIndex[0];
1102:                    shape.branchGroupPath = (BranchGroupRetained[]) branchGroupPaths
1103:                            .get(0);
1104:                    shape.isPickable = s.pickable[0];
1105:                    shape.isCollidable = s.collidable[0];
1106:                    initMirrorShape3D(s, shape, 0);
1107:
1108:                    // Add any scoped lights to the mirror shape
1109:                    if (s.lights != null) {
1110:                        ArrayList l = (ArrayList) s.lights.get(0);
1111:                        for (i = 0; i < l.size(); i++) {
1112:                            shape.addLight((LightRetained) l.get(i));
1113:                        }
1114:                    }
1115:
1116:                    // Add any scoped fog
1117:                    if (s.fogs != null) {
1118:                        ArrayList l = (ArrayList) s.fogs.get(0);
1119:                        for (i = 0; i < l.size(); i++) {
1120:                            shape.addFog((FogRetained) l.get(i));
1121:                        }
1122:                    }
1123:
1124:                    // Add any scoped modelClip
1125:                    if (s.modelClips != null) {
1126:                        ArrayList l = (ArrayList) s.modelClips.get(0);
1127:                        for (i = 0; i < l.size(); i++) {
1128:                            shape.addModelClip((ModelClipRetained) l.get(i));
1129:                        }
1130:
1131:                    }
1132:
1133:                    // Add any scoped alt app
1134:                    if (s.altAppearances != null) {
1135:                        ArrayList l = (ArrayList) s.altAppearances.get(0);
1136:                        for (i = 0; i < l.size(); i++) {
1137:                            shape.addAltApp((AlternateAppearanceRetained) l
1138:                                    .get(i));
1139:                        }
1140:                    }
1141:                    synchronized (mirrorShape3D) {
1142:                        mirrorShape3D.add(shape);
1143:                    }
1144:
1145:                    msList.add(shape);
1146:                    if (s.viewLists != null)
1147:                        shape.viewList = (ArrayList) s.viewLists.get(0);
1148:                    else
1149:                        shape.viewList = null;
1150:
1151:                    if (s.switchTargets != null && s.switchTargets[0] != null) {
1152:                        s.switchTargets[0].addNode(shape, Targets.GEO_TARGETS);
1153:                        shape.closestSwitchParent = s.closestSwitchParents[0];
1154:                        shape.closestSwitchIndex = s.closestSwitchIndices[0];
1155:                    }
1156:                    shape.switchState = (SwitchState) s.switchStates.get(0);
1157:                }
1158:
1159:                for (k = 0; k < msList.size(); k++) {
1160:                    Shape3DRetained sh = (Shape3DRetained) msList.get(k);
1161:
1162:                    if (appearance != null) {
1163:                        synchronized (appearance.liveStateLock) {
1164:                            if (k == 0) { // Do only first time 
1165:                                appearance.setLive(inBackgroundGroup,
1166:                                        s.refCount);
1167:                                appearance.initMirrorObject();
1168:                                if (appearance.renderingAttributes != null)
1169:                                    visible = appearance.renderingAttributes.visible;
1170:                            }
1171:                            sh.appearance = (AppearanceRetained) appearance.mirror;
1172:                            appearance.addAMirrorUser(sh);
1173:
1174:                        }
1175:                    } else {
1176:                        sh.appearance = null;
1177:                    }
1178:
1179:                    if (geometryList != null) {
1180:                        for (gaCnt = 0; gaCnt < geometryList.size(); gaCnt++) {
1181:                            geometry = (GeometryRetained) geometryList
1182:                                    .get(gaCnt);
1183:                            if (geometry != null) {
1184:                                synchronized (geometry.liveStateLock) {
1185:                                    if (k == 0) { // Do only first time 
1186:                                        geometry.setLive(inBackgroundGroup,
1187:                                                s.refCount);
1188:                                    }
1189:                                    geometry.addUser(sh);
1190:                                }
1191:                            }
1192:                        }
1193:
1194:                    }
1195:
1196:                    // after the geometry has been setLived and bounds computed
1197:                    if (k == 0 && boundsAutoCompute) { // Do only once 
1198:                        // user may call setBounds with a bounds other than boundingBox
1199:                        if (!(localBounds instanceof  BoundingBox)) {
1200:                            localBounds = new BoundingBox((BoundingBox) null);
1201:                        }
1202:                        getCombineBounds((BoundingBox) localBounds);
1203:
1204:                    }
1205:                    // Assign GAtom and set the bounds if we are not using switch
1206:                    initializeGAtom(sh);
1207:
1208:                    GeometryAtom ga = getGeomAtom(sh);
1209:
1210:                    // Add the geometry atom for this shape to the nodeList
1211:                    s.nodeList.add(ga);
1212:
1213:                    if (s.transformTargets != null
1214:                            && s.transformTargets[k] != null) {
1215:                        // Add the geometry atom for this shape to the transformTargets
1216:
1217:                        s.transformTargets[k].addNode(ga, Targets.GEO_TARGETS);
1218:                    }
1219:                }
1220:
1221:                s.notifyThreads |= (J3dThread.UPDATE_GEOMETRY
1222:                        | J3dThread.UPDATE_TRANSFORM | J3dThread.UPDATE_RENDER | J3dThread.UPDATE_RENDERING_ENVIRONMENT);
1223:
1224:            }
1225:
1226:            /**
1227:             * This clears all references in a mirror shape
1228:             */
1229:            // This is call in RenderingEnvironmentStructure.removeNode() because that is the
1230:            // last point that will reference this ms.
1231:            // called on the mirror shape ..
1232:            void clearMirrorShape() {
1233:                int i;
1234:
1235:                source = null;
1236:                sourceNode = null;
1237:                parent = null;
1238:
1239:                if (otherAppearance != null) {
1240:                    otherAppearance.sgApp.removeAMirrorUser(this );
1241:                    otherAppearance = null;
1242:                }
1243:
1244:                appearance = null;
1245:
1246:                branchGroupPath = null;
1247:                isPickable = true;
1248:                isCollidable = true;
1249:                branchGroupPath = null;
1250:                // No locking needed. Owner, s3dR, has already been destory.
1251:                // DO NOT clear geometryList, ie. geometryList.clear().
1252:                // It is referred by the source s3DRetained.
1253:                geometryList = null;
1254:
1255:                // Clear the mirror scoping info
1256:                // Remove all the fogs
1257:                for (i = 0; i < numfogs; i++)
1258:                    fogs[i] = null;
1259:                numfogs = 0;
1260:
1261:                // Remove all the modelClips
1262:                for (i = 0; i < numModelClips; i++)
1263:                    modelClips[i] = null;
1264:                numModelClips = 0;
1265:
1266:                // Remove all the lights
1267:                for (i = 0; i < numlights; i++)
1268:                    lights[i] = null;
1269:                numlights = 0;
1270:
1271:                // Remove all the al app
1272:                for (i = 0; i < numAltApps; i++)
1273:                    altApps[i] = null;
1274:                numAltApps = 0;
1275:
1276:                viewList = null;
1277:
1278:            }
1279:
1280:            /**
1281:             * assign a name to this node when it is made live.
1282:             */
1283:            void clearLive(SetLiveState s) {
1284:
1285:                //System.err.println("S3DRetained : clearLive " + s);
1286:
1287:                int i, j, gaCnt;
1288:                Shape3DRetained shape;
1289:                GeometryRetained geometry;
1290:                Object[] shapes;
1291:                ArrayList msList = new ArrayList();
1292:
1293:                super .clearLive(s);
1294:
1295:                if (inSharedGroup) {
1296:                    synchronized (mirrorShape3D) {
1297:                        shapes = mirrorShape3D.toArray();
1298:                        for (i = 0; i < s.keys.length; i++) {
1299:                            for (j = 0; j < shapes.length; j++) {
1300:                                shape = (Shape3DRetained) shapes[j];
1301:                                if (shape.key.equals(s.keys[i])) {
1302:                                    mirrorShape3D.remove(mirrorShape3D
1303:                                            .indexOf(shape));
1304:                                    if (s.switchTargets != null
1305:                                            && s.switchTargets[i] != null) {
1306:                                        s.switchTargets[i].addNode(shape,
1307:                                                Targets.GEO_TARGETS);
1308:                                    }
1309:                                    msList.add(shape);
1310:                                    GeometryAtom ga = getGeomAtom(shape);
1311:
1312:                                    // Add the geometry atom for this shape to the nodeList
1313:                                    s.nodeList.add(ga);
1314:                                    if (s.transformTargets != null
1315:                                            && s.transformTargets[i] != null) {
1316:                                        s.transformTargets[i].addNode(ga,
1317:                                                Targets.GEO_TARGETS);
1318:                                    }
1319:                                }
1320:                            }
1321:                        }
1322:                    }
1323:                } else {
1324:                    // Only entry 0 is valid
1325:                    shape = (Shape3DRetained) mirrorShape3D.get(0);
1326:                    synchronized (mirrorShape3D) {
1327:                        mirrorShape3D.remove(0);
1328:                    }
1329:
1330:                    if (s.switchTargets != null && s.switchTargets[0] != null) {
1331:                        s.switchTargets[0].addNode(shape, Targets.GEO_TARGETS);
1332:                    }
1333:
1334:                    msList.add(shape);
1335:
1336:                    GeometryAtom ga = getGeomAtom(shape);
1337:
1338:                    // Add the geometry atom for this shape to the nodeList
1339:                    s.nodeList.add(ga);
1340:                    if (s.transformTargets != null
1341:                            && s.transformTargets[0] != null) {
1342:                        s.transformTargets[0].addNode(ga, Targets.GEO_TARGETS);
1343:                    }
1344:                }
1345:
1346:                for (int k = 0; k < msList.size(); k++) {
1347:                    Shape3DRetained sh = (Shape3DRetained) msList.get(k);
1348:                    if (appearance != null) {
1349:                        synchronized (appearance.liveStateLock) {
1350:                            if (k == 0) {
1351:                                appearance.clearLive(s.refCount);
1352:                            }
1353:                            appearance.removeAMirrorUser(sh);
1354:                        }
1355:                    }
1356:                    if (geometryList != null) {
1357:                        for (gaCnt = 0; gaCnt < geometryList.size(); gaCnt++) {
1358:                            geometry = (GeometryRetained) geometryList
1359:                                    .get(gaCnt);
1360:                            if (geometry != null) {
1361:                                synchronized (geometry.liveStateLock) {
1362:                                    if (k == 0) {
1363:                                        geometry.clearLive(s.refCount);
1364:                                    }
1365:                                    geometry.removeUser(sh);
1366:                                }
1367:                            }
1368:                        }
1369:                    }
1370:                }
1371:
1372:                s.notifyThreads |= (J3dThread.UPDATE_GEOMETRY
1373:                        | J3dThread.UPDATE_TRANSFORM |
1374:                        // This is used to clear the scope info
1375:                        // of all the mirror shapes
1376:                        J3dThread.UPDATE_RENDERING_ENVIRONMENT | J3dThread.UPDATE_RENDER);
1377:
1378:                if (!source.isLive()) {
1379:                    // Clear the mirror scoping info
1380:                    // Remove all the fogs
1381:                    for (i = 0; i < numfogs; i++)
1382:                        fogs[i] = null;
1383:                    numfogs = 0;
1384:
1385:                    // Remove all the modelClips
1386:                    for (i = 0; i < numModelClips; i++)
1387:                        modelClips[i] = null;
1388:                    numModelClips = 0;
1389:
1390:                    // Remove all the lights
1391:                    for (i = 0; i < numlights; i++)
1392:                        lights[i] = null;
1393:                    numlights = 0;
1394:
1395:                    // Remove all the al app
1396:                    for (i = 0; i < numAltApps; i++)
1397:                        altApps[i] = null;
1398:                    numAltApps = 0;
1399:                }
1400:            }
1401:
1402:            boolean isStatic() {
1403:                if (source.getCapability(Shape3D.ALLOW_APPEARANCE_WRITE)
1404:                        || source.getCapability(Shape3D.ALLOW_GEOMETRY_WRITE)
1405:                        || source
1406:                                .getCapability(Shape3D.ALLOW_APPEARANCE_OVERRIDE_WRITE)) {
1407:                    return false;
1408:                } else {
1409:                    return true;
1410:                }
1411:            }
1412:
1413:            boolean staticXformCanBeApplied() {
1414:
1415:                // static xform can be applied if
1416:                // . shape is not pickable or collidable
1417:                // . geometry is not being shared by more than one shape nodes
1418:                // . geometry will be put in display list
1419:                // . geometry is not readable
1420:
1421:                // no static xform if shape is pickable or collidable because
1422:                // otherwise the static xform will have to be applied to the
1423:                // currentLocalToVworld in the intersect test, it will then
1424:                // be more costly and really beat the purpose of eliminating
1425:                // the static transform group
1426:                if (isPickable || isCollidable
1427:                        || source.getCapability(Shape3D.ALLOW_PICKABLE_WRITE)
1428:                        || source.getCapability(Shape3D.ALLOW_COLLIDABLE_WRITE)) {
1429:                    return false;
1430:                }
1431:
1432:                if (appearance != null
1433:                        && (appearance.transparencyAttributes != null && appearance.transparencyAttributes.transparencyMode != TransparencyAttributes.NONE))
1434:                    return false;
1435:
1436:                GeometryRetained geo;
1437:                boolean alphaEditable;
1438:
1439:                for (int i = 0; i < geometryList.size(); i++) {
1440:                    geo = (GeometryRetained) geometryList.get(i);
1441:                    if (geo != null) {
1442:                        if (geo.refCnt > 1) {
1443:                            return false;
1444:                        }
1445:                        alphaEditable = isAlphaEditable(geo);
1446:                        if (geo instanceof  GeometryArrayRetained) {
1447:                            geo.isEditable = !((GeometryArrayRetained) geo)
1448:                                    .isWriteStatic();
1449:
1450:                            // TODO: for now if vertex data can be returned, then
1451:                            // don't apply static transform
1452:                            if (geo.source
1453:                                    .getCapability(GeometryArray.ALLOW_COORDINATE_READ)
1454:                                    || geo.source
1455:                                            .getCapability(GeometryArray.ALLOW_NORMAL_READ))
1456:                                return false;
1457:
1458:                        }
1459:
1460:                        if (!geo.canBeInDisplayList(alphaEditable)) {
1461:                            return false;
1462:                        }
1463:                    }
1464:                }
1465:                return true;
1466:            }
1467:
1468:            void compile(CompileState compState) {
1469:                AppearanceRetained newApp;
1470:
1471:                super .compile(compState);
1472:
1473:                if (isStatic() && staticXformCanBeApplied()) {
1474:                    mergeFlag = SceneGraphObjectRetained.MERGE;
1475:                    if (J3dDebug.devPhase && J3dDebug.debug) {
1476:                        compState.numShapesWStaticTG++;
1477:                    }
1478:                } else {
1479:                    mergeFlag = SceneGraphObjectRetained.DONT_MERGE;
1480:                    compState.keepTG = true;
1481:                }
1482:
1483:                if (J3dDebug.devPhase && J3dDebug.debug) {
1484:                    compState.numShapes++;
1485:                }
1486:
1487:                if (appearance != null) {
1488:                    appearance.compile(compState);
1489:                    // Non-static apperanace can still be compiled, since in compile
1490:                    // state we will be grouping all shapes that have same appearance
1491:                    // so, when the appearance changes, all the shapes will be affected
1492:                    // For non-static appearances, we don't get an equivalent appearance
1493:                    // from the compile state
1494:                    if (appearance.isStatic()) {
1495:                        newApp = compState.getAppearance(appearance);
1496:                        appearance = newApp;
1497:                    }
1498:                }
1499:
1500:                for (int i = 0; i < geometryList.size(); i++) {
1501:                    GeometryRetained geo = (GeometryRetained) geometryList
1502:                            .get(i);
1503:                    if (geo != null)
1504:                        geo.compile(compState);
1505:                }
1506:
1507:            }
1508:
1509:            void merge(CompileState compState) {
1510:
1511:                if (mergeFlag == SceneGraphObjectRetained.DONT_MERGE) {
1512:
1513:                    // no need to save the staticTransform here
1514:
1515:                    TransformGroupRetained saveStaticTransform = compState.staticTransform;
1516:                    compState.staticTransform = null;
1517:                    super .merge(compState);
1518:                    compState.staticTransform = saveStaticTransform;
1519:                } else {
1520:                    super .merge(compState);
1521:                }
1522:
1523:                if (shapeIsMergeable(compState)) {
1524:                    compState.addShape(this );
1525:                }
1526:            }
1527:
1528:            boolean shapeIsMergeable(CompileState compState) {
1529:                boolean mergeable = true;
1530:                AppearanceRetained newApp;
1531:                int i;
1532:
1533:                GeometryRetained geometry = null;
1534:                int index = 0;
1535:                i = 0;
1536:                /*
1537:                if (isPickable)
1538:                    return false;
1539:                 */
1540:
1541:                // For now, don't merge if the shape has static transform
1542:                if (staticTransform != null)
1543:                    return false;
1544:
1545:                // If this shape's to be immediate parent is orderedGroup or a switchNode
1546:                // this shape is not mergerable
1547:                if (parent instanceof  OrderedGroupRetained
1548:                        || parent instanceof  SwitchRetained)
1549:                    return false;
1550:
1551:                // Get the first geometry that is non-null
1552:                while (geometry == null && index < geometryList.size()) {
1553:                    geometry = (GeometryRetained) geometryList.get(index);
1554:                    index++;
1555:                }
1556:
1557:                if (!(geometry instanceof  GeometryArrayRetained)) {
1558:                    return false;
1559:                }
1560:
1561:                GeometryArrayRetained firstGeo = (GeometryArrayRetained) geometry;
1562:
1563:                for (i = index; (i < geometryList.size() && mergeable); i++) {
1564:                    geometry = (GeometryRetained) geometryList.get(i);
1565:                    if (geometry != null) {
1566:                        GeometryArrayRetained geo = (GeometryArrayRetained) geometry;
1567:
1568:                        if (!geo.isWriteStatic())
1569:                            mergeable = false;
1570:
1571:                        if (geo.vertexFormat != firstGeo.vertexFormat)
1572:                            mergeable = false;
1573:
1574:                    }
1575:                }
1576:
1577:                // For now, turn off lots of capability bits 
1578:                if (source.getCapability(Shape3D.ALLOW_COLLISION_BOUNDS_WRITE)
1579:                        || source.getCapability(Shape3D.ALLOW_APPEARANCE_WRITE)
1580:                        || source
1581:                                .getCapability(Shape3D.ALLOW_APPEARANCE_OVERRIDE_WRITE)
1582:                        || source
1583:                                .getCapability(Shape3D.ALLOW_AUTO_COMPUTE_BOUNDS_WRITE)
1584:                        || source.getCapability(Shape3D.ALLOW_BOUNDS_WRITE)
1585:                        || source.getCapability(Shape3D.ALLOW_COLLIDABLE_WRITE)
1586:                        || source.getCapability(Shape3D.ALLOW_PICKABLE_WRITE)
1587:                        || source.getCapability(Shape3D.ALLOW_GEOMETRY_WRITE)) {
1588:                    mergeable = false;
1589:                }
1590:
1591:                return mergeable;
1592:
1593:            }
1594:
1595:            void getMirrorObjects(ArrayList list, HashKey k) {
1596:                Shape3DRetained ms;
1597:                if (inSharedGroup) {
1598:                    if (k.count == 0) {
1599:                        //		System.err.println("===> CAN NEVER BE TRUE");
1600:                        return;
1601:                    } else {
1602:                        ms = getMirrorShape(k);
1603:                    }
1604:                } else {
1605:                    ms = (Shape3DRetained) mirrorShape3D.get(0);
1606:                }
1607:
1608:                list.add(getGeomAtom(ms));
1609:
1610:            }
1611:
1612:            // Called on the mirror Object
1613:            void addLight(LightRetained light) {
1614:                LightRetained[] newlights;
1615:                int i, n;
1616:                Shape3DRetained ms;
1617:
1618:                if (lights == null) {
1619:                    lights = new LightRetained[10];
1620:                } else if (lights.length == numlights) {
1621:                    newlights = new LightRetained[numlights * 2];
1622:                    for (i = 0; i < numlights; i++) {
1623:                        newlights[i] = lights[i];
1624:                    }
1625:                    lights = newlights;
1626:                }
1627:                lights[numlights] = light;
1628:                numlights++;
1629:            }
1630:
1631:            // called on the mirror object
1632:            void removeLight(LightRetained light) {
1633:                int i;
1634:
1635:                for (i = 0; i < numlights; i++) {
1636:                    if (lights[i] == light) {
1637:                        lights[i] = null;
1638:                        break;
1639:                    }
1640:                }
1641:
1642:                // Shift everyone down one.
1643:                for (i++; i < numlights; i++) {
1644:                    lights[i - 1] = lights[i];
1645:                }
1646:                numlights--;
1647:            }
1648:
1649:            // Called on the mirror object
1650:            void addFog(FogRetained fog) {
1651:                FogRetained[] newfogs;
1652:                int i;
1653:
1654:                if (fogs == null) {
1655:                    fogs = new FogRetained[10];
1656:                } else if (fogs.length == numfogs) {
1657:                    newfogs = new FogRetained[numfogs * 2];
1658:                    for (i = 0; i < numfogs; i++) {
1659:                        newfogs[i] = fogs[i];
1660:                    }
1661:                    fogs = newfogs;
1662:                }
1663:                fogs[numfogs] = fog;
1664:                numfogs++;
1665:            }
1666:
1667:            // called on the mirror object
1668:            void removeFog(FogRetained fog) {
1669:                int i;
1670:
1671:                for (i = 0; i < numfogs; i++) {
1672:                    if (fogs[i] == fog) {
1673:                        fogs[i] = null;
1674:                        break;
1675:                    }
1676:                }
1677:
1678:                // Shift everyone down one.
1679:                for (i++; i < numfogs; i++) {
1680:                    fogs[i - 1] = fogs[i];
1681:                }
1682:                numfogs--;
1683:
1684:            }
1685:
1686:            // Called on the mirror object
1687:            void addModelClip(ModelClipRetained modelClip) {
1688:                ModelClipRetained[] newModelClips;
1689:                int i;
1690:
1691:                if (modelClips == null) {
1692:                    modelClips = new ModelClipRetained[10];
1693:                } else if (modelClips.length == numModelClips) {
1694:                    newModelClips = new ModelClipRetained[numModelClips * 2];
1695:                    for (i = 0; i < numModelClips; i++) {
1696:                        newModelClips[i] = modelClips[i];
1697:                    }
1698:                    modelClips = newModelClips;
1699:                }
1700:                modelClips[numModelClips] = modelClip;
1701:                numModelClips++;
1702:            }
1703:
1704:            // called on the mirror object
1705:            void removeModelClip(ModelClipRetained modelClip) {
1706:                int i;
1707:
1708:                for (i = 0; i < numModelClips; i++) {
1709:                    if (modelClips[i] == modelClip) {
1710:                        modelClips[i] = null;
1711:                        break;
1712:                    }
1713:                }
1714:
1715:                // Shift everyone down one.
1716:                for (i++; i < numModelClips; i++) {
1717:                    modelClips[i - 1] = modelClips[i];
1718:                }
1719:                numModelClips--;
1720:
1721:            }
1722:
1723:            // Called on the mirror object
1724:            void addAltApp(AlternateAppearanceRetained aApp) {
1725:                AlternateAppearanceRetained[] newAltApps;
1726:                int i;
1727:                if (altApps == null) {
1728:                    altApps = new AlternateAppearanceRetained[10];
1729:                } else if (altApps.length == numAltApps) {
1730:                    newAltApps = new AlternateAppearanceRetained[numAltApps * 2];
1731:                    for (i = 0; i < numAltApps; i++) {
1732:                        newAltApps[i] = altApps[i];
1733:                    }
1734:                    altApps = newAltApps;
1735:                }
1736:                altApps[numAltApps] = aApp;
1737:                numAltApps++;
1738:            }
1739:
1740:            // called on the mirror object
1741:            void removeAltApp(AlternateAppearanceRetained aApp) {
1742:                int i;
1743:
1744:                for (i = 0; i < numAltApps; i++) {
1745:                    if (altApps[i] == aApp) {
1746:                        altApps[i] = null;
1747:                        break;
1748:                    }
1749:                }
1750:
1751:                // Shift everyone down one.
1752:                for (i++; i < numAltApps; i++) {
1753:                    altApps[i - 1] = altApps[i];
1754:                }
1755:                numAltApps--;
1756:
1757:            }
1758:
1759:            void updatePickable(HashKey keys[], boolean pick[]) {
1760:                super .updatePickable(keys, pick);
1761:                Shape3DRetained shape;
1762:
1763:                if (!inSharedGroup) {
1764:                    shape = (Shape3DRetained) mirrorShape3D.get(0);
1765:                    shape.isPickable = pick[0];
1766:                } else {
1767:                    int size = mirrorShape3D.size();
1768:                    for (int j = 0; j < keys.length; j++) {
1769:                        for (int i = 0; i < size; i++) {
1770:                            shape = (Shape3DRetained) mirrorShape3D.get(i);
1771:                            if (keys[j].equals(shape.key)) {
1772:                                shape.isPickable = pick[j];
1773:                                break;
1774:                            }
1775:
1776:                        }
1777:                    }
1778:                }
1779:            }
1780:
1781:            void updateCollidable(HashKey keys[], boolean collide[]) {
1782:                super .updateCollidable(keys, collide);
1783:                Shape3DRetained shape;
1784:
1785:                if (!inSharedGroup) {
1786:                    shape = (Shape3DRetained) mirrorShape3D.get(0);
1787:                    shape.isCollidable = collide[0];
1788:                } else {
1789:                    int size = mirrorShape3D.size();
1790:                    for (int j = 0; j < keys.length; j++) {
1791:                        for (int i = 0; i < size; i++) {
1792:                            shape = (Shape3DRetained) mirrorShape3D.get(i);
1793:                            if (keys[j].equals(shape.key)) {
1794:                                shape.isCollidable = collide[j];
1795:                                break;
1796:                            }
1797:
1798:                        }
1799:                    }
1800:                }
1801:            }
1802:
1803:            // New 1.2.1 code ....
1804:
1805:            // Remove the old geometry atoms and reInsert
1806:            // the new geometry atoms and update the transform
1807:            // target list
1808:
1809:            private void sendDataChangedMessage(GeometryRetained newGeom) {
1810:
1811:                int i, j, gaCnt;
1812:                GeometryAtom[] newGAArray = null;
1813:                GeometryAtom[] oldGAArray = null;
1814:                GeometryAtom[] newGeometryAtoms = null;
1815:                int geometryCnt = 0;
1816:                GeometryRetained geometry = null;
1817:
1818:                int s3dMSize = mirrorShape3D.size();
1819:
1820:                if (s3dMSize < 1)
1821:                    return;
1822:
1823:                Shape3DRetained mS3d = (Shape3DRetained) mirrorShape3D.get(0);
1824:
1825:                mS3d.mirrorShape3DLock.writeLock();
1826:
1827:                GeometryAtom oldGA = mS3d.geomAtom;
1828:
1829:                GeometryAtom newGA = new GeometryAtom();
1830:
1831:                if (newGeom != null) {
1832:                    newGeom.addUser(mS3d);
1833:                }
1834:
1835:                int gSize = geometryList.size();
1836:
1837:                for (i = 0; i < gSize; i++) {
1838:                    geometry = (GeometryRetained) geometryList.get(i);
1839:                    if (geometry != null) {
1840:                        newGA.geoType = geometry.geoType;
1841:                        newGA.alphaEditable = mS3d.isAlphaEditable(geometry);
1842:                        break;
1843:                    }
1844:                }
1845:
1846:                if ((geometry != null)
1847:                        && (geometry.geoType == GeometryRetained.GEO_TYPE_TEXT3D)) {
1848:
1849:                    for (i = 0; i < gSize; i++) {
1850:                        geometry = (GeometryRetained) geometryList.get(i);
1851:                        if (geometry != null) {
1852:                            Text3DRetained tempT3d = (Text3DRetained) geometry;
1853:                            geometryCnt += tempT3d.numChars;
1854:                        } else {
1855:                            // This is slightly wasteful, but not quite worth to optimize yet. 
1856:                            geometryCnt++;
1857:                        }
1858:                    }
1859:                    newGA.geometryArray = new GeometryRetained[geometryCnt];
1860:                    newGA.lastLocalTransformArray = new Transform3D[geometryCnt];
1861:                    // Reset geometryCnt;
1862:                    geometryCnt = 0;
1863:
1864:                } else {
1865:                    newGA.geometryArray = new GeometryRetained[gSize];
1866:                }
1867:
1868:                newGA.locale = mS3d.locale;
1869:                newGA.visible = visible;
1870:                newGA.source = mS3d;
1871:
1872:                for (gaCnt = 0; gaCnt < gSize; gaCnt++) {
1873:                    geometry = (GeometryRetained) geometryList.get(gaCnt);
1874:                    if (geometry == null) {
1875:                        newGA.geometryArray[geometryCnt++] = null;
1876:                    } else {
1877:                        if (geometry.geoType == GeometryRetained.GEO_TYPE_TEXT3D) {
1878:                            Text3DRetained t = (Text3DRetained) geometry;
1879:                            GeometryRetained geo;
1880:                            for (i = 0; i < t.numChars; i++, geometryCnt++) {
1881:                                geo = t.geometryList[i];
1882:                                if (geo != null) {
1883:                                    newGA.geometryArray[geometryCnt] = geo;
1884:                                    newGA.lastLocalTransformArray[geometryCnt] = t.charTransforms[i];
1885:
1886:                                } else {
1887:                                    newGA.geometryArray[geometryCnt] = null;
1888:                                    newGA.lastLocalTransformArray[geometryCnt] = null;
1889:                                }
1890:
1891:                            }
1892:
1893:                        } else {
1894:                            newGA.geometryArray[geometryCnt++] = geometry;
1895:                        }
1896:                    }
1897:                }
1898:
1899:                oldGAArray = new GeometryAtom[s3dMSize];
1900:                newGAArray = new GeometryAtom[s3dMSize];
1901:                oldGAArray[0] = oldGA;
1902:                newGAArray[0] = newGA;
1903:
1904:                mS3d.geomAtom = newGA;
1905:                mS3d.mirrorShape3DLock.writeUnlock();
1906:
1907:                // ..... clone the rest of mirrorS3D's GA with the above newGA, but modify
1908:                // its source.
1909:
1910:                for (i = 1; i < s3dMSize; i++) {
1911:                    mS3d = (Shape3DRetained) mirrorShape3D.get(i);
1912:                    mS3d.mirrorShape3DLock.writeLock();
1913:                    oldGA = mS3d.geomAtom;
1914:                    newGA = new GeometryAtom();
1915:
1916:                    if (newGeom != null) {
1917:                        newGeom.addUser(mS3d);
1918:                    }
1919:
1920:                    newGA.geoType = newGAArray[0].geoType;
1921:                    newGA.locale = mS3d.locale;
1922:                    newGA.visible = visible;
1923:                    newGA.source = mS3d;
1924:                    newGA.alphaEditable = newGAArray[0].alphaEditable;
1925:
1926:                    newGA.geometryArray = new GeometryRetained[newGAArray[0].geometryArray.length];
1927:                    for (j = 0; j < newGA.geometryArray.length; j++) {
1928:                        newGA.geometryArray[j] = newGAArray[0].geometryArray[j];
1929:                    }
1930:
1931:                    oldGAArray[i] = oldGA;
1932:                    newGAArray[i] = newGA;
1933:
1934:                    mS3d.geomAtom = newGA;
1935:                    mS3d.mirrorShape3DLock.writeUnlock();
1936:                }
1937:
1938:                TargetsInterface ti = ((GroupRetained) parent)
1939:                        .getClosestTargetsInterface(TargetsInterface.TRANSFORM_TARGETS);
1940:                CachedTargets[] newCtArr = null;
1941:
1942:                if (ti != null) {
1943:                    CachedTargets ct;
1944:                    newCtArr = new CachedTargets[s3dMSize];
1945:
1946:                    for (i = 0; i < s3dMSize; i++) {
1947:
1948:                        ct = ti.getCachedTargets(
1949:                                TargetsInterface.TRANSFORM_TARGETS, i, -1);
1950:                        if (ct != null) {
1951:                            newCtArr[i] = new CachedTargets();
1952:                            newCtArr[i].copy(ct);
1953:                            newCtArr[i].replace(oldGAArray[i], newGAArray[i],
1954:                                    Targets.GEO_TARGETS);
1955:                        } else {
1956:                            newCtArr[i] = null;
1957:                        }
1958:                    }
1959:                    ti.resetCachedTargets(TargetsInterface.TRANSFORM_TARGETS,
1960:                            newCtArr, -1);
1961:                }
1962:
1963:                J3dMessage changeMessage = new J3dMessage();
1964:                changeMessage.type = J3dMessage.SHAPE3D_CHANGED;
1965:                // Who to send this message to ?	
1966:                changeMessage.threads = J3dThread.UPDATE_RENDER
1967:                        | J3dThread.UPDATE_TRANSFORM
1968:                        | J3dThread.UPDATE_GEOMETRY;
1969:                changeMessage.universe = universe;
1970:                changeMessage.args[0] = this ;
1971:                changeMessage.args[1] = new Integer(GEOMETRY_CHANGED);
1972:                changeMessage.args[2] = oldGAArray;
1973:                changeMessage.args[3] = newGAArray;
1974:                if (ti != null) {
1975:                    changeMessage.args[4] = ti;
1976:                    changeMessage.args[5] = newCtArr;
1977:                }
1978:                if (boundsAutoCompute) {
1979:                    getCombineBounds((BoundingBox) localBounds);
1980:                }
1981:                VirtualUniverse.mc.processMessage(changeMessage);
1982:
1983:            }
1984:
1985:            // ********** End of New 1.2.1 code ....
1986:
1987:            Shape3DRetained getMirrorShape(SceneGraphPath path) {
1988:                if (!inSharedGroup) {
1989:                    return (Shape3DRetained) mirrorShape3D.get(0);
1990:                }
1991:                HashKey key = new HashKey("");
1992:                path.getHashKey(key);
1993:                return getMirrorShape(key);
1994:            }
1995:
1996:            Shape3DRetained getMirrorShape(HashKey key) {
1997:                if (key == null) {
1998:                    return (Shape3DRetained) mirrorShape3D.get(0);
1999:                } else {
2000:                    int i = key.equals(localToVworldKeys, 0,
2001:                            localToVworldKeys.length);
2002:
2003:                    if (i >= 0) {
2004:                        return (Shape3DRetained) mirrorShape3D.get(i);
2005:                    }
2006:                }
2007:                // Not possible
2008:                throw new RuntimeException(
2009:                        "Shape3DRetained: MirrorShape Not found!");
2010:            }
2011:
2012:            void setBoundsAutoCompute(boolean autoCompute) {
2013:                GeometryRetained geometry;
2014:                if (autoCompute != boundsAutoCompute) {
2015:                    if (autoCompute) {
2016:                        // localBounds may not have been set to bbox
2017:                        localBounds = new BoundingBox((BoundingBox) null);
2018:                        if (source.isLive() && geometryList != null) {
2019:                            int size = geometryList.size()
2020:                                    * mirrorShape3D.size();
2021:                            for (int i = 0; i < size; i++) {
2022:                                geometry = (GeometryRetained) geometryList
2023:                                        .get(i);
2024:                                geometry.incrComputeGeoBounds();
2025:                            }
2026:                        }
2027:
2028:                        getCombineBounds((BoundingBox) localBounds);
2029:                    } else {
2030:                        if (source.isLive() && geometryList != null) {
2031:                            int size = geometryList.size()
2032:                                    * mirrorShape3D.size();
2033:                            for (int i = 0; i < size; i++) {
2034:                                geometry = (GeometryRetained) geometryList
2035:                                        .get(i);
2036:                                geometry.decrComputeGeoBounds();
2037:                            }
2038:
2039:                        }
2040:                    }
2041:                    super .setBoundsAutoCompute(autoCompute);
2042:                    if (source.isLive()) {
2043:                        J3dMessage message = new J3dMessage();
2044:                        message.type = J3dMessage.BOUNDS_AUTO_COMPUTE_CHANGED;
2045:                        message.threads = J3dThread.UPDATE_TRANSFORM
2046:                                | J3dThread.UPDATE_GEOMETRY
2047:                                | J3dThread.UPDATE_RENDER;
2048:                        message.universe = universe;
2049:                        message.args[0] = getGeomAtomsArray(mirrorShape3D);
2050:                        // no need to clone localBounds
2051:                        message.args[1] = localBounds;
2052:                        VirtualUniverse.mc.processMessage(message);
2053:                    }
2054:                }
2055:            }
2056:
2057:            // This method is called when coordinates of a geometry in the geometrylist
2058:            // changed and autoBoundsCompute is true
2059:
2060:            void updateBounds() {
2061:                localBounds = new BoundingBox((BoundingBox) null);
2062:                getCombineBounds((BoundingBox) localBounds);
2063:                synchronized (mirrorShape3D) {
2064:                    if (source.isLive()) {
2065:                        J3dMessage message = new J3dMessage();
2066:                        message.type = J3dMessage.BOUNDS_AUTO_COMPUTE_CHANGED;
2067:                        message.threads = J3dThread.UPDATE_TRANSFORM
2068:                                | J3dThread.UPDATE_GEOMETRY
2069:                                | J3dThread.UPDATE_RENDER;
2070:                        message.universe = universe;
2071:                        message.args[0] = getGeomAtomsArray(mirrorShape3D);
2072:                        // no need to clone localBounds
2073:                        message.args[1] = localBounds;
2074:                        VirtualUniverse.mc.processMessage(message);
2075:                    }
2076:                }
2077:            }
2078:
2079:            boolean allowIntersect() {
2080:                GeometryRetained ga = null;
2081:
2082:                for (int i = 0; i < geometryList.size(); i++) {
2083:                    ga = (GeometryRetained) geometryList.get(i);
2084:                    if (ga != null)
2085:                        if (!ga.source.getCapability(Geometry.ALLOW_INTERSECT)) {
2086:                            return false;
2087:                        }
2088:                }
2089:                return true;
2090:            }
2091:
2092:            boolean intersectGeometryList(Shape3DRetained otherShape) {
2093:                GeometryRetained geom1, geom2;
2094:                ArrayList gaList = otherShape.geometryList;
2095:                int gaSize = gaList.size();
2096:                Transform3D otherLocalToVworld = otherShape
2097:                        .getCurrentLocalToVworld();
2098:                Transform3D this LocalToVworld = getCurrentLocalToVworld();
2099:                View views = null;
2100:                int primaryViewIdx = -1;
2101:
2102:                if (this  instanceof  OrientedShape3DRetained) {
2103:                    primaryViewIdx = getPrimaryViewIdx();
2104:                    this LocalToVworld.mul(((OrientedShape3DRetained) this )
2105:                            .getOrientedTransform(primaryViewIdx));
2106:                }
2107:
2108:                if (otherShape instanceof  OrientedShape3DRetained) {
2109:                    if (primaryViewIdx < 0) {
2110:                        primaryViewIdx = getPrimaryViewIdx();
2111:                    }
2112:                    otherLocalToVworld
2113:                            .mul(((OrientedShape3DRetained) otherShape)
2114:                                    .getOrientedTransform(primaryViewIdx));
2115:                }
2116:
2117:                for (int i = geometryList.size() - 1; i >= 0; i--) {
2118:                    geom1 = (GeometryRetained) geometryList.get(i);
2119:                    if (geom1 != null) {
2120:                        for (int j = gaSize - 1; j >= 0; j--) {
2121:                            geom2 = (GeometryRetained) gaList.get(j);
2122:                            if ((geom2 != null)
2123:                                    && geom1.intersect(this LocalToVworld,
2124:                                            otherLocalToVworld, geom2)) {
2125:                                return true;
2126:                            }
2127:                        }
2128:                    }
2129:                }
2130:
2131:                return false;
2132:            }
2133:
2134:            boolean intersectGeometryList(Transform3D this LocalToVworld,
2135:                    Bounds targetBound) {
2136:
2137:                GeometryRetained geometry;
2138:
2139:                if (this  instanceof  OrientedShape3DRetained) {
2140:                    Transform3D orientedTransform = ((OrientedShape3DRetained) this )
2141:                            .getOrientedTransform(getPrimaryViewIdx());
2142:                    this LocalToVworld.mul(orientedTransform);
2143:                }
2144:
2145:                for (int i = geometryList.size() - 1; i >= 0; i--) {
2146:                    geometry = (GeometryRetained) geometryList.get(i);
2147:                    if ((geometry != null)
2148:                            && geometry.intersect(this LocalToVworld,
2149:                                    targetBound)) {
2150:                        return true;
2151:                    }
2152:                }
2153:
2154:                return false;
2155:
2156:            }
2157:
2158:            /**
2159:             * This initialize the mirror shape to reflect the state of the
2160:             * real Morph.
2161:             */
2162:            void initMirrorShape3D(SetLiveState s, MorphRetained morph,
2163:                    int index) {
2164:
2165:                GeometryRetained geometry;
2166:
2167:                GeometryAtom[] newGeometryAtoms = null;
2168:
2169:                universe = morph.universe;
2170:                inSharedGroup = morph.inSharedGroup;
2171:                inBackgroundGroup = morph.inBackgroundGroup;
2172:                geometryBackground = morph.geometryBackground;
2173:                parent = morph.parent;
2174:                locale = morph.locale;
2175:
2176:                OrderedPath op = (OrderedPath) s.orderedPaths.get(index);
2177:                if (op.pathElements.size() == 0) {
2178:                    orderedPath = null;
2179:                } else {
2180:                    orderedPath = op;
2181:                }
2182:
2183:                staticTransform = morph.staticTransform;
2184:                if (morph.boundsAutoCompute) {
2185:                    localBounds.set(morph.localBounds);
2186:                }
2187:                bounds = localBounds;
2188:                vwcBounds = new BoundingBox((BoundingBox) null);
2189:                vwcBounds.transform(bounds, getCurrentLocalToVworld(0));
2190:
2191:                if (morph.collisionBound == null) {
2192:                    collisionBound = null;
2193:                    collisionVwcBound = vwcBounds;
2194:                } else {
2195:                    collisionBound = morph.collisionBound;
2196:                    collisionVwcBound = (Bounds) collisionBound.clone();
2197:                    collisionVwcBound.transform(getCurrentLocalToVworld(0));
2198:                }
2199:
2200:                appearanceOverrideEnable = morph.appearanceOverrideEnable;
2201:
2202:                // mga is the final geometry we're interested.
2203:                geometryList = new ArrayList(1);
2204:                geometryList
2205:                        .add((GeometryArrayRetained) morph.morphedGeometryArray.retained);
2206:
2207:                GeometryAtom gAtom = new GeometryAtom();
2208:                gAtom.geometryArray = new GeometryRetained[1];
2209:
2210:                gAtom.locale = locale;
2211:                gAtom.visible = morph.visible;
2212:                gAtom.source = this ;
2213:
2214:                geometry = (GeometryRetained) geometryList.get(0);
2215:
2216:                if (geometry == null) {
2217:                    gAtom.geometryArray[0] = null;
2218:                } else {
2219:                    gAtom.geometryArray[0] = (GeometryArrayRetained) morph.morphedGeometryArray.retained;
2220:                    gAtom.geoType = gAtom.geometryArray[0].geoType;
2221:                }
2222:                geomAtom = gAtom;
2223:
2224:                // Assign the parent of this mirror shape node
2225:                sourceNode = morph;
2226:            }
2227:
2228:            // geometries in morph object is modified, update the geometry
2229:            // list in the mirror shapes and the geometry array in the geometry atom
2230:
2231:            void setMorphGeometry(Geometry geometry, ArrayList mirrorShapes) {
2232:                GeometryAtom oldGA, newGA;
2233:                Shape3DRetained ms;
2234:                TransformGroupRetained tg;
2235:                int nMirrorShapes = mirrorShapes.size();
2236:                int i;
2237:
2238:                GeometryAtom oldGAArray[] = new GeometryAtom[nMirrorShapes];
2239:                GeometryAtom newGAArray[] = new GeometryAtom[nMirrorShapes];
2240:
2241:                for (i = 0; i < nMirrorShapes; i++) {
2242:                    ms = (Shape3DRetained) mirrorShapes.get(i);
2243:
2244:                    oldGA = Shape3DRetained.getGeomAtom(ms);
2245:
2246:                    ms.geometryList = new ArrayList(1);
2247:                    ms.geometryList
2248:                            .add((GeometryArrayRetained) geometry.retained);
2249:
2250:                    newGA = new GeometryAtom();
2251:                    newGA.geometryArray = new GeometryRetained[1];
2252:
2253:                    if (geometry == null) {
2254:                        newGA.geometryArray[0] = null;
2255:                    } else {
2256:                        newGA.geometryArray[0] = (GeometryArrayRetained) geometry.retained;
2257:                        newGA.geoType = newGA.geometryArray[0].geoType;
2258:                    }
2259:
2260:                    newGA.locale = locale;
2261:                    newGA.visible = oldGA.visible;
2262:                    newGA.source = this ;
2263:
2264:                    oldGAArray[i] = oldGA;
2265:                    newGAArray[i] = newGA;
2266:
2267:                    Shape3DRetained.setGeomAtom(ms, newGA);
2268:                }
2269:
2270:                TargetsInterface ti = ((GroupRetained) parent)
2271:                        .getClosestTargetsInterface(TargetsInterface.TRANSFORM_TARGETS);
2272:                CachedTargets[] newCtArr = null;
2273:
2274:                if (ti != null) {
2275:                    CachedTargets ct;
2276:                    newCtArr = new CachedTargets[nMirrorShapes];
2277:
2278:                    for (i = 0; i < nMirrorShapes; i++) {
2279:
2280:                        ct = ti.getCachedTargets(
2281:                                TargetsInterface.TRANSFORM_TARGETS, i, -1);
2282:                        if (ct != null) {
2283:                            newCtArr[i] = new CachedTargets();
2284:                            newCtArr[i].copy(ct);
2285:                            newCtArr[i].replace(oldGAArray[i], newGAArray[i],
2286:                                    Targets.GEO_TARGETS);
2287:                        } else {
2288:                            newCtArr[i] = null;
2289:                        }
2290:                    }
2291:                }
2292:
2293:                // send a Shape GEOMETRY_CHANGED message for all geometry atoms
2294:
2295:                J3dMessage changeMessage = new J3dMessage();
2296:                changeMessage.type = J3dMessage.SHAPE3D_CHANGED;
2297:                changeMessage.threads = J3dThread.UPDATE_RENDER
2298:                        | J3dThread.UPDATE_TRANSFORM
2299:                        | J3dThread.UPDATE_GEOMETRY;
2300:                changeMessage.universe = universe;
2301:                changeMessage.args[0] = this ;
2302:                changeMessage.args[1] = new Integer(GEOMETRY_CHANGED);
2303:                changeMessage.args[2] = oldGAArray;
2304:                changeMessage.args[3] = newGAArray;
2305:                if (ti != null) {
2306:                    changeMessage.args[4] = ti;
2307:                    changeMessage.args[5] = newCtArr;
2308:                }
2309:                VirtualUniverse.mc.processMessage(changeMessage);
2310:            }
2311:
2312:            /**
2313:             * Return an array of geometry atoms belongs to userList.
2314:             * The input is an arraylist of Shape3DRetained type.
2315:             * This is used to send a message of the snapshot of the 
2316:             * geometry atoms that are affected by this change.
2317:             */
2318:            final static GeometryAtom[] getGeomAtomsArray(ArrayList userList) {
2319:                Shape3DRetained ms = null;
2320:                GeometryAtom[] gaArr = null;
2321:                int size, nullCnt = 0, i, j;
2322:
2323:                synchronized (userList) {
2324:                    size = userList.size();
2325:                    gaArr = new GeometryAtom[size];
2326:                    for (i = 0; i < size; i++) {
2327:                        ms = (Shape3DRetained) userList.get(i);
2328:                        ms.mirrorShape3DLock.readLock();
2329:                        if (ms.geomAtom == null) {
2330:                            nullCnt++;
2331:                        }
2332:                        gaArr[i] = ms.geomAtom;
2333:                        ms.mirrorShape3DLock.readUnlock();
2334:                    }
2335:                }
2336:                if (nullCnt == 0) {
2337:                    return gaArr;
2338:                } else if (nullCnt == size) {
2339:                    return null;
2340:                } else {
2341:                    GeometryAtom[] newGaArr = new GeometryAtom[size - nullCnt];
2342:
2343:                    for (i = 0, j = 0; i < size; i++) {
2344:                        if (gaArr[i] != null) {
2345:                            newGaArr[j++] = gaArr[i];
2346:                        }
2347:                    }
2348:                    return newGaArr;
2349:                }
2350:            }
2351:
2352:            /**
2353:             * Return a list of geometry atoms belongs to userList and places a list of
2354:             * universe found in userList in univList.
2355:             * The input is an array of Shape3DRetained type.
2356:             * univList is assume to be empty.
2357:             * This is used to send a message of the snapshot of the 
2358:             * geometry atoms that are affected by this change.
2359:             */
2360:            final static ArrayList getGeomAtomsList(ArrayList userList,
2361:                    ArrayList univList) {
2362:                ArrayList listPerUniverse = new ArrayList();
2363:                int index;
2364:                ArrayList gaList = null;
2365:                Shape3DRetained ms = null;
2366:                boolean moreThanOneUniv = false;
2367:                VirtualUniverse firstFndUniv = null;
2368:
2369:                synchronized (userList) {
2370:                    for (int i = userList.size() - 1; i >= 0; i--) {
2371:                        ms = (Shape3DRetained) userList.get(i);
2372:
2373:                        if (moreThanOneUniv == false) {
2374:                            if (firstFndUniv == null) {
2375:                                firstFndUniv = ms.universe;
2376:                                univList.add(ms.universe);
2377:
2378:                                gaList = new ArrayList();
2379:                                listPerUniverse.add(gaList);
2380:                            } else if (firstFndUniv != ms.universe) {
2381:                                moreThanOneUniv = true;
2382:                                univList.add(ms.universe);
2383:                                gaList = new ArrayList();
2384:                                listPerUniverse.add(gaList);
2385:                            }
2386:                        } else {
2387:                            index = univList.indexOf(ms.universe);
2388:                            if (index < 0) {
2389:                                univList.add(ms.universe);
2390:                                gaList = new ArrayList();
2391:                                listPerUniverse.add(gaList);
2392:                            } else {
2393:                                gaList = (ArrayList) listPerUniverse.get(index);
2394:                            }
2395:                        }
2396:
2397:                        ms.mirrorShape3DLock.readLock();
2398:
2399:                        if (ms.geomAtom != null) {
2400:                            gaList.add(ms.geomAtom);
2401:                        }
2402:                        ms.mirrorShape3DLock.readUnlock();
2403:
2404:                    }
2405:                }
2406:                return listPerUniverse;
2407:            }
2408:
2409:            final static GeometryAtom getGeomAtom(Shape3DRetained shape) {
2410:                GeometryAtom ga;
2411:
2412:                shape.mirrorShape3DLock.readLock();
2413:                ga = shape.geomAtom;
2414:                shape.mirrorShape3DLock.readUnlock();
2415:
2416:                return ga;
2417:            }
2418:
2419:            final static void setGeomAtom(Shape3DRetained shape, GeometryAtom ga) {
2420:                shape.mirrorShape3DLock.writeLock();
2421:                shape.geomAtom = ga;
2422:                shape.mirrorShape3DLock.writeUnlock();
2423:            }
2424:
2425:            // Alpha is editable due to the appearance
2426:            boolean isAlphaEditable(GeometryRetained geo) {
2427:
2428:                boolean alphaEditable = false;
2429:
2430:                if (appearanceOverrideEnable) {
2431:                    alphaEditable = true;
2432:                } else if (geo != null && appearance != null) {
2433:
2434:                    AppearanceRetained app = appearance;
2435:
2436:                    if (source.getCapability(Shape3D.ALLOW_APPEARANCE_WRITE)
2437:                            || source
2438:                                    .getCapability(Shape3D.ALLOW_APPEARANCE_OVERRIDE_WRITE)
2439:                            ||
2440:
2441:                            app.source
2442:                                    .getCapability(Appearance.ALLOW_RENDERING_ATTRIBUTES_WRITE)
2443:                            ||
2444:
2445:                            app.source
2446:                                    .getCapability(Appearance.ALLOW_TRANSPARENCY_ATTRIBUTES_WRITE)
2447:                            ||
2448:
2449:                            (app.renderingAttributes != null && (app.renderingAttributes.source
2450:                                    .getCapability(RenderingAttributes.ALLOW_ALPHA_TEST_FUNCTION_WRITE) || app.renderingAttributes.source
2451:                                    .getCapability(RenderingAttributes.ALLOW_IGNORE_VERTEX_COLORS_WRITE)))
2452:                            ||
2453:
2454:                            (app.transparencyAttributes != null && (app.transparencyAttributes.source
2455:                                    .getCapability(TransparencyAttributes.ALLOW_MODE_WRITE) || app.transparencyAttributes.source
2456:                                    .getCapability(TransparencyAttributes.ALLOW_VALUE_WRITE)))) {
2457:
2458:                        alphaEditable = true;
2459:
2460:                    } else if (geo instanceof  GeometryArrayRetained
2461:                            && (app.source
2462:                                    .getCapability(Appearance.ALLOW_TEXTURE_ATTRIBUTES_WRITE) ||
2463:
2464:                            (app.textureAttributes != null && app.textureAttributes.source
2465:                                    .getCapability(TextureAttributes.ALLOW_MODE_WRITE)))) {
2466:
2467:                        alphaEditable = true;
2468:
2469:                    } else if (geo instanceof  RasterRetained) {
2470:                        if ((((RasterRetained) geo).type & Raster.RASTER_COLOR) != 0
2471:                                && ((RasterRetained) geo).source
2472:                                        .getCapability(Raster.ALLOW_IMAGE_WRITE)) {
2473:
2474:                            alphaEditable = true;
2475:                        }
2476:                    }
2477:                }
2478:                return alphaEditable;
2479:            }
2480:
2481:            // getCombineBounds is faster than computeCombineBounds since it
2482:            // does not recompute the geometry.geoBounds
2483:            void getCombineBounds(BoundingBox bounds) {
2484:
2485:                if (geometryList != null) {
2486:                    BoundingBox bbox = null;
2487:                    GeometryRetained geometry;
2488:
2489:                    if (staticTransform != null) {
2490:                        bbox = new BoundingBox((BoundingBox) null);
2491:                    }
2492:
2493:                    synchronized (bounds) {
2494:                        bounds.setLower(1.0, 1.0, 1.0);
2495:                        bounds.setUpper(-1.0, -1.0, -1.0);
2496:                        for (int i = 0; i < geometryList.size(); i++) {
2497:                            geometry = (GeometryRetained) geometryList.get(i);
2498:                            if ((geometry != null)
2499:                                    && (geometry.geoType != GeometryRetained.GEO_TYPE_NONE)) {
2500:                                synchronized (geometry.geoBounds) {
2501:                                    if (staticTransform != null) {
2502:                                        bbox.set(geometry.geoBounds);
2503:                                        bbox
2504:                                                .transform(staticTransform.transform);
2505:                                        bounds.combine((Bounds) bbox);
2506:                                    } else {
2507:                                        bounds
2508:                                                .combine((Bounds) geometry.geoBounds);
2509:                                    }
2510:                                }
2511:                            }
2512:                        }
2513:                    }
2514:
2515:                    // System.err.println("Shape3DRetained - getCombineBounds");
2516:                    // Enlarge boundingBox to the "minmium bounds" that encompasses all possible
2517:                    // orientation.
2518:                    if (this  instanceof  OrientedShape3DRetained) {
2519:                        double maxVal = Math.abs(bounds.lower.x);
2520:                        double tempVal = Math.abs(bounds.upper.x);
2521:                        if (tempVal > maxVal)
2522:                            maxVal = tempVal;
2523:                        tempVal = Math.abs(bounds.lower.y);
2524:                        if (tempVal > maxVal)
2525:                            maxVal = tempVal;
2526:                        tempVal = Math.abs(bounds.upper.y);
2527:                        if (tempVal > maxVal)
2528:                            maxVal = tempVal;
2529:                        tempVal = Math.abs(bounds.lower.z);
2530:                        if (tempVal > maxVal)
2531:                            maxVal = tempVal;
2532:                        tempVal = Math.abs(bounds.upper.z);
2533:                        if (tempVal > maxVal)
2534:                            maxVal = tempVal;
2535:
2536:                        // System.err.println("Shape3DRetained - bounds (Before) " + bounds);
2537:                        bounds.setLower(-maxVal, -maxVal, -maxVal);
2538:                        bounds.setUpper(maxVal, maxVal, maxVal);
2539:                        // System.err.println("Shape3DRetained - bounds (After) " + bounds);
2540:                    }
2541:
2542:                }
2543:            }
2544:
2545:            boolean isEquivalent(Shape3DRetained shape) {
2546:                if (this .appearance != shape.appearance
2547:                        ||
2548:                        // Scoping info should be same since they are under same group
2549:                        this .appearanceOverrideEnable != shape.appearanceOverrideEnable
2550:                        || this .isPickable != shape.isPickable
2551:                        || this .isCollidable != shape.isCollidable) {
2552:
2553:                    return false;
2554:                }
2555:                if (this .boundsAutoCompute) {
2556:                    if (!shape.boundsAutoCompute)
2557:                        return false;
2558:                } else {
2559:                    // If bounds autoCompute is false
2560:                    // Then check if both bounds are equal
2561:                    if (this .localBounds != null) {
2562:                        if (shape.localBounds != null) {
2563:                            return this .localBounds.equals(shape.localBounds);
2564:                        }
2565:                    } else if (shape.localBounds != null) {
2566:                        return false;
2567:                    }
2568:                }
2569:                if (collisionBound != null) {
2570:                    if (shape.collisionBound == null)
2571:                        return false;
2572:                    else
2573:                        return collisionBound.equals(shape.collisionBound);
2574:                } else if (shape.collisionBound != null)
2575:                    return false;
2576:
2577:                return true;
2578:            }
2579:
2580:            // Bounds can only be set after the geometry is setLived, so has to be done
2581:            // here, if we are not using switchVwcBounds
2582:            void initializeGAtom(Shape3DRetained ms) {
2583:                int i, gaCnt;
2584:                int geometryCnt = 0;
2585:                int gSize = geometryList.size();
2586:                GeometryRetained geometry = null;
2587:
2588:                ms.bounds = localBounds;
2589:                ms.vwcBounds = new BoundingBox((BoundingBox) null);
2590:                ms.vwcBounds
2591:                        .transform(ms.bounds, ms.getCurrentLocalToVworld(0));
2592:
2593:                if (collisionBound == null) {
2594:                    ms.collisionBound = null;
2595:                    ms.collisionVwcBound = ms.vwcBounds;
2596:                } else {
2597:                    ms.collisionBound = collisionBound;
2598:                    ms.collisionVwcBound = (Bounds) ms.collisionBound.clone();
2599:                    ms.collisionVwcBound.transform(ms
2600:                            .getCurrentLocalToVworld(0));
2601:                }
2602:                GeometryAtom gAtom = new GeometryAtom();
2603:                for (gaCnt = 0; gaCnt < gSize; gaCnt++) {
2604:                    geometry = (GeometryRetained) geometryList.get(gaCnt);
2605:                    if (geometry != null) {
2606:                        gAtom.geoType = geometry.geoType;
2607:                        gAtom.alphaEditable = ms.isAlphaEditable(geometry);
2608:                        break;
2609:                    }
2610:                }
2611:                if ((geometry != null)
2612:                        && (geometry.geoType == GeometryRetained.GEO_TYPE_TEXT3D)) {
2613:
2614:                    for (gaCnt = 0; gaCnt < gSize; gaCnt++) {
2615:                        geometry = (GeometryRetained) geometryList.get(gaCnt);
2616:                        if (geometry != null) {
2617:                            Text3DRetained tempT3d = (Text3DRetained) geometry;
2618:                            geometryCnt += tempT3d.numChars;
2619:                        } else {
2620:                            // This is slightly wasteful, but not quite worth to optimize yet. 
2621:                            geometryCnt++;
2622:                        }
2623:                    }
2624:                    gAtom.geometryArray = new GeometryRetained[geometryCnt];
2625:                    gAtom.lastLocalTransformArray = new Transform3D[geometryCnt];
2626:                    // Reset geometryCnt;
2627:                    geometryCnt = 0;
2628:
2629:                } else {
2630:                    gAtom.geometryArray = new GeometryRetained[gSize];
2631:                }
2632:
2633:                for (gaCnt = 0; gaCnt < geometryList.size(); gaCnt++) {
2634:                    geometry = (GeometryRetained) geometryList.get(gaCnt);
2635:                    if (geometry == null) {
2636:                        gAtom.geometryArray[gaCnt] = null;
2637:                    } else {
2638:                        if (geometry.geoType == GeometryRetained.GEO_TYPE_TEXT3D) {
2639:                            Text3DRetained t = (Text3DRetained) geometry;
2640:                            GeometryRetained geo;
2641:                            for (i = 0; i < t.numChars; i++, geometryCnt++) {
2642:                                geo = t.geometryList[i];
2643:                                if (geo != null) {
2644:                                    gAtom.geometryArray[geometryCnt] = geo;
2645:                                    gAtom.lastLocalTransformArray[geometryCnt] = t.charTransforms[i];
2646:                                } else {
2647:                                    gAtom.geometryArray[geometryCnt] = null;
2648:                                    gAtom.lastLocalTransformArray[geometryCnt] = null;
2649:                                }
2650:
2651:                            }
2652:
2653:                        } else {
2654:                            gAtom.geometryArray[gaCnt] = geometry;
2655:                        }
2656:                    }
2657:                }
2658:                gAtom.locale = ms.locale;
2659:                gAtom.visible = visible;
2660:                gAtom.source = ms;
2661:                ms.geomAtom = gAtom;
2662:            }
2663:
2664:            // Check if geomRetained's class is equivalence with the geometry class.
2665:            void checkEquivalenceClass(Geometry geometry, int index) {
2666:
2667:                if (geometry != null) {
2668:                    for (int i = geometryList.size() - 1; i >= 0; i--) {
2669:                        GeometryRetained geomRetained = (GeometryRetained) geometryList
2670:                                .get(i);
2671:                        if ((geomRetained != null) && (index != i)) { // this geometry will replace
2672:                            // current one so there is no need to check
2673:                            if (!geomRetained
2674:                                    .isEquivalenceClass((GeometryRetained) geometry.retained)) {
2675:                                throw new IllegalArgumentException(J3dI18N
2676:                                        .getString("Shape3DRetained5"));
2677:                            }
2678:                            break;
2679:                        }
2680:                    }
2681:                }
2682:            }
2683:
2684:            int indexOfGeometry(Geometry geometry) {
2685:                if (geometry != null)
2686:                    return geometryList.indexOf(geometry.retained);
2687:                else
2688:                    return geometryList.indexOf(null);
2689:            }
2690:
2691:            // Removes the specified geometry from this Shape3DRetained's list of geometries 
2692:            void removeGeometry(Geometry geometry) {
2693:                int ind = indexOfGeometry(geometry);
2694:                if (ind >= 0)
2695:                    removeGeometry(ind);
2696:            }
2697:
2698:            // Removes all the geometries from this node
2699:            void removeAllGeometries() {
2700:                int n = geometryList.size();
2701:
2702:                int i;
2703:                Shape3DRetained mShape;
2704:                GeometryRetained oldGeom = null;
2705:
2706:                if (((Shape3D) this .source).isLive()) {
2707:                    for (int index = n - 1; index >= 0; index--) {
2708:                        oldGeom = (GeometryRetained) (geometryList.get(index));
2709:                        if (oldGeom != null) {
2710:                            oldGeom.clearLive(refCount);
2711:                            oldGeom.decRefCnt();
2712:                            for (i = 0; i < mirrorShape3D.size(); i++) {
2713:                                mShape = (Shape3DRetained) mirrorShape3D.get(i);
2714:                                oldGeom.removeUser(mShape);
2715:                            }
2716:                        }
2717:                        geometryList.remove(index);
2718:                    }
2719:                    sendDataChangedMessage(null);
2720:                } else {
2721:                    for (int index = n - 1; index >= 0; index--) {
2722:                        oldGeom = (GeometryRetained) (geometryList.get(index));
2723:                        if (oldGeom != null) {
2724:                            oldGeom.decRefCnt();
2725:                        }
2726:                        geometryList.remove(index);
2727:                    }
2728:                }
2729:                dirtyBoundsCache();
2730:            }
2731:
2732:            boolean willRemainOpaque(int geoType) {
2733:                if (appearance == null
2734:                        || (appearance.isStatic() && appearance
2735:                                .isOpaque(geoType))) {
2736:                    return true;
2737:                } else {
2738:                    return false;
2739:                }
2740:
2741:            }
2742:
2743:            void handleFrequencyChange(int bit) {
2744:                int mask = 0;
2745:                if (bit == Shape3D.ALLOW_GEOMETRY_WRITE) {
2746:                    mask = GEOMETRY_CHANGED;
2747:                } else if (bit == Shape3D.ALLOW_APPEARANCE_WRITE) {
2748:                    mask = APPEARANCE_CHANGED;
2749:                } else if (bit == Shape3D.ALLOW_APPEARANCE_OVERRIDE_WRITE) {
2750:                    mask = APPEARANCEOVERRIDE_CHANGED;
2751:                }
2752:                if (mask != 0) {
2753:                    if (source.getCapabilityIsFrequent(bit))
2754:                        changedFrequent |= mask;
2755:                    else if (!source.isLive()) {
2756:                        changedFrequent &= ~mask;
2757:                    }
2758:                }
2759:            }
2760:
2761:            // Alpha is editable due to the appearance(Called on the MirrorShape3D)
2762:            boolean isAlphaFrequentlyEditable(GeometryRetained geo) {
2763:
2764:                boolean alphaFrequentlyEditable = false;
2765:                if (appearanceOverrideEnable) {
2766:                    alphaFrequentlyEditable = true;
2767:                } else if (geo != null && appearance != null) {
2768:                    AppearanceRetained app = appearance;
2769:
2770:                    if (((changedFrequent & (APPEARANCE_CHANGED | APPEARANCEOVERRIDE_CHANGED)) != 0)
2771:                            || ((app.changedFrequent & (AppearanceRetained.RENDERING | AppearanceRetained.TRANSPARENCY)) != 0)
2772:                            || (app.renderingAttributes != null && (((app.renderingAttributes.changedFrequent & (RenderingAttributesRetained.IGNORE_VCOLOR | RenderingAttributesRetained.ALPHA_TEST_FUNC)) != 0)))
2773:                            ||
2774:
2775:                            (app.transparencyAttributes != null && ((app.transparencyAttributes.changedFrequent != 0)))) {
2776:
2777:                        alphaFrequentlyEditable = true;
2778:
2779:                    } else if (geo instanceof  GeometryArrayRetained
2780:                            && ((app.changedFrequent & AppearanceRetained.TEXTURE_ATTR) != 0)
2781:                            || (app.textureAttributes != null && ((app.textureAttributes.changedFrequent & TextureAttributes.ALLOW_MODE_WRITE) != 0))) {
2782:                        alphaFrequentlyEditable = true;
2783:
2784:                    } else if (geo instanceof  RasterRetained) {
2785:                        if (((((RasterRetained) geo).type & Raster.RASTER_COLOR) != 0)
2786:                                && (((RasterRetained) geo).cachedChangedFrequent != 0)) {
2787:
2788:                            alphaFrequentlyEditable = true;
2789:                        }
2790:                    }
2791:                }
2792:                //	System.err.println("changedFrequent="+changedFrequent+" sourceNode = "+sourceNode+" isAlphaFrequentlyEditable, = "+alphaFrequentlyEditable);
2793:                return alphaFrequentlyEditable;
2794:            }
2795:
2796:            int getPrimaryViewIdx() {
2797:                // To avoid MT-safe issues when using View, just clone it.
2798:                UnorderList viewList = VirtualUniverse.mc.cloneView();
2799:                View views[] = (View[]) viewList.toArray(false);
2800:                int size = viewList.arraySize();
2801:
2802:                for (int i = 0; i < size; i++) {
2803:                    if (views[i].primaryView) {
2804:                        return views[i].viewIndex;
2805:                    }
2806:                }
2807:                return 0;
2808:            }
2809:
2810:            void searchGeometryAtoms(UnorderList list) {
2811:                list.add(getGeomAtom(getMirrorShape(key)));
2812:            }
2813:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.