Source Code Cross Referenced for GeometryArrayRetained.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) 


00001:        /*
00002:         * $RCSfile: GeometryArrayRetained.java,v $
00003:         *
00004:         * Copyright 1996-2008 Sun Microsystems, Inc.  All Rights Reserved.
00005:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
00006:         *
00007:         * This code is free software; you can redistribute it and/or modify it
00008:         * under the terms of the GNU General Public License version 2 only, as
00009:         * published by the Free Software Foundation.  Sun designates this
00010:         * particular file as subject to the "Classpath" exception as provided
00011:         * by Sun in the LICENSE file that accompanied this code.
00012:         *
00013:         * This code is distributed in the hope that it will be useful, but WITHOUT
00014:         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00015:         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00016:         * version 2 for more details (a copy is included in the LICENSE file that
00017:         * accompanied this code).
00018:         *
00019:         * You should have received a copy of the GNU General Public License version
00020:         * 2 along with this work; if not, write to the Free Software Foundation,
00021:         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
00022:         *
00023:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
00024:         * CA 95054 USA or visit www.sun.com if you need additional information or
00025:         * have any questions.
00026:         *
00027:         * $Revision: 1.12 $
00028:         * $Date: 2008/02/28 20:17:22 $
00029:         * $State: Exp $
00030:         */
00031:
00032:        package javax.media.j3d;
00033:
00034:        import com.sun.j3d.internal.Distance;
00035:        import javax.vecmath.*;
00036:        import java.lang.Math;
00037:        import java.util.ArrayList;
00038:        import java.util.Set;
00039:        import java.util.HashSet;
00040:        import java.util.HashMap;
00041:        import java.util.Vector;
00042:        import java.util.Enumeration;
00043:        import com.sun.j3d.internal.ByteBufferWrapper;
00044:        import com.sun.j3d.internal.BufferWrapper;
00045:        import com.sun.j3d.internal.FloatBufferWrapper;
00046:        import com.sun.j3d.internal.DoubleBufferWrapper;
00047:
00048:        /**
00049:         * The GeometryArray object contains arrays of positional coordinates,
00050:         * colors, normals and/or texture coordinates that describe
00051:         * point, line, or surface geometry.  It is extended to create
00052:         * the various primitive types (e.g., lines, triangle_strips, etc.)
00053:         */
00054:
00055:        abstract class GeometryArrayRetained extends GeometryRetained {
00056:
00057:            // XXXX: Memory footprint reduction. Should have separate object to
00058:            //       to contain specific data such as a ByRef object for
00059:            //       all ByRef related data. So that incases where no
00060:            //       ByRef is needed, the ByRef object reference is
00061:            //       set to null. Hence saving memory!
00062:            //       Need object such as Texture, D3d and ByRef ...
00063:            //
00064:
00065:            // Contains a bitset indicating which components are present
00066:            int vertexFormat;
00067:
00068:            // Whether this geometry was ever rendered as transparent
00069:            int c4fAllocated = 0;
00070:
00071:            // Total Number of vertices
00072:            int vertexCount;
00073:
00074:            // number of vertices used in rendering
00075:            int validVertexCount;
00076:
00077:            // The vertex data in packed format
00078:            float vertexData[];
00079:
00080:            // vertex data in packed format for each screen in multi-screen situation
00081:            // if alpha values of each vertex are to be updated
00082:            private float mvertexData[][];
00083:
00084:            //
00085:            // The following offset/stride values are internally computed
00086:            // from the format
00087:            //
00088:
00089:            // Stride (in words) from one vertex to the next
00090:            int stride;
00091:
00092:            // Stride (in words) from one texture coordinate to the next
00093:            int texCoordStride;
00094:
00095:            // Offset (in words) within each vertex of the coordinate position
00096:            int coordinateOffset;
00097:
00098:            // Offset (in words) within each vertex of the normal
00099:            int normalOffset;
00100:
00101:            // Offset (in words) within each vertex of the color
00102:            int colorOffset;
00103:
00104:            // Offset (in words) within each vertex of the texture coordinate
00105:            int textureOffset;
00106:
00107:            // Offset (in words) within each vertex of each vertex attribute
00108:            int[] vertexAttrOffsets;
00109:
00110:            // Stride (size) of all vertex attributes
00111:            int vertexAttrStride;
00112:
00113:            // alpha value for transparency and texture blending
00114:            private float[] lastAlpha = new float[1];
00115:            float lastScreenAlpha = -1;
00116:
00117:            int colorChanged = 0;
00118:
00119:            // byte to float scale factor
00120:            static final float ByteToFloatScale = 1.0f / 255.0f;
00121:
00122:            // float to byte scale factor
00123:            static final float FloatToByteScale = 255.0f;
00124:
00125:            // Set flag indicating that we are in the updater.  This flag
00126:            // can be used by the various setRef methods to inhibit any
00127:            // update messages
00128:            boolean inUpdater = false;
00129:
00130:            // Array List used for messages
00131:            ArrayList gaList = new ArrayList(1);
00132:
00133:            // Target threads to be notified when morph changes
00134:            static final int targetThreads = (J3dThread.UPDATE_RENDER | J3dThread.UPDATE_GEOMETRY);
00135:
00136:            // used for byReference geometry
00137:            float[] floatRefCoords = null;
00138:            double[] doubleRefCoords = null;
00139:            Point3d[] p3dRefCoords = null;
00140:            Point3f[] p3fRefCoords = null;
00141:
00142:            // Used for NIO buffer geometry
00143:            J3DBuffer coordRefBuffer = null;
00144:            FloatBufferWrapper floatBufferRefCoords = null;
00145:            DoubleBufferWrapper doubleBufferRefCoords = null;
00146:
00147:            // Initial index to use for rendering
00148:            int initialCoordIndex = 0;
00149:            int initialColorIndex = 0;
00150:            int initialNormalIndex = 0;
00151:            int[] initialTexCoordIndex = null;
00152:            int[] initialVertexAttrIndex = null;
00153:            int initialVertexIndex = 0;
00154:
00155:            // used for byReference colors
00156:            float[] floatRefColors = null;
00157:            byte[] byteRefColors = null;
00158:            Color3f[] c3fRefColors = null;
00159:            Color4f[] c4fRefColors = null;
00160:            Color3b[] c3bRefColors = null;
00161:            Color4b[] c4bRefColors = null;
00162:
00163:            // Used for NIO buffer colors
00164:            J3DBuffer colorRefBuffer = null;
00165:            FloatBufferWrapper floatBufferRefColors = null;
00166:            ByteBufferWrapper byteBufferRefColors = null;
00167:
00168:            // flag to indicate if the "by reference" component is already set
00169:            int vertexType = 0;
00170:            static final int PF = 0x1;
00171:            static final int PD = 0x2;
00172:            static final int P3F = 0x4;
00173:            static final int P3D = 0x8;
00174:            static final int VERTEX_DEFINED = PF | PD | P3F | P3D;
00175:
00176:            static final int CF = 0x10;
00177:            static final int CUB = 0x20;
00178:            static final int C3F = 0x40;
00179:            static final int C4F = 0x80;
00180:            static final int C3UB = 0x100;
00181:            static final int C4UB = 0x200;
00182:            static final int COLOR_DEFINED = CF | CUB | C3F | C4F | C3UB | C4UB;
00183:
00184:            static final int NF = 0x400;
00185:            static final int N3F = 0x800;
00186:            static final int NORMAL_DEFINED = NF | N3F;
00187:
00188:            static final int TF = 0x1000;
00189:            static final int T2F = 0x2000;
00190:            static final int T3F = 0x4000;
00191:            static final int TEXCOORD_DEFINED = TF | T2F | T3F;
00192:
00193:            static final int AF = 0x8000;
00194:            static final int VATTR_DEFINED = AF;
00195:
00196:            // Flag word indicating the type of by-ref texCoord. We will copy this to
00197:            // the vertexType field only when the references for all texture coordinate
00198:            // sets are set to non-null values.
00199:            private int texCoordType = 0;
00200:
00201:            // Flag word indicating the type of by-ref vertex attr. We will copy this to
00202:            // the vertexType field only when the references for all vertex attrs
00203:            // are set to non-null values.
00204:            private int vertexAttrType = 0;
00205:
00206:            // flag for execute geometry array when by reference
00207:            static final int COORD_FLOAT = 0x01;
00208:            static final int COORD_DOUBLE = 0x02;
00209:            static final int COLOR_FLOAT = 0x04;
00210:            static final int COLOR_BYTE = 0x08;
00211:            static final int NORMAL_FLOAT = 0x10;
00212:            static final int TEXCOORD_FLOAT = 0x20;
00213:            static final int VATTR_FLOAT = 0x40;
00214:
00215:            // used by "by reference" normals
00216:            float[] floatRefNormals = null;
00217:            Vector3f[] v3fRefNormals = null;
00218:
00219:            // Used for NIO buffer normals
00220:            J3DBuffer normalRefBuffer = null;
00221:            FloatBufferWrapper floatBufferRefNormals = null;
00222:
00223:            // used for "by reference" vertex attrs
00224:            float[][] floatRefVertexAttrs = null;
00225:
00226:            // Used for NIO buffer vertex attrs
00227:            J3DBuffer[] vertexAttrsRefBuffer = null;
00228:            FloatBufferWrapper[] floatBufferRefVertexAttrs = null;
00229:            Object[] nioFloatBufferRefVertexAttrs = null;
00230:
00231:            // used by "by reference" tex coords
00232:            Object[] refTexCoords = null;
00233:            TexCoord2f[] t2fRefTexCoords = null;
00234:            TexCoord3f[] t3fRefTexCoords = null;
00235:
00236:            // Used for NIO buffer tex coords
00237:            Object[] refTexCoordsBuffer = null;
00238:            //FloatBufferWrapper[] floatBufferRefTexCoords = null;
00239:
00240:            // used by interleaved array
00241:            float[] interLeavedVertexData = null;
00242:
00243:            // used by interleaved NIO buffer
00244:            J3DBuffer interleavedVertexBuffer = null;
00245:            FloatBufferWrapper interleavedFloatBufferImpl = null;
00246:
00247:            // pointers used, when transparency is turned on
00248:            // or when its an object such as C3F, P3F etc ..
00249:            float[] mirrorFloatRefCoords = null;
00250:            double[] mirrorDoubleRefCoords = null;
00251:            float[] mirrorFloatRefNormals = null;
00252:            float[][] mirrorFloatRefVertexAttrs = null;
00253:            float[] mirrorFloatRefTexCoords = null;
00254:            Object[] mirrorRefTexCoords = null;
00255:
00256:            float[][] mirrorFloatRefColors = new float[1][];
00257:            byte[][] mirrorUnsignedByteRefColors = new byte[1][];
00258:            float[][] mirrorInterleavedColorPointer = null;
00259:
00260:            // boolean to determine if a mirror was allocated
00261:            int mirrorVertexAllocated = 0;
00262:            int mirrorColorAllocated = 0;
00263:            boolean mirrorNormalAllocated = false;
00264:
00265:            // Some dirty bits for GeometryArrays
00266:            static final int COORDINATE_CHANGED = 0x01;
00267:            static final int NORMAL_CHANGED = 0x02;
00268:            static final int COLOR_CHANGED = 0x04;
00269:            static final int TEXTURE_CHANGED = 0x08;
00270:            static final int BOUNDS_CHANGED = 0x10;
00271:            static final int INDEX_CHANGED = 0x20;
00272:            static final int STRIPCOUNT_CHANGED = 0x40;
00273:            static final int VATTR_CHANGED = 0x80;
00274:            static final int VERTEX_CHANGED = COORDINATE_CHANGED
00275:                    | NORMAL_CHANGED | COLOR_CHANGED | TEXTURE_CHANGED
00276:                    | VATTR_CHANGED;
00277:
00278:            static final int defaultTexCoordSetMap[] = { 0 };
00279:            int texCoordSetCount = 0;
00280:            int[] texCoordSetMap = null;
00281:
00282:            // this array contains offset to the texCoord data for each
00283:            // texture unit.  -1 means no corresponding texCoord data offset
00284:            int[] texCoordSetMapOffset = null;
00285:
00286:            // Vertex attribute information
00287:            int vertexAttrCount = 0;
00288:            int[] vertexAttrSizes = null;
00289:
00290:            // This point to a list of VertexBuffers in a Vector structure
00291:            // Each element correspond to a D3D context that create this VB.
00292:            // Note that this GeometryArray can be used by multiple ctx.
00293:            long pVertexBuffers = 0;
00294:            int dirtyFlag;
00295:
00296:            // each bit corresponds to a unique renderer if shared context
00297:            // or a unique canvas otherwise
00298:            int resourceCreationMask = 0x0;
00299:
00300:            // Fix for Issue 5
00301:            //
00302:            // Replace the per-canvas reference count with a per-RenderBin set
00303:            // of users.  The per-RenderBin set of users of this display list
00304:            // is defined as a HashMap where:
00305:            //
00306:            //   key   = the RenderBin
00307:            //   value = a set of RenderAtomListInfo objects using this
00308:            //           geometry array for display list purposes
00309:            private HashMap dlistUsers = null;
00310:
00311:            // timestamp used to create display list. This is either
00312:            // one per renderer for useSharedCtx, or one per Canvas for non-shared
00313:            // ctx
00314:            private long[] timeStampPerDlist = new long[2];
00315:
00316:            // Unique display list Id, if this geometry is shared
00317:            int dlistId = -1;
00318:            Integer dlistObj = null;
00319:
00320:            // A list of pre-defined bits to indicate which component
00321:            // in this Texture object changed.
00322:            //    static final int DLIST_CREATE_CHANGED      = 0x01;
00323:            static final int INIT_MIRROR_GEOMETRY = 0x02;
00324:
00325:            // A list of Universes that this Geometry is referenced in Morph from
00326:            ArrayList morphUniverseList = null;
00327:
00328:            // A list of ArrayLists which contain all the MorphRetained objects
00329:            // refering to this geometry.  Each list corresponds to the universe
00330:            // above.
00331:            ArrayList morphUserLists = null;
00332:
00333:            // The following variables are only used in compile mode
00334:
00335:            // Offset of a geometry array into the merged array
00336:            int[] geoOffset;
00337:
00338:            // vertexcount of a geometry array in a merge array
00339:            int[] compileVcount;
00340:
00341:            boolean isCompiled = false;
00342:
00343:            boolean isShared = false;
00344:
00345:            IndexedGeometryArrayRetained cloneSourceArray = null;
00346:
00347:            static final double EPS = 1.0e-13;
00348:
00349:            void freeD3DArray(boolean deleteVB) {
00350:                assert VirtualUniverse.mc.isD3D();
00351:                Pipeline.getPipeline().freeD3DArray(this , deleteVB);
00352:            }
00353:
00354:            GeometryArrayRetained() {
00355:                dirtyFlag = INDEX_CHANGED | VERTEX_CHANGED;
00356:                lastAlpha[0] = 1.0f;
00357:            }
00358:
00359:            void setLive(boolean inBackgroundGroup, int refCount) {
00360:                dirtyFlag = VERTEX_CHANGED | INDEX_CHANGED;
00361:                isEditable = !isWriteStatic();
00362:                super .doSetLive(inBackgroundGroup, refCount);
00363:                super .markAsLive();
00364:                // Send message to RenderingAttribute structure to obtain a dlistId
00365:                //	System.err.println("Geometry - "+this+"refCount = "+this.refCount);
00366:                if (this .refCount > 1) {
00367:                    // Send to rendering attribute structure,
00368:                    /*
00369:                    J3dMessage createMessage = new J3dMessage();
00370:                    createMessage.threads = J3dThread.UPDATE_RENDERING_ATTRIBUTES;
00371:                    createMessage.type = J3dMessage.GEOMETRYARRAY_CHANGED;
00372:                    createMessage.universe = null;
00373:                    createMessage.args[0] = this;
00374:                    createMessage.args[1]= new Integer(DLIST_CREATE_CHANGED);
00375:                    VirtualUniverse.mc.processMessage(createMessage);
00376:                     */
00377:                    isShared = true;
00378:                } // Clone geometry only for the first setLive
00379:                else {
00380:                    // If geometry is indexed and use_index_coord is false, unindexify
00381:                    // otherwise, set mirrorGeometry to null (from previous clearLive)
00382:                    if (this  instanceof  IndexedGeometryArrayRetained) {
00383:                        // Send to rendering attribute structure,
00384:                        J3dMessage createMessage = new J3dMessage();
00385:                        createMessage.threads = J3dThread.UPDATE_RENDERING_ATTRIBUTES;
00386:                        createMessage.type = J3dMessage.GEOMETRY_CHANGED;
00387:                        createMessage.universe = null;
00388:                        createMessage.args[0] = null;
00389:                        createMessage.args[1] = this ;
00390:                        createMessage.args[2] = new Integer(
00391:                                INIT_MIRROR_GEOMETRY);
00392:                        VirtualUniverse.mc.processMessage(createMessage);
00393:                    }
00394:                }
00395:
00396:            }
00397:
00398:            void clearLive(int refCount) {
00399:                super .clearLive(refCount);
00400:
00401:                if (this .refCount <= 0) {
00402:                    if (pVertexBuffers != 0) {
00403:                        J3dMessage renderMessage = new J3dMessage();
00404:                        renderMessage.threads = J3dThread.RENDER_THREAD;
00405:                        renderMessage.type = J3dMessage.RENDER_IMMEDIATE;
00406:                        renderMessage.universe = null;
00407:                        renderMessage.view = null;
00408:                        renderMessage.args[0] = null;
00409:                        renderMessage.args[1] = this ;
00410:                        // Any one renderer is fine since VB store the ctx
00411:                        // where it is created.
00412:                        Enumeration e = Screen3D.deviceRendererMap.elements();
00413:                        Renderer rdr = (Renderer) e.nextElement();
00414:                        rdr.rendererStructure.addMessage(renderMessage);
00415:                        VirtualUniverse.mc.setWorkForRequestRenderer();
00416:                    }
00417:                    isShared = false;
00418:                }
00419:            }
00420:
00421:            void computeBoundingBox() {
00422:
00423:                //	System.err.println("computeBoundingBox ....");
00424:
00425:                if (boundsDirty && VirtualUniverse.mc.cacheAutoComputedBounds) {
00426:                    for (ArrayList<Shape3DRetained> users : userLists) {
00427:                        for (Shape3DRetained shape : users)
00428:                            shape.dirtyBoundsCache();
00429:                    }
00430:                }
00431:
00432:                if ((vertexFormat & GeometryArray.BY_REFERENCE) == 0) {
00433:                    // by copy
00434:                    computeBoundingBox(initialVertexIndex, vertexData);
00435:
00436:                } else if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) != 0) { // USE_NIO_BUFFER
00437:                    //System.err.println("vertexFormat & GeometryArray.USE_NIO_BUFFER");
00438:                    if ((vertexFormat & GeometryArray.INTERLEAVED) != 0) {
00439:                        computeBoundingBox(initialCoordIndex,
00440:                                interleavedFloatBufferImpl);
00441:                    } else if ((vertexType & PF) != 0) {
00442:                        computeBoundingBox(floatBufferRefCoords);
00443:                    } else if ((vertexType & PD) != 0) {
00444:                        computeBoundingBox(doubleBufferRefCoords);
00445:                    }
00446:
00447:                } else if ((vertexFormat & GeometryArray.INTERLEAVED) != 0) {
00448:                    //System.err.println("vertexFormat & GeometryArray.INTERLEAVED");
00449:                    computeBoundingBox(initialCoordIndex, interLeavedVertexData);
00450:                } else if ((vertexType & PF) != 0) {
00451:                    //System.err.println("vertexType & PF");
00452:                    computeBoundingBox(floatRefCoords);
00453:                } else if ((vertexType & P3F) != 0) {
00454:                    //System.err.println("vertexType & P3F");
00455:                    computeBoundingBox(p3fRefCoords);
00456:                } else if ((vertexType & P3D) != 0) {
00457:                    //System.err.println("vertexType & P3D");
00458:                    computeBoundingBox(p3dRefCoords);
00459:                } else if ((vertexType & PD) != 0) {
00460:                    //System.err.println("vertexType & PD");
00461:                    computeBoundingBox(doubleRefCoords);
00462:                }
00463:
00464:            }
00465:
00466:            // NullGeometry is true only for byRef case
00467:            void processCoordsChanged(boolean nullGeo) {
00468:
00469:                /*
00470:                  System.err.println("processCoordsChanged : nullGeo " + nullGeo);
00471:                  System.err.println("Before :processCoordsChanged : geoBounds ");
00472:                  System.err.println(geoBounds);
00473:                 */
00474:                if (nullGeo) {
00475:                    synchronized (geoBounds) {
00476:                        geoBounds.setLower(-1.0, -1.0, -1.0);
00477:                        geoBounds.setUpper(1.0, 1.0, 1.0);
00478:                        boundsDirty = false;
00479:                    }
00480:                    synchronized (centroid) {
00481:                        recompCentroid = false;
00482:                        this .centroid.set(geoBounds.getCenter());
00483:                    }
00484:
00485:                } else {
00486:                    // re-compute centroid if used
00487:                    synchronized (centroid) {
00488:                        recompCentroid = true;
00489:                    }
00490:
00491:                    synchronized (geoBounds) {
00492:                        boundsDirty = true;
00493:                        computeBoundingBox();
00494:                    }
00495:
00496:                    /*
00497:                      System.err.println("After :processCoordsChanged : geoBounds ");
00498:                      System.err.println(geoBounds);
00499:                     */
00500:                }
00501:            }
00502:
00503:            void computeBoundingBox(int vIndex, float[] vdata) {
00504:                int i, offset;
00505:                double xmin, xmax, ymin, ymax, zmin, zmax;
00506:
00507:                //System.err.println("Before : computeBoundingBox : geoBounds ");
00508:                //  System.err.println(geoBounds);
00509:
00510:                synchronized (geoBounds) {
00511:
00512:                    // If autobounds compute is false  then return
00513:                    // It is possible that user call getBounds() before
00514:                    // this Geometry add to live scene graph.
00515:                    if ((computeGeoBounds == 0) && (refCount > 0)) {
00516:                        return;
00517:                    }
00518:                    if (!boundsDirty)
00519:                        return;
00520:
00521:                    // Initial offset
00522:                    offset = vIndex * stride + coordinateOffset;
00523:                    // Compute the bounding box
00524:                    xmin = xmax = vdata[offset];
00525:                    ymin = ymax = vdata[offset + 1];
00526:                    zmin = zmax = vdata[offset + 2];
00527:                    offset += stride;
00528:                    for (i = 1; i < validVertexCount; i++) {
00529:                        if (vdata[offset] > xmax)
00530:                            xmax = vdata[offset];
00531:                        if (vdata[offset] < xmin)
00532:                            xmin = vdata[offset];
00533:
00534:                        if (vdata[offset + 1] > ymax)
00535:                            ymax = vdata[offset + 1];
00536:                        if (vdata[offset + 1] < ymin)
00537:                            ymin = vdata[offset + 1];
00538:
00539:                        if (vdata[offset + 2] > zmax)
00540:                            zmax = vdata[offset + 2];
00541:                        if (vdata[offset + 2] < zmin)
00542:                            zmin = vdata[offset + 2];
00543:
00544:                        offset += stride;
00545:                    }
00546:
00547:                    geoBounds.setUpper(xmax, ymax, zmax);
00548:                    geoBounds.setLower(xmin, ymin, zmin);
00549:                    boundsDirty = false;
00550:                }
00551:                /*
00552:                  System.err.println("After : computeBoundingBox : geoBounds ");
00553:                  System.err.println(geoBounds);
00554:                 */
00555:            }
00556:
00557:            // Compute boundingbox for interleaved nio buffer
00558:            void computeBoundingBox(int vIndex, FloatBufferWrapper vdata) {
00559:                int i, offset;
00560:                double xmin, xmax, ymin, ymax, zmin, zmax;
00561:
00562:                synchronized (geoBounds) {
00563:                    // If autobounds compute is false  then return
00564:                    if ((computeGeoBounds == 0) && (refCount > 0)) {
00565:                        return;
00566:                    }
00567:
00568:                    if (!boundsDirty)
00569:                        return;
00570:
00571:                    // Initial offset
00572:                    offset = vIndex * stride + coordinateOffset;
00573:                    // Compute the bounding box
00574:                    xmin = xmax = vdata.get(offset);
00575:                    ymin = ymax = vdata.get(offset + 1);
00576:                    zmin = zmax = vdata.get(offset + 2);
00577:                    offset += stride;
00578:                    for (i = 1; i < validVertexCount; i++) {
00579:                        if (vdata.get(offset) > xmax)
00580:                            xmax = vdata.get(offset);
00581:                        if (vdata.get(offset) < xmin)
00582:                            xmin = vdata.get(offset);
00583:
00584:                        if (vdata.get(offset + 1) > ymax)
00585:                            ymax = vdata.get(offset + 1);
00586:                        if (vdata.get(offset + 1) < ymin)
00587:                            ymin = vdata.get(offset + 1);
00588:
00589:                        if (vdata.get(offset + 2) > zmax)
00590:                            zmax = vdata.get(offset + 2);
00591:                        if (vdata.get(offset + 2) < zmin)
00592:                            zmin = vdata.get(offset + 2);
00593:
00594:                        offset += stride;
00595:                    }
00596:
00597:                    geoBounds.setUpper(xmax, ymax, zmax);
00598:                    geoBounds.setLower(xmin, ymin, zmin);
00599:                    boundsDirty = false;
00600:                }
00601:            }
00602:
00603:            // compute bounding box for coord with noi buffer
00604:            void computeBoundingBox(DoubleBufferWrapper buffer) {
00605:                int i, j, k, sIndex;
00606:                double xmin, xmax, ymin, ymax, zmin, zmax;
00607:
00608:                synchronized (geoBounds) {
00609:                    // If autobounds compute is false  then return
00610:                    if ((computeGeoBounds == 0) && (refCount > 0)) {
00611:                        return;
00612:                    }
00613:
00614:                    if (!boundsDirty)
00615:                        return;
00616:
00617:                    sIndex = initialCoordIndex;
00618:                    int maxIndex = 3 * validVertexCount;
00619:
00620:                    // Compute the bounding box
00621:                    xmin = xmax = buffer.get(sIndex++);
00622:                    ymin = ymax = buffer.get(sIndex++);
00623:                    zmin = zmax = buffer.get(sIndex++);
00624:
00625:                    for (i = sIndex; i < maxIndex; i += 3) {
00626:                        j = i + 1;
00627:                        k = i + 2;
00628:
00629:                        if (buffer.get(i) > xmax)
00630:                            xmax = buffer.get(i);
00631:                        if (buffer.get(i) < xmin)
00632:                            xmin = buffer.get(i);
00633:
00634:                        if (buffer.get(j) > ymax)
00635:                            ymax = buffer.get(j);
00636:                        if (buffer.get(j) < ymin)
00637:                            ymin = buffer.get(j);
00638:
00639:                        if (buffer.get(k) > zmax)
00640:                            zmax = buffer.get(k);
00641:                        if (buffer.get(k) < zmin)
00642:                            zmin = buffer.get(k);
00643:
00644:                    }
00645:                    geoBounds.setUpper(xmax, ymax, zmax);
00646:                    geoBounds.setLower(xmin, ymin, zmin);
00647:                    boundsDirty = false;
00648:                }
00649:            }
00650:
00651:            // compute bounding box for coord with noi buffer
00652:            void computeBoundingBox(FloatBufferWrapper buffer) {
00653:                int i, j, k, sIndex;
00654:                double xmin, xmax, ymin, ymax, zmin, zmax;
00655:
00656:                synchronized (geoBounds) {
00657:                    // If autobounds compute is false  then return
00658:                    if ((computeGeoBounds == 0) && (refCount > 0)) {
00659:                        return;
00660:                    }
00661:
00662:                    if (!boundsDirty)
00663:                        return;
00664:
00665:                    sIndex = initialCoordIndex;
00666:                    int maxIndex = 3 * validVertexCount;
00667:
00668:                    // Compute the bounding box
00669:                    xmin = xmax = buffer.get(sIndex++);
00670:                    ymin = ymax = buffer.get(sIndex++);
00671:                    zmin = zmax = buffer.get(sIndex++);
00672:
00673:                    for (i = sIndex; i < maxIndex; i += 3) {
00674:                        j = i + 1;
00675:                        k = i + 2;
00676:
00677:                        if (buffer.get(i) > xmax)
00678:                            xmax = buffer.get(i);
00679:                        if (buffer.get(i) < xmin)
00680:                            xmin = buffer.get(i);
00681:
00682:                        if (buffer.get(j) > ymax)
00683:                            ymax = buffer.get(j);
00684:                        if (buffer.get(j) < ymin)
00685:                            ymin = buffer.get(j);
00686:
00687:                        if (buffer.get(k) > zmax)
00688:                            zmax = buffer.get(k);
00689:                        if (buffer.get(k) < zmin)
00690:                            zmin = buffer.get(k);
00691:
00692:                    }
00693:                    geoBounds.setUpper(xmax, ymax, zmax);
00694:                    geoBounds.setLower(xmin, ymin, zmin);
00695:                    boundsDirty = false;
00696:                }
00697:            }
00698:
00699:            void computeBoundingBox(float[] coords) {
00700:                // System.err.println("GeometryArrayRetained : computeBoundingBox(float[] coords)");
00701:                int i, j, k, sIndex;
00702:                double xmin, xmax, ymin, ymax, zmin, zmax;
00703:
00704:                synchronized (geoBounds) {
00705:                    // If autobounds compute is false  then return
00706:                    if ((computeGeoBounds == 0) && (refCount > 0)) {
00707:                        return;
00708:                    }
00709:
00710:                    if (!boundsDirty)
00711:                        return;
00712:
00713:                    sIndex = initialCoordIndex;
00714:                    int maxIndex = 3 * validVertexCount;
00715:
00716:                    // Compute the bounding box
00717:                    xmin = xmax = coords[sIndex++];
00718:                    ymin = ymax = coords[sIndex++];
00719:                    zmin = zmax = coords[sIndex++];
00720:
00721:                    for (i = sIndex; i < maxIndex; i += 3) {
00722:                        j = i + 1;
00723:                        k = i + 2;
00724:
00725:                        if (coords[i] > xmax)
00726:                            xmax = coords[i];
00727:                        if (coords[i] < xmin)
00728:                            xmin = coords[i];
00729:
00730:                        if (coords[j] > ymax)
00731:                            ymax = coords[j];
00732:                        if (coords[j] < ymin)
00733:                            ymin = coords[j];
00734:
00735:                        if (coords[k] > zmax)
00736:                            zmax = coords[k];
00737:                        if (coords[k] < zmin)
00738:                            zmin = coords[k];
00739:
00740:                    }
00741:                    geoBounds.setUpper(xmax, ymax, zmax);
00742:                    // System.err.println("max(" + xmax + ", " + ymax + ", " + zmax + ")");
00743:                    geoBounds.setLower(xmin, ymin, zmin);
00744:                    // System.err.println("min(" + xmin + ", " + ymin + ", " + zmin + ")");
00745:
00746:                    boundsDirty = false;
00747:                }
00748:
00749:            }
00750:
00751:            void computeBoundingBox(double[] coords) {
00752:                int i, j, k, sIndex;
00753:                double xmin, xmax, ymin, ymax, zmin, zmax;
00754:
00755:                synchronized (geoBounds) {
00756:                    // If autobounds compute is false  then return
00757:                    if ((computeGeoBounds == 0) && (refCount > 0)) {
00758:                        return;
00759:                    }
00760:
00761:                    if (!boundsDirty)
00762:                        return;
00763:
00764:                    sIndex = initialCoordIndex;
00765:                    int maxIndex = 3 * validVertexCount;
00766:
00767:                    // Compute the bounding box
00768:                    xmin = xmax = coords[sIndex++];
00769:                    ymin = ymax = coords[sIndex++];
00770:                    zmin = zmax = coords[sIndex++];
00771:
00772:                    for (i = sIndex; i < maxIndex; i += 3) {
00773:                        j = i + 1;
00774:                        k = i + 2;
00775:
00776:                        if (coords[i] > xmax)
00777:                            xmax = coords[i];
00778:                        if (coords[i] < xmin)
00779:                            xmin = coords[i];
00780:
00781:                        if (coords[j] > ymax)
00782:                            ymax = coords[j];
00783:                        if (coords[j] < ymin)
00784:                            ymin = coords[j];
00785:
00786:                        if (coords[k] > zmax)
00787:                            zmax = coords[k];
00788:                        if (coords[k] < zmin)
00789:                            zmin = coords[k];
00790:
00791:                    }
00792:                    geoBounds.setUpper(xmax, ymax, zmax);
00793:                    geoBounds.setLower(xmin, ymin, zmin);
00794:                    boundsDirty = false;
00795:                }
00796:
00797:            }
00798:
00799:            void computeBoundingBox(Point3f[] coords) {
00800:
00801:                double xmin, xmax, ymin, ymax, zmin, zmax;
00802:                Point3f p;
00803:
00804:                synchronized (geoBounds) {
00805:                    // If autobounds compute is false  then return
00806:                    if ((computeGeoBounds == 0) && (refCount > 0)) {
00807:                        return;
00808:                    }
00809:
00810:                    if (!boundsDirty)
00811:                        return;
00812:
00813:                    // Compute the bounding box
00814:                    xmin = xmax = coords[initialCoordIndex].x;
00815:                    ymin = ymax = coords[initialCoordIndex].y;
00816:                    zmin = zmax = coords[initialCoordIndex].z;
00817:
00818:                    for (int i = initialCoordIndex + 1; i < validVertexCount; i++) {
00819:                        p = coords[i];
00820:                        if (p.x > xmax)
00821:                            xmax = p.x;
00822:                        if (p.x < xmin)
00823:                            xmin = p.x;
00824:
00825:                        if (p.y > ymax)
00826:                            ymax = p.y;
00827:                        if (p.y < ymin)
00828:                            ymin = p.y;
00829:
00830:                        if (p.z > zmax)
00831:                            zmax = p.z;
00832:                        if (p.z < zmin)
00833:                            zmin = p.z;
00834:
00835:                    }
00836:                    geoBounds.setUpper(xmax, ymax, zmax);
00837:                    geoBounds.setLower(xmin, ymin, zmin);
00838:                    boundsDirty = false;
00839:                }
00840:
00841:            }
00842:
00843:            void computeBoundingBox(Point3d[] coords) {
00844:
00845:                double xmin, xmax, ymin, ymax, zmin, zmax;
00846:                Point3d p;
00847:
00848:                synchronized (geoBounds) {
00849:                    // If autobounds compute is false  then return
00850:                    if ((computeGeoBounds == 0) && (refCount > 0)) {
00851:                        return;
00852:                    }
00853:
00854:                    if (!boundsDirty)
00855:                        return;
00856:
00857:                    // Compute the bounding box
00858:                    xmin = xmax = coords[initialCoordIndex].x;
00859:                    ymin = ymax = coords[initialCoordIndex].y;
00860:                    zmin = zmax = coords[initialCoordIndex].z;
00861:
00862:                    for (int i = initialCoordIndex + 1; i < validVertexCount; i++) {
00863:                        p = coords[i];
00864:                        if (p.x > xmax)
00865:                            xmax = p.x;
00866:                        if (p.x < xmin)
00867:                            xmin = p.x;
00868:
00869:                        if (p.y > ymax)
00870:                            ymax = p.y;
00871:                        if (p.y < ymin)
00872:                            ymin = p.y;
00873:
00874:                        if (p.z > zmax)
00875:                            zmax = p.z;
00876:                        if (p.z < zmin)
00877:                            zmin = p.z;
00878:
00879:                    }
00880:                    geoBounds.setUpper(xmax, ymax, zmax);
00881:                    geoBounds.setLower(xmin, ymin, zmin);
00882:                    boundsDirty = false;
00883:                }
00884:
00885:            }
00886:
00887:            synchronized void update() {
00888:            }
00889:
00890:            void setupMirrorVertexPointer(int vType) {
00891:                int i, index;
00892:
00893:                switch (vType) {
00894:                case PF:
00895:                    if (floatRefCoords == null) {
00896:                        if ((vertexType & VERTEX_DEFINED) == PF) {
00897:                            vertexType &= ~PF;
00898:                            mirrorFloatRefCoords = null;
00899:                            mirrorVertexAllocated &= ~PF;
00900:                        }
00901:                    } else {
00902:                        vertexType |= PF;
00903:                        mirrorFloatRefCoords = floatRefCoords;
00904:                        mirrorVertexAllocated &= ~PF;
00905:                    }
00906:
00907:                    break;
00908:                case PD:
00909:                    if (doubleRefCoords == null) {
00910:                        if ((vertexType & VERTEX_DEFINED) == PD) {
00911:                            mirrorDoubleRefCoords = null;
00912:                            mirrorVertexAllocated &= ~PD;
00913:                            vertexType &= ~PD;
00914:                        }
00915:                        vertexType &= ~PD;
00916:                    } else {
00917:                        vertexType |= PD;
00918:                        mirrorDoubleRefCoords = doubleRefCoords;
00919:                        mirrorVertexAllocated &= ~PD;
00920:                    }
00921:
00922:                    break;
00923:                case P3F:
00924:                    if (p3fRefCoords == null) {
00925:                        vertexType &= ~P3F;
00926:                        // Don't set the mirrorFloatRefCoords to null,
00927:                        // may be able to re-use
00928:                        //	    mirrorFloatRefCoords = null;
00929:                    } else {
00930:                        vertexType |= P3F;
00931:
00932:                        if ((mirrorVertexAllocated & PF) == 0) {
00933:                            mirrorFloatRefCoords = new float[vertexCount * 3];
00934:                            mirrorVertexAllocated |= PF;
00935:                        }
00936:
00937:                        index = initialCoordIndex * 3;
00938:                        for (i = initialCoordIndex; i < validVertexCount; i++) {
00939:                            mirrorFloatRefCoords[index++] = p3fRefCoords[i].x;
00940:                            mirrorFloatRefCoords[index++] = p3fRefCoords[i].y;
00941:                            mirrorFloatRefCoords[index++] = p3fRefCoords[i].z;
00942:                        }
00943:                    }
00944:                    break;
00945:                case P3D:
00946:                    if (p3dRefCoords == null) {
00947:                        vertexType &= ~P3D;
00948:                        // Don't set the mirrorDoubleRefCoords to null,
00949:                        // may be able to re-use
00950:                        //	    mirrorDoubleRefCoords = null;
00951:                    } else {
00952:                        vertexType |= P3D;
00953:
00954:                        if ((mirrorVertexAllocated & PD) == 0) {
00955:                            mirrorDoubleRefCoords = new double[vertexCount * 3];
00956:                            mirrorVertexAllocated |= PD;
00957:                        }
00958:
00959:                        index = initialCoordIndex * 3;
00960:                        for (i = initialCoordIndex; i < validVertexCount; i++) {
00961:                            mirrorDoubleRefCoords[index++] = p3dRefCoords[i].x;
00962:                            mirrorDoubleRefCoords[index++] = p3dRefCoords[i].y;
00963:                            mirrorDoubleRefCoords[index++] = p3dRefCoords[i].z;
00964:                        }
00965:                    }
00966:                    break;
00967:                default:
00968:                    break;
00969:
00970:                }
00971:
00972:            }
00973:
00974:            // If turned transparent the first time, then force it to allocate
00975:            void setupMirrorInterleavedColorPointer(boolean force) {
00976:                int index, length, offset;
00977:                int i;
00978:
00979:                if (force || (c4fAllocated != 0)) { // Color is present
00980:
00981:                    length = 4 * vertexCount;
00982:
00983:                    if (mirrorInterleavedColorPointer == null) {
00984:                        mirrorInterleavedColorPointer = new float[1][length];
00985:                    }
00986:
00987:                    index = 4 * initialVertexIndex;
00988:                    offset = stride * initialVertexIndex + colorOffset;
00989:
00990:                    if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) == 0
00991:                            && interLeavedVertexData != null) { // java array
00992:                        if ((vertexFormat & GeometryArray.WITH_ALPHA) != 0) {
00993:
00994:                            for (i = initialVertexIndex; i < validVertexCount; i++) {
00995:                                mirrorInterleavedColorPointer[0][index++] = interLeavedVertexData[offset];
00996:                                mirrorInterleavedColorPointer[0][index++] = interLeavedVertexData[offset + 1];
00997:                                mirrorInterleavedColorPointer[0][index++] = interLeavedVertexData[offset + 2];
00998:                                mirrorInterleavedColorPointer[0][index++] = interLeavedVertexData[offset + 3];
00999:                                offset += stride;
01000:                            }
01001:                        } else {
01002:                            for (i = initialVertexIndex; i < validVertexCount; i++) {
01003:                                mirrorInterleavedColorPointer[0][index++] = interLeavedVertexData[offset];
01004:                                mirrorInterleavedColorPointer[0][index++] = interLeavedVertexData[offset + 1];
01005:                                mirrorInterleavedColorPointer[0][index++] = interLeavedVertexData[offset + 2];
01006:                                mirrorInterleavedColorPointer[0][index++] = 1.0f;
01007:                                offset += stride;
01008:                            }
01009:                        }
01010:
01011:                    } else { // NIO BUFFER
01012:                        if ((vertexFormat & GeometryArray.WITH_ALPHA) != 0
01013:                                && interleavedFloatBufferImpl != null) {
01014:                            for (i = initialVertexIndex; i < validVertexCount; i++) {
01015:                                interleavedFloatBufferImpl.position(offset);
01016:                                interleavedFloatBufferImpl.get(
01017:                                        mirrorInterleavedColorPointer[0],
01018:                                        index, 4);
01019:                                index += 4;
01020:                                offset += stride;
01021:                            }
01022:                        } else {
01023:                            for (i = initialVertexIndex; i < validVertexCount; i++) {
01024:                                interleavedFloatBufferImpl.position(offset);
01025:                                interleavedFloatBufferImpl.get(
01026:                                        mirrorInterleavedColorPointer[0],
01027:                                        index, 3);
01028:                                mirrorInterleavedColorPointer[0][index + 3] = 1.0f;
01029:                                index += 4;
01030:                                offset += stride;
01031:
01032:                            }
01033:                        }
01034:                    }
01035:                    c4fAllocated = GeometryArray.WITH_ALPHA;
01036:                }
01037:            }
01038:
01039:            // If turned transparent the first time, then force it to allocate
01040:            void setupMirrorColorPointer(int ctype, boolean force) {
01041:                int i, srcIndex = 0, dstIndex = 0;
01042:                int multiplier;
01043:
01044:                if (c4fAllocated == 0 && !force) {
01045:                    multiplier = 3;
01046:                } else {
01047:
01048:                    // If the first time, we are forced to allocate 4f, then
01049:                    // we need to force the allocation of the colors again
01050:                    // for the case when allocation has previously occurred
01051:                    // only for RGB
01052:                    if (force && (c4fAllocated == 0)
01053:                            && (vertexFormat & GeometryArray.WITH_ALPHA) == 0) {
01054:                        mirrorColorAllocated = 0;
01055:                    }
01056:                    c4fAllocated = GeometryArray.WITH_ALPHA;
01057:                    multiplier = 4;
01058:                }
01059:
01060:                if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) == 0) { // java array
01061:                    switch (ctype) {
01062:                    case CF:
01063:                        if (floatRefColors == null) {
01064:                            if ((c4fAllocated == 0) && !force
01065:                                    && (vertexType & COLOR_DEFINED) == CF) {
01066:                                mirrorFloatRefColors[0] = null;
01067:                                mirrorColorAllocated &= ~CF;
01068:                            }
01069:                            vertexType &= ~CF;
01070:                            return;
01071:                        }
01072:
01073:                        vertexType |= CF;
01074:                        if (c4fAllocated == 0 && !force) {
01075:                            mirrorFloatRefColors[0] = floatRefColors;
01076:                            mirrorColorAllocated &= ~CF;
01077:                        } else {
01078:                            if ((mirrorColorAllocated & CF) == 0) {
01079:                                mirrorFloatRefColors[0] = new float[4 * vertexCount];
01080:                                mirrorColorAllocated |= CF;
01081:                            }
01082:
01083:                            if ((vertexFormat & GeometryArray.WITH_ALPHA) == 0) {
01084:
01085:                                srcIndex = initialColorIndex * 3;
01086:                                dstIndex = initialColorIndex * 4;
01087:
01088:                                for (i = initialColorIndex; i < validVertexCount; i++) {
01089:                                    mirrorFloatRefColors[0][dstIndex++] = floatRefColors[srcIndex++];
01090:                                    mirrorFloatRefColors[0][dstIndex++] = floatRefColors[srcIndex++];
01091:                                    mirrorFloatRefColors[0][dstIndex++] = floatRefColors[srcIndex++];
01092:                                    mirrorFloatRefColors[0][dstIndex++] = 1.0f;
01093:                                }
01094:
01095:                            } else {
01096:                                srcIndex = initialColorIndex * 4;
01097:                                System.arraycopy(floatRefColors, srcIndex,
01098:                                        mirrorFloatRefColors[0], srcIndex,
01099:                                        (4 * validVertexCount));
01100:                            }
01101:                        }
01102:                        break;
01103:                    case CUB:
01104:                        if (byteRefColors == null) {
01105:                            if (c4fAllocated == 0 && !force
01106:                                    && ((vertexType & COLOR_DEFINED) == CUB)) {
01107:                                mirrorUnsignedByteRefColors[0] = null;
01108:                                mirrorColorAllocated &= ~CUB;
01109:                            }
01110:                            vertexType &= ~CUB;
01111:                            return;
01112:                        }
01113:                        vertexType |= CUB;
01114:                        if (c4fAllocated == 0 && !force) {
01115:                            mirrorUnsignedByteRefColors[0] = byteRefColors;
01116:                            mirrorColorAllocated &= ~CUB;
01117:                            ;
01118:                        } else {
01119:                            if ((mirrorColorAllocated & CUB) == 0) {
01120:                                mirrorUnsignedByteRefColors[0] = new byte[4 * vertexCount];
01121:                                mirrorColorAllocated |= CUB;
01122:                            }
01123:                            if ((vertexFormat & GeometryArray.WITH_ALPHA) == 0) {
01124:
01125:                                srcIndex = initialColorIndex * 3;
01126:                                dstIndex = initialColorIndex * 4;
01127:
01128:                                for (i = initialColorIndex; i < validVertexCount; i++) {
01129:                                    mirrorUnsignedByteRefColors[0][dstIndex++] = byteRefColors[srcIndex++];
01130:                                    mirrorUnsignedByteRefColors[0][dstIndex++] = byteRefColors[srcIndex++];
01131:                                    mirrorUnsignedByteRefColors[0][dstIndex++] = byteRefColors[srcIndex++];
01132:                                    mirrorUnsignedByteRefColors[0][dstIndex++] = (byte) (255.0);
01133:                                }
01134:                            } else {
01135:                                srcIndex = initialColorIndex * 4;
01136:                                System.arraycopy(byteRefColors, srcIndex,
01137:                                        mirrorUnsignedByteRefColors[0],
01138:                                        srcIndex, (4 * validVertexCount));
01139:                            }
01140:                        }
01141:
01142:                        break;
01143:                    case C3F:
01144:                        if (c3fRefColors == null) {
01145:                            vertexType &= ~C3F;
01146:                            return;
01147:                        }
01148:                        vertexType |= C3F;
01149:
01150:                        if ((mirrorColorAllocated & CF) == 0) {
01151:                            mirrorFloatRefColors[0] = new float[vertexCount
01152:                                    * multiplier];
01153:                            mirrorColorAllocated |= CF;
01154:                        }
01155:                        if ((c4fAllocated & GeometryArray.WITH_ALPHA) == 0) {
01156:
01157:                            dstIndex = initialColorIndex * 3;
01158:                            for (i = initialColorIndex; i < validVertexCount; i++) {
01159:                                mirrorFloatRefColors[0][dstIndex++] = c3fRefColors[i].x;
01160:                                mirrorFloatRefColors[0][dstIndex++] = c3fRefColors[i].y;
01161:                                mirrorFloatRefColors[0][dstIndex++] = c3fRefColors[i].z;
01162:                            }
01163:                        } else {
01164:
01165:                            dstIndex = initialColorIndex * 4;
01166:                            for (i = initialColorIndex; i < validVertexCount; i++) {
01167:                                mirrorFloatRefColors[0][dstIndex++] = c3fRefColors[i].x;
01168:                                mirrorFloatRefColors[0][dstIndex++] = c3fRefColors[i].y;
01169:                                mirrorFloatRefColors[0][dstIndex++] = c3fRefColors[i].z;
01170:                                mirrorFloatRefColors[0][dstIndex++] = 1.0f;
01171:                            }
01172:                        }
01173:
01174:                        break;
01175:                    case C4F:
01176:                        if (c4fRefColors == null) {
01177:                            vertexType &= ~C4F;
01178:                            return;
01179:                        }
01180:                        vertexType |= C4F;
01181:
01182:                        if ((mirrorColorAllocated & CF) == 0) {
01183:                            mirrorFloatRefColors[0] = new float[vertexCount << 2];
01184:                            mirrorColorAllocated |= CF;
01185:                        }
01186:
01187:                        dstIndex = initialColorIndex * 4;
01188:                        for (i = initialColorIndex; i < validVertexCount; i++) {
01189:                            mirrorFloatRefColors[0][dstIndex++] = c4fRefColors[i].x;
01190:                            mirrorFloatRefColors[0][dstIndex++] = c4fRefColors[i].y;
01191:                            mirrorFloatRefColors[0][dstIndex++] = c4fRefColors[i].z;
01192:                            mirrorFloatRefColors[0][dstIndex++] = c4fRefColors[i].w;
01193:                        }
01194:                        break;
01195:                    case C3UB:
01196:                        if (c3bRefColors == null) {
01197:                            vertexType &= ~C3UB;
01198:                            return;
01199:                        }
01200:                        vertexType |= C3UB;
01201:
01202:                        if ((mirrorColorAllocated & CUB) == 0) {
01203:                            mirrorUnsignedByteRefColors[0] = new byte[vertexCount
01204:                                    * multiplier];
01205:                            mirrorColorAllocated |= CUB;
01206:                        }
01207:                        if ((c4fAllocated & GeometryArray.WITH_ALPHA) == 0) {
01208:                            dstIndex = initialColorIndex * 3;
01209:                            for (i = initialColorIndex; i < validVertexCount; i++) {
01210:                                mirrorUnsignedByteRefColors[0][dstIndex++] = c3bRefColors[i].x;
01211:                                mirrorUnsignedByteRefColors[0][dstIndex++] = c3bRefColors[i].y;
01212:                                mirrorUnsignedByteRefColors[0][dstIndex++] = c3bRefColors[i].z;
01213:                            }
01214:                        } else {
01215:                            dstIndex = initialColorIndex * 4;
01216:                            for (i = initialColorIndex; i < validVertexCount; i++) {
01217:                                mirrorUnsignedByteRefColors[0][dstIndex++] = c3bRefColors[i].x;
01218:                                mirrorUnsignedByteRefColors[0][dstIndex++] = c3bRefColors[i].y;
01219:                                mirrorUnsignedByteRefColors[0][dstIndex++] = c3bRefColors[i].z;
01220:                                mirrorUnsignedByteRefColors[0][dstIndex++] = (byte) 255;
01221:                            }
01222:                        }
01223:                        break;
01224:                    case C4UB:
01225:                        if (c4bRefColors == null) {
01226:                            vertexType &= ~C4UB;
01227:                            return;
01228:                        }
01229:                        vertexType |= C4UB;
01230:                        if ((mirrorColorAllocated & CUB) == 0) {
01231:                            mirrorUnsignedByteRefColors[0] = new byte[vertexCount << 2];
01232:                            mirrorColorAllocated |= CUB;
01233:                        }
01234:
01235:                        dstIndex = initialColorIndex * 4;
01236:                        for (i = initialColorIndex; i < validVertexCount; i++) {
01237:                            mirrorUnsignedByteRefColors[0][dstIndex++] = c4bRefColors[i].x;
01238:                            mirrorUnsignedByteRefColors[0][dstIndex++] = c4bRefColors[i].y;
01239:                            mirrorUnsignedByteRefColors[0][dstIndex++] = c4bRefColors[i].z;
01240:                            mirrorUnsignedByteRefColors[0][dstIndex++] = c4bRefColors[i].w;
01241:                        }
01242:                        break;
01243:                    default:
01244:                        break;
01245:                    }
01246:                } else { //USE_NIO_BUFFER is set
01247:                    if (colorRefBuffer == null) {
01248:                        if (c4fAllocated == 0 && !force
01249:                                && (vertexType & COLOR_DEFINED) == CF) {
01250:                            mirrorFloatRefColors[0] = null;
01251:                            mirrorColorAllocated &= ~CF;
01252:                        }
01253:                        vertexType &= ~CF;
01254:
01255:                        if (c4fAllocated == 0 && !force
01256:                                && ((vertexType & COLOR_DEFINED) == CUB)) {
01257:                            mirrorUnsignedByteRefColors[0] = null;
01258:                            mirrorColorAllocated &= ~CUB;
01259:                        }
01260:                        vertexType &= ~CUB;
01261:                        return;
01262:
01263:                    } else if (floatBufferRefColors != null) {
01264:                        vertexType |= CF;
01265:                        vertexType &= ~CUB;
01266:                        if (c4fAllocated == 0 && !force) {
01267:                            // NOTE: make suren mirrorFloatRefColors[0] is set right
01268:                            mirrorFloatRefColors[0] = null;
01269:                            mirrorColorAllocated &= ~CF;
01270:                        } else {
01271:                            if ((mirrorColorAllocated & CF) == 0) {
01272:                                mirrorFloatRefColors[0] = new float[4 * vertexCount];
01273:                                mirrorColorAllocated |= CF;
01274:                            }
01275:                            floatBufferRefColors.rewind();
01276:                            if ((vertexFormat & GeometryArray.WITH_ALPHA) == 0) {
01277:                                srcIndex = initialColorIndex * 3;
01278:                                dstIndex = initialColorIndex * 4;
01279:                                floatBufferRefColors.position(srcIndex);
01280:
01281:                                for (i = initialColorIndex; i < validVertexCount; i++) {
01282:                                    floatBufferRefColors.get(
01283:                                            mirrorFloatRefColors[0], dstIndex,
01284:                                            3);
01285:                                    mirrorFloatRefColors[0][dstIndex + 3] = 1.0f;
01286:                                    dstIndex += 4;
01287:                                }
01288:                            } else {
01289:
01290:                                srcIndex = initialColorIndex * 4;
01291:                                dstIndex = initialColorIndex * 4;
01292:                                floatBufferRefColors.position(srcIndex);
01293:                                for (i = initialColorIndex; i < validVertexCount; i++) {
01294:                                    floatBufferRefColors.get(
01295:                                            mirrorFloatRefColors[0], dstIndex,
01296:                                            4);
01297:                                    dstIndex += 4;
01298:                                }
01299:                            }
01300:                        }
01301:                    } else if (byteBufferRefColors != null) {
01302:                        vertexType |= CUB;
01303:                        vertexType &= ~CF;
01304:                        if (c4fAllocated == 0 && !force) {
01305:                            // NOTE: make sure mirrorUnsignedByteRefColors[0] is set right
01306:                            mirrorUnsignedByteRefColors[0] = null;
01307:                            mirrorColorAllocated &= ~CUB;
01308:                            ;
01309:                        } else {
01310:                            if ((mirrorColorAllocated & CUB) == 0) {
01311:                                mirrorUnsignedByteRefColors[0] = new byte[4 * vertexCount];
01312:                                mirrorColorAllocated |= CUB;
01313:                            }
01314:
01315:                            byteBufferRefColors.rewind();
01316:                            if ((vertexFormat & GeometryArray.WITH_ALPHA) == 0) {
01317:                                srcIndex = initialColorIndex * 3;
01318:                                dstIndex = initialColorIndex * 4;
01319:                                byteBufferRefColors.position(srcIndex);
01320:                                for (i = initialColorIndex; i < validVertexCount; i++) {
01321:                                    byteBufferRefColors.get(
01322:                                            mirrorUnsignedByteRefColors[0],
01323:                                            dstIndex, 3);
01324:                                    mirrorUnsignedByteRefColors[0][dstIndex + 3] = (byte) (255.0);
01325:                                    dstIndex += 4;
01326:                                }
01327:                            } else {
01328:                                srcIndex = initialColorIndex * 4;
01329:                                dstIndex = initialColorIndex * 4;
01330:                                byteBufferRefColors.position(srcIndex);
01331:                                for (i = initialColorIndex; i < validVertexCount; i++) {
01332:                                    byteBufferRefColors.get(
01333:                                            mirrorUnsignedByteRefColors[0],
01334:                                            dstIndex, 4);
01335:                                    dstIndex += 4;
01336:                                }
01337:                            }
01338:                        } // end of else
01339:                    }//end of else if ( byteBufferRefColors != null)
01340:                }//end of NIO BUFFER case
01341:
01342:                colorChanged = 0xffff;
01343:            }
01344:
01345:            void setupMirrorNormalPointer(int ntype) {
01346:                int i, index;
01347:
01348:                switch (ntype) {
01349:                case NF:
01350:                    if (floatRefNormals == null) {
01351:                        if ((vertexType & NORMAL_DEFINED) == NF) {
01352:                            vertexType &= ~NF;
01353:                            mirrorFloatRefNormals = null;
01354:                            mirrorNormalAllocated = false;
01355:                        }
01356:                    } else {
01357:                        vertexType |= NF;
01358:                        mirrorFloatRefNormals = floatRefNormals;
01359:                        mirrorNormalAllocated = false;
01360:                    }
01361:                    break;
01362:                case N3F:
01363:                    if (v3fRefNormals == null) {
01364:                        if ((vertexType & NORMAL_DEFINED) == N3F) {
01365:                            vertexType &= ~N3F;
01366:                        }
01367:                        return;
01368:                    } else {
01369:                        vertexType |= N3F;
01370:                    }
01371:                    if (!mirrorNormalAllocated) {
01372:                        mirrorFloatRefNormals = new float[vertexCount * 3];
01373:                        mirrorNormalAllocated = true;
01374:                    }
01375:
01376:                    index = initialNormalIndex * 3;
01377:                    for (i = initialNormalIndex; i < validVertexCount; i++) {
01378:                        mirrorFloatRefNormals[index++] = v3fRefNormals[i].x;
01379:                        mirrorFloatRefNormals[index++] = v3fRefNormals[i].y;
01380:                        mirrorFloatRefNormals[index++] = v3fRefNormals[i].z;
01381:                    }
01382:                    break;
01383:                default:
01384:                    break;
01385:                }
01386:            }
01387:
01388:            void setupMirrorTexCoordPointer(int type) {
01389:                for (int i = 0; i < texCoordSetCount; i++) {
01390:                    doSetupMirrorTexCoordPointer(i, type);
01391:                }
01392:
01393:                validateTexCoordPointerType();
01394:            }
01395:
01396:            void setupMirrorTexCoordPointer(int texCoordSet, int type) {
01397:                doSetupMirrorTexCoordPointer(texCoordSet, type);
01398:                validateTexCoordPointerType();
01399:            }
01400:
01401:            // If all texCoord pointers are set to a non-null value, then set the
01402:            // texcoord type in the vertexType flag word, else clear the texcoord type
01403:            private void validateTexCoordPointerType() {
01404:                boolean allNonNull = true;
01405:                boolean allNull = true;
01406:                for (int i = 0; i < texCoordSetCount; i++) {
01407:                    if (refTexCoords[i] == null) {
01408:                        allNonNull = false;
01409:                    } else {
01410:                        allNull = false;
01411:                    }
01412:                }
01413:
01414:                // Reset texCoordType if all references are null
01415:                if (allNull) {
01416:                    texCoordType = 0;
01417:                }
01418:
01419:                // Copy texCoordType to vertexType if all references are non-null
01420:                vertexType &= ~TEXCOORD_DEFINED;
01421:                if (allNonNull) {
01422:                    vertexType |= texCoordType;
01423:                }
01424:            }
01425:
01426:            private void doSetupMirrorTexCoordPointer(int texCoordSet, int type) {
01427:                int i, index;
01428:
01429:                switch (type) {
01430:                case TF:
01431:                    texCoordType = TF;
01432:                    mirrorRefTexCoords[texCoordSet] = refTexCoords[texCoordSet];
01433:                    break;
01434:
01435:                case T2F:
01436:                    texCoordType = T2F;
01437:                    t2fRefTexCoords = (TexCoord2f[]) refTexCoords[texCoordSet];
01438:
01439:                    if (t2fRefTexCoords == null) {
01440:                        mirrorRefTexCoords[texCoordSet] = null;
01441:                        break;
01442:                    }
01443:
01444:                    mirrorFloatRefTexCoords = (float[]) mirrorRefTexCoords[texCoordSet];
01445:                    if (mirrorFloatRefTexCoords != null) {
01446:                        if (mirrorFloatRefTexCoords.length < (vertexCount * 2))
01447:                            mirrorRefTexCoords[texCoordSet] = mirrorFloatRefTexCoords = new float[vertexCount * 2];
01448:                    } else {
01449:                        mirrorRefTexCoords[texCoordSet] = mirrorFloatRefTexCoords = new float[vertexCount * 2];
01450:                    }
01451:
01452:                    index = initialTexCoordIndex[texCoordSet] * 2;
01453:                    for (i = initialTexCoordIndex[texCoordSet]; i < validVertexCount; i++) {
01454:                        mirrorFloatRefTexCoords[index++] = t2fRefTexCoords[i].x;
01455:                        mirrorFloatRefTexCoords[index++] = t2fRefTexCoords[i].y;
01456:                    }
01457:                    break;
01458:
01459:                case T3F:
01460:                    texCoordType = T3F;
01461:                    t3fRefTexCoords = (TexCoord3f[]) refTexCoords[texCoordSet];
01462:
01463:                    if (t3fRefTexCoords == null) {
01464:                        mirrorRefTexCoords[texCoordSet] = null;
01465:                        break;
01466:                    }
01467:
01468:                    mirrorFloatRefTexCoords = (float[]) mirrorRefTexCoords[texCoordSet];
01469:                    if (mirrorFloatRefTexCoords != null) {
01470:                        if (mirrorFloatRefTexCoords.length < (vertexCount * 3))
01471:                            mirrorRefTexCoords[texCoordSet] = mirrorFloatRefTexCoords = new float[vertexCount * 3];
01472:                    } else {
01473:                        mirrorRefTexCoords[texCoordSet] = mirrorFloatRefTexCoords = new float[vertexCount * 3];
01474:                    }
01475:
01476:                    index = initialTexCoordIndex[texCoordSet] * 3;
01477:                    for (i = initialTexCoordIndex[texCoordSet]; i < validVertexCount; i++) {
01478:                        mirrorFloatRefTexCoords[index++] = t3fRefTexCoords[i].x;
01479:                        mirrorFloatRefTexCoords[index++] = t3fRefTexCoords[i].y;
01480:                        mirrorFloatRefTexCoords[index++] = t3fRefTexCoords[i].z;
01481:                    }
01482:                    break;
01483:
01484:                default:
01485:                    break;
01486:                }
01487:            }
01488:
01489:            void setupMirrorVertexAttrPointer(int type) {
01490:                for (int i = 0; i < vertexAttrCount; i++) {
01491:                    doSetupMirrorVertexAttrPointer(i, type);
01492:                }
01493:
01494:                validateVertexAttrPointerType();
01495:            }
01496:
01497:            void setupMirrorVertexAttrPointer(int vertexAttrNum, int type) {
01498:                doSetupMirrorVertexAttrPointer(vertexAttrNum, type);
01499:                validateVertexAttrPointerType();
01500:            }
01501:
01502:            // If all vertex attr pointers are set to a non-null value, then set the
01503:            // vertex attr type in the vertexType flag word, else clear the
01504:            // vertex attr type
01505:            private void validateVertexAttrPointerType() {
01506:                boolean allNonNull = true;
01507:                boolean allNull = true;
01508:
01509:                if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) == 0) {
01510:                    for (int i = 0; i < vertexAttrCount; i++) {
01511:                        if (floatRefVertexAttrs[i] == null) {
01512:                            allNonNull = false;
01513:                        } else {
01514:                            allNull = false;
01515:                        }
01516:                    }
01517:                } else {
01518:                    for (int i = 0; i < vertexAttrCount; i++) {
01519:                        if (nioFloatBufferRefVertexAttrs[i] == null) {
01520:                            allNonNull = false;
01521:                        } else {
01522:                            allNull = false;
01523:                        }
01524:                    }
01525:                }
01526:
01527:                // Reset vertexAttrType if all references are null
01528:                if (allNull) {
01529:                    vertexAttrType = 0;
01530:                }
01531:
01532:                // Copy vertexAttrType to vertexType if all references are non-null
01533:                vertexType &= ~VATTR_DEFINED;
01534:                if (allNonNull) {
01535:                    vertexType |= vertexAttrType;
01536:                }
01537:            }
01538:
01539:            private void doSetupMirrorVertexAttrPointer(int vertexAttrNum,
01540:                    int type) {
01541:                switch (type) {
01542:                case AF:
01543:                    vertexAttrType = AF;
01544:                    mirrorFloatRefVertexAttrs[vertexAttrNum] = floatRefVertexAttrs[vertexAttrNum];
01545:                    break;
01546:                default:
01547:                    break;
01548:                }
01549:            }
01550:
01551:            void createGeometryArrayData(int vertexCount, int vertexFormat) {
01552:                if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) {
01553:                    createGeometryArrayData(vertexCount, vertexFormat, 1,
01554:                            defaultTexCoordSetMap);
01555:                } else {
01556:                    createGeometryArrayData(vertexCount, vertexFormat, 0, null);
01557:                }
01558:            }
01559:
01560:            void createGeometryArrayData(int vertexCount, int vertexFormat,
01561:                    int texCoordSetCount, int[] texCoordSetMap) {
01562:
01563:                createGeometryArrayData(vertexCount, vertexFormat,
01564:                        texCoordSetCount, texCoordSetMap, 0, null);
01565:            }
01566:
01567:            void createGeometryArrayData(int vertexCount, int vertexFormat,
01568:                    int texCoordSetCount, int[] texCoordSetMap,
01569:                    int vertexAttrCount, int[] vertexAttrSizes) {
01570:                this .vertexFormat = vertexFormat;
01571:                this .vertexCount = vertexCount;
01572:                this .validVertexCount = vertexCount;
01573:
01574:                this .texCoordSetCount = texCoordSetCount;
01575:                if (texCoordSetMap == null) {
01576:                    this .texCoordSetMap = null;
01577:                } else {
01578:                    this .texCoordSetMap = (int[]) texCoordSetMap.clone();
01579:                }
01580:
01581:                this .vertexAttrCount = vertexAttrCount;
01582:                if (vertexAttrSizes == null) {
01583:                    this .vertexAttrSizes = null;
01584:                } else {
01585:                    this .vertexAttrSizes = (int[]) vertexAttrSizes.clone();
01586:                }
01587:
01588:                this .vertexAttrStride = this .vertexAttrStride();
01589:                this .stride = this .stride();
01590:
01591:                this .vertexAttrOffsets = this .vertexAttrOffsets();
01592:                this .texCoordSetMapOffset = this .texCoordSetMapOffset();
01593:                this .textureOffset = this .textureOffset();
01594:                this .colorOffset = this .colorOffset();
01595:                this .normalOffset = this .normalOffset();
01596:                this .coordinateOffset = this .coordinateOffset();
01597:
01598:                if ((vertexFormat & GeometryArray.BY_REFERENCE) == 0) {
01599:                    this .vertexData = new float[this .vertexCount * this .stride];
01600:                } else { // By reference geometry
01601:                    this .vertexData = null;
01602:                    if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) {
01603:                        this .mirrorRefTexCoords = new Object[texCoordSetCount];
01604:                        this .refTexCoords = new Object[texCoordSetCount]; // keep J3DBufferImp object in nio buffer case
01605:                        if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) != 0)
01606:                            this .refTexCoordsBuffer = new Object[texCoordSetCount]; // keep J3DBuffer object
01607:                    }
01608:                    if ((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) {
01609:                        this .floatRefVertexAttrs = new float[vertexAttrCount][];
01610:                        this .mirrorFloatRefVertexAttrs = new float[vertexAttrCount][];
01611:                        if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) != 0) {
01612:                            this .vertexAttrsRefBuffer = new J3DBuffer[vertexAttrCount];
01613:                            this .floatBufferRefVertexAttrs = new FloatBufferWrapper[vertexAttrCount];
01614:                            this .nioFloatBufferRefVertexAttrs = new Object[vertexAttrCount];
01615:                        }
01616:                    }
01617:                }
01618:                if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) {
01619:                    this .initialTexCoordIndex = new int[texCoordSetCount];
01620:                }
01621:                if ((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) {
01622:                    this .initialVertexAttrIndex = new int[vertexAttrCount];
01623:                }
01624:                noAlpha = ((vertexFormat & GeometryArray.WITH_ALPHA) == 0);
01625:                lastAlpha[0] = 1.0f;
01626:
01627:            }
01628:
01629:            void setVertexFormat(boolean useAlpha, boolean ignoreVC, Context ctx) {
01630:                Pipeline.getPipeline().setVertexFormat(ctx, this , vertexFormat,
01631:                        useAlpha, ignoreVC);
01632:            }
01633:
01634:            void disableGlobalAlpha(Context ctx, boolean useAlpha,
01635:                    boolean ignoreVC) {
01636:                // If global alpha was turned on, then disable it
01637:                Pipeline.getPipeline().disableGlobalAlpha(ctx, this ,
01638:                        vertexFormat, useAlpha, ignoreVC);
01639:            }
01640:
01641:            float[] updateAlphaInFloatRefColors(Canvas3D cv, int screen,
01642:                    float alpha) {
01643:
01644:                //System.err.println("updateAlphaInFloatRefColors  screen = " + screen +
01645:                //		   " alpha " + alpha );
01646:
01647:                // no need to update alpha values if canvas supports global alpha
01648:                if (cv.supportGlobalAlpha()) {
01649:                    cv.setGlobalAlpha(cv.ctx, alpha);
01650:                    return mirrorFloatRefColors[0];
01651:                }
01652:
01653:                // update alpha only if vertex format includes alpha
01654:                if (((vertexFormat | c4fAllocated) & GeometryArray.WITH_ALPHA) == 0)
01655:                    return mirrorFloatRefColors[0];
01656:
01657:                // if alpha is smaller than EPSILON, set it to EPSILON, so that
01658:                // even if alpha is equal to 0, we will not completely lose
01659:                // the original alpha value
01660:                if (alpha <= EPSILON) {
01661:                    alpha = (float) EPSILON;
01662:                }
01663:
01664:                assert lastAlpha != null;
01665:                assert mirrorFloatRefColors != null;
01666:                assert mirrorFloatRefColors.length == lastAlpha.length;
01667:
01668:                // Issue 113 - reallocate lastAlpha array if needed, but no need to
01669:                // update the values here
01670:                if (lastAlpha.length <= screen) {
01671:                    float[] la = new float[screen + 1];
01672:                    for (int i = 0; i < lastAlpha.length; i++) {
01673:                        la[i] = lastAlpha[i];
01674:                    }
01675:                    lastAlpha = la;
01676:                }
01677:
01678:                //System.err.println("updateAlphaInFloatRefColors screen is " + screen
01679:                //		     + " mirrorFloatRefColors.length " +
01680:                //		     mirrorFloatRefColors.length);
01681:
01682:                // allocate a copy of the color data for the screen if needed.
01683:                // this piece of code is only for multi-screens case
01684:                if (mirrorFloatRefColors.length <= screen) {
01685:                    float[][] cfData = new float[screen + 1][];
01686:
01687:                    for (int i = 0; i < mirrorFloatRefColors.length; i++) {
01688:                        cfData[i] = mirrorFloatRefColors[i];
01689:                    }
01690:
01691:                    // Issue 113 - allocate entries for [oldSize..screen];
01692:                    // copy cfData[0] to cfData[oldsize..screen-1] and
01693:                    // lastAlpha[0] to lastAlpha[oldsize..screen-1].
01694:                    for (int i = mirrorFloatRefColors.length; i < screen + 1; i++) {
01695:                        cfData[i] = new float[4 * vertexCount];
01696:                        System.arraycopy(cfData[0], 0, cfData[i], 0,
01697:                                4 * vertexCount);
01698:                        lastAlpha[i] = lastAlpha[0];
01699:                    }
01700:
01701:                    mirrorFloatRefColors = cfData;
01702:
01703:                    // Issue 113 - since we copied the data from screen 0, we don't need
01704:                    // to do any further special processing.
01705:                }
01706:
01707:                assert lastAlpha[screen] >= 0.0;
01708:                /*
01709:                  System.err.println("updateAlphaInFloatRefColors ** : lastAlpha[screen] " +
01710:                		     lastAlpha[screen]);
01711:
01712:                  System.err.println("((colorChanged & (1<<screen)) == 0) " +
01713:                		     ((colorChanged & (1<<screen)) == 0));
01714:                 */
01715:
01716:                if ((colorChanged & (1 << screen)) == 0) {
01717:                    // color data is not modified
01718:                    if (Math.abs(lastAlpha[screen] - alpha) <= EPSILON) {
01719:                        // and if alpha is the same as the last one,
01720:                        // just return the data
01721:                        //System.err.println("updateAlphaInFloatRefColors 0 : alpha is the same as the last one " + alpha);
01722:
01723:                        return mirrorFloatRefColors[screen];
01724:                    } else {
01725:
01726:                        // if alpha is different, update the alpha values
01727:                        //System.err.println("updateAlphaInFloatRefColors 1 : alpha is different, update the alpha values " + alpha);
01728:
01729:                        float m = alpha / lastAlpha[screen];
01730:
01731:                        float[] cdata = mirrorFloatRefColors[screen];
01732:
01733:                        // We've to traverse the whole due to BugId : 4676483
01734:                        for (int i = 0, j = 0; i < vertexCount; i++, j += 4) {
01735:                            cdata[j + 3] = cdata[j + 3] * m;
01736:                        }
01737:                    }
01738:                } else {
01739:                    // color data is modified
01740:                    if (screen == 0) {
01741:
01742:                        // just update alpha values since screen 0 data is
01743:                        // already updated in setupMirrorColorPointer
01744:
01745:                        //System.err.println("updateAlphaInFloatRefColors 2 : just update alpha = " + alpha);
01746:
01747:                        float[] cdata = mirrorFloatRefColors[screen];
01748:
01749:                        // This part is also incorrect due to BugId : 4676483
01750:                        // But traversing the whole array doesn't help either, as there
01751:                        // isn't a mechanism to indicate the the alpha component has
01752:                        // not changed by user.
01753:                        int j = initialColorIndex * 4;
01754:                        for (int i = initialColorIndex; i < validVertexCount; i++, j += 4) {
01755:                            cdata[j + 3] = cdata[j + 3] * alpha;
01756:                        }
01757:                    } else {
01758:                        // update color values from screen 0 data
01759:                        //System.err.println("updateAlphaInFloatRefColors 3 : update color values from screen 0 data " + alpha);
01760:
01761:                        float m;
01762:
01763:                        if ((colorChanged & 1) == 0) {
01764:                            // alpha is up to date in screen 0
01765:                            m = alpha / lastAlpha[0];
01766:                        } else {
01767:                            m = alpha;
01768:                        }
01769:
01770:                        float[] sdata = mirrorFloatRefColors[0];
01771:                        float[] cdata = mirrorFloatRefColors[screen];
01772:
01773:                        int j = initialColorIndex * 4;
01774:                        for (int i = initialColorIndex; i < validVertexCount; i++) {
01775:                            cdata[j] = sdata[j++];
01776:                            cdata[j] = sdata[j++];
01777:                            cdata[j] = sdata[j++];
01778:                            cdata[j] = sdata[j++] * m;
01779:                        }
01780:                    }
01781:                }
01782:
01783:                lastAlpha[screen] = alpha;
01784:                colorChanged &= ~(1 << screen);
01785:                dirtyFlag |= COLOR_CHANGED;
01786:                return mirrorFloatRefColors[screen];
01787:            }
01788:
01789:            byte[] updateAlphaInByteRefColors(Canvas3D cv, int screen,
01790:                    float alpha) {
01791:
01792:                /*
01793:                  System.err.println("updateAlphaInByteRefColors  screen = " + screen +
01794:                  " alpha " + alpha );
01795:                 */
01796:
01797:                // no need to update alpha values if canvas supports global alpha
01798:                if (cv.supportGlobalAlpha()) {
01799:                    cv.setGlobalAlpha(cv.ctx, alpha);
01800:                    return mirrorUnsignedByteRefColors[0];
01801:                }
01802:
01803:                // update alpha only if vertex format includes alpha
01804:                if (((vertexFormat | c4fAllocated) & GeometryArray.WITH_ALPHA) == 0)
01805:                    return mirrorUnsignedByteRefColors[0];
01806:
01807:                // if alpha is smaller than EPSILON, set it to EPSILON, so that
01808:                // even if alpha is equal to 0, we will not completely lose
01809:                // the original alpha value
01810:                if (alpha <= EPSILON) {
01811:                    alpha = (float) EPSILON;
01812:                }
01813:
01814:                assert lastAlpha != null;
01815:                assert mirrorUnsignedByteRefColors != null;
01816:                assert mirrorUnsignedByteRefColors.length == lastAlpha.length;
01817:
01818:                // Issue 113 - reallocate lastAlpha array if needed, but no need to
01819:                // update the values here
01820:                if (lastAlpha.length <= screen) {
01821:                    float[] la = new float[screen + 1];
01822:                    for (int i = 0; i < lastAlpha.length; i++) {
01823:                        la[i] = lastAlpha[i];
01824:                    }
01825:                    lastAlpha = la;
01826:                }
01827:
01828:                // allocate a copy of the color data for the screen if needed.
01829:                // this piece of code is only for multi-screens case
01830:                if (mirrorUnsignedByteRefColors.length <= screen) {
01831:                    byte[][] cbData = new byte[screen + 1][];
01832:                    for (int i = 0; i < mirrorUnsignedByteRefColors.length; i++) {
01833:                        cbData[i] = mirrorUnsignedByteRefColors[i];
01834:                    }
01835:
01836:                    // Issue 113 - allocate entries for [oldSize..screen];
01837:                    // copy cbData[0] to cbData[oldsize..screen-1] and
01838:                    // lastAlpha[0] to lastAlpha[oldsize..screen-1].
01839:                    for (int i = mirrorUnsignedByteRefColors.length; i < screen + 1; i++) {
01840:                        cbData[i] = new byte[4 * vertexCount];
01841:                        System.arraycopy(cbData[0], 0, cbData[i], 0,
01842:                                4 * vertexCount);
01843:                        lastAlpha[i] = lastAlpha[0];
01844:                    }
01845:
01846:                    mirrorUnsignedByteRefColors = cbData;
01847:
01848:                    // Issue 113 - since we copied the data from screen 0, we don't need
01849:                    // to do any further special processing.
01850:                }
01851:
01852:                assert lastAlpha[screen] >= 0.0;
01853:                /*
01854:                System.err.println("updateAlphaInByteRefColors ## : lastAlpha[screen] " +
01855:                	   lastAlpha[screen]);
01856:
01857:                System.err.println("((colorChanged & (1<<screen)) == 0) " +
01858:                	   ((colorChanged & (1<<screen)) == 0));
01859:                 */
01860:
01861:                if ((colorChanged & (1 << screen)) == 0) {
01862:                    // color data is not modified
01863:                    if (Math.abs(lastAlpha[screen] - alpha) <= EPSILON) {
01864:                        // and if alpha is the same as the last one,
01865:                        // just return the data
01866:                        //System.err.println("updateAlphaInByteRefColors 0 : alpha is the same as the last one " + alpha);
01867:
01868:                        return mirrorUnsignedByteRefColors[screen];
01869:                    } else {
01870:                        // if alpha is different, update the alpha values
01871:
01872:                        //System.err.println("updateAlphaInByteRefColors 1 : alpha is different, update the alpha values " + alpha);
01873:
01874:                        float m = alpha / lastAlpha[screen];
01875:
01876:                        byte[] cdata = mirrorUnsignedByteRefColors[screen];
01877:
01878:                        // We've to traverse the whole due to BugId : 4676483
01879:                        for (int i = 0, j = 0; i < vertexCount; i++, j += 4) {
01880:                            cdata[j + 3] = (byte) (((int) cdata[j + 3] & 0xff) * m);
01881:                        }
01882:                    }
01883:                } else {
01884:                    // color data is modified
01885:                    if (screen == 0) {
01886:                        //System.err.println("updateAlphaInByteRefColors 2 : just update alpha =" + alpha);
01887:
01888:                        // just update alpha values since screen 0 data is
01889:                        // already updated in setupMirrorColorPointer
01890:
01891:                        byte[] cdata = mirrorUnsignedByteRefColors[screen];
01892:
01893:                        // This part is also incorrect due to BugId : 4676483
01894:                        // But traversing the whole array doesn't help either, as there
01895:                        // isn't a mechanism to indicate the the alpha component has
01896:                        // not changed by user.
01897:                        int j = initialColorIndex * 4;
01898:                        for (int i = initialColorIndex; i < validVertexCount; i++, j += 4) {
01899:                            cdata[j + 3] = (byte) (((int) cdata[j + 3] & 0xff) * alpha);
01900:                        }
01901:                    } else {
01902:                        // update color values from screen 0 data
01903:                        float m;
01904:
01905:                        //System.err.println("updateAlphaInByteRefColors 3 : update color values from screen 0 data " + alpha);
01906:
01907:                        if ((colorChanged & 1) == 0) {
01908:                            // alpha is up to date in screen 0
01909:                            m = alpha / lastAlpha[0];
01910:                        } else {
01911:                            m = alpha;
01912:                        }
01913:                        byte[] sdata = mirrorUnsignedByteRefColors[0];
01914:                        byte[] cdata = mirrorUnsignedByteRefColors[screen];
01915:
01916:                        int j = initialColorIndex * 4;
01917:                        for (int i = initialColorIndex; i < validVertexCount; i++) {
01918:                            cdata[j] = sdata[j++];
01919:                            cdata[j] = sdata[j++];
01920:                            cdata[j] = sdata[j++];
01921:                            cdata[j] = (byte) (((int) sdata[j++] & 0xff) * m);
01922:                        }
01923:                    }
01924:                }
01925:
01926:                lastAlpha[screen] = alpha;
01927:                colorChanged &= ~(1 << screen);
01928:                dirtyFlag |= COLOR_CHANGED;
01929:                return mirrorUnsignedByteRefColors[screen];
01930:            }
01931:
01932:            Object[] updateAlphaInVertexData(Canvas3D cv, int screen,
01933:                    float alpha) {
01934:
01935:                Object[] retVal = new Object[2];
01936:                retVal[0] = Boolean.FALSE;
01937:
01938:                // no need to update alpha values if canvas supports global alpha
01939:                if (cv.supportGlobalAlpha()) {
01940:                    cv.setGlobalAlpha(cv.ctx, alpha);
01941:                    retVal[1] = vertexData;
01942:                    return retVal;
01943:                }
01944:
01945:                // update alpha only if vertex format includes alpha
01946:                if ((vertexFormat & GeometryArray.COLOR) == 0) {
01947:                    retVal[1] = vertexData;
01948:                    return retVal;
01949:                }
01950:
01951:                // if alpha is smaller than EPSILON, set it to EPSILON, so that
01952:                // even if alpha is equal to 0, we will not completely lose
01953:                // the original alpha value
01954:                if (alpha <= EPSILON) {
01955:                    alpha = (float) EPSILON;
01956:                }
01957:                retVal[0] = Boolean.TRUE;
01958:
01959:                assert lastAlpha != null;
01960:                assert mvertexData == null
01961:                        || mvertexData.length == lastAlpha.length;
01962:
01963:                // Issue 113 - reallocate lastAlpha array if needed, but no need to
01964:                // update the values here
01965:                if (lastAlpha.length <= screen) {
01966:                    float[] la = new float[screen + 1];
01967:                    for (int i = 0; i < lastAlpha.length; i++) {
01968:                        la[i] = lastAlpha[i];
01969:                    }
01970:                    lastAlpha = la;
01971:                }
01972:
01973:                // allocate a copy of the vertex data for the screen if needed.
01974:                // Note that a copy operation only happens in the multi-screens case.
01975:                // We always use the existing vertexData for screen 0.
01976:                if (mvertexData == null || mvertexData.length <= screen) {
01977:
01978:                    float[][] cfData = new float[screen + 1][];
01979:                    int oldSize = 1;
01980:
01981:                    if (mvertexData != null) {
01982:                        oldSize = mvertexData.length;
01983:                        for (int i = 0; i < mvertexData.length; i++) {
01984:                            cfData[i] = mvertexData[i];
01985:                        }
01986:                    }
01987:
01988:                    if (cfData[0] == null) {
01989:                        cfData[0] = vertexData;
01990:                    }
01991:
01992:                    // Issue 113 - allocate entries for [oldSize..screen];
01993:                    // copy cfData[0] to cfData[oldsize..screen-1] and
01994:                    // lastAlpha[0] to lastAlpha[oldsize..screen-1].
01995:                    if (screen > 0) {
01996:                        for (int i = oldSize; i < screen + 1; i++) {
01997:                            cfData[i] = new float[stride * vertexCount];
01998:                            System.arraycopy(cfData[0], 0, cfData[i], 0, stride
01999:                                    * vertexCount);
02000:                            lastAlpha[i] = lastAlpha[0];
02001:                        }
02002:                    }
02003:
02004:                    mvertexData = cfData;
02005:
02006:                    // Issue 113 - since we copied the data from screen 0, we don't need
02007:                    // to do any further special processing.
02008:                }
02009:
02010:                assert lastAlpha[screen] >= 0.0;
02011:
02012:                if ((colorChanged & (1 << screen)) == 0) {
02013:                    // color data is not modified
02014:                    if (Math.abs(lastAlpha[screen] - alpha) <= EPSILON) {
02015:                        // and if alpha is the same as the last one,
02016:                        // just return the data
02017:                        retVal[1] = mvertexData[screen];
02018:                        return retVal;
02019:                    } else {
02020:                        // if alpha is different, update the alpha values
02021:                        float m = alpha / lastAlpha[screen];
02022:
02023:                        float[] cdata = mvertexData[screen];
02024:                        for (int i = 0, j = colorOffset; i < vertexCount; i++, j += stride) {
02025:                            cdata[j + 3] *= m;
02026:                        }
02027:                    }
02028:                } else {
02029:                    // color data is modified
02030:                    if (screen == 0) {
02031:                        // just update alpha values since screen 0 data is
02032:                        // already updated in setupMirrorColorPointer
02033:
02034:                        float[] cdata = mvertexData[screen];
02035:                        double m = alpha / lastAlpha[0];
02036:
02037:                        for (int i = 0, j = colorOffset; i < vertexCount; i++, j += stride) {
02038:                            cdata[j + 3] *= m;
02039:                        }
02040:                    } else {
02041:                        // update color values from screen 0 data
02042:
02043:                        float m = alpha / lastAlpha[0];
02044:                        float[] sdata = mvertexData[0];
02045:                        float[] cdata = mvertexData[screen];
02046:
02047:                        for (int i = 0, j = colorOffset; i < vertexCount; i++, j += stride) {
02048:                            System.arraycopy(sdata, j, cdata, j, 3);
02049:                            cdata[j + 3] = sdata[j + 3] * m;
02050:                        }
02051:                    }
02052:                }
02053:
02054:                lastAlpha[screen] = alpha;
02055:                colorChanged &= ~(1 << screen);
02056:                dirtyFlag |= COLOR_CHANGED;
02057:                retVal[1] = mvertexData[screen];
02058:                return retVal;
02059:            }
02060:
02061:            Object[] updateAlphaInInterLeavedData(Canvas3D cv, int screen,
02062:                    float alpha) {
02063:
02064:                Object[] retVal = new Object[2];
02065:                retVal[0] = Boolean.FALSE;
02066:
02067:                // no need to update alpha values if canvas supports global alpha
02068:                if (cv.supportGlobalAlpha()) {
02069:                    cv.setGlobalAlpha(cv.ctx, alpha);
02070:                    retVal[1] = null;
02071:                    return retVal;
02072:                }
02073:
02074:                // update alpha only if vertex format includes alpha
02075:                if (((vertexFormat | c4fAllocated) & GeometryArray.WITH_ALPHA) == 0) {
02076:                    retVal[1] = mirrorInterleavedColorPointer[0];
02077:                    return retVal;
02078:                }
02079:                int coffset = initialColorIndex << 2; // Each color is 4 floats
02080:
02081:                // if alpha is smaller than EPSILON, set it to EPSILON, so that
02082:                // even if alpha is equal to 0, we will not completely lose
02083:                // the original alpha value
02084:                if (alpha <= EPSILON) {
02085:                    alpha = (float) EPSILON;
02086:                }
02087:                retVal[0] = Boolean.TRUE;
02088:
02089:                assert lastAlpha != null;
02090:                assert mirrorInterleavedColorPointer != null;
02091:                assert mirrorInterleavedColorPointer.length == lastAlpha.length;
02092:
02093:                // Issue 113 - reallocate lastAlpha array if needed, but no need to
02094:                // update the values here
02095:                if (lastAlpha.length <= screen) {
02096:                    float[] la = new float[screen + 1];
02097:                    for (int i = 0; i < lastAlpha.length; i++) {
02098:                        la[i] = lastAlpha[i];
02099:                    }
02100:                    lastAlpha = la;
02101:                }
02102:
02103:                // allocate a copy of the vertex data for the screen if needed.
02104:                // this piece of code is only for multi-screens case
02105:                if (mirrorInterleavedColorPointer.length <= screen) {
02106:
02107:                    float[][] cfData = new float[screen + 1][];
02108:
02109:                    for (int i = 0; i < mirrorInterleavedColorPointer.length; i++) {
02110:                        cfData[i] = mirrorInterleavedColorPointer[i];
02111:                    }
02112:
02113:                    // Issue 113 - allocate entries for [oldSize..screen];
02114:                    // copy cfData[0] to cfData[oldsize..screen-1] and
02115:                    // lastAlpha[0] to lastAlpha[oldsize..screen-1].
02116:                    for (int i = mirrorInterleavedColorPointer.length; i < screen + 1; i++) {
02117:                        cfData[i] = new float[4 * vertexCount];
02118:                        System.arraycopy(cfData[0], 0, cfData[i], 0,
02119:                                4 * vertexCount);
02120:                        lastAlpha[i] = lastAlpha[0];
02121:                    }
02122:
02123:                    mirrorInterleavedColorPointer = cfData;
02124:
02125:                    // Issue 113 - since we copied the data from screen 0, we don't need
02126:                    // to do any further special processing.
02127:                }
02128:
02129:                assert lastAlpha[screen] >= 0.0;
02130:
02131:                if ((colorChanged & (1 << screen)) == 0) {
02132:                    // color data is not modified
02133:                    if (Math.abs(lastAlpha[screen] - alpha) <= EPSILON) {
02134:                        // and if alpha is the same as the last one,
02135:                        // just return the data
02136:                        retVal[1] = mirrorInterleavedColorPointer[screen];
02137:                        return retVal;
02138:                    } else {
02139:
02140:                        // if alpha is different, update the alpha values
02141:
02142:                        float m = alpha / lastAlpha[screen];
02143:
02144:                        float[] cdata = mirrorInterleavedColorPointer[screen];
02145:
02146:                        coffset = initialColorIndex << 2;
02147:                        for (int i = coffset; i < coffset + (vertexCount << 2); i += 4) {
02148:                            cdata[i + 3] = cdata[i + 3] * m;
02149:                        }
02150:                    }
02151:                } else {
02152:                    // color data is modified
02153:                    if (screen == 0) {
02154:
02155:                        // just update alpha values since screen 0 data is
02156:                        // already updated in setupMirrorInterleavedColorPointer
02157:
02158:                        float[] cdata = mirrorInterleavedColorPointer[screen];
02159:
02160:                        for (int i = coffset; i < coffset + (vertexCount << 2); i += 4) {
02161:                            cdata[i + 3] = cdata[i + 3] * alpha;
02162:                        }
02163:                    } else {
02164:                        // update color values from screen 0 data
02165:
02166:                        float m;
02167:
02168:                        if ((colorChanged & 1) == 0) {
02169:                            // alpha is up to date in screen 0
02170:                            m = alpha / lastAlpha[0];
02171:                        } else {
02172:                            m = alpha;
02173:                        }
02174:
02175:                        float[] sdata = mirrorInterleavedColorPointer[0];
02176:                        float[] cdata = mirrorInterleavedColorPointer[screen];
02177:
02178:                        for (int i = coffset; i < coffset + (vertexCount << 2);) {
02179:                            // System.arraycopy(sdata, i, cdata, i, 3);
02180:                            cdata[i] = sdata[i++];
02181:                            cdata[i] = sdata[i++];
02182:                            cdata[i] = sdata[i++];
02183:                            cdata[i] = sdata[i++] * m;
02184:                        }
02185:                    }
02186:                }
02187:
02188:                lastAlpha[screen] = alpha;
02189:                colorChanged &= ~(1 << screen);
02190:                dirtyFlag |= COLOR_CHANGED;
02191:                retVal[1] = mirrorInterleavedColorPointer[screen];
02192:                return retVal;
02193:            }
02194:
02195:            // pass < 0  implies underlying library supports multiTexture, so
02196:            // 		 use the multiTexture extension to send all texture units
02197:            //		 data in one pass
02198:            // pass >= 0 implies one pass for one texture unit state
02199:
02200:            void execute(Canvas3D cv, RenderAtom ra, boolean isNonUniformScale,
02201:                    boolean updateAlpha, float alpha, int screen,
02202:                    boolean ignoreVertexColors) {
02203:
02204:                int cdirty;
02205:                boolean useAlpha = false;
02206:                Object[] retVal;
02207:
02208:                // Check for by-copy case
02209:                if ((vertexFormat & GeometryArray.BY_REFERENCE) == 0) {
02210:                    float[] vdata;
02211:
02212:                    synchronized (this ) {
02213:                        cdirty = dirtyFlag;
02214:                        if (updateAlpha && !ignoreVertexColors) {
02215:                            // update the alpha values
02216:                            retVal = updateAlphaInVertexData(cv, screen, alpha);
02217:                            useAlpha = (retVal[0] == Boolean.TRUE);
02218:                            vdata = (float[]) retVal[1];
02219:
02220:                            // D3D only
02221:                            if (alpha != lastScreenAlpha) {
02222:                                // handle multiple screen case
02223:                                lastScreenAlpha = alpha;
02224:                                cdirty |= COLOR_CHANGED;
02225:                            }
02226:                        } else {
02227:                            vdata = vertexData;
02228:                            // if transparency switch between on/off
02229:                            if (lastScreenAlpha != -1) {
02230:                                lastScreenAlpha = -1;
02231:                                cdirty |= COLOR_CHANGED;
02232:                            }
02233:                        }
02234:                        // geomLock is get in MasterControl when
02235:                        // RenderBin render the geometry. So it is safe
02236:                        // just to set the dirty flag here
02237:                        dirtyFlag = 0;
02238:                    }
02239:
02240:                    Pipeline
02241:                            .getPipeline()
02242:                            .execute(
02243:                                    cv.ctx,
02244:                                    this ,
02245:                                    geoType,
02246:                                    isNonUniformScale,
02247:                                    useAlpha,
02248:                                    ignoreVertexColors,
02249:                                    initialVertexIndex,
02250:                                    validVertexCount,
02251:                                    ((vertexFormat & GeometryArray.COLOR) != 0) ? (vertexFormat | GeometryArray.COLOR_4)
02252:                                            : vertexFormat,
02253:                                    texCoordSetCount,
02254:                                    texCoordSetMap,
02255:                                    (texCoordSetMap == null) ? 0
02256:                                            : texCoordSetMap.length,
02257:                                    texCoordSetMapOffset, cv.numActiveTexUnit,
02258:                                    vertexAttrCount, vertexAttrSizes, vdata,
02259:                                    null, cdirty);
02260:                }
02261:
02262:                //By reference with java array
02263:                else if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) == 0) {
02264:                    // interleaved data
02265:                    if ((vertexFormat & GeometryArray.INTERLEAVED) != 0) {
02266:                        if (interLeavedVertexData == null)
02267:                            return;
02268:
02269:                        float[] cdata = null;
02270:
02271:                        synchronized (this ) {
02272:                            cdirty = dirtyFlag;
02273:                            if (updateAlpha && !ignoreVertexColors) {
02274:                                // update the alpha values
02275:                                retVal = updateAlphaInInterLeavedData(cv,
02276:                                        screen, alpha);
02277:                                useAlpha = (retVal[0] == Boolean.TRUE);
02278:                                cdata = (float[]) retVal[1];
02279:                                if (alpha != lastScreenAlpha) {
02280:                                    lastScreenAlpha = alpha;
02281:                                    cdirty |= COLOR_CHANGED;
02282:                                }
02283:                            } else {
02284:                                // if transparency switch between on/off
02285:                                if (lastScreenAlpha != -1) {
02286:                                    lastScreenAlpha = -1;
02287:                                    cdirty |= COLOR_CHANGED;
02288:                                }
02289:                            }
02290:                            dirtyFlag = 0;
02291:                        }
02292:
02293:                        Pipeline.getPipeline().execute(
02294:                                cv.ctx,
02295:                                this ,
02296:                                geoType,
02297:                                isNonUniformScale,
02298:                                useAlpha,
02299:                                ignoreVertexColors,
02300:                                initialVertexIndex,
02301:                                validVertexCount,
02302:                                vertexFormat,
02303:                                texCoordSetCount,
02304:                                texCoordSetMap,
02305:                                (texCoordSetMap == null) ? 0
02306:                                        : texCoordSetMap.length,
02307:                                texCoordSetMapOffset, cv.numActiveTexUnit,
02308:                                vertexAttrCount, vertexAttrSizes,
02309:                                interLeavedVertexData, cdata, cdirty);
02310:
02311:                    } // end of interleaved case
02312:
02313:                    // non interleaved data
02314:                    else {
02315:
02316:                        // Check if a vertexformat is set, but the array is null
02317:                        // if yes, don't draw anything
02318:                        if ((vertexType == 0)
02319:                                || ((vertexType & VERTEX_DEFINED) == 0)
02320:                                || (((vertexFormat & GeometryArray.COLOR) != 0) && (vertexType & COLOR_DEFINED) == 0)
02321:                                || (((vertexFormat & GeometryArray.NORMALS) != 0) && (vertexType & NORMAL_DEFINED) == 0)
02322:                                || (((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) && (vertexType & VATTR_DEFINED) == 0)
02323:                                || (((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) && (vertexType & TEXCOORD_DEFINED) == 0)) {
02324:                            return;
02325:                        } else {
02326:                            byte[] cbdata = null;
02327:                            float[] cfdata = null;
02328:
02329:                            if ((vertexType & (CF | C3F | C4F)) != 0) {
02330:
02331:                                synchronized (this ) {
02332:                                    cdirty = dirtyFlag;
02333:                                    if (updateAlpha && !ignoreVertexColors) {
02334:                                        cfdata = updateAlphaInFloatRefColors(
02335:                                                cv, screen, alpha);
02336:                                        if (alpha != lastScreenAlpha) {
02337:                                            lastScreenAlpha = alpha;
02338:                                            cdirty |= COLOR_CHANGED;
02339:                                        }
02340:                                    } else {
02341:                                        cfdata = mirrorFloatRefColors[0];
02342:                                        // if transparency switch between on/off
02343:                                        if (lastScreenAlpha != -1) {
02344:                                            lastScreenAlpha = -1;
02345:                                            cdirty |= COLOR_CHANGED;
02346:                                        }
02347:
02348:                                    }
02349:                                    dirtyFlag = 0;
02350:                                }
02351:                            } // end of color in float format
02352:                            else if ((vertexType & (CUB | C3UB | C4UB)) != 0) {
02353:                                synchronized (this ) {
02354:                                    cdirty = dirtyFlag;
02355:                                    if (updateAlpha && !ignoreVertexColors) {
02356:                                        cbdata = updateAlphaInByteRefColors(cv,
02357:                                                screen, alpha);
02358:                                        if (alpha != lastScreenAlpha) {
02359:                                            lastScreenAlpha = alpha;
02360:                                            cdirty |= COLOR_CHANGED;
02361:                                        }
02362:                                    } else {
02363:                                        cbdata = mirrorUnsignedByteRefColors[0];
02364:                                        // if transparency switch between on/off
02365:                                        if (lastScreenAlpha != -1) {
02366:                                            lastScreenAlpha = -1;
02367:                                            cdirty |= COLOR_CHANGED;
02368:                                        }
02369:                                    }
02370:                                    dirtyFlag = 0;
02371:                                }
02372:                            } // end of color in byte format
02373:                            else {
02374:                                cdirty = dirtyFlag;
02375:                            }
02376:                            // setup vdefined to passed to native code
02377:                            int vdefined = 0;
02378:                            if ((vertexType & (PF | P3F)) != 0)
02379:                                vdefined |= COORD_FLOAT;
02380:                            if ((vertexType & (PD | P3D)) != 0)
02381:                                vdefined |= COORD_DOUBLE;
02382:                            if ((vertexType & (CF | C3F | C4F)) != 0)
02383:                                vdefined |= COLOR_FLOAT;
02384:                            if ((vertexType & (CUB | C3UB | C4UB)) != 0)
02385:                                vdefined |= COLOR_BYTE;
02386:                            if ((vertexType & NORMAL_DEFINED) != 0)
02387:                                vdefined |= NORMAL_FLOAT;
02388:                            if ((vertexType & VATTR_DEFINED) != 0)
02389:                                vdefined |= VATTR_FLOAT;
02390:                            if ((vertexType & TEXCOORD_DEFINED) != 0)
02391:                                vdefined |= TEXCOORD_FLOAT;
02392:
02393:                            Pipeline.getPipeline().executeVA(
02394:                                    cv.ctx,
02395:                                    this ,
02396:                                    geoType,
02397:                                    isNonUniformScale,
02398:                                    ignoreVertexColors,
02399:                                    validVertexCount,
02400:                                    (vertexFormat | c4fAllocated),
02401:                                    vdefined,
02402:                                    initialCoordIndex,
02403:                                    mirrorFloatRefCoords,
02404:                                    mirrorDoubleRefCoords,
02405:                                    initialColorIndex,
02406:                                    cfdata,
02407:                                    cbdata,
02408:                                    initialNormalIndex,
02409:                                    mirrorFloatRefNormals,
02410:                                    vertexAttrCount,
02411:                                    vertexAttrSizes,
02412:                                    initialVertexAttrIndex,
02413:                                    mirrorFloatRefVertexAttrs,
02414:                                    ((texCoordSetMap == null) ? 0
02415:                                            : texCoordSetMap.length),
02416:                                    texCoordSetMap, cv.numActiveTexUnit,
02417:                                    initialTexCoordIndex, texCoordStride,
02418:                                    mirrorRefTexCoords, cdirty);
02419:                        }// end of all vertex data being set
02420:                    }// end of non interleaved case
02421:                }// end of by reference with java array
02422:
02423:                //By reference with nio buffer
02424:                else {
02425:                    // interleaved data
02426:                    if ((vertexFormat & GeometryArray.INTERLEAVED) != 0) {
02427:
02428:                        if (interleavedFloatBufferImpl == null)
02429:                            return;
02430:
02431:                        float[] cdata = null;
02432:                        synchronized (this ) {
02433:                            cdirty = dirtyFlag;
02434:                            if (updateAlpha && !ignoreVertexColors) {
02435:                                // update the alpha values
02436:                                // XXXX: to handle alpha case
02437:                                retVal = updateAlphaInInterLeavedData(cv,
02438:                                        screen, alpha);
02439:                                useAlpha = (retVal[0] == Boolean.TRUE);
02440:                                cdata = (float[]) retVal[1];
02441:
02442:                                if (alpha != lastScreenAlpha) {
02443:                                    lastScreenAlpha = alpha;
02444:                                    cdirty |= COLOR_CHANGED;
02445:                                }
02446:                            } else {
02447:                                // XXXX: to handle alpha case
02448:                                cdata = null;
02449:                                // if transparency switch between on/off
02450:                                if (lastScreenAlpha != -1) {
02451:                                    lastScreenAlpha = -1;
02452:                                    cdirty |= COLOR_CHANGED;
02453:                                }
02454:                            }
02455:                            dirtyFlag = 0;
02456:                        }
02457:
02458:                        Pipeline.getPipeline().executeInterleavedBuffer(
02459:                                cv.ctx,
02460:                                this ,
02461:                                geoType,
02462:                                isNonUniformScale,
02463:                                useAlpha,
02464:                                ignoreVertexColors,
02465:                                initialVertexIndex,
02466:                                validVertexCount,
02467:                                vertexFormat,
02468:                                texCoordSetCount,
02469:                                texCoordSetMap,
02470:                                (texCoordSetMap == null) ? 0
02471:                                        : texCoordSetMap.length,
02472:                                texCoordSetMapOffset, cv.numActiveTexUnit,
02473:                                interleavedFloatBufferImpl.getBufferAsObject(),
02474:                                cdata, cdirty);
02475:
02476:                    } // end of interleaved case
02477:
02478:                    // non interleaved data
02479:                    else {
02480:
02481:                        // Check if a vertexformat is set, but the array is null
02482:                        // if yes, don't draw anything
02483:                        if ((vertexType == 0)
02484:                                || ((vertexType & VERTEX_DEFINED) == 0)
02485:                                || (((vertexFormat & GeometryArray.COLOR) != 0) && (vertexType & COLOR_DEFINED) == 0)
02486:                                || (((vertexFormat & GeometryArray.NORMALS) != 0) && (vertexType & NORMAL_DEFINED) == 0)
02487:                                || (((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) && (vertexType & VATTR_DEFINED) == 0)
02488:                                || (((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) && (vertexType & TEXCOORD_DEFINED) == 0)) {
02489:                            return;
02490:                        } else {
02491:                            byte[] cbdata = null;
02492:                            float[] cfdata = null;
02493:
02494:                            if ((vertexType & CF) != 0) {
02495:                                synchronized (this ) {
02496:                                    cdirty = dirtyFlag;
02497:                                    if (updateAlpha && !ignoreVertexColors) {
02498:                                        cfdata = updateAlphaInFloatRefColors(
02499:                                                cv, screen, alpha);
02500:                                        if (alpha != lastScreenAlpha) {
02501:                                            lastScreenAlpha = alpha;
02502:                                            cdirty |= COLOR_CHANGED;
02503:                                        }
02504:                                    } else {
02505:                                        // XXXX: handle transparency case
02506:                                        //cfdata = null;
02507:                                        cfdata = mirrorFloatRefColors[0];
02508:                                        // if transparency switch between on/off
02509:                                        if (lastScreenAlpha != -1) {
02510:                                            lastScreenAlpha = -1;
02511:                                            cdirty |= COLOR_CHANGED;
02512:                                        }
02513:
02514:                                    }
02515:                                    dirtyFlag = 0;
02516:                                }
02517:                            } // end of color in float format
02518:                            else if ((vertexType & CUB) != 0) {
02519:                                synchronized (this ) {
02520:                                    cdirty = dirtyFlag;
02521:                                    if (updateAlpha && !ignoreVertexColors) {
02522:                                        cbdata = updateAlphaInByteRefColors(cv,
02523:                                                screen, alpha);
02524:                                        if (alpha != lastScreenAlpha) {
02525:                                            lastScreenAlpha = alpha;
02526:                                            cdirty |= COLOR_CHANGED;
02527:                                        }
02528:                                    } else {
02529:                                        // XXXX: handle transparency case
02530:                                        //cbdata = null;
02531:                                        cbdata = mirrorUnsignedByteRefColors[0];
02532:                                        // if transparency switch between on/off
02533:                                        if (lastScreenAlpha != -1) {
02534:                                            lastScreenAlpha = -1;
02535:                                            cdirty |= COLOR_CHANGED;
02536:                                        }
02537:                                    }
02538:                                    dirtyFlag = 0;
02539:                                }
02540:                            } // end of color in byte format
02541:                            else {
02542:                                cdirty = dirtyFlag;
02543:                            }
02544:
02545:                            Object vcoord = null, cdataBuffer = null, normal = null;
02546:
02547:                            int vdefined = 0;
02548:                            if ((vertexType & PF) != 0) {
02549:                                vdefined |= COORD_FLOAT;
02550:                                vcoord = floatBufferRefCoords
02551:                                        .getBufferAsObject();
02552:                            } else if ((vertexType & PD) != 0) {
02553:                                vdefined |= COORD_DOUBLE;
02554:                                vcoord = doubleBufferRefCoords
02555:                                        .getBufferAsObject();
02556:                            }
02557:
02558:                            if ((vertexType & CF) != 0) {
02559:                                vdefined |= COLOR_FLOAT;
02560:                                cdataBuffer = floatBufferRefColors
02561:                                        .getBufferAsObject();
02562:                            } else if ((vertexType & CUB) != 0) {
02563:                                vdefined |= COLOR_BYTE;
02564:                                cdataBuffer = byteBufferRefColors
02565:                                        .getBufferAsObject();
02566:                            }
02567:
02568:                            if ((vertexType & NORMAL_DEFINED) != 0) {
02569:                                vdefined |= NORMAL_FLOAT;
02570:                                normal = floatBufferRefNormals
02571:                                        .getBufferAsObject();
02572:                            }
02573:
02574:                            if ((vertexType & VATTR_DEFINED) != 0) {
02575:                                vdefined |= VATTR_FLOAT;
02576:                            }
02577:
02578:                            if ((vertexType & TEXCOORD_DEFINED) != 0)
02579:                                vdefined |= TEXCOORD_FLOAT;
02580:
02581:                            Pipeline.getPipeline().executeVABuffer(
02582:                                    cv.ctx,
02583:                                    this ,
02584:                                    geoType,
02585:                                    isNonUniformScale,
02586:                                    ignoreVertexColors,
02587:                                    validVertexCount,
02588:                                    (vertexFormat | c4fAllocated),
02589:                                    vdefined,
02590:                                    initialCoordIndex,
02591:                                    vcoord,
02592:                                    initialColorIndex,
02593:                                    cdataBuffer,
02594:                                    cfdata,
02595:                                    cbdata,
02596:                                    initialNormalIndex,
02597:                                    normal,
02598:                                    vertexAttrCount,
02599:                                    vertexAttrSizes,
02600:                                    initialVertexAttrIndex,
02601:                                    nioFloatBufferRefVertexAttrs,
02602:                                    ((texCoordSetMap == null) ? 0
02603:                                            : texCoordSetMap.length),
02604:                                    texCoordSetMap, cv.numActiveTexUnit,
02605:                                    initialTexCoordIndex, texCoordStride,
02606:                                    refTexCoords, cdirty);
02607:                        }// end of all vertex data being set
02608:                    }// end of non interleaved case
02609:                }// end of by reference with nio-buffer case
02610:            }
02611:
02612:            void buildGA(Canvas3D cv, RenderAtom ra, boolean isNonUniformScale,
02613:                    boolean updateAlpha, float alpha,
02614:                    boolean ignoreVertexColors, Transform3D xform,
02615:                    Transform3D nxform) {
02616:
02617:                float[] vdata = null;
02618:
02619:                // NIO buffers are no longer supported in display lists
02620:                assert (vertexFormat & GeometryArray.USE_NIO_BUFFER) == 0;
02621:
02622:                if ((vertexFormat & GeometryArray.BY_REFERENCE) == 0) {
02623:                    vdata = vertexData;
02624:                } else if ((vertexFormat & GeometryArray.INTERLEAVED) != 0
02625:                        && ((vertexFormat & GeometryArray.USE_NIO_BUFFER) == 0)) {
02626:                    vdata = interLeavedVertexData;
02627:                }
02628:                if (vdata != null) {
02629:                    /*
02630:                     System.err.println("calling native buildGA()");
02631:                     System.err.println("geoType = "+geoType+" initialVertexIndex = "+initialVertexIndex+" validVertexCount = "+validVertexCount+" vertexFormat = "+vertexFormat+"  vertexData = "+vertexData);
02632:                     */
02633:                    Pipeline.getPipeline().buildGA(
02634:                            cv.ctx,
02635:                            this ,
02636:                            geoType,
02637:                            isNonUniformScale,
02638:                            updateAlpha,
02639:                            alpha,
02640:                            ignoreVertexColors,
02641:                            initialVertexIndex,
02642:                            validVertexCount,
02643:                            vertexFormat,
02644:                            texCoordSetCount,
02645:                            texCoordSetMap,
02646:                            (texCoordSetMap == null) ? 0
02647:                                    : texCoordSetMap.length,
02648:                            texCoordSetMapOffset, vertexAttrCount,
02649:                            vertexAttrSizes,
02650:                            (xform == null) ? null : xform.mat,
02651:                            (nxform == null) ? null : nxform.mat, vdata);
02652:                } else {
02653:                    // Check if a vertexformat is set, but the array is null
02654:                    // if yes, don't draw anything
02655:                    if ((vertexType == 0)
02656:                            || ((vertexType & VERTEX_DEFINED) == 0)
02657:                            || (((vertexFormat & GeometryArray.COLOR) != 0) && (vertexType & COLOR_DEFINED) == 0)
02658:                            || (((vertexFormat & GeometryArray.NORMALS) != 0) && (vertexType & NORMAL_DEFINED) == 0)
02659:                            || (((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) && (vertexType & VATTR_DEFINED) == 0)
02660:                            || (((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) && (vertexType & TEXCOORD_DEFINED) == 0)) {
02661:
02662:                        return;
02663:                    }
02664:
02665:                    // Either non-interleaved, by-ref or nio buffer
02666:                    if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) == 0) {
02667:                        // Java array case
02668:                        // setup vdefined to passed to native code
02669:                        int vdefined = 0;
02670:                        if ((vertexType & (PF | P3F)) != 0)
02671:                            vdefined |= COORD_FLOAT;
02672:                        if ((vertexType & (PD | P3D)) != 0)
02673:                            vdefined |= COORD_DOUBLE;
02674:                        if ((vertexType & (CF | C3F | C4F)) != 0)
02675:                            vdefined |= COLOR_FLOAT;
02676:                        if ((vertexType & (CUB | C3UB | C4UB)) != 0)
02677:                            vdefined |= COLOR_BYTE;
02678:                        if ((vertexType & NORMAL_DEFINED) != 0)
02679:                            vdefined |= NORMAL_FLOAT;
02680:                        if ((vertexType & VATTR_DEFINED) != 0)
02681:                            vdefined |= VATTR_FLOAT;
02682:                        if ((vertexType & TEXCOORD_DEFINED) != 0)
02683:                            vdefined |= TEXCOORD_FLOAT;
02684:
02685:                        Pipeline.getPipeline().buildGAForByRef(
02686:                                cv.ctx,
02687:                                this ,
02688:                                geoType,
02689:                                isNonUniformScale,
02690:                                updateAlpha,
02691:                                alpha,
02692:                                ignoreVertexColors,
02693:                                validVertexCount,
02694:                                vertexFormat,
02695:                                vdefined,
02696:                                initialCoordIndex,
02697:                                mirrorFloatRefCoords,
02698:                                mirrorDoubleRefCoords,
02699:                                initialColorIndex,
02700:                                mirrorFloatRefColors[0],
02701:                                mirrorUnsignedByteRefColors[0],
02702:                                initialNormalIndex,
02703:                                mirrorFloatRefNormals,
02704:                                vertexAttrCount,
02705:                                vertexAttrSizes,
02706:                                initialVertexAttrIndex,
02707:                                mirrorFloatRefVertexAttrs,
02708:                                ((texCoordSetMap == null) ? 0
02709:                                        : texCoordSetMap.length),
02710:                                texCoordSetMap, initialTexCoordIndex,
02711:                                texCoordStride, mirrorRefTexCoords,
02712:                                (xform == null) ? null : xform.mat,
02713:                                (nxform == null) ? null : nxform.mat);
02714:                    }
02715:                    /*
02716:                    // NOTE: NIO buffers are no longer supported in display lists.
02717:                    // This was never enabled by default anyway (only when the
02718:                    // optimizeForSpace property was set to false), so it wasn't
02719:                    // well-tested. If future support is desired, we will need to
02720:                    // add vertex attributes to buildGAForBuffer. There are no plans
02721:                    // to ever do this.
02722:                    else {
02723:                        // NIO Buffer case
02724:                        Object vcoord = null, cdataBuffer=null, normal=null;
02725:
02726:                        int vdefined = 0;
02727:                        if((vertexType & PF)  != 0) {
02728:                            vdefined |= COORD_FLOAT;
02729:                            vcoord = floatBufferRefCoords.getBufferAsObject();
02730:                        } else if((vertexType & PD ) != 0) {
02731:                            vdefined |= COORD_DOUBLE;
02732:                            vcoord = doubleBufferRefCoords.getBufferAsObject();
02733:                        }
02734:
02735:                        if((vertexType & CF ) != 0) {
02736:                            vdefined |= COLOR_FLOAT;
02737:                            cdataBuffer = floatBufferRefColors.getBufferAsObject();
02738:                        } else if((vertexType & CUB) != 0) {
02739:                            vdefined |= COLOR_BYTE;
02740:                            cdataBuffer = byteBufferRefColors.getBufferAsObject();
02741:                        }
02742:
02743:                        if((vertexType & NORMAL_DEFINED) != 0) {
02744:                            vdefined |= NORMAL_FLOAT;
02745:                            normal = floatBufferRefNormals.getBufferAsObject();
02746:                        }
02747:
02748:                        if((vertexType & TEXCOORD_DEFINED) != 0)
02749:                            vdefined |= TEXCOORD_FLOAT;
02750:                        // NOTE : need to add vertex attrs
02751:                        Pipeline.getPipeline().buildGAForBuffer(cv.ctx,
02752:                                this, geoType, isNonUniformScale,
02753:                                updateAlpha, alpha,
02754:                                ignoreVertexColors,
02755:                                validVertexCount,
02756:                                vertexFormat,
02757:                                vdefined,
02758:                                initialCoordIndex,
02759:                                vcoord,
02760:                                initialColorIndex,cdataBuffer,
02761:                                initialNormalIndex, normal,
02762:                                ((texCoordSetMap == null) ? 0:texCoordSetMap.length),
02763:                                texCoordSetMap,
02764:                                initialTexCoordIndex,texCoordStride,
02765:                                refTexCoords,
02766:                                (xform == null) ? null : xform.mat,
02767:                                (nxform == null) ? null : nxform.mat);
02768:                    }
02769:                     */
02770:
02771:                }
02772:
02773:            }
02774:
02775:            void unIndexify(IndexedGeometryArrayRetained src) {
02776:                if ((src.vertexFormat & GeometryArray.USE_NIO_BUFFER) == 0) {
02777:                    unIndexifyJavaArray(src);
02778:                } else {
02779:                    unIndexifyNIOBuffer(src);
02780:                }
02781:            }
02782:
02783:            private void unIndexifyJavaArray(IndexedGeometryArrayRetained src) {
02784:                //        System.err.println("unIndexifyJavaArray");
02785:
02786:                int vOffset = 0, srcOffset, tOffset = 0;
02787:                int index, colorStride = 0;
02788:                float[] vdata = null;
02789:                int i;
02790:                int start, end;
02791:                start = src.initialIndexIndex;
02792:                end = src.initialIndexIndex + src.validIndexCount;
02793:                // If its either "normal" data or interleaved data then ..
02794:                if (((src.vertexFormat & GeometryArray.BY_REFERENCE) == 0)
02795:                        || ((src.vertexFormat & GeometryArray.INTERLEAVED) != 0)) {
02796:
02797:                    if ((src.vertexFormat & GeometryArray.BY_REFERENCE) == 0) {
02798:                        vdata = src.vertexData;
02799:                        if ((src.vertexFormat & GeometryArray.COLOR) != 0)
02800:                            colorStride = 4;
02801:                    } else if ((src.vertexFormat & GeometryArray.INTERLEAVED) != 0) {
02802:                        vdata = src.interLeavedVertexData;
02803:                        if ((src.vertexFormat & GeometryArray.WITH_ALPHA) != 0)
02804:                            colorStride = 4;
02805:                        else if ((src.vertexFormat & GeometryArray.COLOR) != 0)
02806:                            colorStride = 3;
02807:                    }
02808:
02809:                    //	    System.err.println("===> start = "+start+" end = "+end);
02810:                    for (index = start; index < end; index++) {
02811:                        if ((vertexFormat & GeometryArray.NORMALS) != 0) {
02812:                            System.arraycopy(vdata, src.indexNormal[index]
02813:                                    * src.stride + src.normalOffset,
02814:                                    vertexData, vOffset + normalOffset, 3);
02815:                        }
02816:                        if (colorStride == 4) {
02817:                            //		    System.err.println("===> copying color3");
02818:                            System.arraycopy(vdata, src.indexColor[index]
02819:                                    * src.stride + src.colorOffset, vertexData,
02820:                                    vOffset + colorOffset, colorStride);
02821:                        } else if (colorStride == 3) {
02822:                            //		    System.err.println("===> copying color4");
02823:                            System.arraycopy(vdata, src.indexColor[index]
02824:                                    * src.stride + src.colorOffset, vertexData,
02825:                                    vOffset + colorOffset, colorStride);
02826:                            vertexData[vOffset + colorOffset + 3] = 1.0f;
02827:                        }
02828:
02829:                        if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) {
02830:                            int tcOffset = vOffset + textureOffset;
02831:                            int interleavedOffset = 0;
02832:
02833:                            for (i = 0; i < texCoordSetCount; i++, tcOffset += texCoordStride) {
02834:
02835:                                if ((src.vertexFormat & GeometryArray.INTERLEAVED) != 0) {
02836:                                    interleavedOffset = i * texCoordStride;
02837:                                }
02838:
02839:                                System.arraycopy(vdata,
02840:                                        (src.indexTexCoord[i][index])
02841:                                                * src.stride
02842:                                                + src.textureOffset
02843:                                                + interleavedOffset,
02844:                                        vertexData, tcOffset, texCoordStride);
02845:                            }
02846:                        }
02847:
02848:                        if ((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) {
02849:                            // vertex attributes can't be interleaved
02850:                            assert (src.vertexFormat & GeometryArray.INTERLEAVED) == 0;
02851:
02852:                            for (i = 0; i < vertexAttrCount; i++) {
02853:                                int vaOffset = vOffset + vertexAttrOffsets[i];
02854:
02855:                                System.arraycopy(vdata,
02856:                                        (src.indexVertexAttr[i][index])
02857:                                                * src.stride
02858:                                                + src.vertexAttrOffsets[i],
02859:                                        vertexData, vaOffset,
02860:                                        vertexAttrSizes[i]);
02861:                            }
02862:                        }
02863:
02864:                        if ((vertexFormat & GeometryArray.COORDINATES) != 0) {
02865:                            //		    System.err.println("===> copying coords");
02866:                            System.arraycopy(vdata, src.indexCoord[index]
02867:                                    * src.stride + src.coordinateOffset,
02868:                                    vertexData, vOffset + coordinateOffset, 3);
02869:                        }
02870:                        vOffset += stride;
02871:                    }
02872:
02873:                } else {
02874:                    if ((vertexFormat & GeometryArray.NORMALS) != 0) {
02875:                        vOffset = normalOffset;
02876:                        switch ((src.vertexType & NORMAL_DEFINED)) {
02877:                        case NF:
02878:                            for (index = start; index < end; index++) {
02879:                                System.arraycopy(src.floatRefNormals,
02880:                                        src.indexNormal[index] * 3, vertexData,
02881:                                        vOffset, 3);
02882:                                vOffset += stride;
02883:                            }
02884:                            break;
02885:                        case N3F:
02886:                            for (index = start; index < end; index++) {
02887:                                srcOffset = src.indexNormal[index];
02888:                                vertexData[vOffset] = src.v3fRefNormals[srcOffset].x;
02889:                                vertexData[vOffset + 1] = src.v3fRefNormals[srcOffset].y;
02890:                                vertexData[vOffset + 2] = src.v3fRefNormals[srcOffset].z;
02891:                                vOffset += stride;
02892:                            }
02893:                            break;
02894:                        default:
02895:                            break;
02896:                        }
02897:                    }
02898:
02899:                    if ((vertexFormat & GeometryArray.COLOR) != 0) {
02900:                        vOffset = colorOffset;
02901:                        int multiplier = 3;
02902:                        if ((src.vertexFormat & GeometryArray.WITH_ALPHA) != 0)
02903:                            multiplier = 4;
02904:
02905:                        switch ((src.vertexType & COLOR_DEFINED)) {
02906:                        case CF:
02907:                            for (index = start; index < end; index++) {
02908:                                if ((src.vertexFormat & GeometryArray.WITH_ALPHA) != 0) {
02909:                                    System.arraycopy(src.floatRefColors,
02910:                                            src.indexColor[index] * multiplier,
02911:                                            vertexData, vOffset, 4);
02912:                                } else {
02913:                                    System.arraycopy(src.floatRefColors,
02914:                                            src.indexColor[index] * multiplier,
02915:                                            vertexData, vOffset, 3);
02916:                                    vertexData[vOffset + 3] = 1.0f;
02917:                                }
02918:                                vOffset += stride;
02919:                            }
02920:                            break;
02921:                        case CUB:
02922:                            for (index = start; index < end; index++) {
02923:                                srcOffset = src.indexColor[index] * multiplier;
02924:                                vertexData[vOffset] = (src.byteRefColors[srcOffset] & 0xff)
02925:                                        * ByteToFloatScale;
02926:                                vertexData[vOffset + 1] = (src.byteRefColors[srcOffset + 1] & 0xff)
02927:                                        * ByteToFloatScale;
02928:                                vertexData[vOffset + 2] = (src.byteRefColors[srcOffset + 2] & 0xff)
02929:                                        * ByteToFloatScale;
02930:                                if ((src.vertexFormat & GeometryArray.WITH_ALPHA) != 0) {
02931:                                    vertexData[vOffset + 3] = (src.byteRefColors[srcOffset + 3] & 0xff)
02932:                                            * ByteToFloatScale;
02933:                                } else {
02934:                                    vertexData[vOffset + 3] = 1.0f;
02935:                                }
02936:                                vOffset += stride;
02937:                            }
02938:                            break;
02939:                        case C3F:
02940:                            for (index = start; index < end; index++) {
02941:                                srcOffset = src.indexColor[index];
02942:                                vertexData[vOffset] = src.c3fRefColors[srcOffset].x;
02943:                                vertexData[vOffset + 1] = src.c3fRefColors[srcOffset].y;
02944:                                vertexData[vOffset + 2] = src.c3fRefColors[srcOffset].z;
02945:                                vertexData[vOffset + 3] = 1.0f;
02946:                                vOffset += stride;
02947:                            }
02948:                            break;
02949:                        case C4F:
02950:                            for (index = start; index < end; index++) {
02951:                                srcOffset = src.indexColor[index];
02952:                                vertexData[vOffset] = src.c4fRefColors[srcOffset].x;
02953:                                vertexData[vOffset + 1] = src.c4fRefColors[srcOffset].y;
02954:                                vertexData[vOffset + 2] = src.c4fRefColors[srcOffset].z;
02955:                                vertexData[vOffset + 3] = src.c4fRefColors[srcOffset].w;
02956:                                vOffset += stride;
02957:                            }
02958:                            break;
02959:                        case C3UB:
02960:                            for (index = start; index < end; index++) {
02961:                                srcOffset = src.indexColor[index];
02962:                                vertexData[vOffset] = (src.c3bRefColors[srcOffset].x & 0xff)
02963:                                        * ByteToFloatScale;
02964:                                vertexData[vOffset + 1] = (src.c3bRefColors[srcOffset].y & 0xff)
02965:                                        * ByteToFloatScale;
02966:                                vertexData[vOffset + 2] = (src.c3bRefColors[srcOffset].z & 0xff)
02967:                                        * ByteToFloatScale;
02968:                                vertexData[vOffset + 3] = 1.0f;
02969:                                vOffset += stride;
02970:                            }
02971:                            break;
02972:                        case C4UB:
02973:                            for (index = start; index < end; index++) {
02974:                                srcOffset = src.indexColor[index];
02975:                                vertexData[vOffset] = (src.c4bRefColors[srcOffset].x & 0xff)
02976:                                        * ByteToFloatScale;
02977:                                vertexData[vOffset + 1] = (src.c4bRefColors[srcOffset].y & 0xff)
02978:                                        * ByteToFloatScale;
02979:                                vertexData[vOffset + 2] = (src.c4bRefColors[srcOffset].z & 0xff)
02980:                                        * ByteToFloatScale;
02981:                                vertexData[vOffset + 3] = (src.c4bRefColors[srcOffset].w & 0xff)
02982:                                        * ByteToFloatScale;
02983:                                vOffset += stride;
02984:                            }
02985:                            break;
02986:                        default:
02987:                            break;
02988:                        }
02989:                    }
02990:
02991:                    if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) {
02992:                        vOffset = textureOffset;
02993:                        switch ((src.vertexType & TEXCOORD_DEFINED)) {
02994:                        case TF:
02995:                            for (index = start; index < end; index++) {
02996:                                for (i = 0, tOffset = vOffset; i < texCoordSetCount; i++) {
02997:                                    System
02998:                                            .arraycopy(src.refTexCoords[i],
02999:                                                    src.indexTexCoord[i][index]
03000:                                                            * texCoordStride,
03001:                                                    vertexData, tOffset,
03002:                                                    texCoordStride);
03003:                                    tOffset += texCoordStride;
03004:                                }
03005:                                vOffset += stride;
03006:                            }
03007:                            break;
03008:                        case T2F:
03009:                            for (index = start; index < end; index++) {
03010:                                for (i = 0, tOffset = vOffset; i < texCoordSetCount; i++) {
03011:                                    srcOffset = src.indexTexCoord[i][index];
03012:                                    vertexData[tOffset] = ((TexCoord2f[]) src.refTexCoords[i])[srcOffset].x;
03013:                                    vertexData[tOffset + 1] = ((TexCoord2f[]) src.refTexCoords[i])[srcOffset].y;
03014:                                    tOffset += texCoordStride;
03015:                                }
03016:                                vOffset += stride;
03017:                            }
03018:                            break;
03019:                        case T3F:
03020:                            for (index = start; index < end; index++) {
03021:                                for (i = 0, tOffset = vOffset; i < texCoordSetCount; i++) {
03022:                                    srcOffset = src.indexTexCoord[i][index];
03023:                                    vertexData[tOffset] = ((TexCoord3f[]) src.refTexCoords[i])[srcOffset].x;
03024:                                    vertexData[tOffset + 1] = ((TexCoord3f[]) src.refTexCoords[i])[srcOffset].y;
03025:                                    vertexData[tOffset + 2] = ((TexCoord3f[]) src.refTexCoords[i])[srcOffset].z;
03026:                                    tOffset += texCoordStride;
03027:                                }
03028:                                vOffset += stride;
03029:                            }
03030:                            break;
03031:                        default:
03032:                            break;
03033:                        }
03034:                    }
03035:
03036:                    if ((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) {
03037:                        vOffset = 0;
03038:                        switch (src.vertexType & VATTR_DEFINED) {
03039:                        case AF:
03040:                            for (index = start; index < end; index++) {
03041:                                for (i = 0; i < vertexAttrCount; i++) {
03042:                                    int vaOffset = vOffset
03043:                                            + vertexAttrOffsets[i];
03044:                                    System.arraycopy(
03045:                                            src.floatRefVertexAttrs[i],
03046:                                            src.indexVertexAttr[i][index]
03047:                                                    * vertexAttrSizes[i],
03048:                                            vertexData, vaOffset,
03049:                                            vertexAttrSizes[i]);
03050:                                }
03051:                                vOffset += stride;
03052:                            }
03053:                            break;
03054:                        }
03055:                    }
03056:
03057:                    if ((vertexFormat & GeometryArray.COORDINATES) != 0) {
03058:                        vOffset = coordinateOffset;
03059:                        switch ((src.vertexType & VERTEX_DEFINED)) {
03060:                        case PF:
03061:                            for (index = start; index < end; index++) {
03062:                                System.arraycopy(src.floatRefCoords,
03063:                                        src.indexCoord[index] * 3, vertexData,
03064:                                        vOffset, 3);
03065:                                vOffset += stride;
03066:                            }
03067:                            break;
03068:                        case PD:
03069:                            for (index = start; index < end; index++) {
03070:                                srcOffset = src.indexCoord[index] * 3;
03071:                                vertexData[vOffset] = (float) src.doubleRefCoords[srcOffset];
03072:                                vertexData[vOffset + 1] = (float) src.doubleRefCoords[srcOffset + 1];
03073:                                vertexData[vOffset + 2] = (float) src.doubleRefCoords[srcOffset + 2];
03074:                                vOffset += stride;
03075:                            }
03076:                            break;
03077:                        case P3F:
03078:                            for (index = start; index < end; index++) {
03079:                                srcOffset = src.indexCoord[index];
03080:                                vertexData[vOffset] = src.p3fRefCoords[srcOffset].x;
03081:                                vertexData[vOffset + 1] = src.p3fRefCoords[srcOffset].y;
03082:                                vertexData[vOffset + 2] = src.p3fRefCoords[srcOffset].z;
03083:                                vOffset += stride;
03084:                            }
03085:                            break;
03086:                        case P3D:
03087:                            for (index = start; index < end; index++) {
03088:                                srcOffset = src.indexCoord[index];
03089:                                vertexData[vOffset] = (float) src.p3dRefCoords[srcOffset].x;
03090:                                vertexData[vOffset + 1] = (float) src.p3dRefCoords[srcOffset].y;
03091:                                vertexData[vOffset + 2] = (float) src.p3dRefCoords[srcOffset].z;
03092:                                vOffset += stride;
03093:                            }
03094:                            break;
03095:                        default:
03096:                            break;
03097:                        }
03098:                    }
03099:
03100:                }
03101:            }
03102:
03103:            private void unIndexifyNIOBuffer(IndexedGeometryArrayRetained src) {
03104:                //        System.err.println("unIndexifyNIOBuffer");
03105:
03106:                int vOffset = 0, srcOffset, tOffset = 0;
03107:                int index, colorStride = 0;
03108:                float[] vdata = null;
03109:                int i;
03110:                int start, end;
03111:                start = src.initialIndexIndex;
03112:                end = src.initialIndexIndex + src.validIndexCount;
03113:                // If its interleaved data then ..
03114:                if ((src.vertexFormat & GeometryArray.INTERLEAVED) != 0) {
03115:                    if ((src.vertexFormat & GeometryArray.WITH_ALPHA) != 0)
03116:                        colorStride = 4;
03117:                    else if ((src.vertexFormat & GeometryArray.COLOR) != 0)
03118:                        colorStride = 3;
03119:
03120:                    //	    System.err.println("===> start = "+start+" end = "+end);
03121:                    for (index = start; index < end; index++) {
03122:                        if ((vertexFormat & GeometryArray.NORMALS) != 0) {
03123:                            src.interleavedFloatBufferImpl
03124:                                    .position(src.indexNormal[index]
03125:                                            * src.stride + src.normalOffset);
03126:                            src.interleavedFloatBufferImpl.get(vertexData,
03127:                                    vOffset + normalOffset, 3);
03128:                        }
03129:
03130:                        if (colorStride == 4) {
03131:                            src.interleavedFloatBufferImpl
03132:                                    .position(src.indexColor[index]
03133:                                            * src.stride + src.colorOffset);
03134:                            src.interleavedFloatBufferImpl.get(vertexData,
03135:                                    vOffset + colorOffset, colorStride);
03136:                        } else if (colorStride == 3) {
03137:                            src.interleavedFloatBufferImpl
03138:                                    .position(src.indexColor[index]
03139:                                            * src.stride + src.colorOffset);
03140:                            src.interleavedFloatBufferImpl.get(vertexData,
03141:                                    vOffset + colorOffset, colorStride);
03142:                            vertexData[vOffset + colorOffset + 3] = 1.0f;
03143:                        }
03144:
03145:                        if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) {
03146:                            int tcOffset = vOffset + textureOffset;
03147:                            for (i = 0; i < texCoordSetCount; i++, tcOffset += texCoordStride) {
03148:
03149:                                src.interleavedFloatBufferImpl
03150:                                        .position((src.indexTexCoord[i][index])
03151:                                                * src.stride
03152:                                                + src.textureOffset);
03153:                                src.interleavedFloatBufferImpl.get(vertexData,
03154:                                        tcOffset, texCoordStride);
03155:                            }
03156:                        }
03157:                        if ((vertexFormat & GeometryArray.COORDINATES) != 0) {
03158:                            src.interleavedFloatBufferImpl
03159:                                    .position(src.indexCoord[index]
03160:                                            * src.stride + src.coordinateOffset);
03161:                            src.interleavedFloatBufferImpl.get(vertexData,
03162:                                    vOffset + coordinateOffset, 3);
03163:                        }
03164:                        vOffset += stride;
03165:                    }
03166:
03167:                } else {
03168:                    if ((vertexFormat & GeometryArray.NORMALS) != 0) {
03169:                        vOffset = normalOffset;
03170:                        if ((src.vertexType & NORMAL_DEFINED) != 0) {
03171:                            for (index = start; index < end; index++) {
03172:                                src.floatBufferRefNormals
03173:                                        .position(src.indexNormal[index] * 3);
03174:                                src.floatBufferRefNormals.get(vertexData,
03175:                                        vOffset, 3);
03176:                                vOffset += stride;
03177:                            }
03178:                        }
03179:                    }
03180:
03181:                    if ((vertexFormat & GeometryArray.COLOR) != 0) {
03182:                        vOffset = colorOffset;
03183:                        int multiplier = 3;
03184:                        if ((src.vertexFormat & GeometryArray.WITH_ALPHA) != 0)
03185:                            multiplier = 4;
03186:
03187:                        switch ((src.vertexType & COLOR_DEFINED)) {
03188:                        case CF:
03189:                            for (index = start; index < end; index++) {
03190:                                if ((src.vertexFormat & GeometryArray.WITH_ALPHA) != 0) {
03191:                                    src.floatBufferRefColors
03192:                                            .position(src.indexColor[index]
03193:                                                    * multiplier);
03194:                                    src.floatBufferRefColors.get(vertexData,
03195:                                            vOffset, 4);
03196:                                } else {
03197:                                    src.floatBufferRefColors
03198:                                            .position(src.indexColor[index]
03199:                                                    * multiplier);
03200:                                    src.floatBufferRefColors.get(vertexData,
03201:                                            vOffset, 3);
03202:                                    vertexData[vOffset + 3] = 1.0f;
03203:                                }
03204:                                vOffset += stride;
03205:                            }
03206:                            break;
03207:                        case CUB:
03208:                            for (index = start; index < end; index++) {
03209:                                srcOffset = src.indexColor[index] * multiplier;
03210:                                vertexData[vOffset] = (src.byteBufferRefColors
03211:                                        .get(srcOffset) & 0xff)
03212:                                        * ByteToFloatScale;
03213:                                vertexData[vOffset + 1] = (src.byteBufferRefColors
03214:                                        .get(srcOffset + 1) & 0xff)
03215:                                        * ByteToFloatScale;
03216:                                vertexData[vOffset + 2] = (src.byteBufferRefColors
03217:                                        .get(srcOffset + 2) & 0xff)
03218:                                        * ByteToFloatScale;
03219:
03220:                                if ((src.vertexFormat & GeometryArray.WITH_ALPHA) != 0) {
03221:                                    vertexData[vOffset + 3] = (src.byteBufferRefColors
03222:                                            .get(srcOffset + 3) & 0xff)
03223:                                            * ByteToFloatScale;
03224:                                } else {
03225:                                    vertexData[vOffset + 3] = 1.0f;
03226:                                }
03227:                                vOffset += stride;
03228:                            }
03229:                            break;
03230:                        default:
03231:                            break;
03232:                        }
03233:                    }
03234:
03235:                    if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) {
03236:                        vOffset = textureOffset;
03237:                        FloatBufferWrapper texBuffer;
03238:                        if ((src.vertexType & TEXCOORD_DEFINED) != 0) {
03239:                            for (index = start; index < end; index++) {
03240:                                for (i = 0, tOffset = vOffset; i < texCoordSetCount; i++) {
03241:                                    texBuffer = (FloatBufferWrapper) (((J3DBuffer) (src.refTexCoordsBuffer[i]))
03242:                                            .getBufferImpl());
03243:                                    texBuffer
03244:                                            .position(src.indexTexCoord[i][index]
03245:                                                    * texCoordStride);
03246:                                    texBuffer.get(vertexData, tOffset,
03247:                                            texCoordStride);
03248:                                    tOffset += texCoordStride;
03249:                                }
03250:                                vOffset += stride;
03251:                            }
03252:                        }
03253:                    }
03254:
03255:                    if ((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) {
03256:                        vOffset = 0;
03257:                        if ((src.vertexType & VATTR_DEFINED) == AF) {
03258:                            for (index = start; index < end; index++) {
03259:                                for (i = 0; i < vertexAttrCount; i++) {
03260:                                    int vaOffset = vOffset
03261:                                            + vertexAttrOffsets[i];
03262:                                    FloatBufferWrapper vaBuffer = src.floatBufferRefVertexAttrs[i];
03263:                                    vaBuffer
03264:                                            .position(src.indexVertexAttr[i][index]
03265:                                                    * vertexAttrSizes[i]);
03266:                                    vaBuffer.get(vertexData, vaOffset,
03267:                                            vertexAttrSizes[i]);
03268:                                }
03269:                                vOffset += stride;
03270:                            }
03271:                        }
03272:                    }
03273:
03274:                    if ((vertexFormat & GeometryArray.COORDINATES) != 0) {
03275:                        vOffset = coordinateOffset;
03276:                        switch ((src.vertexType & VERTEX_DEFINED)) {
03277:                        case PF:
03278:                            for (index = start; index < end; index++) {
03279:                                src.floatBufferRefCoords
03280:                                        .position(src.indexCoord[index] * 3);
03281:                                src.floatBufferRefCoords.get(vertexData,
03282:                                        vOffset, 3);
03283:                                vOffset += stride;
03284:                            }
03285:                            break;
03286:                        case PD:
03287:                            for (index = start; index < end; index++) {
03288:                                srcOffset = src.indexCoord[index] * 3;
03289:                                vertexData[vOffset] = (float) src.doubleBufferRefCoords
03290:                                        .get(srcOffset);
03291:                                vertexData[vOffset + 1] = (float) src.doubleBufferRefCoords
03292:                                        .get(srcOffset + 1);
03293:                                vertexData[vOffset + 2] = (float) src.doubleBufferRefCoords
03294:                                        .get(srcOffset + 2);
03295:                                vOffset += stride;
03296:                            }
03297:                            break;
03298:                        default:
03299:                            break;
03300:                        }
03301:                    }
03302:
03303:                }
03304:            }
03305:
03306:            /**
03307:             * Returns the vertex stride in numbers of floats as a function
03308:             * of the vertexFormat.
03309:             * @return the stride in floats for this vertex array
03310:             */
03311:            int stride() {
03312:                int stride = 0;
03313:
03314:                if ((this .vertexFormat & GeometryArray.COORDINATES) != 0)
03315:                    stride += 3;
03316:                if ((this .vertexFormat & GeometryArray.NORMALS) != 0)
03317:                    stride += 3;
03318:
03319:                if ((this .vertexFormat & GeometryArray.COLOR) != 0) {
03320:                    if ((this .vertexFormat & GeometryArray.BY_REFERENCE) == 0) {
03321:                        // By copy
03322:                        stride += 4;
03323:                    } else {
03324:                        if ((this .vertexFormat & GeometryArray.WITH_ALPHA) == 0) {
03325:                            stride += 3;
03326:                        } else {
03327:                            stride += 4;
03328:                        }
03329:                    }
03330:                }
03331:
03332:                if ((this .vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) {
03333:
03334:                    if ((this .vertexFormat & GeometryArray.TEXTURE_COORDINATE_2) != 0) {
03335:                        texCoordStride = 2;
03336:                    } else if ((this .vertexFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0) {
03337:                        texCoordStride = 3;
03338:                    } else if ((this .vertexFormat & GeometryArray.TEXTURE_COORDINATE_4) != 0) {
03339:                        texCoordStride = 4;
03340:                    }
03341:
03342:                    stride += texCoordStride * texCoordSetCount;
03343:                }
03344:
03345:                if ((this .vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) {
03346:                    stride += vertexAttrStride;
03347:                }
03348:
03349:                //System.err.println("stride() = " + stride);
03350:                return stride;
03351:            }
03352:
03353:            int[] texCoordSetMapOffset() {
03354:                if (texCoordSetMap == null)
03355:                    return null;
03356:
03357:                texCoordSetMapOffset = new int[texCoordSetMap.length];
03358:                for (int i = 0; i < texCoordSetMap.length; i++) {
03359:                    if (texCoordSetMap[i] == -1) {
03360:                        texCoordSetMapOffset[i] = -1;
03361:                    } else {
03362:                        texCoordSetMapOffset[i] = texCoordSetMap[i]
03363:                                * texCoordStride;
03364:                    }
03365:                }
03366:                return texCoordSetMapOffset;
03367:            }
03368:
03369:            /**
03370:             * Returns the stride of the set of vertex attributes. This is the
03371:             * sum of the sizes of each vertex attribute.
03372:             * @return the stride of the vertex attribute data
03373:             */
03374:            int vertexAttrStride() {
03375:                int sum = 0;
03376:                for (int i = 0; i < vertexAttrCount; i++) {
03377:                    sum += vertexAttrSizes[i];
03378:                }
03379:                return sum;
03380:            }
03381:
03382:            /**
03383:             * Returns the offset in number of floats from the start of a vertex to
03384:             * each per-vertex vertex attribute.
03385:             * @return array of offsets in floats vertex start to the vertex attribute data
03386:             */
03387:            int[] vertexAttrOffsets() {
03388:                int[] offsets;
03389:
03390:                // Create array of offsets to the start of each vertex attribute.
03391:                // The offset of the first attribute is always 0. If no vertex attributes exist,
03392:                // then we will allocate an array of length 1 to avoid some checking elsewhere.
03393:                if (vertexAttrCount > 0) {
03394:                    offsets = new int[vertexAttrCount];
03395:                } else {
03396:                    offsets = new int[1];
03397:                }
03398:                offsets[0] = 0;
03399:                for (int i = 1; i < vertexAttrCount; i++) {
03400:                    offsets[i] = offsets[i - 1] + vertexAttrSizes[i - 1];
03401:                }
03402:
03403:                return offsets;
03404:            }
03405:
03406:            /**
03407:             * Returns the offset in number of floats from the start of a vertex to
03408:             * the per-vertex texture coordinate data.
03409:             * texture coordinate data always follows vertex attribute data
03410:             * @return the offset in floats vertex start to the tetxure data
03411:             */
03412:            int textureOffset() {
03413:                int offset = vertexAttrOffsets[0];
03414:
03415:                if ((this .vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) {
03416:                    offset += vertexAttrStride;
03417:                }
03418:
03419:                return offset;
03420:            }
03421:
03422:            /**
03423:             * Returns the offset in number of floats from the start of a vertex to
03424:             * the per-vertex color data.
03425:             * color data always follows texture data
03426:             * @param vertexFormat the vertex format for this array
03427:             * @return the offset in floats vertex start to the color data
03428:             */
03429:            int colorOffset() {
03430:                int offset = textureOffset;
03431:
03432:                if ((this .vertexFormat & GeometryArray.TEXTURE_COORDINATE_2) != 0)
03433:                    offset += 2 * texCoordSetCount;
03434:                else if ((this .vertexFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0)
03435:                    offset += 3 * texCoordSetCount;
03436:                else if ((this .vertexFormat & GeometryArray.TEXTURE_COORDINATE_4) != 0)
03437:                    offset += 4 * texCoordSetCount;
03438:
03439:                return offset;
03440:            }
03441:
03442:            /**
03443:             * Returns the offset in number of floats from the start of a vertex to
03444:             * the per-vertex normal data.
03445:             * normal data always follows color data
03446:             * @return the offset in floats from the start of a vertex to the normal
03447:             */
03448:            int normalOffset() {
03449:                int offset = colorOffset;
03450:
03451:                if ((this .vertexFormat & GeometryArray.COLOR) != 0) {
03452:                    if ((this .vertexFormat & GeometryArray.BY_REFERENCE) == 0) {
03453:                        offset += 4;
03454:                    } else {
03455:                        if ((this .vertexFormat & GeometryArray.WITH_ALPHA) == 0) {
03456:                            offset += 3;
03457:                        } else {
03458:                            offset += 4;
03459:                        }
03460:                    }
03461:                }
03462:                return offset;
03463:            }
03464:
03465:            /**
03466:             * Returns the offset in number of floats from the start of a vertex to
03467:             * the per vertex coordinate data.
03468:             * @return the offset in floats vertex start to the coordinate data
03469:             */
03470:            int coordinateOffset() {
03471:                int offset = normalOffset;
03472:
03473:                if ((this .vertexFormat & GeometryArray.NORMALS) != 0)
03474:                    offset += 3;
03475:                return offset;
03476:            }
03477:
03478:            /**
03479:             * Returns number of vertices in the GeometryArray
03480:             * @return vertexCount number of vertices in the GeometryArray
03481:             */
03482:            int getVertexCount() {
03483:                return vertexCount;
03484:            }
03485:
03486:            /**
03487:             * Returns vertexFormat in the GeometryArray
03488:             * @return vertexFormat format of vertices in the GeometryArray
03489:             */
03490:            int getVertexFormat() {
03491:                return vertexFormat;
03492:            }
03493:
03494:            /**
03495:             * Retrieves the number of vertex attributes in this GeometryArray
03496:             * object.
03497:             *
03498:             * @return the number of vertex attributes in this GeometryArray
03499:             * object
03500:             */
03501:            int getVertexAttrCount() {
03502:                return vertexAttrCount;
03503:            }
03504:
03505:            /**
03506:             * Retrieves the vertex attribute sizes array from this
03507:             * GeometryArray object.
03508:             *
03509:             * @param vertexAttrSizes an array that will receive a copy of
03510:             * the vertex attribute sizes array.  The array must hold at least
03511:             * <code>vertexAttrCount</code> elements.
03512:             */
03513:            void getVertexAttrSizes(int[] vertexAttrSizes) {
03514:                for (int i = 0; i < vertexAttrCount; i++) {
03515:                    vertexAttrSizes[i] = this .vertexAttrSizes[i];
03516:                }
03517:            }
03518:
03519:            void sendDataChangedMessage(boolean coordinatesChanged) {
03520:                J3dMessage[] m;
03521:                int i, j, k, index, numShapeMessages, numMorphMessages;
03522:                ArrayList shapeList;
03523:                Shape3DRetained s;
03524:                ArrayList morphList;
03525:                MorphRetained morph;
03526:
03527:                synchronized (liveStateLock) {
03528:                    if (source != null && source.isLive()) {
03529:                        // System.err.println("In GeometryArrayRetained - ");
03530:
03531:                        // Send a message to renderBin to rebuild the display list or
03532:                        // process the vertex array accordingly
03533:                        // XXXX: Should I send one per universe, isn't display list
03534:                        // shared by all context/universes?
03535:                        int threads = J3dThread.UPDATE_RENDER;
03536:                        // If the geometry type is Indexed then we need to clone the geometry
03537:                        // We also need to update the cachedChangedFrequent flag
03538:                        threads |= J3dThread.UPDATE_RENDERING_ATTRIBUTES;
03539:
03540:                        synchronized (universeList) {
03541:                            numShapeMessages = universeList.size();
03542:                            m = new J3dMessage[numShapeMessages];
03543:
03544:                            k = 0;
03545:
03546:                            for (i = 0; i < numShapeMessages; i++, k++) {
03547:                                gaList.clear();
03548:
03549:                                shapeList = (ArrayList) userLists.get(i);
03550:                                for (j = 0; j < shapeList.size(); j++) {
03551:                                    s = (Shape3DRetained) shapeList.get(j);
03552:                                    LeafRetained src = (LeafRetained) s.sourceNode;
03553:                                    // Should only need to update distinct localBounds.
03554:                                    if (coordinatesChanged
03555:                                            && src.boundsAutoCompute) {
03556:                                        src.boundsDirty = true;
03557:                                    }
03558:                                }
03559:
03560:                                for (j = 0; j < shapeList.size(); j++) {
03561:                                    s = (Shape3DRetained) shapeList.get(j);
03562:                                    LeafRetained src = (LeafRetained) s.sourceNode;
03563:                                    if (src.boundsDirty) {
03564:                                        // update combine bounds of mirrorShape3Ds. So we need to
03565:                                        // use its bounds and not localBounds.
03566:                                        // bounds is actually a reference to
03567:                                        // mirrorShape3D.source.localBounds.
03568:                                        src.updateBounds();
03569:                                        src.boundsDirty = false;
03570:                                    }
03571:                                    gaList.add(Shape3DRetained.getGeomAtom(s));
03572:                                }
03573:
03574:                                m[k] = new J3dMessage();
03575:
03576:                                m[k].type = J3dMessage.GEOMETRY_CHANGED;
03577:                                // Who to send this message to ?
03578:                                m[k].threads = threads;
03579:                                m[k].args[0] = gaList.toArray();
03580:                                m[k].args[1] = this ;
03581:                                m[k].args[2] = null;
03582:                                m[k].args[3] = new Integer(changedFrequent);
03583:                                m[k].universe = (VirtualUniverse) universeList
03584:                                        .get(i);
03585:                            }
03586:                            VirtualUniverse.mc.processMessage(m);
03587:                        }
03588:
03589:                        if (morphUniverseList != null) {
03590:                            synchronized (morphUniverseList) {
03591:                                numMorphMessages = morphUniverseList.size();
03592:
03593:                                // take care of morph that is referencing this geometry
03594:                                if (numMorphMessages > 0) {
03595:                                    synchronized (morphUniverseList) {
03596:                                        for (i = 0; i < numMorphMessages; i++, k++) {
03597:                                            morphList = (ArrayList) morphUserLists
03598:                                                    .get(i);
03599:                                            for (j = 0; j < morphList.size(); j++) {
03600:                                                morph = (MorphRetained) morphList
03601:                                                        .get(j);
03602:                                                morph
03603:                                                        .updateMorphedGeometryArray(
03604:                                                                this ,
03605:                                                                coordinatesChanged);
03606:                                            }
03607:                                        }
03608:                                    }
03609:                                }
03610:                            }
03611:                        }
03612:                    }
03613:                }
03614:
03615:            }
03616:
03617:            /**
03618:             * Sets the coordinate associated with the vertex at
03619:             * the specified index.
03620:             * @param index the vertex index
03621:             * @param coordinate an array of 3 values containing the new coordinate
03622:             */
03623:            void setCoordinate(int index, float coordinate[]) {
03624:                int offset = this .stride * index + coordinateOffset;
03625:                boolean isLive = source != null && source.isLive();
03626:                if (isLive) {
03627:                    geomLock.getLock();
03628:                }
03629:                dirtyFlag |= COORDINATE_CHANGED;
03630:
03631:                this .vertexData[offset] = coordinate[0];
03632:                this .vertexData[offset + 1] = coordinate[1];
03633:                this .vertexData[offset + 2] = coordinate[2];
03634:
03635:                if (isLive) {
03636:                    geomLock.unLock();
03637:                }
03638:                if (inUpdater || (source == null)) {
03639:                    return;
03640:                }
03641:                if (!isLive) {
03642:                    boundsDirty = true;
03643:                    return;
03644:                }
03645:
03646:                // Compute geo's bounds
03647:                processCoordsChanged(false);
03648:                sendDataChangedMessage(true);
03649:
03650:            }
03651:
03652:            /**
03653:             * Sets the coordinate associated with the vertex at
03654:             * the specified index.
03655:             * @param index the vertex index
03656:             * @param coordinate an array of 3 values containing the new coordinate
03657:             */
03658:            void setCoordinate(int index, double coordinate[]) {
03659:                int offset = this .stride * index + coordinateOffset;
03660:                boolean isLive = source != null && source.isLive();
03661:                if (isLive) {
03662:                    geomLock.getLock();
03663:                }
03664:                dirtyFlag |= COORDINATE_CHANGED;
03665:                this .vertexData[offset] = (float) coordinate[0];
03666:                this .vertexData[offset + 1] = (float) coordinate[1];
03667:                this .vertexData[offset + 2] = (float) coordinate[2];
03668:
03669:                if (isLive) {
03670:                    geomLock.unLock();
03671:                }
03672:
03673:                if (inUpdater || (source == null)) {
03674:                    return;
03675:                }
03676:                if (!isLive) {
03677:                    boundsDirty = true;
03678:                    return;
03679:                }
03680:
03681:                // Compute geo's bounds
03682:                processCoordsChanged(false);
03683:                sendDataChangedMessage(true);
03684:            }
03685:
03686:            /**
03687:             * Sets the coordinate associated with the vertex at
03688:             * the specified index.
03689:             * @param index the vertex index
03690:             * @param coordinate a vector containing the new coordinate
03691:             */
03692:            void setCoordinate(int index, Point3f coordinate) {
03693:                int offset = this .stride * index + coordinateOffset;
03694:                boolean isLive = source != null && source.isLive();
03695:                if (isLive) {
03696:                    geomLock.getLock();
03697:                }
03698:                dirtyFlag |= COORDINATE_CHANGED;
03699:                this .vertexData[offset] = coordinate.x;
03700:                this .vertexData[offset + 1] = coordinate.y;
03701:                this .vertexData[offset + 2] = coordinate.z;
03702:
03703:                if (isLive) {
03704:                    geomLock.unLock();
03705:                }
03706:                if (inUpdater || (source == null)) {
03707:                    return;
03708:                }
03709:                if (!isLive) {
03710:                    boundsDirty = true;
03711:                    return;
03712:                }
03713:
03714:                // Compute geo's bounds
03715:                processCoordsChanged(false);
03716:                sendDataChangedMessage(true);
03717:            }
03718:
03719:            /**
03720:             * Sets the coordinate associated with the vertex at
03721:             * the specified index.
03722:             * @param index the vertex index
03723:             * @param coordinate a vector containing the new coordinate
03724:             */
03725:            void setCoordinate(int index, Point3d coordinate) {
03726:                int offset = this .stride * index + coordinateOffset;
03727:                boolean isLive = source != null && source.isLive();
03728:                if (isLive) {
03729:                    geomLock.getLock();
03730:                }
03731:                dirtyFlag |= COORDINATE_CHANGED;
03732:                this .vertexData[offset] = (float) coordinate.x;
03733:                this .vertexData[offset + 1] = (float) coordinate.y;
03734:                this .vertexData[offset + 2] = (float) coordinate.z;
03735:                if (isLive) {
03736:                    geomLock.unLock();
03737:                }
03738:                if (inUpdater || source == null) {
03739:                    return;
03740:                }
03741:                if (!isLive) {
03742:                    boundsDirty = true;
03743:                    return;
03744:                }
03745:                // Compute geo's bounds
03746:                processCoordsChanged(false);
03747:                sendDataChangedMessage(true);
03748:            }
03749:
03750:            /**
03751:             * Sets the coordinates associated with the vertices starting at
03752:             * the specified index.
03753:             * @param index the vertex index
03754:             * @param coordinates an array of 3*n values containing n new coordinates
03755:             */
03756:            void setCoordinates(int index, float coordinates[]) {
03757:                int offset = this .stride * index + coordinateOffset;
03758:                int i, j, num = coordinates.length;
03759:                boolean isLive = source != null && source.isLive();
03760:                if (isLive) {
03761:                    geomLock.getLock();
03762:                }
03763:                dirtyFlag |= COORDINATE_CHANGED;
03764:
03765:                for (i = 0, j = offset; i < num; i += 3, j += this .stride) {
03766:                    this .vertexData[j] = coordinates[i];
03767:                    this .vertexData[j + 1] = coordinates[i + 1];
03768:                    this .vertexData[j + 2] = coordinates[i + 2];
03769:                }
03770:
03771:                if (isLive) {
03772:                    geomLock.unLock();
03773:                }
03774:                if (inUpdater || source == null) {
03775:                    return;
03776:                }
03777:                if (!isLive) {
03778:                    boundsDirty = true;
03779:                    return;
03780:                }
03781:
03782:                // Compute geo's bounds
03783:                processCoordsChanged(false);
03784:
03785:                sendDataChangedMessage(true);
03786:
03787:            }
03788:
03789:            /**
03790:             * Sets the coordinates associated with the vertices starting at
03791:             * the specified index.
03792:             * @param index the vertex index
03793:             * @param coordinates an array of 3*n values containing n new coordinates
03794:             */
03795:            void setCoordinates(int index, double coordinates[]) {
03796:                int offset = this .stride * index + coordinateOffset;
03797:                int i, j, num = coordinates.length;
03798:                boolean isLive = source != null && source.isLive();
03799:                if (isLive) {
03800:                    geomLock.getLock();
03801:                }
03802:                dirtyFlag |= COORDINATE_CHANGED;
03803:
03804:                for (i = 0, j = offset; i < num; i += 3, j += this .stride) {
03805:                    this .vertexData[j] = (float) coordinates[i];
03806:                    this .vertexData[j + 1] = (float) coordinates[i + 1];
03807:                    this .vertexData[j + 2] = (float) coordinates[i + 2];
03808:                }
03809:
03810:                if (isLive) {
03811:                    geomLock.unLock();
03812:                }
03813:
03814:                if (inUpdater || source == null) {
03815:                    return;
03816:                }
03817:                if (!isLive) {
03818:                    boundsDirty = true;
03819:                    return;
03820:                }
03821:
03822:                // Compute geo's bounds
03823:                processCoordsChanged(false);
03824:
03825:                sendDataChangedMessage(true);
03826:            }
03827:
03828:            /**
03829:             * Sets the coordinates associated with the vertices starting at
03830:             * the specified index.
03831:             * @param index the vertex index
03832:             * @param coordinates an array of vectors containing new coordinates
03833:             */
03834:            void setCoordinates(int index, Point3f coordinates[]) {
03835:                int offset = this .stride * index + coordinateOffset;
03836:                int i, j, num = coordinates.length;
03837:                boolean isLive = source != null && source.isLive();
03838:                if (isLive) {
03839:                    geomLock.getLock();
03840:                }
03841:                dirtyFlag |= COORDINATE_CHANGED;
03842:
03843:                for (i = 0, j = offset; i < num; i++, j += this .stride) {
03844:                    this .vertexData[j] = coordinates[i].x;
03845:                    this .vertexData[j + 1] = coordinates[i].y;
03846:                    this .vertexData[j + 2] = coordinates[i].z;
03847:                }
03848:                if (isLive) {
03849:                    geomLock.unLock();
03850:                }
03851:
03852:                if (inUpdater || source == null) {
03853:                    return;
03854:                }
03855:                if (!isLive) {
03856:                    boundsDirty = true;
03857:                    return;
03858:                }
03859:
03860:                // Compute geo's bounds
03861:                processCoordsChanged(false);
03862:
03863:                sendDataChangedMessage(true);
03864:
03865:            }
03866:
03867:            /**
03868:             * Sets the coordinates associated with the vertices starting at
03869:             * the specified index.
03870:             * @param index the vertex index
03871:             * @param coordinates an array of vectors containing new coordinates
03872:             */
03873:            void setCoordinates(int index, Point3d coordinates[]) {
03874:                int offset = this .stride * index + coordinateOffset;
03875:                int i, j, num = coordinates.length;
03876:                boolean isLive = source != null && source.isLive();
03877:                if (isLive) {
03878:                    geomLock.getLock();
03879:                }
03880:                dirtyFlag |= COORDINATE_CHANGED;
03881:
03882:                for (i = 0, j = offset; i < num; i++, j += this .stride) {
03883:                    this .vertexData[j] = (float) coordinates[i].x;
03884:                    this .vertexData[j + 1] = (float) coordinates[i].y;
03885:                    this .vertexData[j + 2] = (float) coordinates[i].z;
03886:                }
03887:                if (isLive) {
03888:                    geomLock.unLock();
03889:                }
03890:
03891:                if (inUpdater || source == null) {
03892:                    return;
03893:                }
03894:                if (!isLive) {
03895:                    boundsDirty = true;
03896:                    return;
03897:                }
03898:
03899:                // Compute geo's bounds
03900:                processCoordsChanged(false);
03901:
03902:                sendDataChangedMessage(true);
03903:            }
03904:
03905:            /**
03906:             * Sets the coordinates associated with the vertices starting at
03907:             * the specified index for this object using coordinate data starting
03908:             * from vertex index <code>start</code> for <code>length</code> vertices.
03909:             * @param index the vertex index
03910:             * @param coordinates an array of vectors containing new coordinates
03911:             * @param start starting vertex index of data in <code>coordinates</code>  .
03912:             * @param length number of vertices to be copied.
03913:             */
03914:            void setCoordinates(int index, float coordinates[], int start,
03915:                    int length) {
03916:                int offset = this .stride * index + coordinateOffset;
03917:                int i, j;
03918:                boolean isLive = source != null && source.isLive();
03919:                if (isLive) {
03920:                    geomLock.getLock();
03921:                }
03922:                dirtyFlag |= COORDINATE_CHANGED;
03923:                for (i = start * 3, j = offset; i < (start + length) * 3; i += 3, j += this .stride) {
03924:                    this .vertexData[j] = coordinates[i];
03925:                    this .vertexData[j + 1] = coordinates[i + 1];
03926:                    this .vertexData[j + 2] = coordinates[i + 2];
03927:                }
03928:                if (isLive) {
03929:                    geomLock.unLock();
03930:                }
03931:                if (inUpdater || source == null) {
03932:                    return;
03933:                }
03934:                if (!isLive) {
03935:                    boundsDirty = true;
03936:                    return;
03937:                }
03938:
03939:                // Compute geo's bounds
03940:                processCoordsChanged(false);
03941:
03942:                sendDataChangedMessage(true);
03943:            }
03944:
03945:            /**
03946:             * Sets the coordinates associated with the vertices starting at
03947:             * the specified index for this object  using coordinate data starting
03948:             * from vertex index <code>start</code> for <code>length</code> vertices.
03949:             * @param index the vertex index
03950:             * @param coordinates an array of 3*n values containing n new coordinates
03951:             * @param start starting vertex index of data in <code>coordinates</code>  .
03952:             * @param length number of vertices to be copied.
03953:             */
03954:            void setCoordinates(int index, double coordinates[], int start,
03955:                    int length) {
03956:                int offset = this .stride * index + coordinateOffset;
03957:                int i, j;
03958:                boolean isLive = source != null && source.isLive();
03959:                if (isLive) {
03960:                    geomLock.getLock();
03961:                }
03962:                dirtyFlag |= COORDINATE_CHANGED;
03963:
03964:                for (i = start * 3, j = offset; i < (start + length) * 3; i += 3, j += this .stride) {
03965:                    this .vertexData[j] = (float) coordinates[i];
03966:                    this .vertexData[j + 1] = (float) coordinates[i + 1];
03967:                    this .vertexData[j + 2] = (float) coordinates[i + 2];
03968:                }
03969:
03970:                if (isLive) {
03971:                    geomLock.unLock();
03972:                }
03973:                if (inUpdater || (source == null)) {
03974:                    return;
03975:                }
03976:                if (!isLive) {
03977:                    boundsDirty = true;
03978:                    return;
03979:                }
03980:
03981:                // Compute geo's bounds
03982:                processCoordsChanged(false);
03983:
03984:                sendDataChangedMessage(true);
03985:            }
03986:
03987:            /**
03988:             * Sets the coordinates associated with the vertices starting at
03989:             * the specified index for this object using coordinate data starting
03990:             * from vertex index <code>start</code> for <code>length</code> vertices.
03991:             * @param index the vertex index
03992:             * @param coordinates an array of vectors containing new coordinates
03993:             * @param start starting vertex index of data in <code>coordinates</code>  .
03994:             * @param length number of vertices to be copied.
03995:             */
03996:            void setCoordinates(int index, Point3f coordinates[], int start,
03997:                    int length) {
03998:                int offset = this .stride * index + coordinateOffset;
03999:                int i, j;
04000:                boolean isLive = source != null && source.isLive();
04001:                if (isLive) {
04002:                    geomLock.getLock();
04003:                }
04004:                dirtyFlag |= COORDINATE_CHANGED;
04005:
04006:                for (i = start, j = offset; i < start + length; i++, j += this .stride) {
04007:                    this .vertexData[j] = coordinates[i].x;
04008:                    this .vertexData[j + 1] = coordinates[i].y;
04009:                    this .vertexData[j + 2] = coordinates[i].z;
04010:                }
04011:
04012:                if (isLive) {
04013:                    geomLock.unLock();
04014:                }
04015:
04016:                if (inUpdater || (source == null)) {
04017:                    return;
04018:                }
04019:                if (!isLive) {
04020:                    boundsDirty = true;
04021:                    return;
04022:                }
04023:
04024:                // Compute geo's bounds
04025:                processCoordsChanged(false);
04026:
04027:                sendDataChangedMessage(true);
04028:            }
04029:
04030:            /**
04031:             * Sets the coordinates associated with the vertices starting at
04032:             * the specified index for this object using coordinate data starting
04033:             * from vertex index <code>start</code> for <code>length</code> vertices.
04034:             * @param index the vertex index
04035:             * @param coordinates an array of vectors containing new coordinates
04036:             * @param start starting vertex index of data in <code>coordinates</code>  .
04037:             * @param length number of vertices to be copied.
04038:             */
04039:            void setCoordinates(int index, Point3d coordinates[], int start,
04040:                    int length) {
04041:                int offset = this .stride * index + coordinateOffset;
04042:                int i, j;
04043:                boolean isLive = source != null && source.isLive();
04044:                if (isLive) {
04045:                    geomLock.getLock();
04046:                }
04047:                dirtyFlag |= COORDINATE_CHANGED;
04048:
04049:                for (i = start, j = offset; i < start + length; i++, j += this .stride) {
04050:                    this .vertexData[j] = (float) coordinates[i].x;
04051:                    this .vertexData[j + 1] = (float) coordinates[i].y;
04052:                    this .vertexData[j + 2] = (float) coordinates[i].z;
04053:                }
04054:
04055:                if (isLive) {
04056:                    geomLock.unLock();
04057:                }
04058:                if (inUpdater || (source == null)) {
04059:                    return;
04060:                }
04061:                if (!isLive) {
04062:                    boundsDirty = true;
04063:                    return;
04064:                }
04065:
04066:                // Compute geo's bounds
04067:                processCoordsChanged(false);
04068:
04069:                sendDataChangedMessage(true);
04070:            }
04071:
04072:            /**
04073:             * Sets the color associated with the vertex at
04074:             * the specified index.
04075:             * @param index the vertex index
04076:             * @param color an array of 3 or 4 values containing the new color
04077:             */
04078:            void setColor(int index, float color[]) {
04079:                int offset = this .stride * index + colorOffset;
04080:
04081:                boolean isLive = source != null && source.isLive();
04082:                if (isLive) {
04083:                    geomLock.getLock();
04084:                }
04085:                dirtyFlag |= COLOR_CHANGED;
04086:                colorChanged = 0xffff;
04087:                this .vertexData[offset] = color[0];
04088:                this .vertexData[offset + 1] = color[1];
04089:                this .vertexData[offset + 2] = color[2];
04090:                if ((this .vertexFormat & GeometryArray.WITH_ALPHA) != 0)
04091:                    this .vertexData[offset + 3] = color[3] * lastAlpha[0];
04092:                else
04093:                    this .vertexData[offset + 3] = lastAlpha[0];
04094:
04095:                if (isLive) {
04096:                    geomLock.unLock();
04097:                    sendDataChangedMessage(false);
04098:                }
04099:
04100:            }
04101:
04102:            /**
04103:             * Sets the color associated with the vertex at
04104:             * the specified index.
04105:             * @param index the vertex index
04106:             * @param color an array of 3 or 4 values containing the new color
04107:             */
04108:            void setColor(int index, byte color[]) {
04109:                int offset = this .stride * index + colorOffset;
04110:
04111:                boolean isLive = source != null && source.isLive();
04112:                if (isLive) {
04113:                    geomLock.getLock();
04114:                }
04115:
04116:                dirtyFlag |= COLOR_CHANGED;
04117:                colorChanged = 0xffff;
04118:                this .vertexData[offset] = (color[0] & 0xff) * ByteToFloatScale;
04119:                this .vertexData[offset + 1] = (color[1] & 0xff)
04120:                        * ByteToFloatScale;
04121:                this .vertexData[offset + 2] = (color[2] & 0xff)
04122:                        * ByteToFloatScale;
04123:                if ((this .vertexFormat & GeometryArray.WITH_ALPHA) != 0)
04124:                    this .vertexData[offset + 3] = ((color[3] & 0xff) * ByteToFloatScale)
04125:                            * lastAlpha[0];
04126:                else
04127:                    this .vertexData[offset + 3] = lastAlpha[0];
04128:
04129:                if (isLive) {
04130:                    geomLock.unLock();
04131:                    sendDataChangedMessage(false);
04132:                }
04133:
04134:            }
04135:
04136:            /**
04137:             * Sets the color associated with the vertex at
04138:             * the specified index.
04139:             * @param index the vertex index
04140:             * @param color a vector containing the new color
04141:             */
04142:            void setColor(int index, Color3f color) {
04143:                int offset = this .stride * index + colorOffset;
04144:
04145:                boolean isLive = source != null && source.isLive();
04146:                if (isLive) {
04147:                    geomLock.getLock();
04148:                }
04149:
04150:                dirtyFlag |= COLOR_CHANGED;
04151:                colorChanged = 0xffff;
04152:                this .vertexData[offset] = color.x;
04153:                this .vertexData[offset + 1] = color.y;
04154:                this .vertexData[offset + 2] = color.z;
04155:                this .vertexData[offset + 3] = lastAlpha[0];
04156:
04157:                if (isLive) {
04158:                    geomLock.unLock();
04159:                    sendDataChangedMessage(false);
04160:                }
04161:
04162:            }
04163:
04164:            /**
04165:             * Sets the color associated with the vertex at
04166:             * the specified index.
04167:             * @param index the vertex index
04168:             * @param color a vector containing the new color
04169:             */
04170:            void setColor(int index, Color4f color) {
04171:                int offset = this .stride * index + colorOffset;
04172:                boolean isLive = source != null && source.isLive();
04173:                if (isLive) {
04174:                    geomLock.getLock();
04175:                }
04176:                dirtyFlag |= COLOR_CHANGED;
04177:                colorChanged = 0xffff;
04178:                this .vertexData[offset] = color.x;
04179:                this .vertexData[offset + 1] = color.y;
04180:                this .vertexData[offset + 2] = color.z;
04181:                this .vertexData[offset + 3] = color.w * lastAlpha[0];
04182:
04183:                if (isLive) {
04184:                    geomLock.unLock();
04185:                    sendDataChangedMessage(false);
04186:                }
04187:
04188:            }
04189:
04190:            /**
04191:             * Sets the color associated with the vertex at
04192:             * the specified index.
04193:             * @param index the vertex index
04194:             * @param color a vector containing the new color
04195:             */
04196:            void setColor(int index, Color3b color) {
04197:                int offset = this .stride * index + colorOffset;
04198:
04199:                boolean isLive = source != null && source.isLive();
04200:                if (isLive) {
04201:                    geomLock.getLock();
04202:                }
04203:
04204:                dirtyFlag |= COLOR_CHANGED;
04205:                colorChanged = 0xffff;
04206:                this .vertexData[offset] = (color.x & 0xff) * ByteToFloatScale;
04207:                this .vertexData[offset + 1] = (color.y & 0xff)
04208:                        * ByteToFloatScale;
04209:                this .vertexData[offset + 2] = (color.z & 0xff)
04210:                        * ByteToFloatScale;
04211:                this .vertexData[offset + 3] = lastAlpha[0];
04212:
04213:                if (isLive) {
04214:                    geomLock.unLock();
04215:                    sendDataChangedMessage(false);
04216:                }
04217:
04218:            }
04219:
04220:            /**
04221:             * Sets the color associated with the vertex at
04222:             * the specified index.
04223:             * @param index the vertex index
04224:             * @param color a vector containing the new color
04225:             */
04226:            void setColor(int index, Color4b color) {
04227:                int offset = this .stride * index + colorOffset;
04228:
04229:                boolean isLive = source != null && source.isLive();
04230:                if (isLive) {
04231:                    geomLock.getLock();
04232:                }
04233:                dirtyFlag |= COLOR_CHANGED;
04234:                colorChanged = 0xffff;
04235:                this .vertexData[offset] = (color.x * 0xff) * ByteToFloatScale;
04236:                this .vertexData[offset + 1] = (color.y * 0xff)
04237:                        * ByteToFloatScale;
04238:                this .vertexData[offset + 2] = (color.z * 0xff)
04239:                        * ByteToFloatScale;
04240:                this .vertexData[offset + 3] = ((color.w & 0xff) * ByteToFloatScale)
04241:                        * lastAlpha[0];
04242:
04243:                if (isLive) {
04244:                    geomLock.unLock();
04245:                    sendDataChangedMessage(false);
04246:                }
04247:
04248:            }
04249:
04250:            /**
04251:             * Sets the colors associated with the vertices starting at
04252:             * the specified index.
04253:             * @param index the vertex index
04254:             * @param colors an array of 3*n or 4*n values containing n new colors
04255:             */
04256:            void setColors(int index, float colors[]) {
04257:                int offset = this .stride * index + colorOffset;
04258:                int i, j, num = colors.length;
04259:
04260:                boolean isLive = source != null && source.isLive();
04261:                if (isLive) {
04262:                    geomLock.getLock();
04263:                }
04264:                dirtyFlag |= COLOR_CHANGED;
04265:                colorChanged = 0xffff;
04266:
04267:                if ((this .vertexFormat & GeometryArray.WITH_ALPHA) != 0) {
04268:                    for (i = 0, j = offset; i < num; i += 4, j += this .stride) {
04269:                        this .vertexData[j] = colors[i];
04270:                        this .vertexData[j + 1] = colors[i + 1];
04271:                        this .vertexData[j + 2] = colors[i + 2];
04272:                        this .vertexData[j + 3] = colors[i + 3] * lastAlpha[0];
04273:                    }
04274:                } else {
04275:                    for (i = 0, j = offset; i < num; i += 3, j += this .stride) {
04276:                        this .vertexData[j] = colors[i];
04277:                        this .vertexData[j + 1] = colors[i + 1];
04278:                        this .vertexData[j + 2] = colors[i + 2];
04279:                        this .vertexData[j + 3] = lastAlpha[0];
04280:                    }
04281:                }
04282:
04283:                if (isLive) {
04284:                    geomLock.unLock();
04285:                    sendDataChangedMessage(false);
04286:                }
04287:
04288:            }
04289:
04290:            /**
04291:             * Sets the colors associated with the vertices starting at
04292:             * the specified index.
04293:             * @param index the vertex index
04294:             * @param colors an array of 3*n or 4*n values containing n new colors
04295:             */
04296:            void setColors(int index, byte colors[]) {
04297:                int offset = this .stride * index + colorOffset;
04298:                int i, j, num = colors.length;
04299:
04300:                boolean isLive = source != null && source.isLive();
04301:                if (isLive) {
04302:                    geomLock.getLock();
04303:                }
04304:                dirtyFlag |= COLOR_CHANGED;
04305:                colorChanged = 0xffff;
04306:
04307:                if ((this .vertexFormat & GeometryArray.WITH_ALPHA) != 0) {
04308:                    for (i = 0, j = offset; i < num; i += 4, j += this .stride) {
04309:                        this .vertexData[j] = (colors[i] & 0xff)
04310:                                * ByteToFloatScale;
04311:                        this .vertexData[j + 1] = (colors[i + 1] & 0xff)
04312:                                * ByteToFloatScale;
04313:                        this .vertexData[j + 2] = (colors[i + 2] & 0xff)
04314:                                * ByteToFloatScale;
04315:                        this .vertexData[j + 3] = ((colors[i + 3] & 0xff) * ByteToFloatScale)
04316:                                * lastAlpha[0];
04317:                    }
04318:                } else {
04319:                    for (i = 0, j = offset; i < num; i += 3, j += this .stride) {
04320:                        this .vertexData[j] = (colors[i] & 0xff)
04321:                                * ByteToFloatScale;
04322:                        this .vertexData[j + 1] = (colors[i + 1] & 0xff)
04323:                                * ByteToFloatScale;
04324:                        this .vertexData[j + 2] = (colors[i + 2] & 0xff)
04325:                                * ByteToFloatScale;
04326:                        this .vertexData[j + 3] = lastAlpha[0];
04327:                    }
04328:                }
04329:
04330:                if (isLive) {
04331:                    geomLock.unLock();
04332:                    sendDataChangedMessage(false);
04333:                }
04334:
04335:            }
04336:
04337:            /**
04338:             * Sets the colors associated with the vertices starting at
04339:             * the specified index.
04340:             * @param index the vertex index
04341:             * @param colors an array of vectors containing new colors
04342:             */
04343:            void setColors(int index, Color3f colors[]) {
04344:                int offset = this .stride * index + colorOffset;
04345:                int i, j, num = colors.length;
04346:
04347:                boolean isLive = source != null && source.isLive();
04348:                if (isLive) {
04349:                    geomLock.getLock();
04350:                }
04351:                dirtyFlag |= COLOR_CHANGED;
04352:                colorChanged = 0xffff;
04353:
04354:                for (i = 0, j = offset; i < num; i++, j += this .stride) {
04355:                    this .vertexData[j] = colors[i].x;
04356:                    this .vertexData[j + 1] = colors[i].y;
04357:                    this .vertexData[j + 2] = colors[i].z;
04358:                    this .vertexData[j + 3] = lastAlpha[0];
04359:                }
04360:                if (isLive) {
04361:                    geomLock.unLock();
04362:                    sendDataChangedMessage(false);
04363:                }
04364:
04365:            }
04366:
04367:            /**
04368:             * Sets the colors associated with the vertices starting at
04369:             * the specified index.
04370:             * @param index the vertex index
04371:             * @param colors an array of vectors containing new colors
04372:             */
04373:            void setColors(int index, Color4f colors[]) {
04374:                int offset = this .stride * index + colorOffset;
04375:                int i, j, num = colors.length;
04376:                boolean isLive = source != null && source.isLive();
04377:                if (isLive) {
04378:                    geomLock.getLock();
04379:                }
04380:                dirtyFlag |= COLOR_CHANGED;
04381:                colorChanged = 0xffff;
04382:
04383:                for (i = 0, j = offset; i < num; i++, j += this .stride) {
04384:                    this .vertexData[j] = colors[i].x;
04385:                    this .vertexData[j + 1] = colors[i].y;
04386:                    this .vertexData[j + 2] = colors[i].z;
04387:                    this .vertexData[j + 3] = colors[i].w * lastAlpha[0];
04388:                }
04389:                if (isLive) {
04390:                    geomLock.unLock();
04391:                    sendDataChangedMessage(false);
04392:                }
04393:
04394:            }
04395:
04396:            /**
04397:             * Sets the colors associated with the vertices starting at
04398:             * the specified index.
04399:             * @param index the vertex index
04400:             * @param colors an array of vectors containing new colors
04401:             */
04402:            void setColors(int index, Color3b colors[]) {
04403:                int offset = this .stride * index + colorOffset;
04404:                int i, j, num = colors.length;
04405:                boolean isLive = source != null && source.isLive();
04406:                if (isLive) {
04407:                    geomLock.getLock();
04408:                }
04409:                dirtyFlag |= COLOR_CHANGED;
04410:                colorChanged = 0xffff;
04411:                for (i = 0, j = offset; i < num; i++, j += this .stride) {
04412:                    this .vertexData[j] = (colors[i].x & 0xff)
04413:                            * ByteToFloatScale;
04414:                    this .vertexData[j + 1] = (colors[i].y & 0xff)
04415:                            * ByteToFloatScale;
04416:                    this .vertexData[j + 2] = (colors[i].z & 0xff)
04417:                            * ByteToFloatScale;
04418:                    this .vertexData[j + 3] = lastAlpha[0];
04419:                }
04420:
04421:                if (isLive) {
04422:                    geomLock.unLock();
04423:                    sendDataChangedMessage(false);
04424:                }
04425:            }
04426:
04427:            /**
04428:             * Sets the colors associated with the vertices starting at
04429:             * the specified index.
04430:             * @param index the vertex index
04431:             * @param colors an array of vectors containing new colors
04432:             */
04433:            void setColors(int index, Color4b colors[]) {
04434:                int offset = this .stride * index + colorOffset;
04435:                int i, j, num = colors.length;
04436:
04437:                boolean isLive = source != null && source.isLive();
04438:                if (isLive) {
04439:                    geomLock.getLock();
04440:                }
04441:                dirtyFlag |= COLOR_CHANGED;
04442:                colorChanged = 0xffff;
04443:
04444:                for (i = 0, j = offset; i < num; i++, j += this .stride) {
04445:                    this .vertexData[j] = (colors[i].x & 0xff)
04446:                            * ByteToFloatScale;
04447:                    this .vertexData[j + 1] = (colors[i].y & 0xff)
04448:                            * ByteToFloatScale;
04449:                    this .vertexData[j + 2] = (colors[i].z & 0xff)
04450:                            * ByteToFloatScale;
04451:                    this .vertexData[j + 3] = ((colors[i].w & 0xff) * ByteToFloatScale)
04452:                            * lastAlpha[0];
04453:                }
04454:
04455:                if (isLive) {
04456:                    geomLock.unLock();
04457:                    sendDataChangedMessage(false);
04458:                }
04459:
04460:            }
04461:
04462:            /**
04463:             * Sets the colors associated with the vertices starting at
04464:             * the specified index for this object using data in <code>color</code>s
04465:             * starting at index <code>start</code> for <code>length</code> colors.
04466:             * @param index the vertex index
04467:             * @param colors an array of 3*n or 4*n values containing n new colors
04468:             * @param start starting color index of data in <code>colors</code>.
04469:             * @param length number of colors to be copied.
04470:             */
04471:            void setColors(int index, float colors[], int start, int length) {
04472:                int offset = this .stride * index + colorOffset;
04473:                int i, j;
04474:                boolean isLive = source != null && source.isLive();
04475:                if (isLive) {
04476:                    geomLock.getLock();
04477:                }
04478:                dirtyFlag |= COLOR_CHANGED;
04479:                colorChanged = 0xffff;
04480:
04481:                if ((this .vertexFormat & GeometryArray.WITH_ALPHA) != 0) {
04482:                    for (i = start * 4, j = offset; i < (start + length) * 4; i += 4, j += this .stride) {
04483:                        this .vertexData[j] = colors[i];
04484:                        this .vertexData[j + 1] = colors[i + 1];
04485:                        this .vertexData[j + 2] = colors[i + 2];
04486:                        this .vertexData[j + 3] = colors[i + 3] * lastAlpha[0];
04487:                    }
04488:                } else {
04489:                    for (i = start * 3, j = offset; i < (start + length) * 3; i += 3, j += this .stride) {
04490:                        this .vertexData[j] = colors[i];
04491:                        this .vertexData[j + 1] = colors[i + 1];
04492:                        this .vertexData[j + 2] = colors[i + 2];
04493:                        this .vertexData[j + 3] = lastAlpha[0];
04494:                    }
04495:                }
04496:
04497:                if (isLive) {
04498:                    geomLock.unLock();
04499:                    sendDataChangedMessage(false);
04500:                }
04501:
04502:            }
04503:
04504:            /**
04505:             * Sets the colors associated with the vertices starting at
04506:             * the specified index for this object using data in <code>color</code>s
04507:             * starting at index <code>start</code> for <code>length</code> colors.
04508:             * @param index the vertex index
04509:             * @param colors an array of 3*n or 4*n values containing n new colors
04510:             * @param start starting color index of data in <code>colors</code>.
04511:             * @param length number of colors to be copied.
04512:             */
04513:            void setColors(int index, byte colors[], int start, int length) {
04514:                int offset = this .stride * index + colorOffset;
04515:                int i, j;
04516:
04517:                boolean isLive = source != null && source.isLive();
04518:                if (isLive) {
04519:                    geomLock.getLock();
04520:                }
04521:                dirtyFlag |= COLOR_CHANGED;
04522:                colorChanged = 0xffff;
04523:
04524:                if ((this .vertexFormat & GeometryArray.WITH_ALPHA) != 0) {
04525:                    for (i = start * 4, j = offset; i < (start + length) * 4; i += 4, j += this .stride) {
04526:                        this .vertexData[j] = (colors[i] & 0xff)
04527:                                * ByteToFloatScale;
04528:                        this .vertexData[j + 1] = (colors[i + 1] & 0xff)
04529:                                * ByteToFloatScale;
04530:                        this .vertexData[j + 2] = (colors[i + 2] & 0xff)
04531:                                * ByteToFloatScale;
04532:                        this .vertexData[j + 3] = ((colors[i + 3] & 0xff) * ByteToFloatScale)
04533:                                * lastAlpha[0];
04534:                    }
04535:                } else {
04536:                    for (i = start * 3, j = offset; i < (start + length) * 3; i += 3, j += this .stride) {
04537:                        this .vertexData[j] = (colors[i] & 0xff)
04538:                                * ByteToFloatScale;
04539:                        this .vertexData[j + 1] = (colors[i + 1] & 0xff)
04540:                                * ByteToFloatScale;
04541:                        this .vertexData[j + 2] = (colors[i + 2] & 0xff)
04542:                                * ByteToFloatScale;
04543:                        this .vertexData[j + 3] = lastAlpha[0];
04544:                    }
04545:                }
04546:
04547:                if (isLive) {
04548:                    geomLock.unLock();
04549:                    sendDataChangedMessage(false);
04550:                }
04551:
04552:            }
04553:
04554:            /**
04555:             * Sets the colors associated with the vertices starting at
04556:             * the specified index for this object using data in <code>color</code>s
04557:             * starting at index <code>start</code> for <code>length</code> colors.
04558:             * @param index the vertex index
04559:             * @param colors an array of 3*n or 4*n values containing n new colors
04560:             * @param start starting color index of data in <code>colors</code>.
04561:             * @param length number of colors to be copied.
04562:             */
04563:            void setColors(int index, Color3f colors[], int start, int length) {
04564:                int offset = this .stride * index + colorOffset;
04565:                int i, j;
04566:                boolean isLive = source != null && source.isLive();
04567:                if (isLive) {
04568:                    geomLock.getLock();
04569:                }
04570:                dirtyFlag |= COLOR_CHANGED;
04571:                colorChanged = 0xffff;
04572:
04573:                for (i = start, j = offset; i < start + length; i++, j += this .stride) {
04574:                    this .vertexData[j] = colors[i].x;
04575:                    this .vertexData[j + 1] = colors[i].y;
04576:                    this .vertexData[j + 2] = colors[i].z;
04577:                    this .vertexData[j + 3] = lastAlpha[0];
04578:                }
04579:
04580:                if (isLive) {
04581:                    geomLock.unLock();
04582:                    sendDataChangedMessage(false);
04583:                }
04584:
04585:            }
04586:
04587:            /**
04588:             * Sets the colors associated with the vertices starting at
04589:             * the specified index for this object using data in <code>color</code>s
04590:             * starting at index <code>start</code> for <code>length</code> colors.
04591:             * @param index the vertex index
04592:             * @param colors an array of 3*n or 4*n values containing n new colors
04593:             * @param start starting color index of data in <code>colors</code>.
04594:             * @param length number of colors to be copied.
04595:             */
04596:            void setColors(int index, Color4f colors[], int start, int length) {
04597:                int offset = this .stride * index + colorOffset;
04598:                int i, j;
04599:                boolean isLive = source != null && source.isLive();
04600:                if (isLive) {
04601:                    geomLock.getLock();
04602:                }
04603:                dirtyFlag |= COLOR_CHANGED;
04604:                colorChanged = 0xffff;
04605:
04606:                for (i = start, j = offset; i < start + length; i++, j += this .stride) {
04607:                    this .vertexData[j] = colors[i].x;
04608:                    this .vertexData[j + 1] = colors[i].y;
04609:                    this .vertexData[j + 2] = colors[i].z;
04610:                    this .vertexData[j + 3] = colors[i].w * lastAlpha[0];
04611:                }
04612:
04613:                if (isLive) {
04614:                    geomLock.unLock();
04615:                    sendDataChangedMessage(false);
04616:                }
04617:
04618:            }
04619:
04620:            /**
04621:             * Sets the colors associated with the vertices starting at
04622:             * the specified index for this object using data in <code>color</code>s
04623:             * starting at index <code>start</code> for <code>length</code> colors.
04624:             * @param index the vertex index
04625:             * @param colors an array of 3*n or 4*n values containing n new colors
04626:             * @param start starting color index of data in <code>colors</code>.
04627:             * @param length number of colors to be copied.
04628:             */
04629:            void setColors(int index, Color3b colors[], int start, int length) {
04630:                int offset = this .stride * index + colorOffset;
04631:                int i, j;
04632:                boolean isLive = source != null && source.isLive();
04633:                if (isLive) {
04634:                    geomLock.getLock();
04635:                }
04636:                dirtyFlag |= COLOR_CHANGED;
04637:                colorChanged = 0xffff;
04638:
04639:                for (i = start, j = offset; i < start + length; i++, j += this .stride) {
04640:                    this .vertexData[j] = (colors[i].x & 0xff)
04641:                            * ByteToFloatScale;
04642:                    this .vertexData[j + 1] = (colors[i].y & 0xff)
04643:                            * ByteToFloatScale;
04644:                    this .vertexData[j + 2] = (colors[i].z & 0xff)
04645:                            * ByteToFloatScale;
04646:                    this .vertexData[j + 3] = lastAlpha[0];
04647:                }
04648:
04649:                if (isLive) {
04650:                    geomLock.unLock();
04651:                    sendDataChangedMessage(false);
04652:                }
04653:
04654:            }
04655:
04656:            /**
04657:             * Sets the colors associated with the vertices starting at
04658:             * the specified index for this object using data in <code>color</code>s
04659:             * starting at index <code>start</code> for <code>length</code> colors.
04660:             * @param index the vertex index
04661:             * @param colors an array of 3*n or 4*n values containing n new colors
04662:             * @param start starting color index of data in <code>colors</code>.
04663:             * @param length number of colors to be copied.
04664:             */
04665:            void setColors(int index, Color4b colors[], int start, int length) {
04666:                int offset = this .stride * index + colorOffset;
04667:                int i, j;
04668:                boolean isLive = source != null && source.isLive();
04669:                if (isLive) {
04670:                    geomLock.getLock();
04671:                }
04672:                dirtyFlag |= COLOR_CHANGED;
04673:                colorChanged = 0xffff;
04674:
04675:                for (i = start, j = offset; i < start + length; i++, j += this .stride) {
04676:                    this .vertexData[j] = (colors[i].x & 0xff)
04677:                            * ByteToFloatScale;
04678:                    this .vertexData[j + 1] = (colors[i].y & 0xff)
04679:                            * ByteToFloatScale;
04680:                    this .vertexData[j + 2] = (colors[i].z & 0xff)
04681:                            * ByteToFloatScale;
04682:                    this .vertexData[j + 3] = ((colors[i].w & 0xff) * ByteToFloatScale)
04683:                            * lastAlpha[0];
04684:                }
04685:
04686:                if (isLive) {
04687:                    geomLock.unLock();
04688:                    sendDataChangedMessage(false);
04689:                }
04690:
04691:            }
04692:
04693:            /**
04694:             * Sets the normal associated with the vertex at
04695:             * the specified index.
04696:             * @param index the vertex index
04697:             * @param normal the new normal
04698:             */
04699:            void setNormal(int index, float normal[]) {
04700:                int offset = this .stride * index + normalOffset;
04701:                boolean isLive = source != null && source.isLive();
04702:                if (isLive) {
04703:                    geomLock.getLock();
04704:                }
04705:                this .vertexData[offset] = normal[0];
04706:                this .vertexData[offset + 1] = normal[1];
04707:                this .vertexData[offset + 2] = normal[2];
04708:
04709:                if (isLive) {
04710:                    geomLock.unLock();
04711:                    sendDataChangedMessage(false);
04712:                }
04713:
04714:            }
04715:
04716:            /**
04717:             * Sets the normal associated with the vertex at
04718:             * the specified index.
04719:             * @param index the vertex index
04720:             * @param normal the vector containing the new normal
04721:             */
04722:            void setNormal(int index, Vector3f normal) {
04723:                int offset = this .stride * index + normalOffset;
04724:                boolean isLive = source != null && source.isLive();
04725:                if (isLive) {
04726:                    geomLock.getLock();
04727:                }
04728:                dirtyFlag |= NORMAL_CHANGED;
04729:                this .vertexData[offset] = normal.x;
04730:                this .vertexData[offset + 1] = normal.y;
04731:                this .vertexData[offset + 2] = normal.z;
04732:
04733:                if (isLive) {
04734:                    geomLock.unLock();
04735:                    sendDataChangedMessage(false);
04736:                }
04737:
04738:            }
04739:
04740:            /**
04741:             * Sets the normals associated with the vertices starting at
04742:             * the specified index.
04743:             * @param index the vertex index
04744:             * @param normals the new normals
04745:             */
04746:            void setNormals(int index, float normals[]) {
04747:                int offset = this .stride * index + normalOffset;
04748:                int i, j, num = normals.length;
04749:                boolean isLive = source != null && source.isLive();
04750:                if (isLive) {
04751:                    geomLock.getLock();
04752:                }
04753:                dirtyFlag |= NORMAL_CHANGED;
04754:                for (i = 0, j = offset; i < num; i += 3, j += this .stride) {
04755:                    this .vertexData[j] = normals[i];
04756:                    this .vertexData[j + 1] = normals[i + 1];
04757:                    this .vertexData[j + 2] = normals[i + 2];
04758:                }
04759:                if (isLive) {
04760:                    geomLock.unLock();
04761:                    sendDataChangedMessage(false);
04762:                }
04763:
04764:            }
04765:
04766:            /**
04767:             * Sets the normals associated with the vertices starting at
04768:             * the specified index.
04769:             * @param index the vertex index
04770:             * @param normals the vector containing the new normals
04771:             */
04772:            void setNormals(int index, Vector3f normals[]) {
04773:                int offset = this .stride * index + normalOffset;
04774:                int i, j, num = normals.length;
04775:                boolean isLive = source != null && source.isLive();
04776:                if (isLive) {
04777:                    geomLock.getLock();
04778:                }
04779:                dirtyFlag |= NORMAL_CHANGED;
04780:                for (i = 0, j = offset; i < num; i++, j += this .stride) {
04781:                    this .vertexData[j] = normals[i].x;
04782:                    this .vertexData[j + 1] = normals[i].y;
04783:                    this .vertexData[j + 2] = normals[i].z;
04784:                }
04785:                if (isLive) {
04786:                    geomLock.unLock();
04787:                    sendDataChangedMessage(false);
04788:                }
04789:
04790:            }
04791:
04792:            /**
04793:             * Sets the normals associated with the vertices starting at
04794:             * the specified index for this object using data in <code>normals</code>
04795:             * starting at index <code>start</code> and  ending at index <code>start+length</code>.
04796:             * @param index the vertex index
04797:             * @param normals the new normals
04798:             * @param start starting normal index of data in <code>colors</code>  .
04799:             * @param length number of normals to be copied.
04800:             */
04801:            void setNormals(int index, float normals[], int start, int length) {
04802:                int offset = this .stride * index + normalOffset;
04803:                int i, j;
04804:                boolean isLive = source != null && source.isLive();
04805:                if (isLive) {
04806:                    geomLock.getLock();
04807:                }
04808:                dirtyFlag |= NORMAL_CHANGED;
04809:                for (i = start * 3, j = offset; i < (start + length) * 3; i += 3, j += this .stride) {
04810:                    this .vertexData[j] = normals[i];
04811:                    this .vertexData[j + 1] = normals[i + 1];
04812:                    this .vertexData[j + 2] = normals[i + 2];
04813:                }
04814:                if (isLive) {
04815:                    geomLock.unLock();
04816:                    sendDataChangedMessage(false);
04817:                }
04818:
04819:            }
04820:
04821:            /**
04822:             * Sets the normals associated with the vertices starting at
04823:             * the specified index for this object using data in <code>normals</code>
04824:             * starting at index <code>start</code> and  ending at index <code>start+length</code>.
04825:             * @param index the vertex index
04826:             * @param normals the new normals
04827:             * @param start starting normal index of data in <code>colors</code>  .
04828:             * @param length number of normals to be copied.
04829:             */
04830:            void setNormals(int index, Vector3f normals[], int start, int length) {
04831:                int offset = this .stride * index + normalOffset;
04832:                int i, j;
04833:                boolean isLive = source != null && source.isLive();
04834:                if (isLive) {
04835:                    geomLock.getLock();
04836:                }
04837:                dirtyFlag |= NORMAL_CHANGED;
04838:                for (i = start, j = offset; i < start + length; i++, j += this .stride) {
04839:                    this .vertexData[j] = normals[i].x;
04840:                    this .vertexData[j + 1] = normals[i].y;
04841:                    this .vertexData[j + 2] = normals[i].z;
04842:                }
04843:                if (isLive) {
04844:                    geomLock.unLock();
04845:                    sendDataChangedMessage(false);
04846:                }
04847:
04848:            }
04849:
04850:            /**
04851:             * Sets the texture coordinates associated with the vertices starting at
04852:             * the specified index for this object using data in <code>texCoords</code>
04853:             * starting at index <code>start</code> and ending at index <code>start+length</code>.
04854:             * @param index the vertex index
04855:             * @param texCoords the new texture coordinates
04856:             * @param start starting texture coordinate index of data in <code>texCoords</code>  .
04857:             * @param length number of texture Coordinates to be copied.
04858:             */
04859:            void setTextureCoordinates(int texCoordSet, int index,
04860:                    float texCoords[], int start, int length) {
04861:
04862:                if ((this .vertexFormat & GeometryArray.BY_REFERENCE) != 0)
04863:                    throw new IllegalStateException(J3dI18N
04864:                            .getString("GeometryArray82"));
04865:
04866:                if ((this .vertexFormat & GeometryArray.TEXTURE_COORDINATE) == 0)
04867:                    throw new ArrayIndexOutOfBoundsException(J3dI18N
04868:                            .getString("GeometryArray79"));
04869:
04870:                int offset = this .stride * index + textureOffset + texCoordSet
04871:                        * texCoordStride;
04872:                int i, j, k;
04873:                boolean isLive = source != null && source.isLive();
04874:                if (isLive) {
04875:                    geomLock.getLock();
04876:                }
04877:                dirtyFlag |= TEXTURE_CHANGED;
04878:
04879:                if ((this .vertexFormat & GeometryArray.TEXTURE_COORDINATE_4) != 0) {
04880:                    for (i = start * 4, j = offset, k = 0; k < length; j += this .stride, k++) {
04881:                        this .vertexData[j] = texCoords[i++];
04882:                        this .vertexData[j + 1] = texCoords[i++];
04883:                        this .vertexData[j + 2] = texCoords[i++];
04884:                        this .vertexData[j + 3] = texCoords[i++];
04885:                    }
04886:                } else if ((this .vertexFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0) {
04887:                    for (i = start * 3, j = offset, k = 0; k < length; j += this .stride, k++) {
04888:                        this .vertexData[j] = texCoords[i++];
04889:                        this .vertexData[j + 1] = texCoords[i++];
04890:                        this .vertexData[j + 2] = texCoords[i++];
04891:                    }
04892:                } else {
04893:                    for (i = start * 2, j = offset, k = 0; k < length; j += this .stride, k++) {
04894:                        this .vertexData[j] = texCoords[i++];
04895:                        this .vertexData[j + 1] = texCoords[i++];
04896:                    }
04897:                }
04898:                if (isLive) {
04899:                    geomLock.unLock();
04900:                    sendDataChangedMessage(false);
04901:                }
04902:
04903:            }
04904:
04905:            /**
04906:             * Sets the texture coordinates associated with the vertices starting at
04907:             * the specified index for this object using data in <code>texCoords</code>
04908:             * starting at index <code>start</code> and ending at index <code>start+length</code>.
04909:             * @param index the vertex index
04910:             * @param texCoords the new texture coordinates
04911:             * @param start starting texture coordinate index of data in <code>texCoords</code>  .
04912:             * @param length number of texture Coordinates to be copied.
04913:             */
04914:            void setTextureCoordinates(int texCoordSet, int index,
04915:                    Point2f texCoords[], int start, int length) {
04916:
04917:                if ((this .vertexFormat & GeometryArray.BY_REFERENCE) != 0)
04918:                    throw new IllegalStateException(J3dI18N
04919:                            .getString("GeometryArray82"));
04920:
04921:                if ((this .vertexFormat & GeometryArray.TEXTURE_COORDINATE) == 0)
04922:                    throw new ArrayIndexOutOfBoundsException(J3dI18N
04923:                            .getString("GeometryArray79"));
04924:
04925:                int offset = this .stride * index + textureOffset + texCoordSet
04926:                        * texCoordStride;
04927:                int i, j;
04928:
04929:                boolean isLive = source != null && source.isLive();
04930:                if (isLive) {
04931:                    geomLock.getLock();
04932:                }
04933:                dirtyFlag |= TEXTURE_CHANGED;
04934:
04935:                for (i = start, j = offset; i < start + length; i++, j += this .stride) {
04936:                    this .vertexData[j] = texCoords[i].x;
04937:                    this .vertexData[j + 1] = texCoords[i].y;
04938:                }
04939:                if (isLive) {
04940:                    geomLock.unLock();
04941:                    sendDataChangedMessage(false);
04942:                }
04943:
04944:            }
04945:
04946:            /**
04947:             * Sets the texture coordinates associated with the vertices starting at
04948:             * the specified index for this object using data in <code>texCoords</code>
04949:             * starting at index <code>start</code> and ending at index <code>start+length</code>.
04950:             * @param index the vertex index
04951:             * @param texCoords the new texture coordinates
04952:             * @param start starting texture coordinate index of data in <code>texCoords</code>  .
04953:             * @param length number of texture Coordinates to be copied.
04954:             */
04955:            void setTextureCoordinates(int texCoordSet, int index,
04956:                    Point3f texCoords[], int start, int length) {
04957:
04958:                if ((this .vertexFormat & GeometryArray.BY_REFERENCE) != 0)
04959:                    throw new IllegalStateException(J3dI18N
04960:                            .getString("GeometryArray82"));
04961:
04962:                if ((this .vertexFormat & GeometryArray.TEXTURE_COORDINATE) == 0)
04963:                    throw new ArrayIndexOutOfBoundsException(J3dI18N
04964:                            .getString("GeometryArray79"));
04965:
04966:                int offset = this .stride * index + textureOffset + texCoordSet
04967:                        * texCoordStride;
04968:                int i, j;
04969:                boolean isLive = source != null && source.isLive();
04970:                if (isLive) {
04971:                    geomLock.getLock();
04972:                }
04973:                dirtyFlag |= TEXTURE_CHANGED;
04974:
04975:                for (i = start, j = offset; i < start + length; i++, j += this .stride) {
04976:                    this .vertexData[j] = texCoords[i].x;
04977:                    this .vertexData[j + 1] = texCoords[i].y;
04978:                    this .vertexData[j + 2] = texCoords[i].z;
04979:                }
04980:                if (isLive) {
04981:                    geomLock.unLock();
04982:                    sendDataChangedMessage(false);
04983:                }
04984:
04985:            }
04986:
04987:            /**
04988:             * Sets the texture coordinates associated with the vertices starting at
04989:             * the specified index for this object using data in <code>texCoords</code>
04990:             * starting at index <code>start</code> and ending at index <code>start+length</code>.
04991:             * @param index the vertex index
04992:             * @param texCoords the new texture coordinates
04993:             * @param start starting texture coordinate index of data in <code>texCoords</code>  .
04994:             * @param length number of texture Coordinates to be copied.
04995:             */
04996:            void setTextureCoordinates(int texCoordSet, int index,
04997:                    TexCoord2f texCoords[], int start, int length) {
04998:                boolean isLive = source != null && source.isLive();
04999:                if (isLive) {
05000:                    geomLock.getLock();
05001:                }
05002:                dirtyFlag |= TEXTURE_CHANGED;
05003:                if ((this .vertexFormat & GeometryArray.BY_REFERENCE) != 0)
05004:                    throw new IllegalStateException(J3dI18N
05005:                            .getString("GeometryArray82"));
05006:
05007:                if ((this .vertexFormat & GeometryArray.TEXTURE_COORDINATE) == 0)
05008:                    throw new ArrayIndexOutOfBoundsException(J3dI18N
05009:                            .getString("GeometryArray79"));
05010:
05011:                int offset = this .stride * index + textureOffset + texCoordSet
05012:                        * texCoordStride;
05013:                int i, j;
05014:
05015:                for (i = start, j = offset; i < start + length; i++, j += this .stride) {
05016:                    this .vertexData[j] = texCoords[i].x;
05017:                    this .vertexData[j + 1] = texCoords[i].y;
05018:                }
05019:                if (isLive) {
05020:                    geomLock.unLock();
05021:                    sendDataChangedMessage(false);
05022:                }
05023:
05024:            }
05025:
05026:            /**
05027:             * Sets the texture coordinates associated with the vertices starting at
05028:             * the specified index for this object using data in <code>texCoords</code>
05029:             * starting at index <code>start</code> and ending at index <code>start+length</code>.
05030:             * @param index the vertex index
05031:             * @param texCoords the new texture coordinates
05032:             * @param start starting texture coordinate index of data in <code>texCoords</code>  .
05033:             * @param length number of texture Coordinates to be copied.
05034:             */
05035:            void setTextureCoordinates(int texCoordSet, int index,
05036:                    TexCoord3f texCoords[], int start, int length) {
05037:                boolean isLive = source != null && source.isLive();
05038:                if (isLive) {
05039:                    geomLock.getLock();
05040:                }
05041:                dirtyFlag |= TEXTURE_CHANGED;
05042:
05043:                if ((this .vertexFormat & GeometryArray.BY_REFERENCE) != 0)
05044:                    throw new IllegalStateException(J3dI18N
05045:                            .getString("GeometryArray82"));
05046:
05047:                if ((this .vertexFormat & GeometryArray.TEXTURE_COORDINATE) == 0)
05048:                    throw new ArrayIndexOutOfBoundsException(J3dI18N
05049:                            .getString("GeometryArray79"));
05050:
05051:                int offset = this .stride * index + textureOffset + texCoordSet
05052:                        * texCoordStride;
05053:                int i, j;
05054:
05055:                for (i = start, j = offset; i < start + length; i++, j += this .stride) {
05056:                    this .vertexData[j] = texCoords[i].x;
05057:                    this .vertexData[j + 1] = texCoords[i].y;
05058:                    this .vertexData[j + 2] = texCoords[i].z;
05059:                }
05060:                if (isLive) {
05061:                    geomLock.unLock();
05062:                    sendDataChangedMessage(false);
05063:                }
05064:            }
05065:
05066:            /**
05067:             * Sets the texture coordinates associated with the vertices starting at
05068:             * the specified index for this object using data in <code>texCoords</code>
05069:             * starting at index <code>start</code> and ending at index <code>start+length</code>.
05070:             * @param index the vertex index
05071:             * @param texCoords the new texture coordinates
05072:             * @param start starting texture coordinate index of data in <code>texCoords</code>  .
05073:             * @param length number of texture Coordinates to be copied.
05074:             */
05075:            void setTextureCoordinates(int texCoordSet, int index,
05076:                    TexCoord4f texCoords[], int start, int length) {
05077:                boolean isLive = source != null && source.isLive();
05078:                if (isLive) {
05079:                    geomLock.getLock();
05080:                }
05081:                dirtyFlag |= TEXTURE_CHANGED;
05082:
05083:                if ((this .vertexFormat & GeometryArray.BY_REFERENCE) != 0)
05084:                    throw new IllegalStateException(J3dI18N
05085:                            .getString("GeometryArray82"));
05086:
05087:                if ((this .vertexFormat & GeometryArray.TEXTURE_COORDINATE) == 0)
05088:                    throw new ArrayIndexOutOfBoundsException(J3dI18N
05089:                            .getString("GeometryArray79"));
05090:
05091:                int offset = this .stride * index + textureOffset + texCoordSet
05092:                        * texCoordStride;
05093:                int i, j;
05094:
05095:                for (i = start, j = offset; i < start + length; i++, j += this .stride) {
05096:                    this .vertexData[j] = texCoords[i].x;
05097:                    this .vertexData[j + 1] = texCoords[i].y;
05098:                    this .vertexData[j + 2] = texCoords[i].z;
05099:                    this .vertexData[j + 3] = texCoords[i].w;
05100:                }
05101:                if (isLive) {
05102:                    geomLock.unLock();
05103:                    sendDataChangedMessage(false);
05104:                }
05105:            }
05106:
05107:            /**
05108:             * Sets the vertex attribute associated with the vertex at the
05109:             * specified index in the specified vertex attribute number for
05110:             * this object.
05111:             *
05112:             * @param vertexAttrNum vertex attribute number in this geometry array
05113:             * @param index destination vertex index in this geometry array
05114:             * @param vertexAttr the Point2f containing the new vertex attribute
05115:             */
05116:            void setVertexAttr(int vertexAttrNum, int index, Point2f vertexAttr) {
05117:
05118:                int offset = this .stride * index
05119:                        + vertexAttrOffsets[vertexAttrNum];
05120:                boolean isLive = source != null && source.isLive();
05121:                if (isLive) {
05122:                    geomLock.getLock();
05123:                }
05124:                dirtyFlag |= VATTR_CHANGED;
05125:
05126:                this .vertexData[offset] = vertexAttr.x;
05127:                this .vertexData[offset + 1] = vertexAttr.y;
05128:
05129:                if (isLive) {
05130:                    geomLock.unLock();
05131:                    sendDataChangedMessage(false);
05132:                }
05133:            }
05134:
05135:            /**
05136:             * Sets the vertex attribute associated with the vertex at the
05137:             * specified index in the specified vertex attribute number for
05138:             * this object.
05139:             *
05140:             * @param vertexAttrNum vertex attribute number in this geometry array
05141:             * @param index destination vertex index in this geometry array
05142:             * @param vertexAttr the Point3f containing the new vertex attribute
05143:             */
05144:            void setVertexAttr(int vertexAttrNum, int index, Point3f vertexAttr) {
05145:
05146:                int offset = this .stride * index
05147:                        + vertexAttrOffsets[vertexAttrNum];
05148:                boolean isLive = source != null && source.isLive();
05149:                if (isLive) {
05150:                    geomLock.getLock();
05151:                }
05152:                dirtyFlag |= VATTR_CHANGED;
05153:
05154:                this .vertexData[offset] = vertexAttr.x;
05155:                this .vertexData[offset + 1] = vertexAttr.y;
05156:                this .vertexData[offset + 2] = vertexAttr.z;
05157:
05158:                if (isLive) {
05159:                    geomLock.unLock();
05160:                    sendDataChangedMessage(false);
05161:                }
05162:            }
05163:
05164:            /**
05165:             * Sets the vertex attribute associated with the vertex at the
05166:             * specified index in the specified vertex attribute number for
05167:             * this object.
05168:             *
05169:             * @param vertexAttrNum vertex attribute number in this geometry array
05170:             * @param index destination vertex index in this geometry array
05171:             * @param vertexAttr the Point4f containing the new vertex attribute
05172:             */
05173:            void setVertexAttr(int vertexAttrNum, int index, Point4f vertexAttr) {
05174:
05175:                int offset = this .stride * index
05176:                        + vertexAttrOffsets[vertexAttrNum];
05177:                boolean isLive = source != null && source.isLive();
05178:                if (isLive) {
05179:                    geomLock.getLock();
05180:                }
05181:                dirtyFlag |= VATTR_CHANGED;
05182:
05183:                this .vertexData[offset] = vertexAttr.x;
05184:                this .vertexData[offset + 1] = vertexAttr.y;
05185:                this .vertexData[offset + 2] = vertexAttr.z;
05186:                this .vertexData[offset + 3] = vertexAttr.w;
05187:
05188:                if (isLive) {
05189:                    geomLock.unLock();
05190:                    sendDataChangedMessage(false);
05191:                }
05192:            }
05193:
05194:            /**
05195:             * Sets the vertex attributes associated with the vertices
05196:             * starting at the specified index in the specified vertex
05197:             * attribute number for this object using data in
05198:             * <code>vertexAttrs</code> starting at index <code>start</code> and
05199:             * ending at index <code>start+length</code>.
05200:             *
05201:             * @param index starting destination vertex index in this geometry array
05202:             * @param vertexAttrs source array of 1*n, 2*n, 3*n, or 4*n values
05203:             * containing n new vertex attributes
05204:             * @param start starting source vertex index in <code>vertexAttrs</code>
05205:             * array.
05206:             * @param length number of vertex attributes to be copied.
05207:             */
05208:            void setVertexAttrs(int vertexAttrNum, int index,
05209:                    float[] vertexAttrs, int start, int length) {
05210:
05211:                int offset = this .stride * index
05212:                        + vertexAttrOffsets[vertexAttrNum];
05213:                int size = vertexAttrSizes[vertexAttrNum];
05214:                int i, j, k;
05215:                boolean isLive = source != null && source.isLive();
05216:                if (isLive) {
05217:                    geomLock.getLock();
05218:                }
05219:                dirtyFlag |= VATTR_CHANGED;
05220:
05221:                for (i = start * size, j = offset, k = 0; k < length; i += size, j += this .stride, k++) {
05222:                    for (int ii = 0; ii < size; ii++) {
05223:                        this .vertexData[j + ii] = vertexAttrs[i + ii];
05224:                    }
05225:                }
05226:
05227:                if (isLive) {
05228:                    geomLock.unLock();
05229:                    sendDataChangedMessage(false);
05230:                }
05231:            }
05232:
05233:            /**
05234:             * Sets the vertex attributes associated with the vertices
05235:             * starting at the specified index in the specified vertex
05236:             * attribute number for this object using data in
05237:             * <code>vertexAttrs</code> starting at index <code>start</code> and
05238:             * ending at index <code>start+length</code>.
05239:             *
05240:             * @param vertexAttrNum vertex attribute number in this geometry array
05241:             * @param index starting destination vertex index in this geometry array
05242:             * @param vertexAttrs source array of Point2f objects containing new
05243:             * vertex attributes
05244:             * @param start starting source vertex index in <code>vertexAttrs</code>
05245:             * array.
05246:             * @param length number of vertex attributes to be copied.
05247:             */
05248:            void setVertexAttrs(int vertexAttrNum, int index,
05249:                    Point2f[] vertexAttrs, int start, int length) {
05250:
05251:                int offset = this .stride * index
05252:                        + vertexAttrOffsets[vertexAttrNum];
05253:                int i, j, k;
05254:                boolean isLive = source != null && source.isLive();
05255:                if (isLive) {
05256:                    geomLock.getLock();
05257:                }
05258:                dirtyFlag |= VATTR_CHANGED;
05259:
05260:                for (i = start, j = offset, k = 0; k < length; i++, j += this .stride, k++) {
05261:                    this .vertexData[j] = vertexAttrs[i].x;
05262:                    this .vertexData[j + 1] = vertexAttrs[i].y;
05263:                }
05264:                if (isLive) {
05265:                    geomLock.unLock();
05266:                    sendDataChangedMessage(false);
05267:                }
05268:            }
05269:
05270:            /**
05271:             * Sets the vertex attributes associated with the vertices
05272:             * starting at the specified index in the specified vertex
05273:             * attribute number for this object using data in
05274:             * <code>vertexAttrs</code> starting at index <code>start</code> and
05275:             * ending at index <code>start+length</code>.
05276:             *
05277:             * @param vertexAttrNum vertex attribute number in this geometry array
05278:             * @param index starting destination vertex index in this geometry array
05279:             * @param vertexAttrs source array of Point3f objects containing new
05280:             * vertex attributes
05281:             * @param start starting source vertex index in <code>vertexAttrs</code>
05282:             * array.
05283:             * @param length number of vertex attributes to be copied.
05284:             */
05285:            void setVertexAttrs(int vertexAttrNum, int index,
05286:                    Point3f[] vertexAttrs, int start, int length) {
05287:
05288:                int offset = this .stride * index
05289:                        + vertexAttrOffsets[vertexAttrNum];
05290:                int i, j, k;
05291:                boolean isLive = source != null && source.isLive();
05292:                if (isLive) {
05293:                    geomLock.getLock();
05294:                }
05295:                dirtyFlag |= VATTR_CHANGED;
05296:
05297:                for (i = start, j = offset, k = 0; k < length; i++, j += this .stride, k++) {
05298:                    this .vertexData[j] = vertexAttrs[i].x;
05299:                    this .vertexData[j + 1] = vertexAttrs[i].y;
05300:                    this .vertexData[j + 2] = vertexAttrs[i].z;
05301:                }
05302:                if (isLive) {
05303:                    geomLock.unLock();
05304:                    sendDataChangedMessage(false);
05305:                }
05306:            }
05307:
05308:            /**
05309:             * Sets the vertex attributes associated with the vertices
05310:             * starting at the specified index in the specified vertex
05311:             * attribute number for this object using data in
05312:             * <code>vertexAttrs</code> starting at index <code>start</code> and
05313:             * ending at index <code>start+length</code>.
05314:             *
05315:             * @param vertexAttrNum vertex attribute number in this geometry array
05316:             * @param index starting destination vertex index in this geometry array
05317:             * @param vertexAttrs source array of Point4f objects containing new
05318:             * vertex attributes
05319:             * @param start starting source vertex index in <code>vertexAttrs</code>
05320:             * array.
05321:             * @param length number of vertex attributes to be copied.
05322:             */
05323:            void setVertexAttrs(int vertexAttrNum, int index,
05324:                    Point4f[] vertexAttrs, int start, int length) {
05325:
05326:                int offset = this .stride * index
05327:                        + vertexAttrOffsets[vertexAttrNum];
05328:                int i, j, k;
05329:
05330:                boolean isLive = source != null && source.isLive();
05331:                if (isLive) {
05332:                    geomLock.getLock();
05333:                }
05334:                dirtyFlag |= VATTR_CHANGED;
05335:
05336:                for (i = start, j = offset, k = 0; k < length; i++, j += this .stride, k++) {
05337:                    this .vertexData[j] = vertexAttrs[i].x;
05338:                    this .vertexData[j + 1] = vertexAttrs[i].y;
05339:                    this .vertexData[j + 2] = vertexAttrs[i].z;
05340:                    this .vertexData[j + 3] = vertexAttrs[i].w;
05341:                }
05342:                if (isLive) {
05343:                    geomLock.unLock();
05344:                    sendDataChangedMessage(false);
05345:                }
05346:            }
05347:
05348:            /**
05349:             * Gets the coordinate associated with the vertex at
05350:             * the specified index.
05351:             * @param index the vertex index
05352:             * @param coordinate an array of 3 values that will receive the new coordinate
05353:             */
05354:            void getCoordinate(int index, float coordinate[]) {
05355:                int offset = this .stride * index + coordinateOffset;
05356:
05357:                coordinate[0] = this .vertexData[offset];
05358:                coordinate[1] = this .vertexData[offset + 1];
05359:                coordinate[2] = this .vertexData[offset + 2];
05360:            }
05361:
05362:            /**
05363:             * Gets the coordinate associated with the vertex at
05364:             * the specified index.
05365:             * @param index the vertex index
05366:             * @param coordinate an array of 3 values that will receive the new coordinate
05367:             */
05368:            void getCoordinate(int index, double coordinate[]) {
05369:                int offset = this .stride * index + coordinateOffset;
05370:
05371:                coordinate[0] = (double) this .vertexData[offset];
05372:                coordinate[1] = (double) this .vertexData[offset + 1];
05373:                coordinate[2] = (double) this .vertexData[offset + 2];
05374:            }
05375:
05376:            /**
05377:             * Gets the coordinate associated with the vertex at
05378:             * the specified index.
05379:             * @param index the vertex index
05380:             * @param coordinate a vector that will receive the new coordinate
05381:             */
05382:            void getCoordinate(int index, Point3f coordinate) {
05383:                int offset = this .stride * index + coordinateOffset;
05384:
05385:                coordinate.x = this .vertexData[offset];
05386:                coordinate.y = this .vertexData[offset + 1];
05387:                coordinate.z = this .vertexData[offset + 2];
05388:            }
05389:
05390:            /**
05391:             * Gets the coordinate associated with the vertex at
05392:             * the specified index.
05393:             * @param index the vertex index
05394:             * @param coordinate a vector that will receive the new coordinate
05395:             */
05396:            void getCoordinate(int index, Point3d coordinate) {
05397:                int offset = this .stride * index + coordinateOffset;
05398:
05399:                coordinate.x = (double) this .vertexData[offset];
05400:                coordinate.y = (double) this .vertexData[offset + 1];
05401:                coordinate.z = (double) this .vertexData[offset + 2];
05402:            }
05403:
05404:            /**
05405:             * Gets the coordinates associated with the vertices starting at
05406:             * the specified index.
05407:             * @param index the vertex index
05408:             * @param coordinates an array of 3*n values that will receive new coordinates
05409:             */
05410:            void getCoordinates(int index, float coordinates[]) {
05411:                int offset = this .stride * index + coordinateOffset;
05412:                int i, j, num = coordinates.length;
05413:
05414:                for (i = 0, j = offset; i < num; i += 3, j += this .stride) {
05415:                    coordinates[i] = this .vertexData[j];
05416:                    coordinates[i + 1] = this .vertexData[j + 1];
05417:                    coordinates[i + 2] = this .vertexData[j + 2];
05418:                }
05419:            }
05420:
05421:            /**
05422:             * Gets the coordinates associated with the vertices starting at
05423:             * the specified index.
05424:             * @param index the vertex index
05425:             * @param coordinates an array of 3*n values that will receive new coordinates
05426:             */
05427:            void getCoordinates(int index, double coordinates[]) {
05428:                int offset = this .stride * index + coordinateOffset;
05429:                int i, j, num = coordinates.length;
05430:
05431:                for (i = 0, j = offset; i < num; i += 3, j += this .stride) {
05432:                    coordinates[i] = (double) this .vertexData[j];
05433:                    coordinates[i + 1] = (double) this .vertexData[j + 1];
05434:                    coordinates[i + 2] = (double) this .vertexData[j + 2];
05435:                }
05436:            }
05437:
05438:            /**
05439:             * Gets the coordinates associated with the vertices starting at
05440:             * the specified index.
05441:             * @param index the vertex index
05442:             * @param coordinates an array of vectors that will receive new coordinates
05443:             */
05444:            void getCoordinates(int index, Point3f coordinates[]) {
05445:                int offset = this .stride * index + coordinateOffset;
05446:                int i, j, num = coordinates.length;
05447:
05448:                for (i = 0, j = offset; i < num; i++, j += this .stride) {
05449:                    coordinates[i].x = this .vertexData[j];
05450:                    coordinates[i].y = this .vertexData[j + 1];
05451:                    coordinates[i].z = this .vertexData[j + 2];
05452:                }
05453:            }
05454:
05455:            /**
05456:             * Gets the coordinates associated with the vertices starting at
05457:             * the specified index.
05458:             * @param index the vertex index
05459:             * @param coordinates an array of vectors that will receive new coordinates
05460:             */
05461:            void getCoordinates(int index, Point3d coordinates[]) {
05462:                int offset = this .stride * index + coordinateOffset;
05463:                int i, j, num = coordinates.length;
05464:
05465:                for (i = 0, j = offset; i < num; i++, j += this .stride) {
05466:                    coordinates[i].x = (double) this .vertexData[j];
05467:                    coordinates[i].y = (double) this .vertexData[j + 1];
05468:                    coordinates[i].z = (double) this .vertexData[j + 2];
05469:                }
05470:            }
05471:
05472:            /**
05473:             * Gets the color associated with the vertex at
05474:             * the specified index.
05475:             * @param index the vertex index
05476:             * @param color an array of 3 or 4 values that will receive the new color
05477:             */
05478:            void getColor(int index, float color[]) {
05479:                int offset = this .stride * index + colorOffset;
05480:
05481:                color[0] = this .vertexData[offset];
05482:                color[1] = this .vertexData[offset + 1];
05483:                color[2] = this .vertexData[offset + 2];
05484:                if ((this .vertexFormat & GeometryArray.WITH_ALPHA) != 0)
05485:                    color[3] = this .vertexData[offset + 3] / lastAlpha[0];
05486:            }
05487:
05488:            /**
05489:             * Gets the color associated with the vertex at
05490:             * the specified index.
05491:             * @param index the vertex index
05492:             * @param color an array of 3 or 4 values that will receive the new color
05493:             */
05494:            void getColor(int index, byte color[]) {
05495:                int offset = this .stride * index + colorOffset;
05496:
05497:                color[0] = (byte) (this .vertexData[offset] * FloatToByteScale);
05498:                color[1] = (byte) (this .vertexData[offset + 1] * FloatToByteScale);
05499:                color[2] = (byte) (this .vertexData[offset + 2] * FloatToByteScale);
05500:                if ((this .vertexFormat & GeometryArray.WITH_ALPHA) != 0)
05501:                    color[3] = (byte) ((this .vertexData[offset + 3] / lastAlpha[0]) * FloatToByteScale);
05502:            }
05503:
05504:            /**
05505:             * Gets the color associated with the vertex at
05506:             * the specified index.
05507:             * @param index the vertex index
05508:             * @param color a vector that will receive the new color
05509:             */
05510:            void getColor(int index, Color3f color) {
05511:                int offset = this .stride * index + colorOffset;
05512:
05513:                color.x = this .vertexData[offset];
05514:                color.y = this .vertexData[offset + 1];
05515:                color.z = this .vertexData[offset + 2];
05516:            }
05517:
05518:            /**
05519:             * Gets the color associated with the vertex at
05520:             * the specified index.
05521:             * @param index the vertex index
05522:             * @param color a vector that will receive the new color
05523:             */
05524:            void getColor(int index, Color4f color) {
05525:                int offset = this .stride * index + colorOffset;
05526:
05527:                color.x = this .vertexData[offset];
05528:                color.y = this .vertexData[offset + 1];
05529:                color.z = this .vertexData[offset + 2];
05530:                color.w = this .vertexData[offset + 3] / lastAlpha[0];
05531:            }
05532:
05533:            /**
05534:             * Gets the color associated with the vertex at
05535:             * the specified index.
05536:             * @param index the vertex index
05537:             * @param color a vector that will receive the new color
05538:             */
05539:            void getColor(int index, Color3b color) {
05540:                int offset = this .stride * index + colorOffset;
05541:
05542:                color.x = (byte) (this .vertexData[offset] * FloatToByteScale);
05543:                color.y = (byte) (this .vertexData[offset + 1] * FloatToByteScale);
05544:                color.z = (byte) (this .vertexData[offset + 2] * FloatToByteScale);
05545:            }
05546:
05547:            /**
05548:             * Gets the color associated with the vertex at
05549:             * the specified index.
05550:             * @param index the vertex index
05551:             * @param color a vector that will receive the new color
05552:             */
05553:            void getColor(int index, Color4b color) {
05554:                int offset = this .stride * index + colorOffset;
05555:
05556:                color.x = (byte) (this .vertexData[offset] * FloatToByteScale);
05557:                color.y = (byte) (this .vertexData[offset + 1] * FloatToByteScale);
05558:                color.z = (byte) (this .vertexData[offset + 2] * FloatToByteScale);
05559:                color.w = (byte) ((this .vertexData[offset + 3] / lastAlpha[0]) * FloatToByteScale);
05560:            }
05561:
05562:            /**
05563:             * Gets the colors associated with the vertices starting at
05564:             * the specified index.
05565:             * @param index the vertex index
05566:             * @param colors an array of 3*n or 4*n values that will receive n new colors
05567:             */
05568:            void getColors(int index, float colors[]) {
05569:                int offset = this .stride * index + colorOffset;
05570:                int i, j, num = colors.length;
05571:                float val = 1.0f / lastAlpha[0];
05572:
05573:                if ((this .vertexFormat & GeometryArray.WITH_ALPHA) != 0) {
05574:                    for (i = 0, j = offset; i < num; i += 4, j += this .stride) {
05575:                        colors[i] = this .vertexData[j];
05576:                        colors[i + 1] = this .vertexData[j + 1];
05577:                        colors[i + 2] = this .vertexData[j + 2];
05578:                        colors[i + 3] = this .vertexData[j + 3] * val;
05579:                    }
05580:                } else {
05581:                    for (i = 0, j = offset; i < num; i += 3, j += this .stride) {
05582:                        colors[i] = this .vertexData[j];
05583:                        colors[i + 1] = this .vertexData[j + 1];
05584:                        colors[i + 2] = this .vertexData[j + 2];
05585:                    }
05586:                }
05587:            }
05588:
05589:            /**
05590:             * Gets the colors associated with the vertices starting at
05591:             * the specified index.
05592:             * @param index the vertex index
05593:             * @param colors an array of 3*n or 4*n values that will receive new colors
05594:             */
05595:            void getColors(int index, byte colors[]) {
05596:                int offset = this .stride * index + colorOffset;
05597:                int i, j, num = colors.length;
05598:                float val = 1.0f / lastAlpha[0];
05599:
05600:                if ((this .vertexFormat & GeometryArray.WITH_ALPHA) != 0) {
05601:                    for (i = 0, j = offset; i < num; i += 4, j += this .stride) {
05602:                        colors[i] = (byte) (this .vertexData[j] * FloatToByteScale);
05603:                        colors[i + 1] = (byte) (this .vertexData[j + 1] * FloatToByteScale);
05604:                        colors[i + 2] = (byte) (this .vertexData[j + 2] * FloatToByteScale);
05605:                        colors[i + 3] = (byte) ((this .vertexData[j + 3] * val) * FloatToByteScale);
05606:                    }
05607:                } else {
05608:                    for (i = 0, j = offset; i < num; i += 3, j += this .stride) {
05609:                        colors[i] = (byte) (this .vertexData[j] * FloatToByteScale);
05610:                        colors[i + 1] = (byte) (this .vertexData[j + 1] * FloatToByteScale);
05611:                        colors[i + 2] = (byte) (this .vertexData[j + 2] * FloatToByteScale);
05612:                    }
05613:                }
05614:            }
05615:
05616:            /**
05617:             * Gets the colors associated with the vertices starting at
05618:             * the specified index.
05619:             * @param index the vertex index
05620:             * @param colors an array of vectors that will receive new colors
05621:             */
05622:            void getColors(int index, Color3f colors[]) {
05623:                int offset = this .stride * index + colorOffset;
05624:                int i, j, num = colors.length;
05625:
05626:                for (i = 0, j = offset; i < num; i++, j += this .stride) {
05627:                    colors[i].x = this .vertexData[j];
05628:                    colors[i].y = this .vertexData[j + 1];
05629:                    colors[i].z = this .vertexData[j + 2];
05630:                }
05631:            }
05632:
05633:            /**
05634:             * Gets the colors associated with the vertices starting at
05635:             * the specified index.
05636:             * @param index the vertex index
05637:             * @param colors an array of vectors that will receive new colors
05638:             */
05639:            void getColors(int index, Color4f colors[]) {
05640:                int offset = this .stride * index + colorOffset;
05641:                int i, j, num = colors.length;
05642:                float val = 1.0f / lastAlpha[0];
05643:
05644:                for (i = 0, j = offset; i < num; i++, j += this .stride) {
05645:                    colors[i].x = this .vertexData[j];
05646:                    colors[i].y = this .vertexData[j + 1];
05647:                    colors[i].z = this .vertexData[j + 2];
05648:                    colors[i].w = this .vertexData[j + 3] * val;
05649:                }
05650:            }
05651:
05652:            /**
05653:             * Gets the colors associated with the vertices starting at
05654:             * the specified index.
05655:             * @param index the vertex index
05656:             * @param colors an array of vectors that will receive new colors
05657:             */
05658:            void getColors(int index, Color3b colors[]) {
05659:                int offset = this .stride * index + colorOffset;
05660:                int i, j, num = colors.length;
05661:
05662:                for (i = 0, j = offset; i < num; i++, j += this .stride) {
05663:                    colors[i].x = (byte) (this .vertexData[j] * FloatToByteScale);
05664:                    colors[i].y = (byte) (this .vertexData[j + 1] * FloatToByteScale);
05665:                    colors[i].z = (byte) (this .vertexData[j + 2] * FloatToByteScale);
05666:                }
05667:            }
05668:
05669:            /**
05670:             * Gets the colors associated with the vertices starting at
05671:             * the specified index.
05672:             * @param index the vertex index
05673:             * @param colors an array of vectors that will receive new colors
05674:             */
05675:            void getColors(int index, Color4b colors[]) {
05676:                int offset = this .stride * index + colorOffset;
05677:                int i, j, num = colors.length;
05678:                float val = 1.0f / lastAlpha[0];
05679:
05680:                for (i = 0, j = offset; i < num; i++, j += this .stride) {
05681:                    colors[i].x = (byte) (this .vertexData[j] * FloatToByteScale);
05682:                    colors[i].y = (byte) (this .vertexData[j + 1] * FloatToByteScale);
05683:                    colors[i].z = (byte) (this .vertexData[j + 2] * FloatToByteScale);
05684:                    colors[i].w = (byte) (this .vertexData[j + 3] * val * FloatToByteScale);
05685:                }
05686:            }
05687:
05688:            /**
05689:             * Gets the normal associated with the vertex at
05690:             * the specified index.
05691:             * @param index the vertex index
05692:             * @param normal array that will receive the new normal
05693:             */
05694:            void getNormal(int index, float normal[]) {
05695:                int offset = this .stride * index + normalOffset;
05696:
05697:                normal[0] = this .vertexData[offset];
05698:                normal[1] = this .vertexData[offset + 1];
05699:                normal[2] = this .vertexData[offset + 2];
05700:            }
05701:
05702:            /**
05703:             * Gets the normal associated with the vertex at
05704:             * the specified index.
05705:             * @param index the vertex index
05706:             * @param normal the vector that will receive the new normal
05707:             */
05708:            void getNormal(int index, Vector3f normal) {
05709:                int offset = this .stride * index + normalOffset;
05710:
05711:                normal.x = this .vertexData[offset];
05712:                normal.y = this .vertexData[offset + 1];
05713:                normal.z = this .vertexData[offset + 2];
05714:            }
05715:
05716:            /**
05717:             * Gets the normals associated with the vertices starting at
05718:             * the specified index.
05719:             * @param index the vertex index
05720:             * @param normals array that will receive the new normals
05721:             */
05722:            void getNormals(int index, float normals[]) {
05723:                int offset = this .stride * index + normalOffset;
05724:                int i, j, num = normals.length;
05725:
05726:                for (i = 0, j = offset; i < num; i += 3, j += this .stride) {
05727:                    normals[i] = this .vertexData[j];
05728:                    normals[i + 1] = this .vertexData[j + 1];
05729:                    normals[i + 2] = this .vertexData[j + 2];
05730:                }
05731:            }
05732:
05733:            /**
05734:             * Gets the normals associated with the vertices starting at
05735:             * the specified index.
05736:             * @param index the vertex index
05737:             * @param normals the vector that will receive the new normals
05738:             */
05739:            void getNormals(int index, Vector3f normals[]) {
05740:                int offset = this .stride * index + normalOffset;
05741:                int i, j, num = normals.length;
05742:
05743:                for (i = 0, j = offset; i < num; i++, j += this .stride) {
05744:                    normals[i].x = this .vertexData[j];
05745:                    normals[i].y = this .vertexData[j + 1];
05746:                    normals[i].z = this .vertexData[j + 2];
05747:                }
05748:            }
05749:
05750:            /**
05751:             * Gets the texture co-ordinate associated with the vertex at
05752:             * the specified index.
05753:             * @param index the vertex index
05754:             * @param texCoord array that will receive the new texture co-ordinate
05755:             */
05756:            void getTextureCoordinate(int texCoordSet, int index,
05757:                    float texCoord[]) {
05758:                int offset = this .stride * index + textureOffset + texCoordSet
05759:                        * texCoordStride;
05760:
05761:                texCoord[0] = this .vertexData[offset];
05762:                texCoord[1] = this .vertexData[offset + 1];
05763:                if ((this .vertexFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0) {
05764:                    texCoord[2] = this .vertexData[offset + 2];
05765:
05766:                } else if ((this .vertexFormat & GeometryArray.TEXTURE_COORDINATE_4) != 0) {
05767:                    texCoord[2] = this .vertexData[offset + 2];
05768:                    texCoord[3] = this .vertexData[offset + 3];
05769:                }
05770:            }
05771:
05772:            /**
05773:             * Gets the texture co-ordinate associated with the vertex at
05774:             * the specified index.
05775:             * @param index the vertex index
05776:             * @param texCoord the vector that will receive the new texture co-ordinates
05777:             */
05778:            void getTextureCoordinate(int texCoordSet, int index,
05779:                    TexCoord2f texCoord) {
05780:                int offset = this .stride * index + textureOffset + texCoordSet
05781:                        * texCoordStride;
05782:
05783:                texCoord.x = this .vertexData[offset];
05784:                texCoord.y = this .vertexData[offset + 1];
05785:            }
05786:
05787:            /**
05788:             * Gets the texture co-ordinate associated with the vertex at
05789:             * the specified index.
05790:             * @param index the vertex index
05791:             * @param texCoord the vector that will receive the new texture co-ordinates
05792:             */
05793:            void getTextureCoordinate(int texCoordSet, int index,
05794:                    TexCoord3f texCoord) {
05795:                int offset = this .stride * index + textureOffset + texCoordSet
05796:                        * texCoordStride;
05797:
05798:                texCoord.x = this .vertexData[offset];
05799:                texCoord.y = this .vertexData[offset + 1];
05800:                texCoord.z = this .vertexData[offset + 2];
05801:            }
05802:
05803:            /**
05804:             * Gets the texture co-ordinate associated with the vertex at
05805:             * the specified index.
05806:             * @param index the vertex index
05807:             * @param texCoord the vector that will receive the new texture co-ordinates
05808:             */
05809:            void getTextureCoordinate(int texCoordSet, int index,
05810:                    TexCoord4f texCoord) {
05811:                int offset = this .stride * index + textureOffset + texCoordSet
05812:                        * texCoordStride;
05813:
05814:                texCoord.x = this .vertexData[offset];
05815:                texCoord.y = this .vertexData[offset + 1];
05816:                texCoord.z = this .vertexData[offset + 2];
05817:                texCoord.w = this .vertexData[offset + 3];
05818:            }
05819:
05820:            /**
05821:             * Gets the texture co-ordinates associated with the vertices starting at
05822:             * the specified index.
05823:             * @param index the vertex index
05824:             * @param texCoords array that will receive the new texture co-ordinates
05825:             */
05826:            void getTextureCoordinates(int texCoordSet, int index,
05827:                    float texCoords[]) {
05828:                int offset = this .stride * index + textureOffset + texCoordSet
05829:                        * texCoordStride;
05830:                int i, j, num = texCoords.length;
05831:
05832:                if ((this .vertexFormat & GeometryArray.TEXTURE_COORDINATE_4) != 0) {
05833:                    for (i = 0, j = offset; i < num; i += 4, j += this .stride) {
05834:                        texCoords[i] = this .vertexData[j];
05835:                        texCoords[i + 1] = this .vertexData[j + 1];
05836:                        texCoords[i + 2] = this .vertexData[j + 2];
05837:                        texCoords[i + 3] = this .vertexData[j + 3];
05838:                    }
05839:                } else if ((this .vertexFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0) {
05840:                    for (i = 0, j = offset; i < num; i += 3, j += this .stride) {
05841:                        texCoords[i] = this .vertexData[j];
05842:                        texCoords[i + 1] = this .vertexData[j + 1];
05843:                        texCoords[i + 2] = this .vertexData[j + 2];
05844:                    }
05845:                } else {
05846:                    for (i = 0, j = offset; i < num; i += 2, j += this .stride) {
05847:                        texCoords[i] = this .vertexData[j];
05848:                        texCoords[i + 1] = this .vertexData[j + 1];
05849:                    }
05850:                }
05851:            }
05852:
05853:            /**
05854:             * Gets the texture co-ordinates associated with the vertices starting at
05855:             * the specified index.
05856:             * @param index the vertex index
05857:             * @param texCoords the vector that will receive the new texture co-ordinates
05858:             */
05859:            void getTextureCoordinates(int texCoordSet, int index,
05860:                    TexCoord2f texCoords[]) {
05861:                int offset = this .stride * index + textureOffset + texCoordSet
05862:                        * texCoordStride;
05863:                int i, j, num = texCoords.length;
05864:
05865:                for (i = 0, j = offset; i < num; i++, j += this .stride) {
05866:                    texCoords[i].x = this .vertexData[j];
05867:                    texCoords[i].y = this .vertexData[j + 1];
05868:                }
05869:            }
05870:
05871:            /**
05872:             * Gets the texture co-ordinates associated with the vertices starting at
05873:             * the specified index.
05874:             * @param index the vertex index
05875:             * @param texCoords the vector that will receive the new texture co-ordinates
05876:             */
05877:            void getTextureCoordinates(int texCoordSet, int index,
05878:                    TexCoord3f texCoords[]) {
05879:                int offset = this .stride * index + textureOffset + texCoordSet
05880:                        * texCoordStride;
05881:                int i, j, num = texCoords.length;
05882:
05883:                for (i = 0, j = offset; i < num; i++, j += this .stride) {
05884:                    texCoords[i].x = this .vertexData[j];
05885:                    texCoords[i].y = this .vertexData[j + 1];
05886:                    texCoords[i].z = this .vertexData[j + 2];
05887:                }
05888:            }
05889:
05890:            /**
05891:             * Gets the texture co-ordinates associated with the vertices starting at
05892:             * the specified index.
05893:             * @param index the vertex index
05894:             * @param texCoords the vector that will receive the new texture co-ordinates
05895:             */
05896:            void getTextureCoordinates(int texCoordSet, int index,
05897:                    TexCoord4f texCoords[]) {
05898:                int offset = this .stride * index + textureOffset + texCoordSet
05899:                        * texCoordStride;
05900:                int i, j, num = texCoords.length;
05901:
05902:                for (i = 0, j = offset; i < num; i++, j += this .stride) {
05903:                    texCoords[i].x = this .vertexData[j];
05904:                    texCoords[i].y = this .vertexData[j + 1];
05905:                    texCoords[i].z = this .vertexData[j + 2];
05906:                    texCoords[i].w = this .vertexData[j + 3];
05907:                }
05908:            }
05909:
05910:            void getTextureCoordinates(int texCoordSet, int index,
05911:                    Point2f texCoords[]) {
05912:                int offset = this .stride * index + textureOffset + texCoordSet
05913:                        * texCoordStride;
05914:                int i, j, num = texCoords.length;
05915:
05916:                for (i = 0, j = offset; i < num; i++, j += this .stride) {
05917:                    texCoords[i].x = this .vertexData[j];
05918:                    texCoords[i].y = this .vertexData[j + 1];
05919:                }
05920:            }
05921:
05922:            void getTextureCoordinates(int texCoordSet, int index,
05923:                    Point3f texCoords[]) {
05924:                int offset = this .stride * index + textureOffset + texCoordSet
05925:                        * texCoordStride;
05926:                int i, j, num = texCoords.length;
05927:
05928:                for (i = 0, j = offset; i < num; i++, j += this .stride) {
05929:                    texCoords[i].x = this .vertexData[j];
05930:                    texCoords[i].y = this .vertexData[j + 1];
05931:                    texCoords[i].z = this .vertexData[j + 2];
05932:                }
05933:            }
05934:
05935:            /**
05936:             * Gets the vertex attribute associated with the vertex at
05937:             * the specified index in the specified vertex attribute number
05938:             * for this object.
05939:             */
05940:            public void getVertexAttr(int vertexAttrNum, int index,
05941:                    float[] vertexAttr) {
05942:
05943:                int offset = this .stride * index
05944:                        + vertexAttrOffsets[vertexAttrNum];
05945:                int size = vertexAttrSizes[vertexAttrNum];
05946:
05947:                for (int i = 0; i < size; i++) {
05948:                    vertexAttr[i] = this .vertexData[offset + i];
05949:
05950:                }
05951:
05952:            }
05953:
05954:            /**
05955:             * Gets the vertex attribute associated with the vertex at
05956:             * the specified index in the specified vertex attribute number
05957:             * for this object.
05958:             */
05959:            public void getVertexAttr(int vertexAttrNum, int index,
05960:                    Point2f vertexAttr) {
05961:
05962:                int offset = this .stride * index
05963:                        + vertexAttrOffsets[vertexAttrNum];
05964:
05965:                vertexAttr.x = this .vertexData[offset];
05966:                vertexAttr.y = this .vertexData[offset + 1];
05967:
05968:            }
05969:
05970:            /**
05971:             * Gets the vertex attribute associated with the vertex at
05972:             * the specified index in the specified vertex attribute number
05973:             * for this object.
05974:             */
05975:            public void getVertexAttr(int vertexAttrNum, int index,
05976:                    Point3f vertexAttr) {
05977:
05978:                int offset = this .stride * index
05979:                        + vertexAttrOffsets[vertexAttrNum];
05980:
05981:                vertexAttr.x = this .vertexData[offset];
05982:                vertexAttr.y = this .vertexData[offset + 1];
05983:                vertexAttr.z = this .vertexData[offset + 2];
05984:
05985:            }
05986:
05987:            /**
05988:             * Gets the vertex attribute associated with the vertex at
05989:             * the specified index in the specified vertex attribute number
05990:             * for this object.
05991:             */
05992:            public void getVertexAttr(int vertexAttrNum, int index,
05993:                    Point4f vertexAttr) {
05994:
05995:                int offset = this .stride * index
05996:                        + vertexAttrOffsets[vertexAttrNum];
05997:
05998:                vertexAttr.x = this .vertexData[offset];
05999:                vertexAttr.y = this .vertexData[offset + 1];
06000:                vertexAttr.z = this .vertexData[offset + 2];
06001:                vertexAttr.w = this .vertexData[offset + 3];
06002:
06003:            }
06004:
06005:            /**
06006:             * Gets the vertex attributes associated with the vertices starting at
06007:             * the specified index in the specified vertex attribute number
06008:             * for this object.
06009:             */
06010:            public void getVertexAttrs(int vertexAttrNum, int index,
06011:                    float[] vertexAttrs) {
06012:
06013:                int offset = this .stride * index
06014:                        + vertexAttrOffsets[vertexAttrNum];
06015:                int size = vertexAttrSizes[vertexAttrNum];
06016:                int i, j, k;
06017:
06018:                for (i = 0, j = offset; ((i < vertexAttrs.length) && (j < this .vertexData.length)); i += size, j += this .stride) {
06019:                    for (k = 0; k < size; k++) {
06020:                        vertexAttrs[i + k] = this .vertexData[j + k];
06021:                    }
06022:                }
06023:
06024:            }
06025:
06026:            /**
06027:             * Gets the vertex attributes associated with the vertices starting at
06028:             * the specified index in the specified vertex attribute number
06029:             * for this object.
06030:             */
06031:            public void getVertexAttrs(int vertexAttrNum, int index,
06032:                    Point2f[] vertexAttrs) {
06033:
06034:                int offset = this .stride * index
06035:                        + vertexAttrOffsets[vertexAttrNum];
06036:                int i, j;
06037:
06038:                for (i = 0, j = offset; ((i < vertexAttrs.length) && (j < this .vertexData.length)); i++, j += this .stride) {
06039:                    vertexAttrs[i].x = this .vertexData[j];
06040:                    vertexAttrs[i].y = this .vertexData[j + 1];
06041:                }
06042:
06043:            }
06044:
06045:            /**
06046:             * Gets the vertex attributes associated with the vertices starting at
06047:             * the specified index in the specified vertex attribute number
06048:             * for this object.
06049:             */
06050:            public void getVertexAttrs(int vertexAttrNum, int index,
06051:                    Point3f[] vertexAttrs) {
06052:
06053:                int offset = this .stride * index
06054:                        + vertexAttrOffsets[vertexAttrNum];
06055:                int i, j;
06056:
06057:                for (i = 0, j = offset; ((i < vertexAttrs.length) && (j < this .vertexData.length)); i++, j += this .stride) {
06058:                    vertexAttrs[i].x = this .vertexData[j];
06059:                    vertexAttrs[i].y = this .vertexData[j + 1];
06060:                    vertexAttrs[i].z = this .vertexData[j + 2];
06061:                }
06062:
06063:            }
06064:
06065:            /**
06066:             * Gets the vertex attributes associated with the vertices starting at
06067:             * the specified index in the specified vertex attribute number
06068:             * for this object.
06069:             */
06070:            public void getVertexAttrs(int vertexAttrNum, int index,
06071:                    Point4f[] vertexAttrs) {
06072:
06073:                int offset = this .stride * index
06074:                        + vertexAttrOffsets[vertexAttrNum];
06075:                int i, j;
06076:
06077:                for (i = 0, j = offset; ((i < vertexAttrs.length) && (j < this .vertexData.length)); i++, j += this .stride) {
06078:                    vertexAttrs[i].x = this .vertexData[j];
06079:                    vertexAttrs[i].y = this .vertexData[j + 1];
06080:                    vertexAttrs[i].z = this .vertexData[j + 2];
06081:                    vertexAttrs[i].w = this .vertexData[j + 3];
06082:                }
06083:
06084:            }
06085:
06086:            /**
06087:             * Updates geometry array data.
06088:             */
06089:            void updateData(GeometryUpdater updater) {
06090:                boolean nullGeo = false;
06091:
06092:                // Add yourself to obtain the geometry lock
06093:                // and Thread.currentThread().sleep until you get the lock
06094:                geomLock.getLock();
06095:
06096:                inUpdater = true;
06097:                updater.updateData((Geometry) source);
06098:                inUpdater = false;
06099:                if ((vertexFormat & GeometryArray.BY_REFERENCE) != 0) {
06100:                    if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) != 0) {
06101:                        // XXXX: handle the nio buffer
06102:                        if (!(this  instanceof  IndexedGeometryArrayRetained)
06103:                                || (vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) != 0) {
06104:                            if (((vertexFormat & GeometryArray.INTERLEAVED) != 0)) {
06105:                                setupMirrorInterleavedColorPointer(false);
06106:                                nullGeo = (interleavedFloatBufferImpl == null);
06107:                            } else {
06108:                                setupMirrorColorPointer(
06109:                                        (vertexType & COLOR_DEFINED), false);
06110:                                nullGeo = ((vertexType & GeometryArrayRetained.VERTEX_DEFINED) == 0);
06111:                            }
06112:                        }
06113:                    } else {
06114:                        if (!(this  instanceof  IndexedGeometryArrayRetained)
06115:                                || (vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) != 0) {
06116:                            if (((vertexFormat & GeometryArray.INTERLEAVED) != 0)) {
06117:                                setupMirrorInterleavedColorPointer(false);
06118:                                nullGeo = (interLeavedVertexData == null);
06119:                            } else {
06120:                                setupMirrorVertexPointer(vertexType
06121:                                        & VERTEX_DEFINED);
06122:                                setupMirrorColorPointer(
06123:                                        (vertexType & COLOR_DEFINED), false);
06124:                                setupMirrorNormalPointer(vertexType
06125:                                        & NORMAL_DEFINED);
06126:                                setupMirrorTexCoordPointer(texCoordType);
06127:                                setupMirrorVertexAttrPointer(vertexAttrType);
06128:                                nullGeo = ((vertexType & GeometryArrayRetained.VERTEX_DEFINED) == 0);
06129:                            }
06130:                        }
06131:                    }
06132:
06133:                    //NVaidya
06134:                    // User may or may not have changed indices in updater callback.
06135:                    // We need to presume that the user may indeed have and, thus, will
06136:                    // need to recompute maxCoordIndex unconditionally while
06137:                    // geomLock is still locked.
06138:                    if ((vertexFormat & GeometryArray.BY_REFERENCE_INDICES) != 0) {
06139:                        assert (this  instanceof  IndexedGeometryArrayRetained);
06140:
06141:                        if (((IndexedGeometryArrayRetained) this )
06142:                                .getCoordIndicesRef() == null) {
06143:                            nullGeo = true;
06144:                        }
06145:                        ((IndexedGeometryArrayRetained) this )
06146:                                .doPostUpdaterUpdate();
06147:                    }
06148:                }
06149:
06150:                dirtyFlag |= VERTEX_CHANGED;
06151:                colorChanged = 0xffff;
06152:                geomLock.unLock();
06153:
06154:                if (source != null && source.isLive()) {
06155:                    processCoordsChanged(nullGeo);
06156:                    sendDataChangedMessage(true);
06157:                }
06158:            }
06159:
06160:            boolean intersectBoundingBox(Point3d coordinates[],
06161:                    BoundingBox box, double dist[], Point3d iPnt) {
06162:                int i, j;
06163:                int out[] = new int[6];
06164:
06165:                //Do trivial vertex test.
06166:                for (i = 0; i < 6; i++)
06167:                    out[i] = 0;
06168:                for (i = 0; i < coordinates.length; i++) {
06169:                    if ((coordinates[i].x >= box.lower.x)
06170:                            && (coordinates[i].x <= box.upper.x)
06171:                            && (coordinates[i].y >= box.lower.y)
06172:                            && (coordinates[i].y <= box.upper.y)
06173:                            && (coordinates[i].z >= box.lower.z)
06174:                            && (coordinates[i].z <= box.upper.z))
06175:                        // We're done! It's inside the boundingbox.
06176:                        return true;
06177:                    else {
06178:                        if (coordinates[i].x < box.lower.x)
06179:                            out[0]++; // left
06180:                        if (coordinates[i].y < box.lower.y)
06181:                            out[1]++; // bottom
06182:                        if (coordinates[i].z < box.lower.z)
06183:                            out[2]++; // back
06184:                        if (coordinates[i].x > box.upper.x)
06185:                            out[3]++; // right
06186:                        if (coordinates[i].y > box.upper.y)
06187:                            out[4]++; // top
06188:                        if (coordinates[i].z > box.upper.z)
06189:                            out[5]++; // front
06190:                    }
06191:
06192:                }
06193:
06194:                if ((out[0] == coordinates.length)
06195:                        || (out[1] == coordinates.length)
06196:                        || (out[2] == coordinates.length)
06197:                        || (out[3] == coordinates.length)
06198:                        || (out[4] == coordinates.length)
06199:                        || (out[5] == coordinates.length))
06200:                    // we're done. primitive is outside of boundingbox.
06201:                    return false;
06202:
06203:                // Setup bounding planes.
06204:                Point3d pCoor[] = new Point3d[4];
06205:                for (i = 0; i < 4; i++)
06206:                    pCoor[i] = new Point3d();
06207:
06208:                // left plane.
06209:                pCoor[0].set(box.lower.x, box.lower.y, box.lower.z);
06210:                pCoor[1].set(box.lower.x, box.lower.y, box.upper.z);
06211:                pCoor[2].set(box.lower.x, box.upper.y, box.upper.z);
06212:                pCoor[3].set(box.lower.x, box.upper.y, box.lower.z);
06213:
06214:                if (intersectPolygon(pCoor, coordinates)) {
06215:                    if (dist != null) {
06216:                        computeMinDistance(pCoor, box.getCenter(), null, dist,
06217:                                iPnt);
06218:                    }
06219:                    return true;
06220:                }
06221:
06222:                // right plane.
06223:                pCoor[0].set(box.upper.x, box.lower.y, box.lower.z);
06224:                pCoor[1].set(box.upper.x, box.upper.y, box.lower.z);
06225:                pCoor[2].set(box.upper.x, box.upper.y, box.upper.z);
06226:                pCoor[3].set(box.upper.x, box.lower.y, box.upper.z);
06227:                if (intersectPolygon(pCoor, coordinates)) {
06228:                    if (dist != null) {
06229:                        computeMinDistance(pCoor, box.getCenter(), null, dist,
06230:                                iPnt);
06231:                    }
06232:                    return true;
06233:                }
06234:
06235:                // bottom plane.
06236:                pCoor[0].set(box.upper.x, box.lower.y, box.upper.z);
06237:                pCoor[1].set(box.lower.x, box.lower.y, box.upper.z);
06238:                pCoor[2].set(box.lower.x, box.lower.y, box.lower.z);
06239:                pCoor[3].set(box.upper.x, box.lower.y, box.lower.z);
06240:                if (intersectPolygon(pCoor, coordinates)) {
06241:                    if (dist != null) {
06242:                        computeMinDistance(pCoor, box.getCenter(), null, dist,
06243:                                iPnt);
06244:                    }
06245:                    return true;
06246:                }
06247:                // top plane.
06248:                pCoor[0].set(box.upper.x, box.upper.y, box.upper.z);
06249:                pCoor[1].set(box.upper.x, box.upper.y, box.lower.z);
06250:                pCoor[2].set(box.lower.x, box.upper.y, box.lower.z);
06251:                pCoor[3].set(box.lower.x, box.upper.y, box.upper.z);
06252:                if (intersectPolygon(pCoor, coordinates)) {
06253:                    if (dist != null) {
06254:                        computeMinDistance(pCoor, box.getCenter(), null, dist,
06255:                                iPnt);
06256:                    }
06257:                    return true;
06258:                }
06259:
06260:                // front plane.
06261:                pCoor[0].set(box.upper.x, box.upper.y, box.upper.z);
06262:                pCoor[1].set(box.lower.x, box.upper.y, box.upper.z);
06263:                pCoor[2].set(box.lower.x, box.lower.y, box.upper.z);
06264:                pCoor[3].set(box.upper.x, box.lower.y, box.upper.z);
06265:                if (intersectPolygon(pCoor, coordinates)) {
06266:                    if (dist != null) {
06267:                        computeMinDistance(pCoor, box.getCenter(), null, dist,
06268:                                iPnt);
06269:                    }
06270:                    return true;
06271:                }
06272:
06273:                // back plane.
06274:                pCoor[0].set(box.upper.x, box.upper.y, box.lower.z);
06275:                pCoor[1].set(box.upper.x, box.lower.y, box.lower.z);
06276:                pCoor[2].set(box.lower.x, box.lower.y, box.lower.z);
06277:                pCoor[3].set(box.lower.x, box.upper.y, box.lower.z);
06278:                if (intersectPolygon(pCoor, coordinates)) {
06279:                    if (dist != null) {
06280:                        computeMinDistance(pCoor, box.getCenter(), null, dist,
06281:                                iPnt);
06282:                    }
06283:                    return true;
06284:                }
06285:                return false;
06286:            }
06287:
06288:            boolean intersectBoundingSphere(Point3d coordinates[],
06289:                    BoundingSphere sphere, double dist[], Point3d iPnt) {
06290:                int i, j;
06291:                Vector3d tempV3D = new Vector3d();
06292:                boolean esFlag;
06293:
06294:                //Do trivial vertex test.
06295:
06296:                for (i = 0; i < coordinates.length; i++) {
06297:                    tempV3D.x = coordinates[i].x - sphere.center.x;
06298:                    tempV3D.y = coordinates[i].y - sphere.center.y;
06299:                    tempV3D.z = coordinates[i].z - sphere.center.z;
06300:
06301:                    if (tempV3D.length() <= sphere.radius) {
06302:                        // We're done! It's inside the boundingSphere.
06303:                        if (dist != null) {
06304:                            computeMinDistance(coordinates, sphere.getCenter(),
06305:                                    null, dist, iPnt);
06306:                        }
06307:
06308:                        return true;
06309:                    }
06310:                }
06311:
06312:                for (i = 0; i < coordinates.length; i++) {
06313:                    if (i < (coordinates.length - 1))
06314:                        esFlag = edgeIntersectSphere(sphere, coordinates[i],
06315:                                coordinates[i + 1]);
06316:                    else
06317:                        esFlag = edgeIntersectSphere(sphere, coordinates[i],
06318:                                coordinates[0]);
06319:                    if (esFlag == true) {
06320:                        if (dist != null) {
06321:                            computeMinDistance(coordinates, sphere.getCenter(),
06322:                                    null, dist, iPnt);
06323:                        }
06324:
06325:                        return true;
06326:                    }
06327:                }
06328:
06329:                if (coordinates.length < 3) {
06330:                    return false; // We're done with line.
06331:                }
06332:
06333:                // Find rho.
06334:                // Compute plane normal.
06335:                Vector3d vec0 = new Vector3d(); // Edge vector from point 0 to point 1;
06336:                Vector3d vec1 = new Vector3d(); // Edge vector from point 0 to point 2 or 3;
06337:                Vector3d pNrm = new Vector3d();
06338:                Vector3d pa = new Vector3d();
06339:                Point3d q = new Point3d();
06340:                double nLenSq, pqLen, pNrmDotPa, tq;
06341:
06342:                // compute plane normal for coordinates.
06343:                for (i = 0; i < coordinates.length - 1;) {
06344:                    vec0.x = coordinates[i + 1].x - coordinates[i].x;
06345:                    vec0.y = coordinates[i + 1].y - coordinates[i].y;
06346:                    vec0.z = coordinates[i + 1].z - coordinates[i++].z;
06347:                    if (vec0.length() > 0.0)
06348:                        break;
06349:                }
06350:
06351:                for (j = i; j < coordinates.length - 1; j++) {
06352:                    vec1.x = coordinates[j + 1].x - coordinates[j].x;
06353:                    vec1.y = coordinates[j + 1].y - coordinates[j].y;
06354:                    vec1.z = coordinates[j + 1].z - coordinates[j].z;
06355:                    if (vec1.length() > 0.0)
06356:                        break;
06357:                }
06358:
06359:                if (j == (coordinates.length - 1)) {
06360:                    // System.err.println("(1) Degenerate polygon.");
06361:                    return false; // Degenerate polygon.
06362:                }
06363:
06364:                /*
06365:                  for(i=0; i<coordinates.length; i++)
06366:                  System.err.println("coordinates P" + i + " " + coordinates[i]);
06367:                  for(i=0; i<coord2.length; i++)
06368:                  System.err.println("coord2 P" + i + " " + coord2[i]);
06369:                 */
06370:
06371:                pNrm.cross(vec0, vec1);
06372:
06373:                nLenSq = pNrm.lengthSquared();
06374:                if (nLenSq == 0.0) {
06375:                    // System.err.println("(2) Degenerate polygon.");
06376:                    return false; // Degenerate polygon.
06377:                }
06378:
06379:                pa.x = coordinates[0].x - sphere.center.x;
06380:                pa.y = coordinates[0].y - sphere.center.y;
06381:                pa.z = coordinates[0].z - sphere.center.z;
06382:
06383:                pNrmDotPa = pNrm.dot(pa);
06384:
06385:                pqLen = Math.sqrt(pNrmDotPa * pNrmDotPa / nLenSq);
06386:
06387:                if (pqLen > sphere.radius) {
06388:                    return false;
06389:                }
06390:
06391:                tq = pNrmDotPa / nLenSq;
06392:
06393:                q.x = sphere.center.x + tq * pNrm.x;
06394:                q.y = sphere.center.y + tq * pNrm.y;
06395:                q.z = sphere.center.z + tq * pNrm.z;
06396:
06397:                // PolyPnt2D Test.
06398:                if (pointIntersectPolygon2D(pNrm, coordinates, q)) {
06399:                    if (dist != null) {
06400:                        computeMinDistance(coordinates, sphere.getCenter(),
06401:                                pNrm, dist, iPnt);
06402:                    }
06403:                    return true;
06404:                }
06405:                return false;
06406:
06407:            }
06408:
06409:            boolean intersectBoundingPolytope(Point3d coordinates[],
06410:                    BoundingPolytope polytope, double dist[], Point3d iPnt) {
06411:                boolean debug = false;
06412:
06413:                Point4d tP4d = new Point4d();
06414:
06415:                // this is a multiplier to the halfplane distance coefficients
06416:                double distanceSign = -1.0;
06417:
06418:                if (coordinates.length == 2) {
06419:                    // we'll handle line separately.
06420:                    if (polytope
06421:                            .intersect(coordinates[0], coordinates[1], tP4d)) {
06422:                        if (dist != null) {
06423:                            iPnt.x = tP4d.x;
06424:                            iPnt.y = tP4d.y;
06425:                            iPnt.z = tP4d.z;
06426:                            Point3d pc = polytope.getCenter();
06427:                            double x = iPnt.x - pc.x;
06428:                            double y = iPnt.y - pc.y;
06429:                            double z = iPnt.z - pc.z;
06430:                            dist[0] = Math.sqrt(x * x + y * y + z * z);
06431:                        }
06432:                        return true;
06433:                    }
06434:                    return false;
06435:                }
06436:
06437:                // It is a triangle or a quad.
06438:
06439:                // first test to see if any of the coordinates are all inside of the
06440:                // intersection polytope's half planes
06441:                // essentially do a matrix multiply of the constraintMatrix K*3 with
06442:                // the input coordinates 3*1 = K*1 vector
06443:
06444:                if (debug) {
06445:                    System.err.println("The value of the input vertices are: ");
06446:                    for (int i = 0; i < coordinates.length; i++) {
06447:                        System.err.println("The " + i + " th vertex is: "
06448:                                + coordinates[i]);
06449:                    }
06450:
06451:                    System.err
06452:                            .println("The value of the input bounding Polytope's planes =");
06453:                    for (int i = 0; i < polytope.planes.length; i++) {
06454:                        System.err.println("The " + i + " th plane is: "
06455:                                + polytope.planes[i]);
06456:                    }
06457:
06458:                }
06459:
06460:                // the direction for the intersection cost function
06461:                double centers[] = new double[4];
06462:                centers[0] = 0.8;
06463:                centers[1] = 0.9;
06464:                centers[2] = 1.1;
06465:                centers[3] = 1.2;
06466:
06467:                boolean intersection = true;
06468:                boolean PreTest = false;
06469:
06470:                if (PreTest) {
06471:                    // for each coordinate, test it with each half plane
06472:                    for (int i = 0; i < coordinates.length; i++) {
06473:                        for (int j = 0; j < polytope.planes.length; j++) {
06474:                            if ((polytope.planes[j].x * coordinates[i].x
06475:                                    + polytope.planes[j].y * coordinates[i].y + polytope.planes[j].z
06476:                                    * coordinates[i].z) <= (distanceSign)
06477:                                    * polytope.planes[j].w) {
06478:                                // the point satisfies this particular hyperplane
06479:                                intersection = true;
06480:                            } else {
06481:                                // the point fails this hyper plane try with a new hyper plane
06482:                                intersection = false;
06483:                                break;
06484:                            }
06485:                        }
06486:                        if (intersection) {
06487:                            // a point was found to be completely inside the bounding hull
06488:                            if (dist != null) {
06489:                                computeMinDistance(coordinates, polytope
06490:                                        .getCenter(), null, dist, iPnt);
06491:                            }
06492:                            return true;
06493:                        }
06494:                    }
06495:                } // end of pretest
06496:
06497:                // at this point all points are outside of the bounding hull
06498:                // build the problem tableau for the linear program
06499:
06500:                int numberCols = polytope.planes.length + 2
06501:                        + coordinates.length + 1;
06502:                int numberRows = 1 + coordinates.length;
06503:
06504:                double problemTableau[][] = new double[numberRows][numberCols];
06505:
06506:                // compute -Mtrans = -A*P
06507:
06508:                for (int i = 0; i < polytope.planes.length; i++) {
06509:                    for (int j = 0; j < coordinates.length; j++) {
06510:                        problemTableau[j][i] = (-1.0)
06511:                                * (polytope.planes[i].x * coordinates[j].x
06512:                                        + polytope.planes[i].y
06513:                                        * coordinates[j].y + polytope.planes[i].z
06514:                                        * coordinates[j].z);
06515:                    }
06516:                }
06517:
06518:                // add the other rows
06519:                for (int i = 0; i < coordinates.length; i++) {
06520:                    problemTableau[i][polytope.planes.length] = -1.0;
06521:                    problemTableau[i][polytope.planes.length + 1] = 1.0;
06522:
06523:                    for (int j = 0; j < coordinates.length; j++) {
06524:                        if (i == j) {
06525:                            problemTableau[i][j + polytope.planes.length + 2] = 1.0;
06526:                        } else {
06527:                            problemTableau[i][j + polytope.planes.length + 2] = 0.0;
06528:                        }
06529:
06530:                        // place the last column elements the Ci's
06531:                        problemTableau[i][numberCols - 1] = centers[i];
06532:                    }
06533:                }
06534:
06535:                // place the final rows value
06536:                for (int j = 0; j < polytope.planes.length; j++) {
06537:                    problemTableau[numberRows - 1][j] = (distanceSign)
06538:                            * polytope.planes[j].w;
06539:                }
06540:                problemTableau[numberRows - 1][polytope.planes.length] = 1.0;
06541:                problemTableau[numberRows - 1][polytope.planes.length + 1] = -1.0;
06542:                for (int j = 0; j < coordinates.length; j++) {
06543:                    problemTableau[numberRows - 1][polytope.planes.length + 2
06544:                            + j] = 0.0;
06545:                }
06546:
06547:                if (debug) {
06548:                    System.err.println("The value of the problem tableau is: ");
06549:                    for (int i = 0; i < problemTableau.length; i++) {
06550:                        for (int j = 0; j < problemTableau[0].length; j++) {
06551:                            System.err.print(problemTableau[i][j] + "  ");
06552:                        }
06553:                        System.err.println();
06554:                    }
06555:                }
06556:
06557:                double distance = generalStandardSimplexSolver(problemTableau,
06558:                        Float.NEGATIVE_INFINITY);
06559:                if (debug) {
06560:                    System.err
06561:                            .println("The value returned by the general standard simplex = "
06562:                                    + distance);
06563:                }
06564:                if (distance == Float.POSITIVE_INFINITY) {
06565:                    return false;
06566:                }
06567:                if (dist != null) {
06568:                    computeMinDistance(coordinates, polytope.getCenter(), null,
06569:                            dist, iPnt);
06570:                }
06571:                return true;
06572:
06573:            }
06574:
06575:            // optimized version using arrays of doubles, but using the standard simplex
06576:            // method to solve the LP tableau.  This version has not been optimized to
06577:            // work with a particular size input tableau and is much slower than some
06578:            // of the other variants...supposedly
06579:            double generalStandardSimplexSolver(double problemTableau[][],
06580:                    double stopingValue) {
06581:                boolean debug = false;
06582:                int numRow = problemTableau.length;
06583:                int numCol = problemTableau[0].length;
06584:                boolean optimal = false;
06585:                int i, pivotRowIndex, pivotColIndex;
06586:                double maxElement, element, endElement, ratio, prevRatio;
06587:                int count = 0;
06588:                double multiplier;
06589:
06590:                if (debug) {
06591:                    System.err.println("The number of rows is : " + numRow);
06592:                    System.err.println("The number of columns is : " + numCol);
06593:                }
06594:
06595:                // until the optimal solution is found continue to do
06596:                // iterations of the simplex method
06597:                while (!optimal) {
06598:
06599:                    if (debug) {
06600:                        System.err.println("input problem tableau is:");
06601:                        for (int k = 0; k < numRow; k++) {
06602:                            for (int j = 0; j < numCol; j++) {
06603:                                System.err.println("kth, jth value is:" + k
06604:                                        + " " + j + " : "
06605:                                        + problemTableau[k][j]);
06606:                            }
06607:                        }
06608:                    }
06609:
06610:                    // test to see if the current solution is optimal
06611:                    // check all bottom row elements except the right most one and
06612:                    // if all positive or zero its optimal
06613:                    for (i = 0, maxElement = 0, pivotColIndex = -1; i < numCol - 1; i++) {
06614:                        // a bottom row element
06615:                        element = problemTableau[numRow - 1][i];
06616:                        if (element < maxElement) {
06617:                            maxElement = element;
06618:                            pivotColIndex = i;
06619:                        }
06620:                    }
06621:
06622:                    // if there is no negative non-zero element then we
06623:                    // have found an optimal solution (the last row of the tableau)
06624:                    if (pivotColIndex == -1) {
06625:                        // found an optimal solution
06626:                        //System.err.println("Found an optimal solution");
06627:                        optimal = true;
06628:                    }
06629:
06630:                    //System.err.println("The value of maxElement is:" + maxElement);
06631:
06632:                    if (!optimal) {
06633:                        // Case when the solution is not optimal but not known to be
06634:                        // either unbounded or infeasable
06635:
06636:                        // from the above we have found the maximum negative element in
06637:                        // bottom row, we have also found the column for this value
06638:                        // the pivotColIndex represents this
06639:
06640:                        // initialize the values for the algorithm, -1 for pivotRowIndex
06641:                        // indicates no solution
06642:
06643:                        prevRatio = Float.POSITIVE_INFINITY;
06644:                        ratio = 0.0;
06645:                        pivotRowIndex = -1;
06646:
06647:                        // note if all of the elements in the pivot column are zero or
06648:                        // negative the problem is unbounded.
06649:                        for (i = 0; i < numRow - 1; i++) {
06650:                            element = problemTableau[i][pivotColIndex]; // r value
06651:                            endElement = problemTableau[i][numCol - 1]; // s value
06652:
06653:                            // pivot according to the rule that we want to choose the row
06654:                            // with smallest s/r ratio see third case
06655:                            // currently we ignore valuse of r==0 (case 1) and cases where the
06656:                            // ratio is negative, i.e. either r or s are negative (case 2)
06657:                            if (element == 0) {
06658:                                if (debug) {
06659:                                    System.err
06660:                                            .println("Division by zero has occurred");
06661:                                    System.err
06662:                                            .println("Within the linear program solver");
06663:                                    System.err
06664:                                            .println("Ignoring the zero as a potential pivot");
06665:                                }
06666:                            } else if ((element < 0.0) || (endElement < 0.0)) {
06667:                                if (debug) {
06668:                                    System.err
06669:                                            .println("Ignoring cases where element is negative");
06670:                                    System.err
06671:                                            .println("The value of element is: "
06672:                                                    + element);
06673:                                    System.err
06674:                                            .println("The value of end Element is: "
06675:                                                    + endElement);
06676:                                }
06677:                            } else {
06678:                                ratio = endElement / element; // should be s/r
06679:                                if (debug) {
06680:                                    System.err
06681:                                            .println("The value of element is: "
06682:                                                    + element);
06683:                                    System.err
06684:                                            .println("The value of endElement is: "
06685:                                                    + endElement);
06686:                                    System.err
06687:                                            .println("The value of ratio is: "
06688:                                                    + ratio);
06689:                                    System.err
06690:                                            .println("The value of prevRatio is: "
06691:                                                    + prevRatio);
06692:                                    System.err
06693:                                            .println("Value of ratio <= prevRatio is :"
06694:                                                    + (ratio <= prevRatio));
06695:                                }
06696:                                if (ratio <= prevRatio) {
06697:                                    if (debug) {
06698:                                        System.err
06699:                                                .println("updating prevRatio with ratio");
06700:                                    }
06701:                                    prevRatio = ratio;
06702:                                    pivotRowIndex = i;
06703:                                }
06704:                            }
06705:                        }
06706:
06707:                        // if the pivotRowIndex is still -1 then we know the pivotColumn
06708:                        // has no viable pivot points and the solution is unbounded or
06709:                        // infeasable (all pivot elements were either zero or negative or
06710:                        // the right most value was negative (the later shouldn't happen?)
06711:                        if (pivotRowIndex == -1) {
06712:                            if (debug) {
06713:                                System.err.println("UNABLE TO FIND SOLUTION");
06714:                                System.err
06715:                                        .println("The system is infeasable or unbounded");
06716:                            }
06717:                            return (Float.POSITIVE_INFINITY);
06718:                        }
06719:
06720:                        // we now have the pivot row and col all that remains is
06721:                        // to divide through by this value and subtract the appropriate
06722:                        // multiple of the pivot row from all other rows to obtain
06723:                        // a tableau which has a column of all zeros and one 1 in the
06724:                        // intersection of pivot row and col
06725:
06726:                        // divide through by the pivot value
06727:                        double pivotValue = problemTableau[pivotRowIndex][pivotColIndex];
06728:
06729:                        if (debug) {
06730:                            System.err.println("The value of row index is: "
06731:                                    + pivotRowIndex);
06732:                            System.err.println("The value of col index is: "
06733:                                    + pivotColIndex);
06734:                            System.err.println("The value of pivotValue is: "
06735:                                    + pivotValue);
06736:                        }
06737:                        // divide through by s on the pivot row to obtain a 1 in pivot col
06738:                        for (i = 0; i < numCol; i++) {
06739:                            problemTableau[pivotRowIndex][i] = problemTableau[pivotRowIndex][i]
06740:                                    / pivotValue;
06741:                        }
06742:
06743:                        // subtract appropriate multiple of pivot row from all other rows
06744:                        // to zero out all rows except the final row and the pivot row
06745:                        for (i = 0; i < numRow; i++) {
06746:                            if (i != pivotRowIndex) {
06747:                                multiplier = problemTableau[i][pivotColIndex];
06748:                                for (int j = 0; j < numCol; j++) {
06749:                                    problemTableau[i][j] = problemTableau[i][j]
06750:                                            - multiplier
06751:                                            * problemTableau[pivotRowIndex][j];
06752:                                }
06753:                            }
06754:                        }
06755:                    }
06756:                    // case when the element is optimal
06757:                }
06758:                return (problemTableau[numRow - 1][numCol - 1]);
06759:            }
06760:
06761:            boolean edgeIntersectSphere(BoundingSphere sphere, Point3d start,
06762:                    Point3d end) {
06763:                double abLenSq, acLenSq, apLenSq, abDotAp, radiusSq;
06764:                Vector3d ab = new Vector3d();
06765:                Vector3d ap = new Vector3d();
06766:
06767:                ab.x = end.x - start.x;
06768:                ab.y = end.y - start.y;
06769:                ab.z = end.z - start.z;
06770:
06771:                ap.x = sphere.center.x - start.x;
06772:                ap.y = sphere.center.y - start.y;
06773:                ap.z = sphere.center.z - start.z;
06774:
06775:                abDotAp = ab.dot(ap);
06776:
06777:                if (abDotAp < 0.0) {
06778:                    return false; // line segment points away from sphere.
06779:                }
06780:
06781:                abLenSq = ab.lengthSquared();
06782:                acLenSq = abDotAp * abDotAp / abLenSq;
06783:
06784:                if (acLenSq < abLenSq) {
06785:                    return false; // C doesn't lies between end points of edge.
06786:                }
06787:
06788:                radiusSq = sphere.radius * sphere.radius;
06789:                apLenSq = ap.lengthSquared();
06790:
06791:                if ((apLenSq - acLenSq) <= radiusSq) {
06792:                    return true;
06793:                }
06794:
06795:                return false;
06796:
06797:            }
06798:
06799:            double det2D(Point2d a, Point2d b, Point2d p) {
06800:                return (((p).x - (a).x) * ((a).y - (b).y) + ((a).y - (p).y)
06801:                        * ((a).x - (b).x));
06802:            }
06803:
06804:            // Assume coord is CCW.
06805:            boolean pointIntersectPolygon2D(Vector3d normal, Point3d[] coord,
06806:                    Point3d point) {
06807:
06808:                double absNrmX, absNrmY, absNrmZ;
06809:                Point2d coord2D[] = new Point2d[coord.length];
06810:                Point2d pnt = new Point2d();
06811:
06812:                int i, j, axis;
06813:
06814:                // Project 3d points onto 2d plane.
06815:                // Note : Area of polygon is not preserve in this projection, but
06816:                // it doesn't matter here.
06817:
06818:                // Find the axis of projection.
06819:                absNrmX = Math.abs(normal.x);
06820:                absNrmY = Math.abs(normal.y);
06821:                absNrmZ = Math.abs(normal.z);
06822:
06823:                if (absNrmX > absNrmY)
06824:                    axis = 0;
06825:                else
06826:                    axis = 1;
06827:
06828:                if (axis == 0) {
06829:                    if (absNrmX < absNrmZ)
06830:                        axis = 2;
06831:                } else if (axis == 1) {
06832:                    if (absNrmY < absNrmZ)
06833:                        axis = 2;
06834:                }
06835:
06836:                // System.err.println("Normal " + normal + " axis " + axis );
06837:
06838:                for (i = 0; i < coord.length; i++) {
06839:                    coord2D[i] = new Point2d();
06840:
06841:                    switch (axis) {
06842:                    case 0:
06843:                        coord2D[i].x = coord[i].y;
06844:                        coord2D[i].y = coord[i].z;
06845:                        break;
06846:
06847:                    case 1:
06848:                        coord2D[i].x = coord[i].x;
06849:                        coord2D[i].y = coord[i].z;
06850:                        break;
06851:
06852:                    case 2:
06853:                        coord2D[i].x = coord[i].x;
06854:                        coord2D[i].y = coord[i].y;
06855:                        break;
06856:                    }
06857:
06858:                    // System.err.println("i " + i + " u " + uCoor[i] + " v " + vCoor[i]);
06859:                }
06860:
06861:                switch (axis) {
06862:                case 0:
06863:                    pnt.x = point.y;
06864:                    pnt.y = point.z;
06865:                    break;
06866:
06867:                case 1:
06868:                    pnt.x = point.x;
06869:                    pnt.y = point.z;
06870:                    break;
06871:
06872:                case 2:
06873:                    pnt.x = point.x;
06874:                    pnt.y = point.y;
06875:                    break;
06876:                }
06877:
06878:                // Do determinant test.
06879:                for (j = 0; j < coord.length; j++) {
06880:                    if (j < (coord.length - 1))
06881:                        if (det2D(coord2D[j], coord2D[j + 1], pnt) > 0.0)
06882:                            ;
06883:                        else
06884:                            return false;
06885:                    else if (det2D(coord2D[j], coord2D[0], pnt) > 0.0)
06886:                        ;
06887:                    else
06888:                        return false;
06889:                }
06890:
06891:                return true;
06892:
06893:            }
06894:
06895:            boolean edgeIntersectPlane(Vector3d normal, Point3d pnt,
06896:                    Point3d start, Point3d end, Point3d iPnt) {
06897:
06898:                Vector3d tempV3d = new Vector3d();
06899:                Vector3d direction = new Vector3d();
06900:                double pD, pNrmDotrDir, tr;
06901:
06902:                // Compute plane D.
06903:                tempV3d.set((Tuple3d) pnt);
06904:                pD = normal.dot(tempV3d);
06905:
06906:                direction.x = end.x - start.x;
06907:                direction.y = end.y - start.y;
06908:                direction.z = end.z - start.z;
06909:
06910:                pNrmDotrDir = normal.dot(direction);
06911:
06912:                // edge is parallel to plane.
06913:                if (pNrmDotrDir == 0.0) {
06914:                    // System.err.println("Edge is parallel to plane.");
06915:                    return false;
06916:                }
06917:
06918:                tempV3d.set((Tuple3d) start);
06919:
06920:                tr = (pD - normal.dot(tempV3d)) / pNrmDotrDir;
06921:
06922:                // Edge intersects the plane behind the edge's start.
06923:                // or exceed the edge's length.
06924:                if ((tr < 0.0) || (tr > 1.0)) {
06925:                    // System.err.println("Edge intersects the plane behind the start or exceed end.");
06926:                    return false;
06927:                }
06928:
06929:                iPnt.x = start.x + tr * direction.x;
06930:                iPnt.y = start.y + tr * direction.y;
06931:                iPnt.z = start.z + tr * direction.z;
06932:
06933:                return true;
06934:
06935:            }
06936:
06937:            // Assume coord is CCW.
06938:            boolean edgeIntersectPolygon2D(Vector3d normal, Point3d[] coord,
06939:                    Point3d[] seg) {
06940:
06941:                double absNrmX, absNrmY, absNrmZ;
06942:                Point2d coord2D[] = new Point2d[coord.length];
06943:                Point2d seg2D[] = new Point2d[2];
06944:
06945:                int i, j, axis;
06946:
06947:                // Project 3d points onto 2d plane.
06948:                // Note : Area of polygon is not preserve in this projection, but
06949:                // it doesn't matter here.
06950:
06951:                // Find the axis of projection.
06952:                absNrmX = Math.abs(normal.x);
06953:                absNrmY = Math.abs(normal.y);
06954:                absNrmZ = Math.abs(normal.z);
06955:
06956:                if (absNrmX > absNrmY)
06957:                    axis = 0;
06958:                else
06959:                    axis = 1;
06960:
06961:                if (axis == 0) {
06962:                    if (absNrmX < absNrmZ)
06963:                        axis = 2;
06964:                } else if (axis == 1) {
06965:                    if (absNrmY < absNrmZ)
06966:                        axis = 2;
06967:                }
06968:
06969:                // System.err.println("Normal " + normal + " axis " + axis );
06970:
06971:                for (i = 0; i < coord.length; i++) {
06972:                    coord2D[i] = new Point2d();
06973:
06974:                    switch (axis) {
06975:                    case 0:
06976:                        coord2D[i].x = coord[i].y;
06977:                        coord2D[i].y = coord[i].z;
06978:                        break;
06979:
06980:                    case 1:
06981:                        coord2D[i].x = coord[i].x;
06982:                        coord2D[i].y = coord[i].z;
06983:                        break;
06984:
06985:                    case 2:
06986:                        coord2D[i].x = coord[i].x;
06987:                        coord2D[i].y = coord[i].y;
06988:                        break;
06989:                    }
06990:
06991:                    // System.err.println("i " + i + " u " + uCoor[i] + " v " + vCoor[i]);
06992:                }
06993:
06994:                for (i = 0; i < 2; i++) {
06995:                    seg2D[i] = new Point2d();
06996:                    switch (axis) {
06997:                    case 0:
06998:                        seg2D[i].x = seg[i].y;
06999:                        seg2D[i].y = seg[i].z;
07000:                        break;
07001:
07002:                    case 1:
07003:                        seg2D[i].x = seg[i].x;
07004:                        seg2D[i].y = seg[i].z;
07005:                        break;
07006:
07007:                    case 2:
07008:                        seg2D[i].x = seg[i].x;
07009:                        seg2D[i].y = seg[i].y;
07010:                        break;
07011:                    }
07012:
07013:                    // System.err.println("i " + i + " u " + uSeg[i] + " v " + vSeg[i]);
07014:                }
07015:
07016:                // Do determinant test.
07017:                boolean pntTest[][] = new boolean[2][coord.length];
07018:                boolean testFlag;
07019:
07020:                for (j = 0; j < coord.length; j++) {
07021:                    for (i = 0; i < 2; i++) {
07022:                        if (j < (coord.length - 1))
07023:                            pntTest[i][j] = (det2D(coord2D[j], coord2D[j + 1],
07024:                                    seg2D[i]) < 0.0);
07025:                        else
07026:                            pntTest[i][j] = (det2D(coord2D[j], coord2D[0],
07027:                                    seg2D[i]) < 0.0);
07028:                    }
07029:
07030:                    if ((pntTest[0][j] == false) && (pntTest[1][j] == false))
07031:                        return false;
07032:                }
07033:
07034:                testFlag = true;
07035:                for (i = 0; i < coord.length; i++) {
07036:                    if (pntTest[0][i] == false) {
07037:                        testFlag = false;
07038:                        break;
07039:                    }
07040:                }
07041:
07042:                if (testFlag == true)
07043:                    return true; // start point is inside polygon.
07044:
07045:                testFlag = true;
07046:                for (i = 0; i < coord.length; i++) {
07047:                    if (pntTest[1][i] == false) {
07048:                        testFlag = false;
07049:                        break;
07050:                    }
07051:                }
07052:
07053:                if (testFlag == true)
07054:                    return true; // end point is inside polygon.
07055:
07056:                int cnt = 0;
07057:                for (i = 0; i < coord.length; i++) {
07058:                    if (det2D(seg2D[0], seg2D[1], coord2D[i]) < 0.0)
07059:                        cnt++;
07060:                }
07061:
07062:                if ((cnt == 0) || (cnt == coord.length))
07063:                    return false;
07064:
07065:                return true;
07066:
07067:            }
07068:
07069:            // New stuffs .....
07070:            double getCompValue(Point3d v, int i) {
07071:                switch (i) {
07072:                case 0:
07073:                    return v.x;
07074:                case 1:
07075:                    return v.y;
07076:                }
07077:                // Has to return something, so set the default to z component.
07078:                return v.z;
07079:            }
07080:
07081:            double getCompValue(Point3d v0, Point3d v1, int i) {
07082:                switch (i) {
07083:                case 0:
07084:                    return (v0.x - v1.x);
07085:                case 1:
07086:                    return (v0.y - v1.y);
07087:                }
07088:                // Has to return some, so set the default to z component.
07089:                return (v0.z - v1.z);
07090:            }
07091:
07092:            boolean pointInTri(Point3d v0, Point3d u0, Point3d u1, Point3d u2,
07093:                    Vector3d normal) {
07094:
07095:                double nAbsX, nAbsY, nAbsZ;
07096:                int i0, i1;
07097:
07098:                // first project onto an axis-aligned plane, that maximizes the area
07099:                // of the triangles, compute indices i0, i1.
07100:                nAbsX = Math.abs(normal.x);
07101:                nAbsY = Math.abs(normal.y);
07102:                nAbsZ = Math.abs(normal.z);
07103:
07104:                if (nAbsX > nAbsY) {
07105:                    if (nAbsX > nAbsZ) {
07106:                        i0 = 1; //  nAbsX is greatest.
07107:                        i1 = 2;
07108:                    } else {
07109:                        i0 = 0; //  nAbsZ is greatest.
07110:                        i1 = 1;
07111:                    }
07112:                } else { // nAbsX <= nAbsY
07113:                    if (nAbsZ > nAbsY) {
07114:                        i0 = 0; //  nAbsZ is greatest.
07115:                        i1 = 1;
07116:                    } else {
07117:                        i0 = 0; //  nAbsY is greatest.
07118:                        i1 = 2;
07119:                    }
07120:                }
07121:                return pointInTri(v0, u0, u1, u2, i0, i1);
07122:            }
07123:
07124:            boolean pointInTri(Point3d v0, Point3d u0, Point3d u1, Point3d u2,
07125:                    int i0, int i1) {
07126:
07127:                double a, b, c, d0, d1, d2;
07128:                // is T1 completely inside T2 ?
07129:                // check if v0 is inside tri(u0,u1,u2)
07130:
07131:                a = getCompValue(u1, u0, i1);
07132:                b = -(getCompValue(u1, u0, i0));
07133:                c = -a * getCompValue(u0, i0) - b * getCompValue(u0, i1);
07134:                d0 = a * getCompValue(v0, i0) + b * getCompValue(v0, i1) + c;
07135:
07136:                a = getCompValue(u2, u1, i1);
07137:                b = -(getCompValue(u2, u1, i0));
07138:                c = -a * getCompValue(u1, i0) - b * getCompValue(u1, i1);
07139:                d1 = a * getCompValue(v0, i0) + b * getCompValue(v0, i1) + c;
07140:
07141:                a = getCompValue(u0, u2, i1);
07142:                b = -(getCompValue(u0, u2, i0));
07143:                c = -a * getCompValue(u2, i0) - b * getCompValue(u2, i1);
07144:                d2 = a * getCompValue(v0, i0) + b * getCompValue(v0, i1) + c;
07145:
07146:                if (d0 * d1 > 0.0) {
07147:                    if (d0 * d2 > 0.0) {
07148:                        return true;
07149:                    }
07150:                }
07151:                return false;
07152:            }
07153:
07154:            // this edge to edge test is based on Franlin Antonio's gem:
07155:            // "Faster line segment intersection", in Graphics Gems III, pp 199-202
07156:            boolean edgeAgainstEdge(Point3d v0, Point3d u0, Point3d u1,
07157:                    double aX, double aY, int i0, int i1) {
07158:                double bX, bY, cX, cY, e, d, f;
07159:
07160:                bX = getCompValue(u0, u1, i0);
07161:                bY = getCompValue(u0, u1, i1);
07162:                cX = getCompValue(v0, u0, i0);
07163:                cY = getCompValue(v0, u0, i1);
07164:
07165:                f = aY * bX - aX * bY;
07166:                d = bY * cX - bX * cY;
07167:                if ((f > 0 && d >= 0 && d <= f) || (f < 0 && d <= 0 && d >= f)) {
07168:                    e = aX * cY - aY * cX;
07169:                    if (f > 0) {
07170:                        if (e >= 0 && e <= f)
07171:                            return true;
07172:                    } else {
07173:                        if (e <= 0 && e >= f)
07174:                            return true;
07175:                    }
07176:                }
07177:
07178:                return false;
07179:            }
07180:
07181:            boolean edgeAgainstTriEdges(Point3d v0, Point3d v1, Point3d u0,
07182:                    Point3d u1, Point3d u2, int i0, int i1) {
07183:                double aX, aY;
07184:
07185:                // aX = v1[i0] - v0[i0];
07186:                // aY = v1[i1] - v0[i1];
07187:                aX = getCompValue(v1, v0, i0);
07188:                aY = getCompValue(v1, v0, i1);
07189:
07190:                // test edge u0, u1 against v0, v1
07191:                if (edgeAgainstEdge(v0, u0, u1, aX, aY, i0, i1))
07192:                    return true;
07193:                // test edge u1, u2 against v0, v1
07194:                if (edgeAgainstEdge(v0, u1, u2, aX, aY, i0, i1))
07195:                    return true;
07196:                // test edge u2, u0 against v0, v1
07197:                if (edgeAgainstEdge(v0, u2, u0, aX, aY, i0, i1))
07198:                    return true;
07199:
07200:                return false;
07201:
07202:            }
07203:
07204:            boolean coplanarTriTri(Vector3d normal, Point3d v0, Point3d v1,
07205:                    Point3d v2, Point3d u0, Point3d u1, Point3d u2) {
07206:
07207:                double nAbsX, nAbsY, nAbsZ;
07208:                int i0, i1;
07209:
07210:                // first project onto an axis-aligned plane, that maximizes the area
07211:                // of the triangles, compute indices i0, i1.
07212:                nAbsX = Math.abs(normal.x);
07213:                nAbsY = Math.abs(normal.y);
07214:                nAbsZ = Math.abs(normal.z);
07215:
07216:                if (nAbsX > nAbsY) {
07217:                    if (nAbsX > nAbsZ) {
07218:                        i0 = 1; //  nAbsX is greatest.
07219:                        i1 = 2;
07220:                    } else {
07221:                        i0 = 0; //  nAbsZ is greatest.
07222:                        i1 = 1;
07223:                    }
07224:                } else { // nAbsX <= nAbsY
07225:                    if (nAbsZ > nAbsY) {
07226:                        i0 = 0; //  nAbsZ is greatest.
07227:                        i1 = 1;
07228:                    } else {
07229:                        i0 = 0; //  nAbsY is greatest.
07230:                        i1 = 2;
07231:                    }
07232:                }
07233:
07234:                // test all edges of triangle 1 against the edges of triangle 2
07235:                if (edgeAgainstTriEdges(v0, v1, u0, u1, u2, i0, i1))
07236:                    return true;
07237:
07238:                if (edgeAgainstTriEdges(v1, v2, u0, u1, u2, i0, i1))
07239:                    return true;
07240:
07241:                if (edgeAgainstTriEdges(v2, v0, u0, u1, u2, i0, i1))
07242:                    return true;
07243:
07244:                // finally, test if tri1 is totally contained in tri2 or vice versa.
07245:                if (pointInTri(v0, u0, u1, u2, i0, i1))
07246:                    return true;
07247:
07248:                if (pointInTri(u0, v0, v1, v2, i0, i1))
07249:                    return true;
07250:
07251:                return false;
07252:            }
07253:
07254:            boolean intersectTriPnt(Point3d v0, Point3d v1, Point3d v2,
07255:                    Point3d u) {
07256:
07257:                Vector3d e1 = new Vector3d();
07258:                Vector3d e2 = new Vector3d();
07259:                Vector3d n1 = new Vector3d();
07260:                Vector3d tempV3d = new Vector3d();
07261:
07262:                double d1, du;
07263:
07264:                // compute plane equation of triange(coord1)
07265:                e1.x = v1.x - v0.x;
07266:                e1.y = v1.y - v0.y;
07267:                e1.z = v1.z - v0.z;
07268:
07269:                e2.x = v2.x - v0.x;
07270:                e2.y = v2.y - v0.y;
07271:                e2.z = v2.z - v0.z;
07272:
07273:                n1.cross(e1, e2);
07274:
07275:                if (n1.length() == 0.0) {
07276:                    // System.err.println("(1) Degenerate triangle.");
07277:                    return false; // Degenerate triangle.
07278:                }
07279:
07280:                tempV3d.set((Tuple3d) v0);
07281:                d1 = -n1.dot(tempV3d); // plane equation 1: n1.x + d1 = 0
07282:
07283:                // put u to compute signed distance to the plane.
07284:                tempV3d.set((Tuple3d) u);
07285:                du = n1.dot(tempV3d) + d1;
07286:
07287:                // coplanarity robustness check
07288:                if (Math.abs(du) < EPS)
07289:                    du = 0.0;
07290:
07291:                // no intersection occurs
07292:                if (du != 0.0) {
07293:                    return false;
07294:                }
07295:
07296:                double nAbsX, nAbsY, nAbsZ;
07297:                int i0, i1;
07298:
07299:                // first project onto an axis-aligned plane, that maximizes the area
07300:                // of the triangles, compute indices i0, i1.
07301:                nAbsX = Math.abs(n1.x);
07302:                nAbsY = Math.abs(n1.y);
07303:                nAbsZ = Math.abs(n1.z);
07304:
07305:                if (nAbsX > nAbsY) {
07306:                    if (nAbsX > nAbsZ) {
07307:                        i0 = 1; //  nAbsX is greatest.
07308:                        i1 = 2;
07309:                    } else {
07310:                        i0 = 0; //  nAbsZ is greatest.
07311:                        i1 = 1;
07312:                    }
07313:                } else { // nAbsX <= nAbsY
07314:                    if (nAbsZ > nAbsY) {
07315:                        i0 = 0; //  nAbsZ is greatest.
07316:                        i1 = 1;
07317:                    } else {
07318:                        i0 = 0; //  nAbsY is greatest.
07319:                        i1 = 2;
07320:                    }
07321:                }
07322:
07323:                // finally, test if u is totally contained in tri.
07324:                if (pointInTri(u, v0, v1, v2, i0, i1)) {
07325:                    return true;
07326:                }
07327:
07328:                return false;
07329:            }
07330:
07331:            /**
07332:             * Return flag indicating whether two triangles intersect.  This
07333:             * uses Tomas Moller's code for fast triangle-triangle
07334:             * intersection from his "Real-Time Rendering" book.
07335:             *
07336:             * The code is now divisionless. It tests for separating by planes
07337:             * parallel to either triangle.  If neither separate the
07338:             * triangles, then two cases are considered. First case is if the
07339:             * normals to the triangles are parallel. In that case, the
07340:             * triangles are coplanar and a sequence of tests are made to see
07341:             * if edges of each triangle intersect the other triangle. If the
07342:             * normals are not parallel, then the two triangles can intersect
07343:             * only on the line of intersection of the two planes. The
07344:             * intervals of intersection of the triangles with the line of
07345:             * intersection of the two planes are computed and tested for
07346:             * overlap.
07347:             */
07348:            boolean intersectTriTri(Point3d v0, Point3d v1, Point3d v2,
07349:                    Point3d u0, Point3d u1, Point3d u2) {
07350:
07351:                // System.err.println("In intersectTriTri ...");
07352:                Vector3d e1 = new Vector3d();
07353:                Vector3d e2 = new Vector3d();
07354:                Vector3d n1 = new Vector3d();
07355:                Vector3d n2 = new Vector3d();
07356:                Vector3d tempV3d = new Vector3d();
07357:
07358:                double d1, d2;
07359:                double du0, du1, du2, dv0, dv1, dv2;
07360:                double du0du1, du0du2, dv0dv1, dv0dv2;
07361:                int index;
07362:                double vp0 = 0.0, vp1 = 0.0, vp2 = 0.0;
07363:                double up0 = 0.0, up1 = 0.0, up2 = 0.0;
07364:                double bb, cc, max;
07365:
07366:                // compute plane equation of triange(coord1)
07367:                e1.x = v1.x - v0.x;
07368:                e1.y = v1.y - v0.y;
07369:                e1.z = v1.z - v0.z;
07370:
07371:                e2.x = v2.x - v0.x;
07372:                e2.y = v2.y - v0.y;
07373:                e2.z = v2.z - v0.z;
07374:
07375:                n1.cross(e1, e2);
07376:
07377:                if (n1.length() == 0.0) {
07378:                    // System.err.println("(1) Degenerate triangle.");
07379:                    return false; // Degenerate triangle.
07380:                }
07381:
07382:                tempV3d.set((Tuple3d) v0);
07383:                d1 = -n1.dot(tempV3d); // plane equation 1: n1.x + d1 = 0
07384:
07385:                // put u0, u1, and u2 into plane equation 1
07386:                // to compute signed distance to the plane.
07387:                tempV3d.set((Tuple3d) u0);
07388:                du0 = n1.dot(tempV3d) + d1;
07389:                tempV3d.set((Tuple3d) u1);
07390:                du1 = n1.dot(tempV3d) + d1;
07391:                tempV3d.set((Tuple3d) u2);
07392:                du2 = n1.dot(tempV3d) + d1;
07393:
07394:                // coplanarity robustness check
07395:                if (Math.abs(du0) < EPS)
07396:                    du0 = 0.0;
07397:                if (Math.abs(du1) < EPS)
07398:                    du1 = 0.0;
07399:                if (Math.abs(du2) < EPS)
07400:                    du2 = 0.0;
07401:
07402:                du0du1 = du0 * du1;
07403:                du0du2 = du0 * du2;
07404:
07405:                // same sign on all of them + not equal 0 ?
07406:                // no intersection occurs
07407:                if (du0du1 > 0.0 && du0du2 > 0.0) {
07408:                    // System.err.println("In intersectTriTri : du0du1>0.0 && du0du2>0.0");
07409:                    return false;
07410:                }
07411:
07412:                // compute plane of triangle(coord2)
07413:                e1.x = u1.x - u0.x;
07414:                e1.y = u1.y - u0.y;
07415:                e1.z = u1.z - u0.z;
07416:
07417:                e2.x = u2.x - u0.x;
07418:                e2.y = u2.y - u0.y;
07419:                e2.z = u2.z - u0.z;
07420:
07421:                n2.cross(e1, e2);
07422:
07423:                if (n2.length() == 0.0) {
07424:                    // System.err.println("(2) Degenerate triangle.");
07425:                    return false; // Degenerate triangle.
07426:                }
07427:
07428:                tempV3d.set((Tuple3d) u0);
07429:                d2 = -n2.dot(tempV3d); // plane equation 2: n2.x + d2 = 0
07430:
07431:                // put v0, v1, and v2 into plane equation 2
07432:                // to compute signed distance to the plane.
07433:                tempV3d.set((Tuple3d) v0);
07434:                dv0 = n2.dot(tempV3d) + d2;
07435:                tempV3d.set((Tuple3d) v1);
07436:                dv1 = n2.dot(tempV3d) + d2;
07437:                tempV3d.set((Tuple3d) v2);
07438:                dv2 = n2.dot(tempV3d) + d2;
07439:
07440:                // coplanarity robustness check
07441:                if (Math.abs(dv0) < EPS)
07442:                    dv0 = 0.0;
07443:                if (Math.abs(dv1) < EPS)
07444:                    dv1 = 0.0;
07445:                if (Math.abs(dv2) < EPS)
07446:                    dv2 = 0.0;
07447:
07448:                dv0dv1 = dv0 * dv1;
07449:                dv0dv2 = dv0 * dv2;
07450:
07451:                // same sign on all of them + not equal 0 ?
07452:                // no intersection occurs
07453:                if (dv0dv1 > 0.0 && dv0dv2 > 0.0) {
07454:                    // System.err.println("In intersectTriTri : dv0dv1>0.0 && dv0dv2>0.0");
07455:                    return false;
07456:                }
07457:                // compute direction of intersection line.
07458:                tempV3d.cross(n1, n2);
07459:
07460:                // compute and index to the largest component of tempV3d.
07461:                max = Math.abs(tempV3d.x);
07462:                index = 0;
07463:                bb = Math.abs(tempV3d.y);
07464:                cc = Math.abs(tempV3d.z);
07465:                if (bb > max) {
07466:                    max = bb;
07467:                    index = 1;
07468:                }
07469:                if (cc > max) {
07470:                    max = cc;
07471:                    index = 2;
07472:                }
07473:
07474:                // this is the simplified projection onto L.
07475:
07476:                switch (index) {
07477:                case 0:
07478:                    vp0 = v0.x;
07479:                    vp1 = v1.x;
07480:                    vp2 = v2.x;
07481:
07482:                    up0 = u0.x;
07483:                    up1 = u1.x;
07484:                    up2 = u2.x;
07485:                    break;
07486:                case 1:
07487:                    vp0 = v0.y;
07488:                    vp1 = v1.y;
07489:                    vp2 = v2.y;
07490:
07491:                    up0 = u0.y;
07492:                    up1 = u1.y;
07493:                    up2 = u2.y;
07494:                    break;
07495:                case 2:
07496:                    vp0 = v0.z;
07497:                    vp1 = v1.z;
07498:                    vp2 = v2.z;
07499:
07500:                    up0 = u0.z;
07501:                    up1 = u1.z;
07502:                    up2 = u2.z;
07503:                    break;
07504:                }
07505:
07506:                // compute intereval for triangle 1.
07507:                double a = 0.0, b = 0.0, c = 0.0, x0 = 0.0, x1 = 0.0;
07508:                if (dv0dv1 > 0.0) {
07509:                    // here we know that dv0dv2 <= 0.0 that is dv0 and dv1 are on the same side,
07510:                    // dv2 on the other side or on the plane.
07511:                    a = vp2;
07512:                    b = (vp0 - vp2) * dv2;
07513:                    c = (vp1 - vp2) * dv2;
07514:                    x0 = dv2 - dv0;
07515:                    x1 = dv2 - dv1;
07516:                } else if (dv0dv2 > 0.0) {
07517:                    // here we know that dv0dv1<=0.0
07518:                    a = vp1;
07519:                    b = (vp0 - vp1) * dv1;
07520:                    c = (vp2 - vp1) * dv1;
07521:                    x0 = dv1 - dv0;
07522:                    x1 = dv1 - dv2;
07523:                } else if ((dv1 * dv2 > 0.0) || (dv0 != 0.0)) {
07524:                    // here we know that dv0vd1<=0.0 or that dv0!=0.0
07525:                    a = vp0;
07526:                    b = (vp1 - vp0) * dv0;
07527:                    c = (vp2 - vp0) * dv0;
07528:                    x0 = dv0 - dv1;
07529:                    x1 = dv0 - dv2;
07530:                } else if (dv1 != 0.0) {
07531:                    a = vp1;
07532:                    b = (vp0 - vp1) * dv1;
07533:                    c = (vp2 - vp1) * dv1;
07534:                    x0 = dv1 - dv0;
07535:                    x1 = dv1 - dv2;
07536:                } else if (dv2 != 0.0) {
07537:                    a = vp2;
07538:                    b = (vp0 - vp2) * dv2;
07539:                    c = (vp1 - vp2) * dv2;
07540:                    x0 = dv2 - dv0;
07541:                    x1 = dv2 - dv1;
07542:                } else {
07543:                    // triangles are coplanar
07544:                    boolean toreturn = coplanarTriTri(n1, v0, v1, v2, u0, u1,
07545:                            u2);
07546:                    return toreturn;
07547:                }
07548:
07549:                // compute intereval for triangle 2.
07550:                double d = 0.0, e = 0.0, f = 0.0, y0 = 0.0, y1 = 0.0;
07551:                if (du0du1 > 0.0) {
07552:                    // here we know that du0du2 <= 0.0 that is du0 and du1 are on the same side,
07553:                    // du2 on the other side or on the plane.
07554:                    d = up2;
07555:                    e = (up0 - up2) * du2;
07556:                    f = (up1 - up2) * du2;
07557:                    y0 = du2 - du0;
07558:                    y1 = du2 - du1;
07559:                } else if (du0du2 > 0.0) {
07560:                    // here we know that du0du1<=0.0
07561:                    d = up1;
07562:                    e = (up0 - up1) * du1;
07563:                    f = (up2 - up1) * du1;
07564:                    y0 = du1 - du0;
07565:                    y1 = du1 - du2;
07566:                } else if ((du1 * du2 > 0.0) || (du0 != 0.0)) {
07567:                    // here we know that du0du1<=0.0 or that D0!=0.0
07568:                    d = up0;
07569:                    e = (up1 - up0) * du0;
07570:                    f = (up2 - up0) * du0;
07571:                    y0 = du0 - du1;
07572:                    y1 = du0 - du2;
07573:                } else if (du1 != 0.0) {
07574:                    d = up1;
07575:                    e = (up0 - up1) * du1;
07576:                    f = (up2 - up1) * du1;
07577:                    y0 = du1 - du0;
07578:                    y1 = du1 - du2;
07579:                } else if (du2 != 0.0) {
07580:                    d = up2;
07581:                    e = (up0 - up2) * du2;
07582:                    f = (up1 - up2) * du2;
07583:                    y0 = du2 - du0;
07584:                    y1 = du2 - du1;
07585:                } else {
07586:                    // triangles are coplanar
07587:                    //	    System.err.println("In intersectTriTri : coplanarTriTri test 2");
07588:                    boolean toreturn = coplanarTriTri(n2, v0, v1, v2, u0, u1,
07589:                            u2);
07590:                    return toreturn;
07591:                }
07592:
07593:                double xx, yy, xxyy, tmp, isect1S, isect1E, isect2S, isect2E;
07594:                xx = x0 * x1;
07595:                yy = y0 * y1;
07596:                xxyy = xx * yy;
07597:
07598:                tmp = a * xxyy;
07599:                isect1S = tmp + b * x1 * yy;
07600:                isect1E = tmp + c * x0 * yy;
07601:
07602:                tmp = d * xxyy;
07603:                isect2S = tmp + e * y1 * xx;
07604:                isect2E = tmp + f * y0 * xx;
07605:
07606:                // sort so that isect1S <= isect1E
07607:                if (isect1S > isect1E) {
07608:                    tmp = isect1S;
07609:                    isect1S = isect1E;
07610:                    isect1E = tmp;
07611:                }
07612:
07613:                // sort so that isect2S <= isect2E
07614:                if (isect2S > isect2E) {
07615:                    tmp = isect2S;
07616:                    isect2S = isect2E;
07617:                    isect2E = tmp;
07618:                }
07619:
07620:                if (isect1E < isect2S || isect2E < isect1S) {
07621:                    // System.err.println("In intersectTriTri :isect1E<isect2S || isect2E<isect1S");
07622:                    // System.err.println("In intersectTriTri : return false");
07623:                    return false;
07624:                }
07625:
07626:                //	 System.err.println("In intersectTriTri : return true");
07627:                return true;
07628:
07629:            }
07630:
07631:            boolean intersectPolygon(Point3d coord1[], Point3d coord2[]) {
07632:                int i, j;
07633:                Vector3d vec0 = new Vector3d(); // Edge vector from point 0 to point 1;
07634:                Vector3d vec1 = new Vector3d(); // Edge vector from point 0 to point 2 or 3;
07635:                Vector3d pNrm = new Vector3d();
07636:                boolean epFlag;
07637:
07638:                // compute plane normal for coord1.
07639:                for (i = 0; i < coord1.length - 1;) {
07640:                    vec0.x = coord1[i + 1].x - coord1[i].x;
07641:                    vec0.y = coord1[i + 1].y - coord1[i].y;
07642:                    vec0.z = coord1[i + 1].z - coord1[i++].z;
07643:                    if (vec0.length() > 0.0)
07644:                        break;
07645:                }
07646:
07647:                for (j = i; j < coord1.length - 1; j++) {
07648:                    vec1.x = coord1[j + 1].x - coord1[j].x;
07649:                    vec1.y = coord1[j + 1].y - coord1[j].y;
07650:                    vec1.z = coord1[j + 1].z - coord1[j].z;
07651:                    if (vec1.length() > 0.0)
07652:                        break;
07653:                }
07654:
07655:                if (j == (coord1.length - 1)) {
07656:                    // System.err.println("(1) Degenerate polygon.");
07657:                    return false; // Degenerate polygon.
07658:                }
07659:
07660:                /*
07661:                  for(i=0; i<coord1.length; i++)
07662:                  System.err.println("coord1 P" + i + " " + coord1[i]);
07663:                  for(i=0; i<coord2.length; i++)
07664:                  System.err.println("coord2 P" + i + " " + coord2[i]);
07665:                 */
07666:
07667:                pNrm.cross(vec0, vec1);
07668:
07669:                if (pNrm.length() == 0.0) {
07670:                    // System.err.println("(2) Degenerate polygon.");
07671:                    return false; // Degenerate polygon.
07672:                }
07673:
07674:                j = 0;
07675:                Point3d seg[] = new Point3d[2];
07676:                seg[0] = new Point3d();
07677:                seg[1] = new Point3d();
07678:
07679:                for (i = 0; i < coord2.length; i++) {
07680:                    if (i < (coord2.length - 1))
07681:                        epFlag = edgeIntersectPlane(pNrm, coord1[0], coord2[i],
07682:                                coord2[i + 1], seg[j]);
07683:                    else
07684:                        epFlag = edgeIntersectPlane(pNrm, coord1[0], coord2[i],
07685:                                coord2[0], seg[j]);
07686:                    if (epFlag) {
07687:                        if (++j > 1) {
07688:                            break;
07689:                        }
07690:                    }
07691:                }
07692:
07693:                if (j == 0) {
07694:                    return false;
07695:                }
07696:
07697:                if (coord2.length < 3) {
07698:                    boolean toreturn = pointIntersectPolygon2D(pNrm, coord1,
07699:                            seg[0]);
07700:                    return toreturn;
07701:                } else {
07702:                    boolean toreturn = edgeIntersectPolygon2D(pNrm, coord1, seg);
07703:                    return toreturn;
07704:                }
07705:            }
07706:
07707:            /**
07708:             * Return true if triangle or quad intersects with ray and the
07709:             * distance is stored in dist[0] and the intersect point in iPnt
07710:             * (if iPnt is not null).
07711:             */
07712:            boolean intersectRay(Point3d coordinates[], PickRay ray,
07713:                    double dist[], Point3d iPnt) {
07714:
07715:                return intersectRayOrSegment(coordinates, ray.direction,
07716:                        ray.origin, dist, iPnt, false);
07717:
07718:            }
07719:
07720:            /**
07721:             * Return true if triangle or quad intersects with segment and
07722:             * the distance is stored in dist[0].
07723:             */
07724:            boolean intersectSegment(Point3d coordinates[], Point3d start,
07725:                    Point3d end, double dist[], Point3d iPnt) {
07726:                boolean result;
07727:                Vector3d direction = new Vector3d();
07728:                direction.x = end.x - start.x;
07729:                direction.y = end.y - start.y;
07730:                direction.z = end.z - start.z;
07731:                result = intersectRayOrSegment(coordinates, direction, start,
07732:                        dist, iPnt, true);
07733:                return result;
07734:            }
07735:
07736:            /**
07737:             *  Return true if triangle or quad intersects with ray and the distance is
07738:             *  stored in pr.
07739:             */
07740:            boolean intersectRayOrSegment(Point3d coordinates[],
07741:                    Vector3d direction, Point3d origin, double dist[],
07742:                    Point3d iPnt, boolean isSegment) {
07743:                Vector3d vec0, vec1, pNrm, tempV3d;
07744:                vec0 = new Vector3d();
07745:                vec1 = new Vector3d();
07746:                pNrm = new Vector3d();
07747:
07748:                double absNrmX, absNrmY, absNrmZ, pD = 0.0;
07749:                double pNrmDotrDir = 0.0;
07750:
07751:                boolean isIntersect = false;
07752:                int i, j, k = 0, l = 0;
07753:
07754:                // Compute plane normal.
07755:                for (i = 0; i < coordinates.length; i++) {
07756:                    if (i != coordinates.length - 1) {
07757:                        l = i + 1;
07758:                    } else {
07759:                        l = 0;
07760:                    }
07761:                    vec0.x = coordinates[l].x - coordinates[i].x;
07762:                    vec0.y = coordinates[l].y - coordinates[i].y;
07763:                    vec0.z = coordinates[l].z - coordinates[i].z;
07764:                    if (vec0.length() > 0.0) {
07765:                        break;
07766:                    }
07767:                }
07768:
07769:                for (j = l; j < coordinates.length; j++) {
07770:                    if (j != coordinates.length - 1) {
07771:                        k = j + 1;
07772:                    } else {
07773:                        k = 0;
07774:                    }
07775:                    vec1.x = coordinates[k].x - coordinates[j].x;
07776:                    vec1.y = coordinates[k].y - coordinates[j].y;
07777:                    vec1.z = coordinates[k].z - coordinates[j].z;
07778:                    if (vec1.length() > 0.0) {
07779:                        break;
07780:                    }
07781:                }
07782:
07783:                pNrm.cross(vec0, vec1);
07784:
07785:                if ((vec1.length() == 0) || (pNrm.length() == 0)) {
07786:                    // degenerate to line if vec0.length() == 0
07787:                    // or vec0.length > 0 and vec0 parallel to vec1
07788:                    k = (l == 0 ? coordinates.length - 1 : l - 1);
07789:                    isIntersect = intersectLineAndRay(coordinates[l],
07790:                            coordinates[k], origin, direction, dist, iPnt);
07791:
07792:                    // put the Vectors on the freelist
07793:                    return isIntersect;
07794:                }
07795:
07796:                // It is possible that Quad is degenerate to Triangle
07797:                // at this point
07798:
07799:                pNrmDotrDir = pNrm.dot(direction);
07800:
07801:                // Ray is parallel to plane.
07802:                if (pNrmDotrDir == 0.0) {
07803:                    // Ray is parallel to plane
07804:                    // Check line/triangle intersection on plane.
07805:                    for (i = 0; i < coordinates.length; i++) {
07806:                        if (i != coordinates.length - 1) {
07807:                            k = i + 1;
07808:                        } else {
07809:                            k = 0;
07810:                        }
07811:                        if (intersectLineAndRay(coordinates[i], coordinates[k],
07812:                                origin, direction, dist, iPnt)) {
07813:                            isIntersect = true;
07814:                            break;
07815:                        }
07816:                    }
07817:                    return isIntersect;
07818:                }
07819:
07820:                // Plane equation: (p - p0)*pNrm = 0 or p*pNrm = pD;
07821:                tempV3d = new Vector3d();
07822:                tempV3d.set((Tuple3d) coordinates[0]);
07823:                pD = pNrm.dot(tempV3d);
07824:                tempV3d.set((Tuple3d) origin);
07825:
07826:                // Substitute Ray equation:
07827:                // p = origin + pi.distance*direction
07828:                // into the above Plane equation
07829:
07830:                dist[0] = (pD - pNrm.dot(tempV3d)) / pNrmDotrDir;
07831:
07832:                // Ray intersects the plane behind the ray's origin.
07833:                if ((dist[0] < -EPS) || (isSegment && (dist[0] > 1.0 + EPS))) {
07834:                    // Ray intersects the plane behind the ray's origin
07835:                    // or intersect point not fall in Segment
07836:                    return false;
07837:                }
07838:
07839:                // Now, one thing for sure the ray intersect the plane.
07840:                // Find the intersection point.
07841:                if (iPnt == null) {
07842:                    iPnt = new Point3d();
07843:                }
07844:                iPnt.x = origin.x + direction.x * dist[0];
07845:                iPnt.y = origin.y + direction.y * dist[0];
07846:                iPnt.z = origin.z + direction.z * dist[0];
07847:
07848:                // Project 3d points onto 2d plane
07849:                // Find the axis so that area of projection is maximize.
07850:                absNrmX = Math.abs(pNrm.x);
07851:                absNrmY = Math.abs(pNrm.y);
07852:                absNrmZ = Math.abs(pNrm.z);
07853:
07854:                // All sign of (y - y0) (x1 - x0) - (x - x0) (y1 - y0)
07855:                // must agree.
07856:                double sign, t, lastSign = 0;
07857:                Point3d p0 = coordinates[coordinates.length - 1];
07858:                Point3d p1 = coordinates[0];
07859:
07860:                isIntersect = true;
07861:
07862:                if (absNrmX > absNrmY) {
07863:                    if (absNrmX < absNrmZ) {
07864:                        for (i = 0; i < coordinates.length; i++) {
07865:                            p0 = coordinates[i];
07866:                            p1 = (i != coordinates.length - 1 ? coordinates[i + 1]
07867:                                    : coordinates[0]);
07868:                            sign = (iPnt.y - p0.y) * (p1.x - p0.x)
07869:                                    - (iPnt.x - p0.x) * (p1.y - p0.y);
07870:                            if (isNonZero(sign)) {
07871:                                if (sign * lastSign < 0) {
07872:                                    isIntersect = false;
07873:                                    break;
07874:                                }
07875:                                lastSign = sign;
07876:                            } else { // point on line, check inside interval
07877:                                t = p1.y - p0.y;
07878:                                if (isNonZero(t)) {
07879:                                    t = (iPnt.y - p0.y) / t;
07880:                                    isIntersect = ((t > -EPS) && (t < 1 + EPS));
07881:                                    break;
07882:                                } else {
07883:                                    t = p1.x - p0.x;
07884:                                    if (isNonZero(t)) {
07885:                                        t = (iPnt.x - p0.x) / t;
07886:                                        isIntersect = ((t > -EPS) && (t < 1 + EPS));
07887:                                        break;
07888:                                    } else {
07889:                                        // Ignore degenerate line=>point happen when Quad => Triangle.
07890:                                        // Note that by next round sign*lastSign = 0 so it will
07891:                                        // not pass the interest test. This should only happen once in the
07892:                                        // loop because we already check for degenerate geometry before.
07893:                                    }
07894:                                }
07895:                            }
07896:                        }
07897:                    } else {
07898:                        for (i = 0; i < coordinates.length; i++) {
07899:                            p0 = coordinates[i];
07900:                            p1 = (i != coordinates.length - 1 ? coordinates[i + 1]
07901:                                    : coordinates[0]);
07902:                            sign = (iPnt.y - p0.y) * (p1.z - p0.z)
07903:                                    - (iPnt.z - p0.z) * (p1.y - p0.y);
07904:                            if (isNonZero(sign)) {
07905:                                if (sign * lastSign < 0) {
07906:                                    isIntersect = false;
07907:                                    break;
07908:                                }
07909:                                lastSign = sign;
07910:                            } else { // point on line, check inside interval
07911:                                t = p1.y - p0.y;
07912:
07913:                                if (isNonZero(t)) {
07914:                                    t = (iPnt.y - p0.y) / t;
07915:                                    isIntersect = ((t > -EPS) && (t < 1 + EPS));
07916:                                    break;
07917:
07918:                                } else {
07919:                                    t = p1.z - p0.z;
07920:                                    if (isNonZero(t)) {
07921:                                        t = (iPnt.z - p0.z) / t;
07922:                                        isIntersect = ((t > -EPS) && (t < 1 + EPS));
07923:                                        break;
07924:                                    } else {
07925:                                        //degenerate line=>point
07926:                                    }
07927:                                }
07928:                            }
07929:                        }
07930:                    }
07931:                } else {
07932:                    if (absNrmY < absNrmZ) {
07933:                        for (i = 0; i < coordinates.length; i++) {
07934:                            p0 = coordinates[i];
07935:                            p1 = (i != coordinates.length - 1 ? coordinates[i + 1]
07936:                                    : coordinates[0]);
07937:                            sign = (iPnt.y - p0.y) * (p1.x - p0.x)
07938:                                    - (iPnt.x - p0.x) * (p1.y - p0.y);
07939:                            if (isNonZero(sign)) {
07940:                                if (sign * lastSign < 0) {
07941:                                    isIntersect = false;
07942:                                    break;
07943:                                }
07944:                                lastSign = sign;
07945:                            } else { // point on line, check inside interval
07946:                                t = p1.y - p0.y;
07947:                                if (isNonZero(t)) {
07948:                                    t = (iPnt.y - p0.y) / t;
07949:                                    isIntersect = ((t > -EPS) && (t < 1 + EPS));
07950:                                    break;
07951:                                } else {
07952:                                    t = p1.x - p0.x;
07953:                                    if (isNonZero(t)) {
07954:                                        t = (iPnt.x - p0.x) / t;
07955:                                        isIntersect = ((t > -EPS) && (t < 1 + EPS));
07956:                                        break;
07957:                                    } else {
07958:                                        //degenerate line=>point
07959:                                    }
07960:                                }
07961:                            }
07962:                        }
07963:                    } else {
07964:                        for (i = 0; i < coordinates.length; i++) {
07965:                            p0 = coordinates[i];
07966:                            p1 = (i != coordinates.length - 1 ? coordinates[i + 1]
07967:                                    : coordinates[0]);
07968:                            sign = (iPnt.x - p0.x) * (p1.z - p0.z)
07969:                                    - (iPnt.z - p0.z) * (p1.x - p0.x);
07970:                            if (isNonZero(sign)) {
07971:                                if (sign * lastSign < 0) {
07972:                                    isIntersect = false;
07973:                                    break;
07974:                                }
07975:                                lastSign = sign;
07976:                            } else { // point on line, check inside interval
07977:                                t = p1.x - p0.x;
07978:                                if (isNonZero(t)) {
07979:                                    t = (iPnt.x - p0.x) / t;
07980:                                    isIntersect = ((t > -EPS) && (t < 1 + EPS));
07981:                                    break;
07982:                                } else {
07983:                                    t = p1.z - p0.z;
07984:                                    if (isNonZero(t)) {
07985:                                        t = (iPnt.z - p0.z) / t;
07986:                                        isIntersect = ((t > -EPS) && (t < 1 + EPS));
07987:                                        break;
07988:                                    } else {
07989:                                        //degenerate line=>point
07990:                                    }
07991:                                }
07992:                            }
07993:                        }
07994:                    }
07995:                }
07996:
07997:                if (isIntersect) {
07998:                    dist[0] *= direction.length();
07999:                }
08000:                return isIntersect;
08001:            }
08002:
08003:            static final boolean isNonZero(double v) {
08004:                return ((v > EPS) || (v < -EPS));
08005:
08006:            }
08007:
08008:            /**
08009:             * Return true if point is on the inside of halfspace test. The
08010:             * halfspace is partition by the plane of triangle or quad.
08011:             */
08012:            boolean inside(Point3d coordinates[], PickPoint point, int ccw) {
08013:
08014:                Vector3d vec0 = new Vector3d(); // Edge vector from point 0 to point 1;
08015:                Vector3d vec1 = new Vector3d(); // Edge vector from point 0 to point 2 or 3;
08016:                Vector3d pNrm = new Vector3d();
08017:                double absNrmX, absNrmY, absNrmZ, pD = 0.0;
08018:                Vector3d tempV3d = new Vector3d();
08019:                double pNrmDotrDir = 0.0;
08020:
08021:                double tempD;
08022:
08023:                int i, j;
08024:
08025:                // Compute plane normal.
08026:                for (i = 0; i < coordinates.length - 1;) {
08027:                    vec0.x = coordinates[i + 1].x - coordinates[i].x;
08028:                    vec0.y = coordinates[i + 1].y - coordinates[i].y;
08029:                    vec0.z = coordinates[i + 1].z - coordinates[i++].z;
08030:                    if (vec0.length() > 0.0)
08031:                        break;
08032:                }
08033:
08034:                for (j = i; j < coordinates.length - 1; j++) {
08035:                    vec1.x = coordinates[j + 1].x - coordinates[j].x;
08036:                    vec1.y = coordinates[j + 1].y - coordinates[j].y;
08037:                    vec1.z = coordinates[j + 1].z - coordinates[j].z;
08038:                    if (vec1.length() > 0.0)
08039:                        break;
08040:                }
08041:
08042:                if (j == (coordinates.length - 1)) {
08043:                    // System.err.println("(1) Degenerate polygon.");
08044:                    return false; // Degenerate polygon.
08045:                }
08046:
08047:                /*
08048:                   System.err.println("Ray orgin : " + ray.origin + " dir " + ray.direction);
08049:                   System.err.println("Triangle/Quad :");
08050:                   for(i=0; i<coordinates.length; i++)
08051:                   System.err.println("P" + i + " " + coordinates[i]);
08052:                 */
08053:
08054:                if (ccw == 0x1)
08055:                    pNrm.cross(vec0, vec1);
08056:                else
08057:                    pNrm.cross(vec1, vec0);
08058:
08059:                if (pNrm.length() == 0.0) {
08060:                    // System.err.println("(2) Degenerate polygon.");
08061:                    return false; // Degenerate polygon.
08062:                }
08063:                // Compute plane D.
08064:                tempV3d.set((Tuple3d) coordinates[0]);
08065:                pD = pNrm.dot(tempV3d);
08066:                tempV3d.set((Tuple3d) point.location);
08067:
08068:                return ((pD - pNrm.dot(tempV3d)) <= 0);
08069:            }
08070:
08071:            boolean intersectPntAndPnt(Point3d pnt1, Point3d pnt2) {
08072:                return ((pnt1.x == pnt2.x) && (pnt1.y == pnt2.y) && (pnt1.z == pnt2.z));
08073:            }
08074:
08075:            boolean intersectPntAndRay(Point3d pnt, Point3d ori, Vector3d dir,
08076:                    double dist[]) {
08077:                int flag = 0;
08078:                double temp;
08079:
08080:                if (dir.x != 0.0) {
08081:                    flag = 0;
08082:                    dist[0] = (pnt.x - ori.x) / dir.x;
08083:                } else if (dir.y != 0.0) {
08084:                    if (pnt.x != ori.x)
08085:                        return false;
08086:                    flag = 1;
08087:                    dist[0] = (pnt.y - ori.y) / dir.y;
08088:                } else if (dir.z != 0.0) {
08089:                    if ((pnt.x != ori.x) || (pnt.y != ori.y))
08090:                        return false;
08091:                    flag = 2;
08092:                    dist[0] = (pnt.z - ori.z) / dir.z;
08093:
08094:                } else
08095:                    return false;
08096:
08097:                if (dist[0] < 0.0)
08098:                    return false;
08099:
08100:                if (flag == 0) {
08101:                    temp = ori.y + dist[0] * dir.y;
08102:                    if ((pnt.y < (temp - EPS)) || (pnt.y > (temp + EPS)))
08103:                        return false;
08104:                }
08105:
08106:                if (flag < 2) {
08107:                    temp = ori.z + dist[0] * dir.z;
08108:                    if ((pnt.z < (temp - EPS)) || (pnt.z > (temp + EPS)))
08109:                        return false;
08110:                }
08111:
08112:                return true;
08113:
08114:            }
08115:
08116:            boolean intersectLineAndRay(Point3d start, Point3d end,
08117:                    Point3d ori, Vector3d dir, double dist[], Point3d iPnt) {
08118:
08119:                double m00, m01, m10, m11;
08120:                double mInv00, mInv01, mInv10, mInv11;
08121:                double dmt, t, s, tmp1, tmp2;
08122:                Vector3d lDir;
08123:
08124:                //     System.err.println("GeometryArrayRetained : intersectLineAndRay");
08125:                //     System.err.println("start " + start + " end " + end );
08126:                //     System.err.println("ori " + ori + " dir " + dir);
08127:
08128:                lDir = new Vector3d();
08129:                lDir.x = (end.x - start.x);
08130:                lDir.y = (end.y - start.y);
08131:                lDir.z = (end.z - start.z);
08132:
08133:                m00 = lDir.x;
08134:                m01 = -dir.x;
08135:                m10 = lDir.y;
08136:                m11 = -dir.y;
08137:
08138:                // Get the determinant.
08139:                dmt = (m00 * m11) - (m10 * m01);
08140:
08141:                if (dmt == 0.0) { // No solution, check degenerate line
08142:                    boolean isIntersect = false;
08143:                    if ((lDir.x == 0) && (lDir.y == 0) && (lDir.z == 0)) {
08144:                        isIntersect = intersectPntAndRay(start, ori, dir, dist);
08145:                        if (isIntersect && (iPnt != null)) {
08146:                            iPnt.set(start);
08147:                        }
08148:                    }
08149:                    return isIntersect;
08150:                }
08151:                // Find the inverse.
08152:                tmp1 = 1 / dmt;
08153:
08154:                mInv00 = tmp1 * m11;
08155:                mInv01 = tmp1 * (-m01);
08156:                mInv10 = tmp1 * (-m10);
08157:                mInv11 = tmp1 * m00;
08158:
08159:                tmp1 = ori.x - start.x;
08160:                tmp2 = ori.y - start.y;
08161:
08162:                t = mInv00 * tmp1 + mInv01 * tmp2;
08163:                s = mInv10 * tmp1 + mInv11 * tmp2;
08164:
08165:                if (s < 0.0) { // Before the origin of ray.
08166:                    // System.err.println("Before the origin of ray " + s);
08167:                    return false;
08168:                }
08169:                if ((t < 0) || (t > 1.0)) {// Before or after the end points of line.
08170:                    // System.err.println("Before or after the end points of line. " + t);
08171:                    return false;
08172:                }
08173:
08174:                tmp1 = ori.z + s * dir.z;
08175:                tmp2 = start.z + t * lDir.z;
08176:
08177:                if ((tmp1 < (tmp2 - EPS)) || (tmp1 > (tmp2 + EPS))) {
08178:                    // System.err.println("No intersection : tmp1 " + tmp1 + " tmp2 " + tmp2);
08179:                    return false;
08180:                }
08181:
08182:                dist[0] = s;
08183:
08184:                if (iPnt != null) {
08185:                    // compute point of intersection.
08186:                    iPnt.x = ori.x + dir.x * dist[0];
08187:                    iPnt.y = ori.y + dir.y * dist[0];
08188:                    iPnt.z = ori.z + dir.z * dist[0];
08189:                }
08190:
08191:                // System.err.println("Intersected : tmp1 " + tmp1 + " tmp2 " + tmp2);
08192:                return true;
08193:            }
08194:
08195:            /**
08196:              Return true if triangle or quad intersects with cylinder. The
08197:              distance is stored in dist.
08198:             */
08199:            boolean intersectCylinder(Point3d coordinates[], PickCylinder cyl,
08200:                    double dist[], Point3d iPnt) {
08201:
08202:                Point3d origin = new Point3d();
08203:                Point3d end = new Point3d();
08204:                Vector3d direction = new Vector3d();
08205:                Point3d iPnt1 = new Point3d();
08206:                Vector3d originToIpnt = new Vector3d();
08207:
08208:                if (iPnt == null) {
08209:                    iPnt = new Point3d();
08210:                }
08211:
08212:                // Get cylinder information
08213:                cyl.getOrigin(origin);
08214:                cyl.getDirection(direction);
08215:                double radius = cyl.getRadius();
08216:
08217:                if (cyl instanceof  PickCylinderSegment) {
08218:                    ((PickCylinderSegment) cyl).getEnd(end);
08219:                }
08220:
08221:                // If the ray intersects, we're good (do not do this if we only have
08222:                // a segment
08223:                if (coordinates.length > 2) {
08224:                    if (cyl instanceof  PickCylinderRay) {
08225:                        if (intersectRay(coordinates, new PickRay(origin,
08226:                                direction), dist, iPnt)) {
08227:                            return true;
08228:                        }
08229:                    } else {
08230:                        if (intersectSegment(coordinates, origin, end, dist,
08231:                                iPnt)) {
08232:                            return true;
08233:                        }
08234:                    }
08235:                }
08236:
08237:                // Ray doesn't intersect, check distance to edges
08238:                double sqDistToEdge;
08239:                int j;
08240:                for (int i = 0; i < coordinates.length; i++) {
08241:                    j = (i < coordinates.length - 1 ? i + 1 : 0);
08242:                    if (cyl instanceof  PickCylinderSegment) {
08243:                        sqDistToEdge = Distance.segmentToSegment(origin, end,
08244:                                coordinates[i], coordinates[j], iPnt1, iPnt,
08245:                                null);
08246:                    } else {
08247:                        sqDistToEdge = Distance.rayToSegment(origin, direction,
08248:                                coordinates[i], coordinates[j], iPnt1, iPnt,
08249:                                null);
08250:                    }
08251:                    if (sqDistToEdge <= radius * radius) {
08252:                        originToIpnt.sub(iPnt1, origin);
08253:                        dist[0] = originToIpnt.length();
08254:                        return true;
08255:                    }
08256:                }
08257:                return false;
08258:            }
08259:
08260:            /**
08261:              Return true if triangle or quad intersects with cone. The
08262:              distance is stored in dist.
08263:             */
08264:            boolean intersectCone(Point3d coordinates[], PickCone cone,
08265:                    double[] dist, Point3d iPnt) {
08266:
08267:                Point3d origin = new Point3d();
08268:                Point3d end = new Point3d();
08269:                Vector3d direction = new Vector3d();
08270:                Vector3d originToIpnt = new Vector3d();
08271:                double distance;
08272:
08273:                Point3d iPnt1 = new Point3d();
08274:                Vector3d vector = new Vector3d();
08275:
08276:                if (iPnt == null) {
08277:                    iPnt = new Point3d();
08278:                }
08279:                // Get cone information
08280:                cone.getOrigin(origin);
08281:                cone.getDirection(direction);
08282:                double radius;
08283:
08284:                if (cone instanceof  PickConeSegment) {
08285:                    ((PickConeSegment) cone).getEnd(end);
08286:                }
08287:
08288:                // If the ray intersects, we're good (do not do this if we only have
08289:                // a segment
08290:                if (coordinates.length > 2) {
08291:                    if (cone instanceof  PickConeRay) {
08292:                        if (intersectRay(coordinates, new PickRay(origin,
08293:                                direction), dist, iPnt)) {
08294:                            return true;
08295:                        }
08296:                    } else {
08297:                        if (intersectSegment(coordinates, origin, end, dist,
08298:                                iPnt)) {
08299:                            return true;
08300:                        }
08301:                    }
08302:                }
08303:
08304:                // Ray doesn't intersect, check distance to edges
08305:                double sqDistToEdge;
08306:                int j = 0;
08307:                for (int i = 0; i < coordinates.length; i++) {
08308:                    j = (i < coordinates.length - 1 ? i + 1 : 0);
08309:                    if (cone instanceof  PickConeSegment) {
08310:                        sqDistToEdge = Distance.segmentToSegment(origin, end,
08311:                                coordinates[i], coordinates[j], iPnt1, iPnt,
08312:                                null);
08313:                    } else {
08314:                        sqDistToEdge = Distance.rayToSegment(origin, direction,
08315:                                coordinates[i], coordinates[j], iPnt1, iPnt,
08316:                                null);
08317:                    }
08318:                    originToIpnt.sub(iPnt1, origin);
08319:                    distance = originToIpnt.length();
08320:                    radius = Math.tan(cone.getSpreadAngle()) * distance;
08321:                    if (sqDistToEdge <= radius * radius) {
08322:                        //	System.err.println ("intersectCone: edge "+i+" intersected");
08323:                        dist[0] = distance;
08324:                        return true;
08325:                    }
08326:                }
08327:                return false;
08328:            }
08329:
08330:            /**
08331:              Return true if point intersects with cylinder and the distance is
08332:              stored in dist.
08333:             */
08334:            boolean intersectCylinder(Point3d pt, PickCylinder cyl,
08335:                    double[] dist) {
08336:
08337:                Point3d origin = new Point3d();
08338:                Point3d end = new Point3d();
08339:                Vector3d direction = new Vector3d();
08340:                Point3d iPnt = new Point3d();
08341:                Vector3d originToIpnt = new Vector3d();
08342:
08343:                // Get cylinder information
08344:                cyl.getOrigin(origin);
08345:                cyl.getDirection(direction);
08346:                double radius = cyl.getRadius();
08347:                double sqDist;
08348:
08349:                if (cyl instanceof  PickCylinderSegment) {
08350:                    ((PickCylinderSegment) cyl).getEnd(end);
08351:                    sqDist = Distance.pointToSegment(pt, origin, end, iPnt,
08352:                            null);
08353:                } else {
08354:                    sqDist = Distance.pointToRay(pt, origin, direction, iPnt,
08355:                            null);
08356:                }
08357:                if (sqDist <= radius * radius) {
08358:                    originToIpnt.sub(iPnt, origin);
08359:                    dist[0] = originToIpnt.length();
08360:                    return true;
08361:                }
08362:                return false;
08363:            }
08364:
08365:            /**
08366:              Return true if point intersects with cone and the
08367:              distance is stored in pi.
08368:             */
08369:            boolean intersectCone(Point3d pt, PickCone cone, double[] dist) {
08370:                Point3d origin = new Point3d();
08371:                Point3d end = new Point3d();
08372:                Vector3d direction = new Vector3d();
08373:                Point3d iPnt = new Point3d();
08374:                Vector3d originToIpnt = new Vector3d();
08375:
08376:                // Get cone information
08377:                cone.getOrigin(origin);
08378:                cone.getDirection(direction);
08379:                double radius;
08380:                double distance;
08381:                double sqDist;
08382:
08383:                if (iPnt == null) {
08384:                    iPnt = new Point3d();
08385:                }
08386:
08387:                if (cone instanceof  PickConeSegment) {
08388:                    ((PickConeSegment) cone).getEnd(end);
08389:                    sqDist = Distance.pointToSegment(pt, origin, end, iPnt,
08390:                            null);
08391:                } else {
08392:                    sqDist = Distance.pointToRay(pt, origin, direction, iPnt,
08393:                            null);
08394:                }
08395:                originToIpnt.sub(iPnt, origin);
08396:                distance = originToIpnt.length();
08397:                radius = Math.tan(cone.getSpreadAngle()) * distance;
08398:                if (sqDist <= radius * radius) {
08399:                    dist[0] = distance;
08400:                    return true;
08401:                }
08402:                return false;
08403:            }
08404:
08405:            void setCoordRefBuffer(J3DBuffer coords) {
08406:                if (coords != null) {
08407:                    switch (coords.getBufferType()) {
08408:                    case J3DBuffer.TYPE_FLOAT:
08409:                        assert ((FloatBufferWrapper) coords.getBufferImpl())
08410:                                .isDirect();
08411:                        break;
08412:                    case J3DBuffer.TYPE_DOUBLE:
08413:                        assert ((DoubleBufferWrapper) coords.getBufferImpl())
08414:                                .isDirect();
08415:                        break;
08416:                    case J3DBuffer.TYPE_NULL:
08417:                        throw new IllegalArgumentException(J3dI18N
08418:                                .getString("GeometryArray115"));
08419:
08420:                    default:
08421:                        throw new IllegalArgumentException(J3dI18N
08422:                                .getString("GeometryArray116"));
08423:                    }
08424:
08425:                    if (this  instanceof  IndexedGeometryArrayRetained) {
08426:                        IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained) this ;
08427:                        if (3 * idx.maxCoordIndex >= coords.getBufferImpl()
08428:                                .limit()) {
08429:                            throw new ArrayIndexOutOfBoundsException(J3dI18N
08430:                                    .getString("IndexedGeometryArray23"));
08431:                        }
08432:                    } else if (coords.getBufferImpl().limit() < (3 * (initialCoordIndex + validVertexCount))) {
08433:                        throw new ArrayIndexOutOfBoundsException(J3dI18N
08434:                                .getString("GeometryArray99"));
08435:                    }
08436:                }
08437:
08438:                // lock the geometry and start to do real work
08439:                boolean isLive = source != null && source.isLive();
08440:                if (isLive) {
08441:                    geomLock.getLock();
08442:                }
08443:                dirtyFlag |= COORDINATE_CHANGED;
08444:                coordRefBuffer = coords;
08445:                if (coords == null) {
08446:                    floatBufferRefCoords = null;
08447:                    doubleBufferRefCoords = null;
08448:                    // XXXX: if not mix java array with nio buffer
08449:                    // vertexType can be used as vertexTypeBuffer
08450:                    vertexType &= ~PD;
08451:                    vertexType &= ~PF;
08452:                } else {
08453:                    switch (coords.getBufferType()) {
08454:                    case J3DBuffer.TYPE_FLOAT:
08455:                        floatBufferRefCoords = (FloatBufferWrapper) coords
08456:                                .getBufferImpl();
08457:                        doubleBufferRefCoords = null;
08458:                        vertexType |= PF;
08459:                        vertexType &= ~PD;
08460:                        break;
08461:                    case J3DBuffer.TYPE_DOUBLE:
08462:                        floatBufferRefCoords = null;
08463:                        doubleBufferRefCoords = (DoubleBufferWrapper) coords
08464:                                .getBufferImpl();
08465:                        vertexType |= PD;
08466:                        vertexType &= ~PF;
08467:                        break;
08468:                    default:
08469:                        break;
08470:                    }
08471:                }
08472:
08473:                // need not call setupMirrorVertexPointer() since
08474:                // we are not going to set mirror in NIO buffer case
08475:                // XXXX: if we need to mix java array with buffer,
08476:                //        we may need to consider setupMirrorVertexPointer()
08477:
08478:                if (isLive) {
08479:                    geomLock.unLock();
08480:                }
08481:                if (!inUpdater && source != null) {
08482:                    if (isLive) {
08483:                        processCoordsChanged((coords == null));
08484:                        sendDataChangedMessage(true);
08485:                    } else {
08486:                        boundsDirty = true;
08487:                    }
08488:                }
08489:
08490:            }
08491:
08492:            J3DBuffer getCoordRefBuffer() {
08493:                return coordRefBuffer;
08494:            }
08495:
08496:            void setCoordRefFloat(float[] coords) {
08497:
08498:                // If non-null coordinate and vertType is either  defined
08499:                // to be something other than PF, then issue an error
08500:                if (coords != null) {
08501:                    if ((vertexType & VERTEX_DEFINED) != 0
08502:                            && (vertexType & VERTEX_DEFINED) != PF) {
08503:                        throw new IllegalArgumentException(J3dI18N
08504:                                .getString("GeometryArray98"));
08505:                    }
08506:
08507:                    if (this  instanceof  IndexedGeometryArrayRetained) {
08508:                        IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained) this ;
08509:
08510:                        if (3 * idx.maxCoordIndex >= coords.length) {
08511:                            throw new ArrayIndexOutOfBoundsException(J3dI18N
08512:                                    .getString("IndexedGeometryArray23"));
08513:                        }
08514:                    } else if (coords.length < 3 * (initialCoordIndex + validVertexCount)) {
08515:                        throw new ArrayIndexOutOfBoundsException(J3dI18N
08516:                                .getString("GeometryArray99"));
08517:                    }
08518:                }
08519:                boolean isLive = source != null && source.isLive();
08520:                if (isLive) {
08521:                    geomLock.getLock();
08522:                }
08523:                dirtyFlag |= COORDINATE_CHANGED;
08524:
08525:                floatRefCoords = coords;
08526:                if (inUpdater
08527:                        || (this  instanceof  IndexedGeometryArrayRetained && ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
08528:                    if (coords == null)
08529:                        vertexType &= ~PF;
08530:                    else
08531:                        vertexType |= PF;
08532:                } else {
08533:                    setupMirrorVertexPointer(PF);
08534:                }
08535:
08536:                if (isLive) {
08537:                    geomLock.unLock();
08538:                }
08539:                if (!inUpdater && source != null) {
08540:                    if (isLive) {
08541:                        processCoordsChanged(coords == null);
08542:                        sendDataChangedMessage(true);
08543:                    } else {
08544:                        boundsDirty = true;
08545:                    }
08546:                }
08547:            }
08548:
08549:            float[] getCoordRefFloat() {
08550:                return floatRefCoords;
08551:            }
08552:
08553:            void setCoordRefDouble(double[] coords) {
08554:
08555:                if (coords != null) {
08556:                    if ((vertexType & VERTEX_DEFINED) != 0
08557:                            && (vertexType & VERTEX_DEFINED) != PD) {
08558:                        throw new IllegalArgumentException(J3dI18N
08559:                                .getString("GeometryArray98"));
08560:                    }
08561:
08562:                    if (this  instanceof  IndexedGeometryArrayRetained) {
08563:                        IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained) this ;
08564:                        if (3 * idx.maxCoordIndex >= coords.length) {
08565:                            throw new ArrayIndexOutOfBoundsException(J3dI18N
08566:                                    .getString("IndexedGeometryArray23"));
08567:                        }
08568:                    } else if (coords.length < 3 * (initialCoordIndex + validVertexCount)) {
08569:                        throw new ArrayIndexOutOfBoundsException(J3dI18N
08570:                                .getString("GeometryArray99"));
08571:                    }
08572:                }
08573:                boolean isLive = source != null && source.isLive();
08574:                if (isLive) {
08575:                    geomLock.getLock();
08576:                }
08577:                dirtyFlag |= COORDINATE_CHANGED;
08578:                doubleRefCoords = coords;
08579:                if (inUpdater
08580:                        || (this  instanceof  IndexedGeometryArrayRetained && ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
08581:                    if (coords == null)
08582:                        vertexType &= ~PD;
08583:                    else
08584:                        vertexType |= PD;
08585:                } else {
08586:                    setupMirrorVertexPointer(PD);
08587:                }
08588:                if (isLive) {
08589:                    geomLock.unLock();
08590:                }
08591:                if (!inUpdater && source != null) {
08592:                    if (isLive) {
08593:                        processCoordsChanged(coords == null);
08594:                        sendDataChangedMessage(true);
08595:                    } else {
08596:                        boundsDirty = true;
08597:                    }
08598:                }
08599:            }
08600:
08601:            double[] getCoordRefDouble() {
08602:                return doubleRefCoords;
08603:            }
08604:
08605:            void setCoordRef3f(Point3f[] coords) {
08606:
08607:                if (coords != null) {
08608:                    if ((vertexType & VERTEX_DEFINED) != 0
08609:                            && (vertexType & VERTEX_DEFINED) != P3F) {
08610:                        throw new IllegalArgumentException(J3dI18N
08611:                                .getString("GeometryArray98"));
08612:                    }
08613:
08614:                    if (this  instanceof  IndexedGeometryArrayRetained) {
08615:                        IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained) this ;
08616:
08617:                        if (idx.maxCoordIndex >= coords.length) {
08618:                            throw new ArrayIndexOutOfBoundsException(J3dI18N
08619:                                    .getString("IndexedGeometryArray23"));
08620:                        }
08621:                    } else if (coords.length < (initialCoordIndex + validVertexCount)) {
08622:                        throw new ArrayIndexOutOfBoundsException(J3dI18N
08623:                                .getString("GeometryArray99"));
08624:                    }
08625:                }
08626:                boolean isLive = source != null && source.isLive();
08627:                if (isLive) {
08628:                    geomLock.getLock();
08629:                }
08630:                dirtyFlag |= COORDINATE_CHANGED;
08631:                p3fRefCoords = coords;
08632:                if (inUpdater
08633:                        || (this  instanceof  IndexedGeometryArrayRetained && ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
08634:                    if (coords == null)
08635:                        vertexType &= ~P3F;
08636:                    else
08637:                        vertexType |= P3F;
08638:                } else {
08639:                    setupMirrorVertexPointer(P3F);
08640:                }
08641:                if (isLive) {
08642:                    geomLock.unLock();
08643:                }
08644:                if (!inUpdater && source != null) {
08645:                    if (isLive) {
08646:                        processCoordsChanged(coords == null);
08647:                        sendDataChangedMessage(true);
08648:                    } else {
08649:                        boundsDirty = true;
08650:                    }
08651:                }
08652:            }
08653:
08654:            Point3f[] getCoordRef3f() {
08655:                return p3fRefCoords;
08656:
08657:            }
08658:
08659:            void setCoordRef3d(Point3d[] coords) {
08660:
08661:                if (coords != null) {
08662:                    if ((vertexType & VERTEX_DEFINED) != 0
08663:                            && (vertexType & VERTEX_DEFINED) != P3D) {
08664:                        throw new IllegalArgumentException(J3dI18N
08665:                                .getString("GeometryArray98"));
08666:                    }
08667:
08668:                    if (this  instanceof  IndexedGeometryArrayRetained) {
08669:                        IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained) this ;
08670:
08671:                        if (idx.maxCoordIndex >= coords.length) {
08672:                            throw new ArrayIndexOutOfBoundsException(J3dI18N
08673:                                    .getString("IndexedGeometryArray23"));
08674:                        }
08675:                    } else if (coords.length < (initialCoordIndex + validVertexCount)) {
08676:                        throw new ArrayIndexOutOfBoundsException(J3dI18N
08677:                                .getString("GeometryArray99"));
08678:                    }
08679:                }
08680:                boolean isLive = source != null && source.isLive();
08681:                if (isLive) {
08682:                    geomLock.getLock();
08683:                }
08684:                dirtyFlag |= COORDINATE_CHANGED;
08685:                p3dRefCoords = coords;
08686:                if (inUpdater
08687:                        || (this  instanceof  IndexedGeometryArrayRetained && ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
08688:                    if (coords == null)
08689:                        vertexType &= ~P3D;
08690:                    else
08691:                        vertexType |= P3D;
08692:                } else {
08693:                    setupMirrorVertexPointer(P3D);
08694:                }
08695:                if (isLive) {
08696:                    geomLock.unLock();
08697:                }
08698:                if (!inUpdater && source != null) {
08699:                    if (isLive) {
08700:                        processCoordsChanged(coords == null);
08701:                        sendDataChangedMessage(true);
08702:                    } else {
08703:                        boundsDirty = true;
08704:                    }
08705:                }
08706:            }
08707:
08708:            Point3d[] getCoordRef3d() {
08709:                return p3dRefCoords;
08710:            }
08711:
08712:            void setColorRefFloat(float[] colors) {
08713:
08714:                if (colors != null) {
08715:                    if ((vertexType & COLOR_DEFINED) != 0
08716:                            && (vertexType & COLOR_DEFINED) != CF) {
08717:                        throw new IllegalArgumentException(J3dI18N
08718:                                .getString("GeometryArray98"));
08719:                    }
08720:
08721:                    if ((vertexFormat & GeometryArray.COLOR) == 0) {
08722:                        throw new IllegalStateException(J3dI18N
08723:                                .getString("GeometryArray123"));
08724:                    }
08725:
08726:                    if (this  instanceof  IndexedGeometryArrayRetained) {
08727:                        IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained) this ;
08728:
08729:                        if (getColorStride() * idx.maxColorIndex >= colors.length) {
08730:                            throw new ArrayIndexOutOfBoundsException(J3dI18N
08731:                                    .getString("IndexedGeometryArray24"));
08732:                        }
08733:                    } else if (colors.length < getColorStride()
08734:                            * (initialColorIndex + validVertexCount)) {
08735:                        throw new ArrayIndexOutOfBoundsException(J3dI18N
08736:                                .getString("GeometryArray112"));
08737:                    }
08738:                }
08739:
08740:                boolean isLive = source != null && source.isLive();
08741:                if (isLive) {
08742:                    geomLock.getLock();
08743:                }
08744:                dirtyFlag |= COLOR_CHANGED;
08745:                colorChanged = 0xffff;
08746:                floatRefColors = colors;
08747:                if (inUpdater
08748:                        || (this  instanceof  IndexedGeometryArrayRetained && ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
08749:                    if (colors == null)
08750:                        vertexType &= ~CF;
08751:                    else
08752:                        vertexType |= CF;
08753:                } else {
08754:                    setupMirrorColorPointer(CF, false);
08755:                }
08756:
08757:                if (isLive) {
08758:                    geomLock.unLock();
08759:                }
08760:                if (!inUpdater && isLive) {
08761:                    sendDataChangedMessage(false);
08762:                }
08763:
08764:            }
08765:
08766:            float[] getColorRefFloat() {
08767:                return floatRefColors;
08768:            }
08769:
08770:            // set the color with nio buffer
08771:            void setColorRefBuffer(J3DBuffer colors) {
08772:                if (colors != null) {
08773:                    switch (colors.getBufferType()) {
08774:                    case J3DBuffer.TYPE_FLOAT:
08775:                        assert ((FloatBufferWrapper) colors.getBufferImpl())
08776:                                .isDirect();
08777:                        break;
08778:                    case J3DBuffer.TYPE_BYTE:
08779:                        assert ((ByteBufferWrapper) colors.getBufferImpl())
08780:                                .isDirect();
08781:                        break;
08782:                    case J3DBuffer.TYPE_NULL:
08783:                        throw new IllegalArgumentException(J3dI18N
08784:                                .getString("GeometryArray115"));
08785:
08786:                    default:
08787:                        throw new IllegalArgumentException(J3dI18N
08788:                                .getString("GeometryArray116"));
08789:                    }
08790:
08791:                    if ((vertexFormat & GeometryArray.COLOR) == 0) {
08792:                        throw new IllegalStateException(J3dI18N
08793:                                .getString("GeometryArray123"));
08794:                    }
08795:
08796:                    if (this  instanceof  IndexedGeometryArrayRetained) {
08797:                        IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained) this ;
08798:
08799:                        if (getColorStride() * idx.maxColorIndex >= colors
08800:                                .getBufferImpl().limit()) {
08801:                            throw new ArrayIndexOutOfBoundsException(J3dI18N
08802:                                    .getString("IndexedGeometryArray24"));
08803:                        }
08804:                    } else if (colors.getBufferImpl().limit() < getColorStride()
08805:                            * (initialColorIndex + validVertexCount)) {
08806:                        throw new ArrayIndexOutOfBoundsException(J3dI18N
08807:                                .getString("GeometryArray112"));
08808:                    }
08809:                }
08810:
08811:                boolean isLive = source != null && source.isLive();
08812:                if (isLive) {
08813:                    geomLock.getLock();
08814:                }
08815:                dirtyFlag |= COLOR_CHANGED;
08816:                colorChanged = 0xffff;
08817:                colorRefBuffer = colors;
08818:                if (colors == null) {
08819:                    floatBufferRefColors = null;
08820:                    byteBufferRefColors = null;
08821:                } else {
08822:                    switch (colors.getBufferType()) {
08823:                    case J3DBuffer.TYPE_FLOAT:
08824:                        floatBufferRefColors = (FloatBufferWrapper) colors
08825:                                .getBufferImpl();
08826:                        byteBufferRefColors = null;
08827:                        break;
08828:
08829:                    case J3DBuffer.TYPE_BYTE:
08830:                        byteBufferRefColors = (ByteBufferWrapper) colors
08831:                                .getBufferImpl();
08832:                        floatBufferRefColors = null;
08833:                        break;
08834:                    default:
08835:                        break;
08836:                    }
08837:                }
08838:                if (inUpdater
08839:                        || (this  instanceof  IndexedGeometryArrayRetained && ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
08840:                    if (colors == null) {
08841:                        vertexType &= ~CF;
08842:                        vertexType &= ~CUB;
08843:                    } else {
08844:                        switch (colors.getBufferType()) {
08845:                        case J3DBuffer.TYPE_FLOAT:
08846:                            vertexType |= CF;
08847:                            vertexType &= ~CUB;
08848:                            break;
08849:
08850:                        case J3DBuffer.TYPE_BYTE:
08851:                            vertexType |= CUB;
08852:                            vertexType &= ~CF;
08853:                            break;
08854:                        default:
08855:                            break;
08856:                        }
08857:                    }
08858:                } else {
08859:                    setupMirrorColorPointer(CF | CUB, false);
08860:                }
08861:
08862:                if (isLive) {
08863:                    geomLock.unLock();
08864:                }
08865:
08866:                if (!inUpdater && isLive) {
08867:                    sendDataChangedMessage(false);
08868:                }
08869:            }
08870:
08871:            // return the color data in nio buffer format
08872:            J3DBuffer getColorRefBuffer() {
08873:                return colorRefBuffer;
08874:            }
08875:
08876:            void setColorRefByte(byte[] colors) {
08877:
08878:                if (colors != null) {
08879:                    if ((vertexType & COLOR_DEFINED) != 0
08880:                            && (vertexType & COLOR_DEFINED) != CUB) {
08881:                        throw new IllegalArgumentException(J3dI18N
08882:                                .getString("GeometryArray98"));
08883:                    }
08884:
08885:                    if ((vertexFormat & GeometryArray.COLOR) == 0) {
08886:                        throw new IllegalStateException(J3dI18N
08887:                                .getString("GeometryArray123"));
08888:                    }
08889:
08890:                    if (this  instanceof  IndexedGeometryArrayRetained) {
08891:                        IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained) this ;
08892:
08893:                        if (getColorStride() * idx.maxColorIndex >= colors.length) {
08894:                            throw new ArrayIndexOutOfBoundsException(J3dI18N
08895:                                    .getString("IndexedGeometryArray24"));
08896:                        }
08897:                    } else if (colors.length < getColorStride()
08898:                            * (initialColorIndex + validVertexCount)) {
08899:                        throw new ArrayIndexOutOfBoundsException(J3dI18N
08900:                                .getString("GeometryArray112"));
08901:                    }
08902:                }
08903:                boolean isLive = source != null && source.isLive();
08904:                if (isLive) {
08905:                    geomLock.getLock();
08906:                }
08907:                dirtyFlag |= COLOR_CHANGED;
08908:                colorChanged = 0xffff;
08909:                byteRefColors = colors;
08910:                if (inUpdater
08911:                        || (this  instanceof  IndexedGeometryArrayRetained && ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
08912:                    if (colors == null)
08913:                        vertexType &= ~CUB;
08914:                    else
08915:                        vertexType |= CUB;
08916:                } else {
08917:                    setupMirrorColorPointer(CUB, false);
08918:                }
08919:                if (isLive) {
08920:                    geomLock.unLock();
08921:                }
08922:
08923:                if (!inUpdater && isLive) {
08924:                    sendDataChangedMessage(false);
08925:                }
08926:
08927:            }
08928:
08929:            byte[] getColorRefByte() {
08930:                return byteRefColors;
08931:            }
08932:
08933:            void setColorRef3f(Color3f[] colors) {
08934:
08935:                if (colors != null) {
08936:                    if ((vertexType & COLOR_DEFINED) != 0
08937:                            && (vertexType & COLOR_DEFINED) != C3F) {
08938:                        throw new IllegalArgumentException(J3dI18N
08939:                                .getString("GeometryArray98"));
08940:                    }
08941:
08942:                    if ((vertexFormat & GeometryArray.COLOR_3) == 0) {
08943:                        throw new IllegalStateException(J3dI18N
08944:                                .getString("GeometryArray92"));
08945:                    }
08946:
08947:                    if (this  instanceof  IndexedGeometryArrayRetained) {
08948:                        IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained) this ;
08949:                        if (idx.maxColorIndex >= colors.length) {
08950:                            throw new ArrayIndexOutOfBoundsException(J3dI18N
08951:                                    .getString("IndexedGeometryArray24"));
08952:                        }
08953:                    } else if (colors.length < (initialColorIndex + validVertexCount)) {
08954:                        throw new ArrayIndexOutOfBoundsException(J3dI18N
08955:                                .getString("GeometryArray112"));
08956:                    }
08957:                }
08958:
08959:                boolean isLive = source != null && source.isLive();
08960:                if (isLive) {
08961:                    geomLock.getLock();
08962:                }
08963:                dirtyFlag |= COLOR_CHANGED;
08964:                colorChanged = 0xffff;
08965:                c3fRefColors = colors;
08966:                if (inUpdater
08967:                        || (this  instanceof  IndexedGeometryArrayRetained && ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
08968:                    if (colors == null)
08969:                        vertexType &= ~C3F;
08970:                    else
08971:                        vertexType |= C3F;
08972:                } else {
08973:                    setupMirrorColorPointer(C3F, false);
08974:                }
08975:
08976:                if (isLive) {
08977:                    geomLock.unLock();
08978:                }
08979:
08980:                if (!inUpdater && isLive) {
08981:                    sendDataChangedMessage(false);
08982:                }
08983:
08984:            }
08985:
08986:            Color3f[] getColorRef3f() {
08987:                return c3fRefColors;
08988:            }
08989:
08990:            void setColorRef4f(Color4f[] colors) {
08991:
08992:                if (colors != null) {
08993:                    if ((vertexType & COLOR_DEFINED) != 0
08994:                            && (vertexType & COLOR_DEFINED) != C4F) {
08995:                        throw new IllegalArgumentException(J3dI18N
08996:                                .getString("GeometryArray98"));
08997:                    }
08998:                    if ((vertexFormat & GeometryArray.COLOR_4) == 0) {
08999:                        throw new IllegalStateException(J3dI18N
09000:                                .getString("GeometryArray93"));
09001:                    }
09002:
09003:                    if (this  instanceof  IndexedGeometryArrayRetained) {
09004:                        IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained) this ;
09005:                        if (idx.maxColorIndex >= colors.length) {
09006:                            throw new ArrayIndexOutOfBoundsException(J3dI18N
09007:                                    .getString("IndexedGeometryArray24"));
09008:                        }
09009:                    } else if (colors.length < (initialColorIndex + validVertexCount)) {
09010:                        throw new ArrayIndexOutOfBoundsException(J3dI18N
09011:                                .getString("GeometryArray112"));
09012:                    }
09013:                }
09014:                boolean isLive = source != null && source.isLive();
09015:                if (isLive) {
09016:                    geomLock.getLock();
09017:                }
09018:                dirtyFlag |= COLOR_CHANGED;
09019:                colorChanged = 0xffff;
09020:                c4fRefColors = colors;
09021:                if (inUpdater
09022:                        || (this  instanceof  IndexedGeometryArrayRetained && ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
09023:                    if (colors == null)
09024:                        vertexType &= ~C4F;
09025:                    else
09026:                        vertexType |= C4F;
09027:                } else {
09028:                    setupMirrorColorPointer(C4F, false);
09029:                }
09030:                if (isLive) {
09031:                    geomLock.unLock();
09032:                }
09033:
09034:                if (!inUpdater && isLive) {
09035:                    sendDataChangedMessage(false);
09036:                }
09037:            }
09038:
09039:            Color4f[] getColorRef4f() {
09040:                return c4fRefColors;
09041:            }
09042:
09043:            void setColorRef3b(Color3b[] colors) {
09044:
09045:                if (colors != null) {
09046:
09047:                    if ((vertexType & COLOR_DEFINED) != 0
09048:                            && (vertexType & COLOR_DEFINED) != C3UB) {
09049:                        throw new IllegalArgumentException(J3dI18N
09050:                                .getString("GeometryArray98"));
09051:                    }
09052:
09053:                    if ((vertexFormat & GeometryArray.COLOR_3) == 0) {
09054:                        throw new IllegalStateException(J3dI18N
09055:                                .getString("GeometryArray92"));
09056:                    }
09057:
09058:                    if (this  instanceof  IndexedGeometryArrayRetained) {
09059:                        IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained) this ;
09060:
09061:                        if (idx.maxColorIndex >= colors.length) {
09062:                            throw new ArrayIndexOutOfBoundsException(J3dI18N
09063:                                    .getString("IndexedGeometryArray24"));
09064:                        }
09065:                    } else if (colors.length < (initialColorIndex + validVertexCount)) {
09066:                        throw new ArrayIndexOutOfBoundsException(J3dI18N
09067:                                .getString("GeometryArray112"));
09068:                    }
09069:                }
09070:
09071:                boolean isLive = source != null && source.isLive();
09072:                if (isLive) {
09073:                    geomLock.getLock();
09074:                }
09075:                dirtyFlag |= COLOR_CHANGED;
09076:                colorChanged = 0xffff;
09077:                c3bRefColors = colors;
09078:                if (inUpdater
09079:                        || (this  instanceof  IndexedGeometryArrayRetained && ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
09080:                    if (colors == null)
09081:                        vertexType &= ~C3UB;
09082:                    else
09083:                        vertexType |= C3UB;
09084:                } else {
09085:                    setupMirrorColorPointer(C3UB, false);
09086:                }
09087:
09088:                if (isLive) {
09089:                    geomLock.unLock();
09090:                }
09091:
09092:                if (!inUpdater && isLive) {
09093:                    sendDataChangedMessage(false);
09094:                }
09095:            }
09096:
09097:            Color3b[] getColorRef3b() {
09098:                return c3bRefColors;
09099:            }
09100:
09101:            void setColorRef4b(Color4b[] colors) {
09102:
09103:                if (colors != null) {
09104:                    if ((vertexType & COLOR_DEFINED) != 0
09105:                            && (vertexType & COLOR_DEFINED) != C4UB) {
09106:                        throw new IllegalArgumentException(J3dI18N
09107:                                .getString("GeometryArray98"));
09108:                    }
09109:
09110:                    if ((vertexFormat & GeometryArray.COLOR_4) == 0) {
09111:                        throw new IllegalStateException(J3dI18N
09112:                                .getString("GeometryArray93"));
09113:                    }
09114:
09115:                    if (this  instanceof  IndexedGeometryArrayRetained) {
09116:                        IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained) this ;
09117:
09118:                        if (idx.maxColorIndex >= colors.length) {
09119:                            throw new ArrayIndexOutOfBoundsException(J3dI18N
09120:                                    .getString("IndexedGeometryArray24"));
09121:                        }
09122:                    } else if (colors.length < (initialColorIndex + validVertexCount)) {
09123:                        throw new ArrayIndexOutOfBoundsException(J3dI18N
09124:                                .getString("GeometryArray112"));
09125:                    }
09126:                }
09127:                boolean isLive = source != null && source.isLive();
09128:                if (isLive) {
09129:                    geomLock.getLock();
09130:                }
09131:                dirtyFlag |= COLOR_CHANGED;
09132:                colorChanged = 0xffff;
09133:                c4bRefColors = colors;
09134:                if (inUpdater
09135:                        || (this  instanceof  IndexedGeometryArrayRetained && ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
09136:                    if (colors == null)
09137:                        vertexType &= ~C4UB;
09138:                    else
09139:                        vertexType |= C4UB;
09140:                } else {
09141:                    setupMirrorColorPointer(C4UB, false);
09142:                }
09143:
09144:                if (isLive) {
09145:                    geomLock.unLock();
09146:                }
09147:                if (!inUpdater && isLive) {
09148:                    sendDataChangedMessage(false);
09149:                }
09150:            }
09151:
09152:            Color4b[] getColorRef4b() {
09153:                return c4bRefColors;
09154:            }
09155:
09156:            void setNormalRefFloat(float[] normals) {
09157:
09158:                if (normals != null) {
09159:                    if ((vertexType & NORMAL_DEFINED) != 0
09160:                            && (vertexType & NORMAL_DEFINED) != NF) {
09161:                        throw new IllegalArgumentException(J3dI18N
09162:                                .getString("GeometryArray98"));
09163:                    }
09164:
09165:                    if ((vertexFormat & GeometryArray.NORMALS) == 0) {
09166:                        throw new IllegalStateException(J3dI18N
09167:                                .getString("GeometryArray122"));
09168:                    }
09169:
09170:                    if (this  instanceof  IndexedGeometryArrayRetained) {
09171:                        IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained) this ;
09172:
09173:                        if (idx.maxNormalIndex * 3 >= normals.length) {
09174:                            throw new ArrayIndexOutOfBoundsException(J3dI18N
09175:                                    .getString("IndexedGeometryArray26"));
09176:                        }
09177:                    } else if (normals.length < 3 * (initialNormalIndex + validVertexCount)) {
09178:                        throw new ArrayIndexOutOfBoundsException(J3dI18N
09179:                                .getString("GeometryArray111"));
09180:                    }
09181:                }
09182:                boolean isLive = source != null && source.isLive();
09183:                if (isLive) {
09184:                    geomLock.getLock();
09185:                }
09186:                dirtyFlag |= NORMAL_CHANGED;
09187:                floatRefNormals = normals;
09188:                if (inUpdater
09189:                        || (this  instanceof  IndexedGeometryArrayRetained && ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
09190:                    if (normals == null)
09191:                        vertexType &= ~NF;
09192:                    else
09193:                        vertexType |= NF;
09194:                } else {
09195:                    setupMirrorNormalPointer(NF);
09196:                }
09197:                if (isLive) {
09198:                    geomLock.unLock();
09199:                }
09200:                if (!inUpdater && isLive) {
09201:                    sendDataChangedMessage(false);
09202:                }
09203:
09204:            }
09205:
09206:            float[] getNormalRefFloat() {
09207:                return floatRefNormals;
09208:            }
09209:
09210:            // setup the normal with nio buffer
09211:            void setNormalRefBuffer(J3DBuffer normals) {
09212:
09213:                FloatBufferWrapper bufferImpl = null;
09214:
09215:                if (normals != null) {
09216:                    if (normals.getBufferType() != J3DBuffer.TYPE_FLOAT)
09217:                        throw new IllegalArgumentException(J3dI18N
09218:                                .getString("GeometryArray116"));
09219:
09220:                    bufferImpl = (FloatBufferWrapper) normals.getBufferImpl();
09221:
09222:                    assert bufferImpl.isDirect();
09223:
09224:                    if ((vertexFormat & GeometryArray.NORMALS) == 0) {
09225:                        throw new IllegalStateException(J3dI18N
09226:                                .getString("GeometryArray122"));
09227:                    }
09228:
09229:                    if (this  instanceof  IndexedGeometryArrayRetained) {
09230:                        IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained) this ;
09231:                        if (idx.maxNormalIndex * 3 >= ((FloatBufferWrapper) normals
09232:                                .getBufferImpl()).limit()) {
09233:                            throw new ArrayIndexOutOfBoundsException(J3dI18N
09234:                                    .getString("IndexedGeometryArray26"));
09235:                        }
09236:                    } else if (bufferImpl.limit() < 3 * (initialNormalIndex + validVertexCount)) {
09237:                        throw new ArrayIndexOutOfBoundsException(J3dI18N
09238:                                .getString("GeometryArray111"));
09239:                    }
09240:                }
09241:                boolean isLive = source != null && source.isLive();
09242:                if (isLive) {
09243:                    geomLock.getLock();
09244:                }
09245:                dirtyFlag |= NORMAL_CHANGED;
09246:                normalRefBuffer = normals;
09247:
09248:                if (normals == null) {
09249:                    vertexType &= ~NF;
09250:                    floatBufferRefNormals = null;
09251:                } else {
09252:                    vertexType |= NF;
09253:                    floatBufferRefNormals = bufferImpl;
09254:                }
09255:                if (isLive) {
09256:                    geomLock.unLock();
09257:                }
09258:                if (!inUpdater && isLive) {
09259:                    sendDataChangedMessage(false);
09260:                }
09261:            }
09262:
09263:            J3DBuffer getNormalRefBuffer() {
09264:                return normalRefBuffer;
09265:            }
09266:
09267:            void setNormalRef3f(Vector3f[] normals) {
09268:
09269:                if (normals != null) {
09270:                    if ((vertexType & NORMAL_DEFINED) != 0
09271:                            && (vertexType & NORMAL_DEFINED) != N3F) {
09272:                        throw new IllegalArgumentException(J3dI18N
09273:                                .getString("GeometryArray98"));
09274:                    }
09275:
09276:                    if ((vertexFormat & GeometryArray.NORMALS) == 0) {
09277:                        throw new IllegalStateException(J3dI18N
09278:                                .getString("GeometryArray122"));
09279:                    }
09280:
09281:                    if (this  instanceof  IndexedGeometryArrayRetained) {
09282:                        IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained) this ;
09283:                        if (idx.maxNormalIndex >= normals.length) {
09284:                            throw new ArrayIndexOutOfBoundsException(J3dI18N
09285:                                    .getString("IndexedGeometryArray26"));
09286:                        }
09287:                    } else if (normals.length < (initialNormalIndex + validVertexCount)) {
09288:                        throw new ArrayIndexOutOfBoundsException(J3dI18N
09289:                                .getString("GeometryArray111"));
09290:                    }
09291:                }
09292:                boolean isLive = source != null && source.isLive();
09293:                if (isLive) {
09294:                    geomLock.getLock();
09295:                }
09296:                dirtyFlag |= NORMAL_CHANGED;
09297:                v3fRefNormals = normals;
09298:                if (inUpdater
09299:                        || (this  instanceof  IndexedGeometryArrayRetained && ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
09300:                    if (normals == null)
09301:                        vertexType &= ~N3F;
09302:                    else
09303:                        vertexType |= N3F;
09304:                } else {
09305:                    setupMirrorNormalPointer(N3F);
09306:                }
09307:                if (isLive) {
09308:                    geomLock.unLock();
09309:                }
09310:                if (!inUpdater && isLive) {
09311:                    sendDataChangedMessage(false);
09312:                }
09313:            }
09314:
09315:            Vector3f[] getNormalRef3f() {
09316:                return v3fRefNormals;
09317:            }
09318:
09319:            final int getColorStride() {
09320:                return ((vertexFormat & GeometryArray.WITH_ALPHA) != 0 ? 4 : 3);
09321:            }
09322:
09323:            final int getTexStride() {
09324:                if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_2) != 0) {
09325:                    return 2;
09326:                }
09327:                if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0) {
09328:                    return 3;
09329:                }
09330:                if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_4) != 0) {
09331:                    return 4;
09332:                }
09333:
09334:                throw new ArrayIndexOutOfBoundsException(J3dI18N
09335:                        .getString("GeometryArray121"));
09336:            }
09337:
09338:            void setTexCoordRefFloat(int texCoordSet, float[] texCoords) {
09339:
09340:                if (texCoordType != 0 && texCoordType != TF) {
09341:                    if (texCoords != null) {
09342:                        throw new IllegalArgumentException(J3dI18N
09343:                                .getString("GeometryArray98"));
09344:                    }
09345:                    return;
09346:                }
09347:
09348:                if (texCoords != null) {
09349:
09350:                    int ts = getTexStride();
09351:
09352:                    if (this  instanceof  IndexedGeometryArrayRetained) {
09353:                        IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained) this ;
09354:
09355:                        if (idx.maxTexCoordIndices[texCoordSet] * ts >= texCoords.length) {
09356:                            throw new ArrayIndexOutOfBoundsException(J3dI18N
09357:                                    .getString("IndexedGeometryArray25"));
09358:                        }
09359:                    } else if (texCoords.length < ts
09360:                            * (initialTexCoordIndex[texCoordSet] + validVertexCount)) {
09361:                        throw new ArrayIndexOutOfBoundsException(J3dI18N
09362:                                .getString("GeometryArray113"));
09363:                    }
09364:                }
09365:                boolean isLive = source != null && source.isLive();
09366:                if (isLive) {
09367:                    geomLock.getLock();
09368:                }
09369:                dirtyFlag |= TEXTURE_CHANGED;
09370:                refTexCoords[texCoordSet] = texCoords;
09371:                if (inUpdater
09372:                        || (this  instanceof  IndexedGeometryArrayRetained && ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
09373:                    texCoordType = TF;
09374:                    validateTexCoordPointerType();
09375:                } else {
09376:                    setupMirrorTexCoordPointer(texCoordSet, TF);
09377:                }
09378:                if (isLive) {
09379:                    geomLock.unLock();
09380:                }
09381:                if (!inUpdater && isLive) {
09382:                    sendDataChangedMessage(false);
09383:                }
09384:            }
09385:
09386:            float[] getTexCoordRefFloat(int texCoordSet) {
09387:                return ((float[]) refTexCoords[texCoordSet]);
09388:            }
09389:
09390:            // set the tex coord with nio buffer
09391:            void setTexCoordRefBuffer(int texCoordSet, J3DBuffer texCoords) {
09392:
09393:                FloatBufferWrapper bufferImpl = null;
09394:
09395:                if (texCoords != null) {
09396:                    if (texCoords.getBufferType() != J3DBuffer.TYPE_FLOAT)
09397:                        throw new IllegalArgumentException(J3dI18N
09398:                                .getString("GeometryArray116"));
09399:
09400:                    bufferImpl = (FloatBufferWrapper) texCoords.getBufferImpl();
09401:                    int bufferSize = bufferImpl.limit();
09402:
09403:                    assert bufferImpl.isDirect();
09404:
09405:                    int ts = getTexStride();
09406:
09407:                    if (this  instanceof  IndexedGeometryArrayRetained) {
09408:                        IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained) this ;
09409:                        if (idx.maxTexCoordIndices[texCoordSet] * ts >= bufferSize) {
09410:                            throw new ArrayIndexOutOfBoundsException(J3dI18N
09411:                                    .getString("IndexedGeometryArray25"));
09412:                        }
09413:                    } else if (bufferSize < ts
09414:                            * (initialTexCoordIndex[texCoordSet] + validVertexCount)) {
09415:                        throw new ArrayIndexOutOfBoundsException(J3dI18N
09416:                                .getString("GeometryArray113"));
09417:                    }
09418:                }
09419:                boolean isLive = source != null && source.isLive();
09420:                if (isLive) {
09421:                    geomLock.getLock();
09422:                }
09423:                dirtyFlag |= TEXTURE_CHANGED;
09424:                // refTexCoordsBuffer contains J3DBuffer object for tex coord
09425:                refTexCoordsBuffer[texCoordSet] = texCoords;
09426:                if (texCoords == null) {
09427:                    refTexCoords[texCoordSet] = null;
09428:                } else {
09429:                    // refTexCoords contains NIOBuffer object for tex coord
09430:                    refTexCoords[texCoordSet] = bufferImpl.getBufferAsObject();
09431:                }
09432:                texCoordType = TF;
09433:                validateTexCoordPointerType();
09434:                if (isLive) {
09435:                    geomLock.unLock();
09436:                }
09437:                if (!inUpdater && isLive) {
09438:                    sendDataChangedMessage(false);
09439:                }
09440:            }
09441:
09442:            J3DBuffer getTexCoordRefBuffer(int texCoordSet) {
09443:                return (J3DBuffer) (refTexCoordsBuffer[texCoordSet]);
09444:            }
09445:
09446:            void setTexCoordRef2f(int texCoordSet, TexCoord2f[] texCoords) {
09447:
09448:                if (texCoordType != 0 && texCoordType != T2F) {
09449:                    if (texCoords != null) {
09450:                        throw new IllegalArgumentException(J3dI18N
09451:                                .getString("GeometryArray98"));
09452:                    }
09453:                    return;
09454:                }
09455:
09456:                if (texCoords != null) {
09457:                    if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_2) == 0) {
09458:                        throw new IllegalStateException(J3dI18N
09459:                                .getString("GeometryArray94"));
09460:                    }
09461:
09462:                    if (this  instanceof  IndexedGeometryArrayRetained) {
09463:                        IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained) this ;
09464:
09465:                        if (idx.maxTexCoordIndices[texCoordSet] >= texCoords.length) {
09466:                            throw new ArrayIndexOutOfBoundsException(J3dI18N
09467:                                    .getString("IndexedGeometryArray25"));
09468:                        }
09469:                    } else if (texCoords.length < (initialTexCoordIndex[texCoordSet] + validVertexCount)) {
09470:                        throw new ArrayIndexOutOfBoundsException(J3dI18N
09471:                                .getString("GeometryArray113"));
09472:                    }
09473:
09474:                }
09475:                boolean isLive = source != null && source.isLive();
09476:                if (isLive) {
09477:                    geomLock.getLock();
09478:                }
09479:                dirtyFlag |= TEXTURE_CHANGED;
09480:                refTexCoords[texCoordSet] = texCoords;
09481:                if (inUpdater
09482:                        || (this  instanceof  IndexedGeometryArrayRetained && ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
09483:                    texCoordType = T2F;
09484:                    validateTexCoordPointerType();
09485:                } else {
09486:                    setupMirrorTexCoordPointer(texCoordSet, T2F);
09487:                }
09488:                if (isLive) {
09489:                    geomLock.unLock();
09490:                }
09491:                if (!inUpdater && isLive) {
09492:                    sendDataChangedMessage(false);
09493:                }
09494:            }
09495:
09496:            TexCoord2f[] getTexCoordRef2f(int texCoordSet) {
09497:                if (refTexCoords != null && refTexCoords[texCoordSet] != null
09498:                        && refTexCoords[texCoordSet] instanceof  TexCoord2f[]) {
09499:                    return ((TexCoord2f[]) refTexCoords[texCoordSet]);
09500:                } else {
09501:                    return null;
09502:                }
09503:            }
09504:
09505:            void setTexCoordRef3f(int texCoordSet, TexCoord3f[] texCoords) {
09506:
09507:                if (texCoordType != 0 && texCoordType != T3F) {
09508:                    if (texCoords != null) {
09509:                        throw new IllegalArgumentException(J3dI18N
09510:                                .getString("GeometryArray98"));
09511:                    }
09512:                    return;
09513:                }
09514:
09515:                if (texCoords != null) {
09516:
09517:                    if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_3) == 0) {
09518:                        throw new IllegalStateException(J3dI18N
09519:                                .getString("GeometryArray95"));
09520:                    }
09521:
09522:                    if (this  instanceof  IndexedGeometryArrayRetained) {
09523:                        IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained) this ;
09524:
09525:                        if (idx.maxTexCoordIndices[texCoordSet] >= texCoords.length) {
09526:                            throw new ArrayIndexOutOfBoundsException(J3dI18N
09527:                                    .getString("IndexedGeometryArray25"));
09528:                        }
09529:
09530:                    } else if (texCoords.length < (initialTexCoordIndex[texCoordSet] + validVertexCount)) {
09531:                        throw new ArrayIndexOutOfBoundsException(J3dI18N
09532:                                .getString("GeometryArray113"));
09533:                    }
09534:
09535:                }
09536:                boolean isLive = source != null && source.isLive();
09537:                if (isLive) {
09538:                    geomLock.getLock();
09539:                }
09540:                dirtyFlag |= TEXTURE_CHANGED;
09541:                refTexCoords[texCoordSet] = texCoords;
09542:                if (inUpdater
09543:                        || (this  instanceof  IndexedGeometryArrayRetained && ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
09544:                    texCoordType = T3F;
09545:                    validateTexCoordPointerType();
09546:                } else {
09547:                    setupMirrorTexCoordPointer(texCoordSet, T3F);
09548:                }
09549:                if (isLive) {
09550:                    geomLock.unLock();
09551:                }
09552:                if (!inUpdater && isLive) {
09553:                    sendDataChangedMessage(false);
09554:                }
09555:            }
09556:
09557:            TexCoord3f[] getTexCoordRef3f(int texCoordSet) {
09558:                if (refTexCoords != null && refTexCoords[texCoordSet] != null
09559:                        && refTexCoords[texCoordSet] instanceof  TexCoord3f[]) {
09560:                    return ((TexCoord3f[]) refTexCoords[texCoordSet]);
09561:                } else {
09562:                    return null;
09563:                }
09564:            }
09565:
09566:            /**
09567:             * Sets the float vertex attribute array reference for the
09568:             * specified vertex attribute number to the specified array.
09569:             */
09570:            void setVertexAttrRefFloat(int vertexAttrNum, float[] vertexAttrs) {
09571:
09572:                // XXXX: Add the following test if we ever add double-precision types
09573:                /*
09574:                if (vertexAttrType != 0 && vertexAttrType != AF) {
09575:                    if (vertexAttrs != null) {
09576:                        // XXXX: new exception string
09577:                        throw new IllegalArgumentException(
09578:                                J3dI18N.getString("GeometryArray98-XXX"));
09579:                    }
09580:                    return;
09581:                }
09582:                 */
09583:
09584:                if (vertexAttrs != null) {
09585:                    int sz = vertexAttrSizes[vertexAttrNum];
09586:
09587:                    if (this  instanceof  IndexedGeometryArrayRetained) {
09588:                        IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained) this ;
09589:
09590:                        if (sz * idx.maxVertexAttrIndices[vertexAttrNum] >= vertexAttrs.length) {
09591:                            throw new ArrayIndexOutOfBoundsException(J3dI18N
09592:                                    .getString("IndexedGeometryArray30"));
09593:                        }
09594:
09595:                    } else if (vertexAttrs.length < sz
09596:                            * (initialVertexAttrIndex[vertexAttrNum] + validVertexCount)) {
09597:                        throw new ArrayIndexOutOfBoundsException(J3dI18N
09598:                                .getString("GeometryArray129"));
09599:                    }
09600:                }
09601:                boolean isLive = source != null && source.isLive();
09602:                if (isLive) {
09603:                    geomLock.getLock();
09604:                }
09605:                dirtyFlag |= VATTR_CHANGED;
09606:                floatRefVertexAttrs[vertexAttrNum] = vertexAttrs;
09607:                if (inUpdater
09608:                        || (this  instanceof  IndexedGeometryArrayRetained && ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
09609:                    vertexAttrType = AF;
09610:                    validateVertexAttrPointerType();
09611:                } else {
09612:                    setupMirrorVertexAttrPointer(vertexAttrNum, AF);
09613:                }
09614:                if (isLive) {
09615:                    geomLock.unLock();
09616:                }
09617:                if (!inUpdater && isLive) {
09618:                    sendDataChangedMessage(false);
09619:                }
09620:            }
09621:
09622:            /**
09623:             * Gets the float vertex attribute array reference for the specified
09624:             * vertex attribute number.
09625:             */
09626:            float[] getVertexAttrRefFloat(int vertexAttrNum) {
09627:                return floatRefVertexAttrs[vertexAttrNum];
09628:            }
09629:
09630:            /**
09631:             * Sets the vertex attribute buffer reference for the specified
09632:             * vertex attribute number to the specified buffer object.
09633:             */
09634:            void setVertexAttrRefBuffer(int vertexAttrNum, J3DBuffer vertexAttrs) {
09635:
09636:                FloatBufferWrapper bufferImpl = null;
09637:
09638:                if (vertexAttrs != null) {
09639:                    if (vertexAttrs.getBufferType() != J3DBuffer.TYPE_FLOAT)
09640:                        throw new IllegalArgumentException(J3dI18N
09641:                                .getString("GeometryArray116"));
09642:
09643:                    bufferImpl = (FloatBufferWrapper) vertexAttrs
09644:                            .getBufferImpl();
09645:                    int bufferSize = bufferImpl.limit();
09646:
09647:                    assert bufferImpl.isDirect();
09648:
09649:                    int sz = vertexAttrSizes[vertexAttrNum];
09650:
09651:                    if (this  instanceof  IndexedGeometryArrayRetained) {
09652:                        IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained) this ;
09653:
09654:                        if (idx.maxVertexAttrIndices[vertexAttrNum] * sz >= bufferSize) {
09655:                            throw new ArrayIndexOutOfBoundsException(J3dI18N
09656:                                    .getString("IndexedGeometryArray30"));
09657:                        }
09658:                    } else if (bufferSize < sz
09659:                            * (initialVertexAttrIndex[vertexAttrNum] + validVertexCount)) {
09660:                        throw new ArrayIndexOutOfBoundsException(J3dI18N
09661:                                .getString("GeometryArray129"));
09662:                    }
09663:                }
09664:                boolean isLive = source != null && source.isLive();
09665:                if (isLive) {
09666:                    geomLock.getLock();
09667:                }
09668:                dirtyFlag |= VATTR_CHANGED;
09669:                vertexAttrsRefBuffer[vertexAttrNum] = vertexAttrs;
09670:                if (vertexAttrs == null) {
09671:                    floatBufferRefVertexAttrs[vertexAttrNum] = null;
09672:                    nioFloatBufferRefVertexAttrs[vertexAttrNum] = null;
09673:                } else {
09674:                    floatBufferRefVertexAttrs[vertexAttrNum] = bufferImpl;
09675:                    nioFloatBufferRefVertexAttrs[vertexAttrNum] = bufferImpl
09676:                            .getBufferAsObject();
09677:                }
09678:                vertexAttrType = AF;
09679:                validateVertexAttrPointerType();
09680:                if (isLive) {
09681:                    geomLock.unLock();
09682:                }
09683:                if (!inUpdater && isLive) {
09684:                    sendDataChangedMessage(false);
09685:                }
09686:
09687:            }
09688:
09689:            /**
09690:             * Gets the vertex attribute array buffer reference for the specified
09691:             * vertex attribute number.
09692:             */
09693:            J3DBuffer getVertexAttrRefBuffer(int vertexAttrNum) {
09694:                return vertexAttrsRefBuffer[vertexAttrNum];
09695:            }
09696:
09697:            void setInterleavedVertices(float[] vertexData) {
09698:                if (vertexData != null) {
09699:
09700:                    if (this  instanceof  IndexedGeometryArrayRetained) {
09701:                        IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained) this ;
09702:
09703:                        if (stride * idx.maxCoordIndex >= vertexData.length) {
09704:                            throw new ArrayIndexOutOfBoundsException(J3dI18N
09705:                                    .getString("IndexedGeometryArray23"));
09706:                        }
09707:
09708:                        if ((this .vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) {
09709:                            for (int i = 0; i < texCoordSetCount; i++) {
09710:                                if (stride * idx.maxTexCoordIndices[i] >= vertexData.length) {
09711:                                    throw new ArrayIndexOutOfBoundsException(
09712:                                            J3dI18N
09713:                                                    .getString("IndexedGeometryArray25"));
09714:                                }
09715:                            }
09716:                        }
09717:
09718:                        if (((this .vertexFormat & GeometryArray.COLOR) != 0)
09719:                                && (stride * idx.maxColorIndex >= vertexData.length)) {
09720:                            throw new ArrayIndexOutOfBoundsException(J3dI18N
09721:                                    .getString("IndexedGeometryArray24"));
09722:                        }
09723:
09724:                        if (((this .vertexFormat & GeometryArray.NORMALS) != 0)
09725:                                && (stride * idx.maxNormalIndex >= vertexData.length)) {
09726:                            throw new ArrayIndexOutOfBoundsException(J3dI18N
09727:                                    .getString("IndexedGeometryArray26"));
09728:                        }
09729:                    } else {
09730:                        if (vertexData.length < (stride * (initialVertexIndex + validVertexCount)))
09731:                            throw new ArrayIndexOutOfBoundsException(J3dI18N
09732:                                    .getString("GeometryArray114"));
09733:                    }
09734:                }
09735:
09736:                // If the geometry has been rendered transparent, then make a copy
09737:                // of the color pointer with 4f
09738:                boolean isLive = source != null && source.isLive();
09739:                if (isLive) {
09740:                    geomLock.getLock();
09741:                }
09742:                dirtyFlag |= VERTEX_CHANGED;
09743:                colorChanged = 0xffff;
09744:                interLeavedVertexData = vertexData;
09745:                if (inUpdater
09746:                        || (this  instanceof  IndexedGeometryArrayRetained && ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
09747:                    setupMirrorInterleavedColorPointer(false);
09748:                }
09749:                if (isLive) {
09750:                    geomLock.unLock();
09751:                }
09752:                if (!inUpdater && isLive) {
09753:                    processCoordsChanged(vertexData == null);
09754:                    sendDataChangedMessage(true);
09755:                }
09756:            }
09757:
09758:            // set the interleaved vertex with NIO buffer
09759:            void setInterleavedVertexBuffer(J3DBuffer vertexData) {
09760:
09761:                FloatBufferWrapper bufferImpl = null;
09762:
09763:                if (vertexData != null) {
09764:
09765:                    if (vertexData.getBufferType() != J3DBuffer.TYPE_FLOAT)
09766:                        throw new IllegalArgumentException(J3dI18N
09767:                                .getString("GeometryArray116"));
09768:
09769:                    bufferImpl = (FloatBufferWrapper) vertexData
09770:                            .getBufferImpl();
09771:
09772:                    assert bufferImpl.isDirect();
09773:
09774:                    int bufferSize = bufferImpl.limit();
09775:
09776:                    if (this  instanceof  IndexedGeometryArrayRetained) {
09777:                        IndexedGeometryArrayRetained idx = (IndexedGeometryArrayRetained) this ;
09778:
09779:                        if (stride * idx.maxCoordIndex >= bufferSize) {
09780:                            throw new ArrayIndexOutOfBoundsException(J3dI18N
09781:                                    .getString("IndexedGeometryArray23"));
09782:                        }
09783:
09784:                        if ((this .vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) {
09785:                            for (int i = 0; i < texCoordSetCount; i++) {
09786:                                if (stride * idx.maxTexCoordIndices[i] >= bufferSize) {
09787:                                    throw new ArrayIndexOutOfBoundsException(
09788:                                            J3dI18N
09789:                                                    .getString("IndexedGeometryArray25"));
09790:                                }
09791:                            }
09792:                        }
09793:
09794:                        if (((this .vertexFormat & GeometryArray.COLOR) != 0)
09795:                                && (stride * idx.maxColorIndex >= bufferSize)) {
09796:                            throw new ArrayIndexOutOfBoundsException(J3dI18N
09797:                                    .getString("IndexedGeometryArray24"));
09798:                        }
09799:
09800:                        if (((this .vertexFormat & GeometryArray.NORMALS) != 0)
09801:                                && (stride * idx.maxNormalIndex >= bufferSize)) {
09802:                            throw new ArrayIndexOutOfBoundsException(J3dI18N
09803:                                    .getString("IndexedGeometryArray23"));
09804:                        }
09805:                    } else {
09806:                        if (bufferSize < (stride * (initialVertexIndex + validVertexCount)))
09807:                            throw new ArrayIndexOutOfBoundsException(J3dI18N
09808:                                    .getString("GeometryArray114"));
09809:                    }
09810:                }
09811:                // If the geometry has been rendered transparent, then make a copy
09812:                // of the color pointer with 4f
09813:                boolean isLive = source != null && source.isLive();
09814:                if (isLive) {
09815:                    geomLock.getLock();
09816:                }
09817:                dirtyFlag |= VERTEX_CHANGED;
09818:                colorChanged = 0xffff;
09819:                interleavedVertexBuffer = vertexData;
09820:
09821:                if (vertexData == null)
09822:                    interleavedFloatBufferImpl = null;
09823:                else
09824:                    interleavedFloatBufferImpl = bufferImpl;
09825:
09826:                if (inUpdater
09827:                        || (this  instanceof  IndexedGeometryArrayRetained && ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0))) {
09828:                    setupMirrorInterleavedColorPointer(false);
09829:                }
09830:                if (isLive) {
09831:                    geomLock.unLock();
09832:                }
09833:                if (!inUpdater && isLive) {
09834:                    processCoordsChanged(vertexData == null);
09835:                    sendDataChangedMessage(true);
09836:                }
09837:            }
09838:
09839:            float[] getInterleavedVertices() {
09840:                return interLeavedVertexData;
09841:            }
09842:
09843:            J3DBuffer getInterleavedVertexBuffer() {
09844:                return interleavedVertexBuffer;
09845:            }
09846:
09847:            void setValidVertexCount(int validVertexCount) {
09848:
09849:                boolean nullGeo = false;
09850:                if (validVertexCount < 0) {
09851:                    throw new IllegalArgumentException(J3dI18N
09852:                            .getString("GeometryArray110"));
09853:                }
09854:
09855:                if ((initialVertexIndex + validVertexCount) > vertexCount) {
09856:                    throw new IllegalArgumentException(J3dI18N
09857:                            .getString("GeometryArray100"));
09858:                }
09859:
09860:                if ((vertexFormat & GeometryArray.INTERLEAVED) != 0) {
09861:                    // Interleaved, by-ref
09862:
09863:                    // use nio buffer for interleaved data
09864:                    if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) != 0
09865:                            && interleavedFloatBufferImpl != null) {
09866:                        if (interleavedFloatBufferImpl.limit() < stride
09867:                                * (initialVertexIndex + validVertexCount)) {
09868:                            throw new ArrayIndexOutOfBoundsException(J3dI18N
09869:                                    .getString("GeometryArray114"));
09870:                        }
09871:                    }
09872:                    //use java array for interleaved data
09873:                    else if (interLeavedVertexData != null) {
09874:                        if (interLeavedVertexData.length < stride
09875:                                * (initialVertexIndex + validVertexCount)) {
09876:                            throw new ArrayIndexOutOfBoundsException(J3dI18N
09877:                                    .getString("GeometryArray114"));
09878:                        }
09879:                    } else {
09880:                        nullGeo = true;
09881:                    }
09882:                } else if ((vertexFormat & GeometryArray.BY_REFERENCE) != 0) {
09883:                    // Non-interleaved, by-ref
09884:
09885:                    if ((initialCoordIndex + validVertexCount) > vertexCount) {
09886:                        throw new IllegalArgumentException(J3dI18N
09887:                                .getString("GeometryArray104"));
09888:                    }
09889:                    if ((initialColorIndex + validVertexCount) > vertexCount) {
09890:                        throw new IllegalArgumentException(J3dI18N
09891:                                .getString("GeometryArray101"));
09892:                    }
09893:                    if ((initialNormalIndex + validVertexCount) > vertexCount) {
09894:                        throw new IllegalArgumentException(J3dI18N
09895:                                .getString("GeometryArray102"));
09896:                    }
09897:
09898:                    if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) {
09899:                        for (int i = 0; i < texCoordSetCount; i++) {
09900:                            if ((initialTexCoordIndex[i] + validVertexCount) > vertexCount) {
09901:                                throw new IllegalArgumentException(J3dI18N
09902:                                        .getString("GeometryArray103"));
09903:                            }
09904:                        }
09905:                    }
09906:
09907:                    if ((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) {
09908:                        for (int i = 0; i < vertexAttrCount; i++) {
09909:                            if ((initialVertexAttrIndex[i] + validVertexCount) > vertexCount) {
09910:                                throw new IllegalArgumentException(J3dI18N
09911:                                        .getString("GeometryArray130"));
09912:                            }
09913:                        }
09914:                    }
09915:
09916:                    if ((vertexType & GeometryArrayRetained.VERTEX_DEFINED) == 0) {
09917:                        nullGeo = true;
09918:                    }
09919:
09920:                    if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) != 0) {
09921:                        // by reference with nio buffer
09922:                        switch ((vertexType & GeometryArrayRetained.VERTEX_DEFINED)) {
09923:                        case PF:
09924:                            if (floatBufferRefCoords.limit() < 3 * (initialCoordIndex + validVertexCount)) {
09925:                                throw new ArrayIndexOutOfBoundsException(
09926:                                        J3dI18N.getString("GeometryArray99"));
09927:                            }
09928:                            break;
09929:                        case PD:
09930:                            if (doubleBufferRefCoords.limit() < 3 * (initialCoordIndex + validVertexCount)) {
09931:                                throw new ArrayIndexOutOfBoundsException(
09932:                                        J3dI18N.getString("GeometryArray99"));
09933:                            }
09934:                            break;
09935:                        }
09936:
09937:                        switch ((vertexType & COLOR_DEFINED)) {
09938:                        case CF:
09939:                            if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_3) {
09940:                                if (floatBufferRefColors.limit() < 3 * (initialColorIndex + validVertexCount)) {
09941:                                    throw new ArrayIndexOutOfBoundsException(
09942:                                            J3dI18N
09943:                                                    .getString("GeometryArray112"));
09944:                                }
09945:                            } else if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_4) {
09946:                                if (floatBufferRefColors.limit() < 4 * (initialColorIndex + validVertexCount)) {
09947:                                    throw new ArrayIndexOutOfBoundsException(
09948:                                            J3dI18N
09949:                                                    .getString("GeometryArray112"));
09950:                                }
09951:                            }
09952:                            break;
09953:                        case CUB:
09954:                            if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_3) {
09955:                                if (byteBufferRefColors.limit() < 3 * (initialColorIndex + validVertexCount)) {
09956:                                    throw new ArrayIndexOutOfBoundsException(
09957:                                            J3dI18N
09958:                                                    .getString("GeometryArray112"));
09959:                                }
09960:                            } else if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_4) {
09961:                                if (byteBufferRefColors.limit() < 4 * (initialColorIndex + validVertexCount)) {
09962:                                    throw new ArrayIndexOutOfBoundsException(
09963:                                            J3dI18N
09964:                                                    .getString("GeometryArray112"));
09965:                                }
09966:                            }
09967:                            break;
09968:                        }
09969:                        switch ((vertexType & GeometryArrayRetained.TEXCOORD_DEFINED)) {
09970:                        case TF:
09971:                            FloatBufferWrapper texBuffer;
09972:                            for (int i = 0; i < texCoordSetCount; i++) {
09973:                                texBuffer = (FloatBufferWrapper) (((J3DBuffer) refTexCoordsBuffer[i])
09974:                                        .getBufferImpl());
09975:                                if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_2) != 0) {
09976:                                    if (texBuffer.limit() < 2 * (initialTexCoordIndex[i] + validVertexCount)) {
09977:                                        throw new ArrayIndexOutOfBoundsException(
09978:                                                J3dI18N
09979:                                                        .getString("GeometryArray113"));
09980:                                    }
09981:                                } else if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0) {
09982:                                    if (texBuffer.limit() < 3 * (initialTexCoordIndex[i] + validVertexCount)) {
09983:                                        throw new ArrayIndexOutOfBoundsException(
09984:                                                J3dI18N
09985:                                                        .getString("GeometryArray113"));
09986:                                    }
09987:                                } else if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_4) != 0) {
09988:                                    if (texBuffer.limit() < 4 * (initialTexCoordIndex[i] + validVertexCount)) {
09989:                                        throw new ArrayIndexOutOfBoundsException(
09990:                                                J3dI18N
09991:                                                        .getString("GeometryArray113"));
09992:                                    }
09993:                                }
09994:                            }
09995:                            break;
09996:                        }
09997:                        switch ((vertexType & GeometryArrayRetained.NORMAL_DEFINED)) {
09998:                        case NF:
09999:                            if (floatBufferRefNormals.limit() < 3 * (initialNormalIndex + validVertexCount)) {
10000:                                throw new ArrayIndexOutOfBoundsException(
10001:                                        J3dI18N.getString("GeometryArray111"));
10002:                            }
10003:                            break;
10004:                        }
10005:                        switch ((vertexType & GeometryArrayRetained.VATTR_DEFINED)) {
10006:                        case AF:
10007:                            for (int i = 0; i < vertexAttrCount; i++) {
10008:                                int sz = vertexAttrSizes[i];
10009:                                if (floatBufferRefVertexAttrs[i].limit() < (sz * (initialVertexAttrIndex[i] + validVertexCount))) {
10010:                                    throw new ArrayIndexOutOfBoundsException(
10011:                                            J3dI18N
10012:                                                    .getString("GeometryArray129"));
10013:                                }
10014:                            }
10015:                            break;
10016:                        }
10017:                    }
10018:                    // By reference with java array
10019:                    else {
10020:                        switch ((vertexType & GeometryArrayRetained.VERTEX_DEFINED)) {
10021:                        case PF:
10022:                            if (floatRefCoords.length < 3 * (initialCoordIndex + validVertexCount)) {
10023:                                throw new ArrayIndexOutOfBoundsException(
10024:                                        J3dI18N.getString("GeometryArray99"));
10025:                            }
10026:                            break;
10027:                        case PD:
10028:                            if (doubleRefCoords.length < 3 * (initialCoordIndex + validVertexCount)) {
10029:                                throw new ArrayIndexOutOfBoundsException(
10030:                                        J3dI18N.getString("GeometryArray99"));
10031:                            }
10032:                            break;
10033:                        case P3F:
10034:                            if (p3fRefCoords.length < (initialCoordIndex + validVertexCount)) {
10035:                                throw new ArrayIndexOutOfBoundsException(
10036:                                        J3dI18N.getString("GeometryArray99"));
10037:                            }
10038:                            break;
10039:                        case P3D:
10040:                            if (p3dRefCoords.length < (initialCoordIndex + validVertexCount)) {
10041:                                throw new ArrayIndexOutOfBoundsException(
10042:                                        J3dI18N.getString("GeometryArray99"));
10043:                            }
10044:                            break;
10045:                        }
10046:                        switch ((vertexType & COLOR_DEFINED)) {
10047:                        case CF:
10048:                            if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_3) {
10049:                                if (floatRefColors.length < 3 * (initialColorIndex + validVertexCount)) {
10050:                                    throw new ArrayIndexOutOfBoundsException(
10051:                                            J3dI18N
10052:                                                    .getString("GeometryArray112"));
10053:                                }
10054:                            } else if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_4) {
10055:                                if (floatRefColors.length < 4 * (initialColorIndex + validVertexCount)) {
10056:                                    throw new ArrayIndexOutOfBoundsException(
10057:                                            J3dI18N
10058:                                                    .getString("GeometryArray112"));
10059:                                }
10060:                            }
10061:                            break;
10062:                        case CUB:
10063:                            if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_3) {
10064:                                if (byteRefColors.length < 3 * (initialColorIndex + validVertexCount)) {
10065:                                    throw new ArrayIndexOutOfBoundsException(
10066:                                            J3dI18N
10067:                                                    .getString("GeometryArray112"));
10068:                                }
10069:                            } else if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_4) {
10070:                                if (byteRefColors.length < 4 * (initialColorIndex + validVertexCount)) {
10071:                                    throw new ArrayIndexOutOfBoundsException(
10072:                                            J3dI18N
10073:                                                    .getString("GeometryArray112"));
10074:                                }
10075:                            }
10076:                            break;
10077:                        case C3F:
10078:                            if (c3fRefColors.length < (initialColorIndex + validVertexCount)) {
10079:                                throw new ArrayIndexOutOfBoundsException(
10080:                                        J3dI18N.getString("GeometryArray112"));
10081:                            }
10082:                            break;
10083:                        case C4F:
10084:                            if (c4fRefColors.length < (initialColorIndex + validVertexCount)) {
10085:                                throw new ArrayIndexOutOfBoundsException(
10086:                                        J3dI18N.getString("GeometryArray112"));
10087:                            }
10088:                            break;
10089:                        case C3UB:
10090:                            if (c3bRefColors.length < (initialColorIndex + validVertexCount)) {
10091:                                throw new ArrayIndexOutOfBoundsException(
10092:                                        J3dI18N.getString("GeometryArray112"));
10093:                            }
10094:                            break;
10095:                        case C4UB:
10096:                            if (c4bRefColors.length < (initialColorIndex + validVertexCount)) {
10097:                                throw new ArrayIndexOutOfBoundsException(
10098:                                        J3dI18N.getString("GeometryArray112"));
10099:                            }
10100:                            break;
10101:                        }
10102:                        switch ((vertexType & GeometryArrayRetained.TEXCOORD_DEFINED)) {
10103:                        case TF:
10104:                            for (int i = 0; i < texCoordSetCount; i++) {
10105:                                if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_2) != 0) {
10106:                                    if (((float[]) refTexCoords[i]).length < 2 * (initialTexCoordIndex[i] + validVertexCount)) {
10107:                                        throw new ArrayIndexOutOfBoundsException(
10108:                                                J3dI18N
10109:                                                        .getString("GeometryArray113"));
10110:                                    }
10111:                                } else if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0) {
10112:                                    if (((float[]) refTexCoords[i]).length < 3 * (initialTexCoordIndex[i] + validVertexCount)) {
10113:                                        throw new ArrayIndexOutOfBoundsException(
10114:                                                J3dI18N
10115:                                                        .getString("GeometryArray113"));
10116:                                    } else if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_4) != 0) {
10117:                                        if (((float[]) refTexCoords[i]).length < 4 * (initialTexCoordIndex[i] + validVertexCount)) {
10118:                                            throw new ArrayIndexOutOfBoundsException(
10119:                                                    J3dI18N
10120:                                                            .getString("GeometryArray113"));
10121:                                        }
10122:                                    }
10123:                                }
10124:                            }
10125:                            break;
10126:                        case T2F:
10127:                            for (int i = 0; i < texCoordSetCount; i++) {
10128:                                if (((TexCoord2f[]) refTexCoords[i]).length < (initialTexCoordIndex[i] + validVertexCount)) {
10129:                                    throw new ArrayIndexOutOfBoundsException(
10130:                                            J3dI18N
10131:                                                    .getString("GeometryArray113"));
10132:                                }
10133:                            }
10134:                            break;
10135:                        case T3F:
10136:                            for (int i = 0; i < texCoordSetCount; i++) {
10137:                                if (((TexCoord3f[]) refTexCoords[i]).length < (initialTexCoordIndex[i] + validVertexCount)) {
10138:                                    throw new ArrayIndexOutOfBoundsException(
10139:                                            J3dI18N
10140:                                                    .getString("GeometryArray113"));
10141:                                }
10142:                            }
10143:                            break;
10144:                        }
10145:                        switch ((vertexType & GeometryArrayRetained.NORMAL_DEFINED)) {
10146:                        case NF:
10147:                            if (floatRefNormals.length < 3 * (initialNormalIndex + validVertexCount)) {
10148:                                throw new ArrayIndexOutOfBoundsException(
10149:                                        J3dI18N.getString("GeometryArray111"));
10150:                            }
10151:                            break;
10152:                        case N3F:
10153:                            if (v3fRefNormals.length < (initialNormalIndex + validVertexCount)) {
10154:                                throw new ArrayIndexOutOfBoundsException(
10155:                                        J3dI18N.getString("GeometryArray111"));
10156:                            }
10157:                        }
10158:                        switch ((vertexType & GeometryArrayRetained.VATTR_DEFINED)) {
10159:                        case AF:
10160:                            for (int i = 0; i < vertexAttrCount; i++) {
10161:                                int sz = vertexAttrSizes[i];
10162:                                if (floatRefVertexAttrs[i].length < (sz * (initialVertexAttrIndex[i] + validVertexCount))) {
10163:                                    throw new ArrayIndexOutOfBoundsException(
10164:                                            J3dI18N
10165:                                                    .getString("GeometryArray129"));
10166:                                }
10167:                            }
10168:                            break;
10169:                        }
10170:                    }
10171:                }
10172:                boolean isLive = source != null && source.isLive();
10173:                if (isLive) {
10174:                    geomLock.getLock();
10175:                }
10176:                dirtyFlag |= VERTEX_CHANGED;
10177:                this .validVertexCount = validVertexCount;
10178:
10179:                if (isLive) {
10180:                    geomLock.unLock();
10181:                }
10182:
10183:                if (!inUpdater && isLive) {
10184:                    processCoordsChanged(nullGeo);
10185:                    sendDataChangedMessage(true);
10186:                }
10187:            }
10188:
10189:            int getValidVertexCount() {
10190:                return validVertexCount;
10191:            }
10192:
10193:            //Used for interleaved data (array or nio buffer)
10194:            void setInitialVertexIndex(int initialVertexIndex) {
10195:                boolean nullGeo = false;
10196:
10197:                if ((initialVertexIndex + validVertexCount) > vertexCount) {
10198:                    throw new IllegalArgumentException(J3dI18N
10199:                            .getString("GeometryArray100"));
10200:                }
10201:
10202:                if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) != 0
10203:                        && interleavedFloatBufferImpl != null) {
10204:                    if (interleavedFloatBufferImpl.limit() < stride
10205:                            * (initialVertexIndex + validVertexCount)) {
10206:                        throw new ArrayIndexOutOfBoundsException(J3dI18N
10207:                                .getString("GeometryArray114"));
10208:                    }
10209:                }
10210:                // interleaved data using java array
10211:                else if (interLeavedVertexData != null) {
10212:                    if (interLeavedVertexData.length < stride
10213:                            * (initialVertexIndex + validVertexCount)) {
10214:                        throw new ArrayIndexOutOfBoundsException(J3dI18N
10215:                                .getString("GeometryArray114"));
10216:                    }
10217:                } else {
10218:                    nullGeo = (vertexFormat & GeometryArray.INTERLEAVED) != 0; // Only for byRef
10219:                }
10220:                boolean isLive = source != null && source.isLive();
10221:                if (isLive) {
10222:                    geomLock.getLock();
10223:                }
10224:                dirtyFlag |= VERTEX_CHANGED;
10225:                this .initialVertexIndex = initialVertexIndex;
10226:                if (isLive) {
10227:                    geomLock.unLock();
10228:                }
10229:                if (!inUpdater && isLive) {
10230:                    processCoordsChanged(nullGeo);
10231:                    sendDataChangedMessage(true);
10232:                }
10233:            }
10234:
10235:            int getInitialVertexIndex() {
10236:                return initialVertexIndex;
10237:            }
10238:
10239:            void setInitialCoordIndex(int initialCoordIndex) {
10240:                if ((initialCoordIndex + validVertexCount) > vertexCount) {
10241:                    throw new IllegalArgumentException(J3dI18N
10242:                            .getString("GeometryArray104"));
10243:                }
10244:                // use NIO buffer
10245:                if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) != 0) {
10246:                    switch ((vertexType & GeometryArrayRetained.VERTEX_DEFINED)) {
10247:                    case PF:
10248:                        if (floatBufferRefCoords.limit() < (initialCoordIndex + validVertexCount)) {
10249:                            throw new ArrayIndexOutOfBoundsException(J3dI18N
10250:                                    .getString("GeometryArray99"));
10251:                        }
10252:                        break;
10253:                    case PD:
10254:                        if (doubleBufferRefCoords.limit() < (initialCoordIndex + validVertexCount)) {
10255:                            throw new ArrayIndexOutOfBoundsException(J3dI18N
10256:                                    .getString("GeometryArray99"));
10257:                        }
10258:                        break;
10259:                    }
10260:                } else {
10261:                    switch ((vertexType & GeometryArrayRetained.VERTEX_DEFINED)) {
10262:                    case PF:
10263:                        if (floatRefCoords.length < 3 * (initialCoordIndex + validVertexCount)) {
10264:                            throw new ArrayIndexOutOfBoundsException(J3dI18N
10265:                                    .getString("GeometryArray99"));
10266:                        }
10267:                        break;
10268:                    case PD:
10269:                        if (doubleRefCoords.length < 3 * (initialCoordIndex + validVertexCount)) {
10270:                            throw new ArrayIndexOutOfBoundsException(J3dI18N
10271:                                    .getString("GeometryArray99"));
10272:                        }
10273:                        break;
10274:                    case P3F:
10275:                        if (p3fRefCoords.length < (initialCoordIndex + validVertexCount)) {
10276:                            throw new ArrayIndexOutOfBoundsException(J3dI18N
10277:                                    .getString("GeometryArray99"));
10278:                        }
10279:                        break;
10280:                    case P3D:
10281:                        if (p3dRefCoords.length < (initialCoordIndex + validVertexCount)) {
10282:                            throw new ArrayIndexOutOfBoundsException(J3dI18N
10283:                                    .getString("GeometryArray99"));
10284:                        }
10285:                        break;
10286:                    }
10287:                }
10288:                boolean isLive = source != null && source.isLive();
10289:                if (isLive) {
10290:                    geomLock.getLock();
10291:                }
10292:                dirtyFlag |= COORDINATE_CHANGED;
10293:                this .initialCoordIndex = initialCoordIndex;
10294:                dirtyFlag |= COORDINATE_CHANGED;
10295:                if (isLive) {
10296:                    geomLock.unLock();
10297:                }
10298:                // Send a message, since bounds changed
10299:                if (!inUpdater && isLive) {
10300:                    processCoordsChanged((vertexType & GeometryArrayRetained.VERTEX_DEFINED) == 0);
10301:                    sendDataChangedMessage(true);
10302:                }
10303:            }
10304:
10305:            int getInitialCoordIndex() {
10306:                return initialCoordIndex;
10307:            }
10308:
10309:            void setInitialColorIndex(int initialColorIndex) {
10310:                if ((initialColorIndex + validVertexCount) > vertexCount) {
10311:                    throw new IllegalArgumentException(J3dI18N
10312:                            .getString("GeometryArray101"));
10313:                }
10314:                // NIO BUFFER CASE
10315:                if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) != 0) {
10316:                    switch ((vertexType & COLOR_DEFINED)) {
10317:                    case CF:
10318:                        if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_3) {
10319:                            if (floatBufferRefColors.limit() < 3 * (initialColorIndex + validVertexCount)) {
10320:                                throw new ArrayIndexOutOfBoundsException(
10321:                                        J3dI18N.getString("GeometryArray112"));
10322:                            }
10323:                        } else if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_4) {
10324:                            if (floatBufferRefColors.limit() < 4 * (initialColorIndex + validVertexCount)) {
10325:                                throw new ArrayIndexOutOfBoundsException(
10326:                                        J3dI18N.getString("GeometryArray112"));
10327:                            }
10328:                        }
10329:                        break;
10330:
10331:                    case CUB:
10332:                        if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_3) {
10333:                            if (byteBufferRefColors.limit() < 3 * (initialColorIndex + validVertexCount)) {
10334:                                throw new ArrayIndexOutOfBoundsException(
10335:                                        J3dI18N.getString("GeometryArray112"));
10336:                            }
10337:                        } else if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_4) {
10338:                            if (byteBufferRefColors.limit() < 4 * (initialColorIndex + validVertexCount)) {
10339:                                throw new ArrayIndexOutOfBoundsException(
10340:                                        J3dI18N.getString("GeometryArray112"));
10341:                            }
10342:                        }
10343:                        break;
10344:                    }
10345:                }
10346:                // Java ARRAY CASE
10347:                else {
10348:                    switch ((vertexType & COLOR_DEFINED)) {
10349:                    case CF:
10350:                        if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_3) {
10351:                            if (floatRefColors.length < 3 * (initialColorIndex + validVertexCount)) {
10352:                                throw new ArrayIndexOutOfBoundsException(
10353:                                        J3dI18N.getString("GeometryArray112"));
10354:                            }
10355:                        } else if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_4) {
10356:                            if (floatRefColors.length < 4 * (initialColorIndex + validVertexCount)) {
10357:                                throw new ArrayIndexOutOfBoundsException(
10358:                                        J3dI18N.getString("GeometryArray112"));
10359:                            }
10360:                        }
10361:                        break;
10362:                    case CUB:
10363:                        if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_3) {
10364:                            if (byteRefColors.length < 3 * (initialColorIndex + validVertexCount)) {
10365:                                throw new ArrayIndexOutOfBoundsException(
10366:                                        J3dI18N.getString("GeometryArray112"));
10367:                            }
10368:                        } else if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_4) {
10369:                            if (byteRefColors.length < 4 * (initialColorIndex + validVertexCount)) {
10370:                                throw new ArrayIndexOutOfBoundsException(
10371:                                        J3dI18N.getString("GeometryArray112"));
10372:                            }
10373:                        }
10374:                        break;
10375:                    case C3F:
10376:                        if (c3fRefColors.length < (initialColorIndex + validVertexCount)) {
10377:                            throw new ArrayIndexOutOfBoundsException(J3dI18N
10378:                                    .getString("GeometryArray112"));
10379:                        }
10380:                        break;
10381:                    case C4F:
10382:                        if (c4fRefColors.length < (initialColorIndex + validVertexCount)) {
10383:                            throw new ArrayIndexOutOfBoundsException(J3dI18N
10384:                                    .getString("GeometryArray112"));
10385:                        }
10386:                        break;
10387:                    case C3UB:
10388:                        if (c3bRefColors.length < (initialColorIndex + validVertexCount)) {
10389:                            throw new ArrayIndexOutOfBoundsException(J3dI18N
10390:                                    .getString("GeometryArray112"));
10391:                        }
10392:                        break;
10393:                    case C4UB:
10394:                        if (c4bRefColors.length < (initialColorIndex + validVertexCount)) {
10395:                            throw new ArrayIndexOutOfBoundsException(J3dI18N
10396:                                    .getString("GeometryArray112"));
10397:                        }
10398:                        break;
10399:                    }
10400:                }
10401:                boolean isLive = source != null && source.isLive();
10402:                if (isLive) {
10403:                    geomLock.getLock();
10404:                }
10405:                dirtyFlag |= COLOR_CHANGED;
10406:                colorChanged = 0xffff;
10407:                this .initialColorIndex = initialColorIndex;
10408:                if (isLive) {
10409:                    geomLock.unLock();
10410:                }
10411:                // There is no need to send message for by reference, since we
10412:                // use VA
10413:
10414:            }
10415:
10416:            int getInitialColorIndex() {
10417:                return initialColorIndex;
10418:            }
10419:
10420:            void setInitialNormalIndex(int initialNormalIndex) {
10421:                if ((initialNormalIndex + validVertexCount) > vertexCount) {
10422:                    throw new IllegalArgumentException(J3dI18N
10423:                            .getString("GeometryArray102"));
10424:                }
10425:                if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) != 0) {
10426:                    if ((vertexType & NORMAL_DEFINED) == NF) {
10427:                        if (floatBufferRefNormals.limit() < 3 * (initialNormalIndex + validVertexCount)) {
10428:                            throw new ArrayIndexOutOfBoundsException(J3dI18N
10429:                                    .getString("GeometryArray111"));
10430:                        }
10431:                    }
10432:                } else {
10433:                    switch ((vertexType & NORMAL_DEFINED)) {
10434:                    case NF:
10435:                        if (floatRefNormals.length < 3 * (initialNormalIndex + validVertexCount)) {
10436:                            throw new ArrayIndexOutOfBoundsException(J3dI18N
10437:                                    .getString("GeometryArray111"));
10438:                        }
10439:                        break;
10440:                    case N3F:
10441:                        if (v3fRefNormals.length < (initialNormalIndex + validVertexCount)) {
10442:                            throw new ArrayIndexOutOfBoundsException(J3dI18N
10443:                                    .getString("GeometryArray111"));
10444:                        }
10445:                    }
10446:                }
10447:                boolean isLive = source != null && source.isLive();
10448:                if (isLive) {
10449:                    geomLock.getLock();
10450:                }
10451:                dirtyFlag |= NORMAL_CHANGED;
10452:                this .initialNormalIndex = initialNormalIndex;
10453:                if (isLive) {
10454:                    geomLock.unLock();
10455:                }
10456:                // There is no need to send message for by reference, since we
10457:                // use VA
10458:            }
10459:
10460:            int getInitialNormalIndex() {
10461:                return initialNormalIndex;
10462:            }
10463:
10464:            /**
10465:             * Sets the initial vertex attribute index for the specified
10466:             * vertex attribute number for this GeometryArray object.
10467:             */
10468:            void setInitialVertexAttrIndex(int vertexAttrNum,
10469:                    int initialVertexAttrIndex) {
10470:
10471:                if ((initialVertexAttrIndex + validVertexCount) > vertexCount) {
10472:                    throw new IllegalArgumentException(J3dI18N
10473:                            .getString("GeometryArray130"));
10474:                }
10475:
10476:                int sz = vertexAttrSizes[vertexAttrNum];
10477:                int minLength = sz
10478:                        * (initialVertexAttrIndex + validVertexCount);
10479:                if ((vertexType & VATTR_DEFINED) == AF) {
10480:                    if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) != 0) {
10481:                        if (floatBufferRefVertexAttrs[vertexAttrNum].limit() < minLength) {
10482:                            throw new ArrayIndexOutOfBoundsException(J3dI18N
10483:                                    .getString("GeometryArray129"));
10484:                        }
10485:                    } else {
10486:                        if (floatRefVertexAttrs[vertexAttrNum].length < minLength) {
10487:                            throw new ArrayIndexOutOfBoundsException(J3dI18N
10488:                                    .getString("GeometryArray129"));
10489:                        }
10490:                    }
10491:                }
10492:                boolean isLive = source != null && source.isLive();
10493:                if (isLive) {
10494:                    geomLock.getLock();
10495:                }
10496:                dirtyFlag |= VATTR_CHANGED;
10497:                this .initialVertexAttrIndex[vertexAttrNum] = initialVertexAttrIndex;
10498:                if (isLive) {
10499:                    geomLock.unLock();
10500:                }
10501:                // There is no need to send message for by reference, since we
10502:                // use VA
10503:            }
10504:
10505:            /**
10506:             * Gets the initial vertex attribute index for the specified
10507:             * vertex attribute number for this GeometryArray object.
10508:             */
10509:            int getInitialVertexAttrIndex(int vertexAttrNum) {
10510:                return initialVertexAttrIndex[vertexAttrNum];
10511:            }
10512:
10513:            void setInitialTexCoordIndex(int texCoordSet,
10514:                    int initialTexCoordIndex) {
10515:                if ((initialTexCoordIndex + validVertexCount) > vertexCount) {
10516:                    throw new IllegalArgumentException(J3dI18N
10517:                            .getString("GeometryArray103"));
10518:                }
10519:
10520:                if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) != 0) {
10521:                    if ((vertexType & TEXCOORD_DEFINED) == TF) {
10522:                        FloatBufferWrapper texBuffer = (FloatBufferWrapper) (((J3DBuffer) refTexCoordsBuffer[texCoordSet])
10523:                                .getBufferImpl());
10524:                        if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_2) != 0) {
10525:                            if (texBuffer.limit() < 2 * (initialTexCoordIndex + validVertexCount)) {
10526:                                throw new ArrayIndexOutOfBoundsException(
10527:                                        J3dI18N.getString("GeometryArray113"));
10528:                            }
10529:                        } else if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0) {
10530:                            if (texBuffer.limit() < 3 * (initialTexCoordIndex + validVertexCount)) {
10531:                                throw new ArrayIndexOutOfBoundsException(
10532:                                        J3dI18N.getString("GeometryArray113"));
10533:                            }
10534:                        } else if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_4) != 0) {
10535:                            if (texBuffer.limit() < 4 * (initialTexCoordIndex + validVertexCount)) {
10536:                                throw new ArrayIndexOutOfBoundsException(
10537:                                        J3dI18N.getString("GeometryArray113"));
10538:                            }
10539:                        }
10540:                    }
10541:                } else {
10542:                    switch ((vertexType & TEXCOORD_DEFINED)) {
10543:                    case TF:
10544:                        if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_2) != 0) {
10545:                            if (((float[]) refTexCoords[texCoordSet]).length < 2 * (initialTexCoordIndex + validVertexCount)) {
10546:                                throw new ArrayIndexOutOfBoundsException(
10547:                                        J3dI18N.getString("GeometryArray113"));
10548:                            }
10549:                        } else if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0) {
10550:                            if (((float[]) refTexCoords[texCoordSet]).length < 3 * (initialTexCoordIndex + validVertexCount)) {
10551:                                throw new ArrayIndexOutOfBoundsException(
10552:                                        J3dI18N.getString("GeometryArray113"));
10553:                            }
10554:                        } else if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_4) != 0) {
10555:                            if (((float[]) refTexCoords[texCoordSet]).length < 4 * (initialTexCoordIndex + validVertexCount)) {
10556:                                throw new ArrayIndexOutOfBoundsException(
10557:                                        J3dI18N.getString("GeometryArray113"));
10558:                            }
10559:                        }
10560:                        break;
10561:                    case T2F:
10562:                        if (((TexCoord2f[]) refTexCoords[texCoordSet]).length < (initialTexCoordIndex + validVertexCount)) {
10563:                            throw new ArrayIndexOutOfBoundsException(J3dI18N
10564:                                    .getString("GeometryArray113"));
10565:                        }
10566:                        break;
10567:                    case T3F:
10568:                        if (((TexCoord3f[]) refTexCoords[texCoordSet]).length < (initialTexCoordIndex + validVertexCount)) {
10569:                            throw new ArrayIndexOutOfBoundsException(J3dI18N
10570:                                    .getString("GeometryArray113"));
10571:                        }
10572:                        break;
10573:                    }
10574:                }
10575:                boolean isLive = source != null && source.isLive();
10576:                if (isLive) {
10577:                    geomLock.getLock();
10578:                }
10579:                dirtyFlag |= TEXTURE_CHANGED;
10580:                this .initialTexCoordIndex[texCoordSet] = initialTexCoordIndex;
10581:                if (isLive) {
10582:                    geomLock.unLock();
10583:                }
10584:                // There is no need to send message for by reference, since we
10585:                // use VA
10586:            }
10587:
10588:            int getInitialTexCoordIndex(int texCoordSet) {
10589:                return initialTexCoordIndex[texCoordSet];
10590:            }
10591:
10592:            int getTexCoordSetCount() {
10593:                return this .texCoordSetCount;
10594:            }
10595:
10596:            int getTexCoordSetMapLength() {
10597:                if (this .texCoordSetMap != null)
10598:                    return this .texCoordSetMap.length;
10599:                else
10600:                    return 0;
10601:            }
10602:
10603:            void getTexCoordSetMap(int[] texCoordSetMap) {
10604:
10605:                if (this .texCoordSetMap != null) {
10606:                    for (int i = 0; i < this .texCoordSetMap.length; i++) {
10607:                        texCoordSetMap[i] = this .texCoordSetMap[i];
10608:                    }
10609:                }
10610:            }
10611:
10612:            void freeDlistId() {
10613:                if (dlistId != -1) {
10614:                    VirtualUniverse.mc.freeDisplayListId(dlistObj);
10615:                    dlistId = -1;
10616:                }
10617:            }
10618:
10619:            void assignDlistId() {
10620:                if (dlistId == -1) {
10621:                    dlistObj = VirtualUniverse.mc.getDisplayListId();
10622:                    dlistId = dlistObj.intValue();
10623:                }
10624:            }
10625:
10626:            // Add the specified render atom as a user of this geometry array
10627:            // (for the specified render bin)
10628:            void addDlistUser(RenderBin renderBin, RenderAtomListInfo ra) {
10629:                if (dlistUsers == null) {
10630:                    dlistUsers = new HashMap(2, 1.0f);
10631:                }
10632:
10633:                Set raSet = (Set) dlistUsers.get(renderBin);
10634:                if (raSet == null) {
10635:                    raSet = new HashSet();
10636:                    dlistUsers.put(renderBin, raSet);
10637:                }
10638:                raSet.add(ra);
10639:            }
10640:
10641:            // Remove the specified render atom from the set of users of this
10642:            // geometry array (for the specified render bin)
10643:            void removeDlistUser(RenderBin renderBin, RenderAtomListInfo ra) {
10644:                if (dlistUsers == null) {
10645:                    // Nothing to do
10646:                    return;
10647:                }
10648:
10649:                Set raSet = (Set) dlistUsers.get(renderBin);
10650:                if (raSet == null) {
10651:                    // Nothing to do
10652:                    return;
10653:                }
10654:                raSet.remove(ra);
10655:            }
10656:
10657:            // Returns true if the set of render atoms using this geometry
10658:            // array in the specified render bin is empty.
10659:            boolean isDlistUserSetEmpty(RenderBin renderBin) {
10660:                if (dlistUsers == null) {
10661:                    return true;
10662:                }
10663:
10664:                Set raSet = (Set) dlistUsers.get(renderBin);
10665:                if (raSet == null) {
10666:                    return true;
10667:                }
10668:                return raSet.isEmpty();
10669:            }
10670:
10671:            // This method is used for debugging only
10672:            int numDlistUsers(RenderBin renderBin) {
10673:                if (isDlistUserSetEmpty(renderBin)) {
10674:                    return 0;
10675:                }
10676:                Set raSet = (Set) dlistUsers.get(renderBin);
10677:                return raSet.size();
10678:            }
10679:
10680:            void setDlistTimeStamp(int rdrBit, long timeStamp) {
10681:                int index = getIndex(rdrBit);
10682:                if (index >= timeStampPerDlist.length) {
10683:                    long[] newList = new long[index * 2];
10684:                    for (int i = 0; i < timeStampPerDlist.length; i++) {
10685:                        newList[i] = timeStampPerDlist[i];
10686:                    }
10687:                    timeStampPerDlist = newList;
10688:                }
10689:                timeStampPerDlist[index] = timeStamp;
10690:            }
10691:
10692:            long getDlistTimeStamp(int rdrBit) {
10693:                int index = getIndex(rdrBit);
10694:                // If index is greater than what currently exists, increase
10695:                // the array and return zero
10696:                if (index >= timeStampPerDlist.length) {
10697:                    setDlistTimeStamp(rdrBit, 0);
10698:                }
10699:                return timeStampPerDlist[index];
10700:            }
10701:
10702:            int getIndex(int bit) {
10703:                int num = 0;
10704:
10705:                while (bit > 0) {
10706:                    num++;
10707:                    bit >>= 1;
10708:                }
10709:                return num;
10710:            }
10711:
10712:            boolean isWriteStatic() {
10713:
10714:                if (source.getCapability(GeometryArray.ALLOW_COORDINATE_WRITE)
10715:                        || source
10716:                                .getCapability(GeometryArray.ALLOW_COLOR_WRITE)
10717:                        || source
10718:                                .getCapability(GeometryArray.ALLOW_NORMAL_WRITE)
10719:                        || source
10720:                                .getCapability(GeometryArray.ALLOW_TEXCOORD_WRITE)
10721:                        || source
10722:                                .getCapability(GeometryArray.ALLOW_VERTEX_ATTR_WRITE)
10723:                        || source
10724:                                .getCapability(GeometryArray.ALLOW_COUNT_WRITE)
10725:                        || source
10726:                                .getCapability(GeometryArray.ALLOW_REF_DATA_WRITE))
10727:                    return false;
10728:
10729:                return true;
10730:            }
10731:
10732:            /**
10733:             * The functions below are only used in compile mode
10734:             */
10735:            void setCompiled(ArrayList curList) {
10736:                int i;
10737:                int num = curList.size();
10738:                int offset = 0;
10739:                geoOffset = new int[num];
10740:                compileVcount = new int[num];
10741:                int vcount = 0, vformat = 0;
10742:                vcount = 0;
10743:                isCompiled = true;
10744:
10745:                if (num > 0)
10746:                    source = ((SceneGraphObjectRetained) curList.get(0)).source;
10747:                for (i = 0; i < num; i++) {
10748:                    // Build the back mapping
10749:                    GeometryArrayRetained geo = (GeometryArrayRetained) curList
10750:                            .get(i);
10751:                    ((GeometryArray) geo.source).retained = this ;
10752:                    compileVcount[i] = geo.getValidVertexCount();
10753:                    vcount += geo.getValidVertexCount();
10754:                    geoOffset[i] = offset;
10755:                    offset += geo.stride() * compileVcount[i];
10756:                    vformat = geo.getVertexFormat();
10757:                }
10758:                createGeometryArrayData(vcount, vformat);
10759:
10760:                // Assign the initial and valid fields
10761:                validVertexCount = vcount;
10762:                initialVertexIndex = 0;
10763:
10764:                mergeGeometryArrays(curList);
10765:
10766:            }
10767:
10768:            /*
10769:            // Ununsed
10770:            int getVertexCount(int index) {
10771:            return compileVcount[index];
10772:            }
10773:
10774:
10775:            int getValidVertexCount(int index) {
10776:            return compileVcount[index];
10777:            }
10778:
10779:
10780:            int getInitialVertexIndex(int index) {
10781:            return 0;
10782:            }
10783:             */
10784:
10785:            void mergeGeometryArrays(ArrayList list) {
10786:                float[] curVertexData;
10787:                int length, srcOffset;
10788:                int curOffset = 0;
10789:                // We only merge if the texCoordSetCount is 1 and there are no
10790:                // vertex attrs
10791:                if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) {
10792:                    texCoordSetCount = 1;
10793:                    texCoordSetMap = new int[1];
10794:                    texCoordSetMap[0] = 1;
10795:                }
10796:                for (int i = 0; i < list.size(); i++) {
10797:                    GeometryArrayRetained geo = (GeometryArrayRetained) list
10798:                            .get(i);
10799:                    // Take into account the validVertexCount and initialVertexIndex
10800:                    curVertexData = geo.vertexData;
10801:                    length = geo.validVertexCount * stride;
10802:                    srcOffset = geo.initialVertexIndex * stride;
10803:                    System.arraycopy(curVertexData, srcOffset, this .vertexData,
10804:                            curOffset, length);
10805:                    curOffset += length;
10806:
10807:                    // assign geoBounds
10808:                    geoBounds.combine(geo.geoBounds);
10809:
10810:                }
10811:                this .centroid.set(geoBounds.getCenter());
10812:            }
10813:
10814:            boolean isMergeable() {
10815:
10816:                // For now, turn off by ref geometry
10817:                if ((vertexFormat & GeometryArray.BY_REFERENCE) != 0)
10818:                    return false;
10819:
10820:                if (!isStatic())
10821:                    return false;
10822:
10823:                // If there is more than one set of texture coordinate set defined
10824:                // then don't merge geometry (we avoid dealing with texCoordSetMap
10825:                if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0
10826:                        && (texCoordSetCount > 1 || texCoordSetMap != null
10827:                                && texCoordSetMap.length > 1)) {
10828:                    return false;
10829:                }
10830:
10831:                // We will avoid merging geometry if there are any vertex attributes.
10832:                if ((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) {
10833:                    return false;
10834:                }
10835:
10836:                // If intersect is allowed turn off merging
10837:                if (source.getCapability(Geometry.ALLOW_INTERSECT))
10838:                    return false;
10839:
10840:                return true;
10841:            }
10842:
10843:            void compile(CompileState compState) {
10844:                super .compile(compState);
10845:
10846:                if ((vertexFormat & GeometryArray.NORMALS) != 0) {
10847:                    compState.needNormalsTransform = true;
10848:                }
10849:            }
10850:
10851:            void mergeTransform(TransformGroupRetained xform) {
10852:                if (geoBounds != null) {
10853:                    geoBounds.transform(xform.transform);
10854:                }
10855:            }
10856:
10857:            // This adds a MorphRetained to the list of users of this geometry
10858:            void addMorphUser(MorphRetained m) {
10859:                int index;
10860:                ArrayList morphList;
10861:
10862:                if (morphUniverseList == null) {
10863:                    morphUniverseList = new ArrayList(1);
10864:                    morphUserLists = new ArrayList(1);
10865:                }
10866:                synchronized (morphUniverseList) {
10867:                    if (morphUniverseList.contains(m.universe)) {
10868:                        index = morphUniverseList.indexOf(m.universe);
10869:                        morphList = (ArrayList) morphUserLists.get(index);
10870:                        morphList.add(m);
10871:                    } else {
10872:                        morphUniverseList.add(m.universe);
10873:                        morphList = new ArrayList(5);
10874:                        morphList.add(m);
10875:                        morphUserLists.add(morphList);
10876:                    }
10877:                }
10878:            }
10879:
10880:            // This adds a MorphRetained to the list of users of this geometry
10881:            void removeMorphUser(MorphRetained m) {
10882:                int index;
10883:                ArrayList morphList;
10884:
10885:                if (morphUniverseList == null)
10886:                    return;
10887:
10888:                synchronized (morphUniverseList) {
10889:                    index = morphUniverseList.indexOf(m.universe);
10890:                    morphList = (ArrayList) morphUserLists.get(index);
10891:                    morphList.remove(morphList.indexOf(m));
10892:                    if (morphList.size() == 0) {
10893:                        morphUserLists.remove(index);
10894:                        morphUniverseList.remove(index);
10895:                    }
10896:                }
10897:            }
10898:
10899:            // Initialize mirror object when geometry is first setLived
10900:            void initMirrorGeometry() {
10901:                geomLock.getLock();
10902:                if (this  instanceof  IndexedGeometryArrayRetained) {
10903:                    if ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) == 0) {
10904:                        mirrorGeometry = ((IndexedGeometryArrayRetained) this )
10905:                                .cloneNonIndexedGeometry();
10906:                    } else {
10907:                        mirrorGeometry = null;
10908:                    }
10909:                }
10910:                geomLock.unLock();
10911:
10912:            }
10913:
10914:            // Update Mirror Object in response to change in geometry
10915:            void updateMirrorGeometry() {
10916:                geomLock.getLock();
10917:                if (this  instanceof  IndexedGeometryArrayRetained) {
10918:                    if (mirrorGeometry != null) {
10919:                        mirrorGeometry = ((IndexedGeometryArrayRetained) this )
10920:                                .cloneNonIndexedGeometry();
10921:                    }
10922:                }
10923:                geomLock.unLock();
10924:
10925:            }
10926:
10927:            // Used by the picking intersect routines
10928:            void getVertexData(int i, Point3d pnts) {
10929:                int offset;
10930:                if ((vertexFormat & GeometryArray.BY_REFERENCE) == 0) {
10931:                    offset = stride * i + coordinateOffset;
10932:                    pnts.x = this .vertexData[offset];
10933:                    pnts.y = this .vertexData[offset + 1];
10934:                    pnts.z = this .vertexData[offset + 2];
10935:                    return;
10936:                }
10937:
10938:                if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) == 0) {
10939:                    if ((vertexFormat & GeometryArray.INTERLEAVED) != 0) {
10940:                        offset = stride * i + coordinateOffset;
10941:                        pnts.x = this .interLeavedVertexData[offset];
10942:                        pnts.y = this .interLeavedVertexData[offset + 1];
10943:                        pnts.z = this .interLeavedVertexData[offset + 2];
10944:                    } else {
10945:                        switch ((vertexType & GeometryArrayRetained.VERTEX_DEFINED)) {
10946:                        case GeometryArrayRetained.PF:
10947:                            offset = i * 3;
10948:                            pnts.x = this .floatRefCoords[offset];
10949:                            pnts.y = this .floatRefCoords[offset + 1];
10950:                            pnts.z = this .floatRefCoords[offset + 2];
10951:                            break;
10952:                        case GeometryArrayRetained.PD:
10953:                            offset = i * 3;
10954:                            pnts.x = this .doubleRefCoords[offset];
10955:                            pnts.y = this .doubleRefCoords[offset + 1];
10956:                            pnts.z = this .doubleRefCoords[offset + 2];
10957:                            break;
10958:                        case GeometryArrayRetained.P3F:
10959:                            pnts.x = this .p3fRefCoords[i].x;
10960:                            pnts.y = this .p3fRefCoords[i].y;
10961:                            pnts.z = this .p3fRefCoords[i].z;
10962:                            break;
10963:                        case GeometryArrayRetained.P3D:
10964:                            pnts.x = this .p3dRefCoords[i].x;
10965:                            pnts.y = this .p3dRefCoords[i].y;
10966:                            pnts.z = this .p3dRefCoords[i].z;
10967:                            break;
10968:                        }
10969:                    }
10970:                }// end of non nio buffer
10971:                else { // NIO BUFFER
10972:                    if ((vertexFormat & GeometryArray.INTERLEAVED) != 0) {
10973:                        offset = stride * i + coordinateOffset;
10974:                        pnts.x = this .interleavedFloatBufferImpl.get(offset);
10975:                        pnts.y = this .interleavedFloatBufferImpl
10976:                                .get(offset + 1);
10977:                        pnts.z = this .interleavedFloatBufferImpl
10978:                                .get(offset + 2);
10979:                    } else {
10980:                        switch ((vertexType & GeometryArrayRetained.VERTEX_DEFINED)) {
10981:                        case GeometryArrayRetained.PF:
10982:                            offset = i * 3;
10983:                            pnts.x = this .floatBufferRefCoords.get(offset);
10984:                            pnts.y = this .floatBufferRefCoords.get(offset + 1);
10985:                            pnts.z = this .floatBufferRefCoords.get(offset + 2);
10986:                            break;
10987:                        case GeometryArrayRetained.PD:
10988:                            offset = i * 3;
10989:                            pnts.x = this .doubleBufferRefCoords.get(offset);
10990:                            pnts.y = this .doubleBufferRefCoords.get(offset + 1);
10991:                            pnts.z = this .doubleBufferRefCoords.get(offset + 2);
10992:                            break;
10993:                        }
10994:                    }
10995:                } // end of nio buffer
10996:            }
10997:
10998:            void getCrossValue(Point3d p1, Point3d p2, Vector3d value) {
10999:                value.x += p1.y * p2.z - p1.z * p2.y;
11000:                value.y += p2.x * p1.z - p2.z * p1.x;
11001:                value.z += p1.x * p2.y - p1.y * p2.x;
11002:            }
11003:
11004:            boolean intersect(Transform3D this LocalToVworld,
11005:                    Transform3D otherLocalToVworld, GeometryRetained geom) {
11006:
11007:                Transform3D t3d = new Transform3D();
11008:                boolean isIntersect = false;
11009:
11010:                if (geom instanceof  GeometryArrayRetained) {
11011:                    GeometryArrayRetained geomArray = (GeometryArrayRetained) geom;
11012:
11013:                    if (geomArray.validVertexCount >= validVertexCount) {
11014:                        t3d.invert(otherLocalToVworld);
11015:                        t3d.mul(this LocalToVworld);
11016:                        isIntersect = intersect(t3d, geom);
11017:                    } else {
11018:                        t3d.invert(this LocalToVworld);
11019:                        t3d.mul(otherLocalToVworld);
11020:                        isIntersect = geomArray.intersect(t3d, this );
11021:                    }
11022:                } else {
11023:                    t3d.invert(this LocalToVworld);
11024:                    t3d.mul(otherLocalToVworld);
11025:                    isIntersect = geom.intersect(t3d, this );
11026:                }
11027:                return isIntersect;
11028:            }
11029:
11030:            int getNumCoordCount() {
11031:                int count = 0;
11032:                if ((vertexFormat & GeometryArray.COORDINATES) != 0) {
11033:                    if ((vertexFormat & GeometryArray.BY_REFERENCE) == 0) {
11034:                        count = vertexCount;
11035:                        return count;
11036:                    }
11037:
11038:                    if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) == 0) {
11039:                        if ((vertexFormat & GeometryArray.INTERLEAVED) == 0) {
11040:                            switch ((vertexType & GeometryArrayRetained.VERTEX_DEFINED)) {
11041:                            case PF:
11042:                                count = floatRefCoords.length / 3;
11043:                                break;
11044:                            case PD:
11045:                                count = doubleRefCoords.length / 3;
11046:                                break;
11047:                            case P3F:
11048:                                count = p3fRefCoords.length;
11049:                                break;
11050:                            case P3D:
11051:                                count = p3dRefCoords.length;
11052:                                break;
11053:                            }
11054:                        } else {
11055:                            count = interLeavedVertexData.length / stride;
11056:                        }
11057:                    } else { // nio buffer
11058:                        if ((vertexFormat & GeometryArray.INTERLEAVED) == 0) {
11059:                            switch ((vertexType & GeometryArrayRetained.VERTEX_DEFINED)) {
11060:                            case PF:
11061:                                count = floatBufferRefCoords.limit() / 3; // XXXX: limit or capacity?
11062:                                break;
11063:                            case PD:
11064:                                count = doubleBufferRefCoords.limit() / 3;
11065:                                break;
11066:                            }
11067:                        } else {
11068:                            count = interleavedFloatBufferImpl.limit() / stride;
11069:                        }
11070:                    }
11071:                }
11072:                return count;
11073:            }
11074:
11075:            int getNumColorCount() {
11076:                int count = 0;
11077:                if ((vertexFormat & GeometryArray.COLOR) != 0) {
11078:                    if ((vertexFormat & GeometryArray.BY_REFERENCE) == 0) {
11079:                        count = vertexCount;
11080:                        return count;
11081:                    }
11082:                    if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) == 0) {
11083:                        if ((vertexFormat & GeometryArray.INTERLEAVED) == 0) {
11084:                            switch ((vertexType & GeometryArrayRetained.COLOR_DEFINED)) {
11085:                            case CF:
11086:                                if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_3) {
11087:                                    count = floatRefColors.length / 3;
11088:                                } else if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_4) {
11089:                                    count = floatRefColors.length / 4;
11090:                                }
11091:                                break;
11092:                            case CUB:
11093:                                if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_3) {
11094:                                    count = byteRefColors.length / 3;
11095:                                } else if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_4) {
11096:                                    count = byteRefColors.length / 4;
11097:                                }
11098:                                break;
11099:                            case C3F:
11100:                                count = c3fRefColors.length;
11101:                                break;
11102:                            case C4F:
11103:                                count = c4fRefColors.length;
11104:                                break;
11105:                            case C3UB:
11106:                                count = c3bRefColors.length;
11107:                                break;
11108:                            case C4UB:
11109:                                count = c4bRefColors.length;
11110:                                break;
11111:                            }
11112:                        } else {
11113:                            count = interLeavedVertexData.length / stride;
11114:                        }
11115:                    } // end of non nio buffer
11116:                    else {
11117:                        if ((vertexFormat & GeometryArray.INTERLEAVED) == 0) {
11118:                            switch ((vertexType & GeometryArrayRetained.COLOR_DEFINED)) {
11119:                            case CF:
11120:                                if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_3) {
11121:                                    count = floatBufferRefColors.limit() / 3;
11122:                                } else if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_4) {
11123:                                    count = floatBufferRefColors.limit() / 4;
11124:                                }
11125:                                break;
11126:                            case CUB:
11127:                                if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_3) {
11128:                                    count = byteBufferRefColors.limit() / 3;
11129:                                } else if ((vertexFormat & GeometryArray.COLOR_4) == GeometryArray.COLOR_4) {
11130:                                    count = byteBufferRefColors.limit() / 4;
11131:                                }
11132:                                break;
11133:                            }
11134:                        } else {
11135:                            count = interleavedFloatBufferImpl.limit() / stride;
11136:                        }
11137:                    } // end of nio buffer
11138:                }
11139:                return count;
11140:            }
11141:
11142:            int getNumNormalCount() {
11143:                int count = 0;
11144:                if ((vertexFormat & GeometryArray.NORMALS) != 0) {
11145:                    if ((vertexFormat & GeometryArray.BY_REFERENCE) == 0) {
11146:                        count = vertexCount;
11147:                        return count;
11148:                    }
11149:
11150:                    if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) == 0) {
11151:                        if ((vertexFormat & GeometryArray.INTERLEAVED) == 0) {
11152:                            switch ((vertexType & NORMAL_DEFINED)) {
11153:                            case NF:
11154:                                count = floatRefNormals.length / 3;
11155:                                break;
11156:                            case N3F:
11157:                                count = v3fRefNormals.length;
11158:                                break;
11159:                            }
11160:                        } else {
11161:                            count = interLeavedVertexData.length / stride;
11162:                        }
11163:                    } // end of non nio buffer
11164:                    else {
11165:                        if ((vertexFormat & GeometryArray.INTERLEAVED) == 0) {
11166:                            if ((vertexType & NORMAL_DEFINED) == NF) {
11167:                                count = floatBufferRefNormals.limit() / 3;
11168:                            }
11169:                        } else {
11170:                            count = interleavedFloatBufferImpl.limit() / stride;
11171:                        }
11172:                    }
11173:                }
11174:                return count;
11175:            }
11176:
11177:            int getNumTexCoordCount(int i) {
11178:                int count = 0;
11179:                if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) {
11180:                    if ((vertexFormat & GeometryArray.BY_REFERENCE) == 0) {
11181:                        count = vertexCount;
11182:                        return count;
11183:                    }
11184:
11185:                    if ((vertexFormat & GeometryArray.USE_NIO_BUFFER) == 0) {
11186:                        if ((vertexFormat & GeometryArray.INTERLEAVED) == 0) {
11187:                            switch ((vertexType & TEXCOORD_DEFINED)) {
11188:                            case TF:
11189:                                if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_2) != 0) {
11190:                                    count = ((float[]) refTexCoords[i]).length / 2;
11191:                                } else if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0) {
11192:                                    count = ((float[]) refTexCoords[i]).length / 3;
11193:                                } else if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_4) != 0) {
11194:                                    count = ((float[]) refTexCoords[i]).length / 4;
11195:                                }
11196:
11197:                                break;
11198:                            case T2F:
11199:                                count = ((TexCoord2f[]) refTexCoords[i]).length;
11200:                                break;
11201:                            case T3F:
11202:                                count = ((TexCoord3f[]) refTexCoords[i]).length;
11203:                            }
11204:                        } else {
11205:                            count = interLeavedVertexData.length / stride;
11206:                        }
11207:                    } else { // nio buffer
11208:                        if ((vertexFormat & GeometryArray.INTERLEAVED) == 0) {
11209:                            if ((vertexType & TEXCOORD_DEFINED) == TF) {
11210:                                FloatBufferWrapper texBuffer = (FloatBufferWrapper) (((J3DBuffer) refTexCoordsBuffer[i])
11211:                                        .getBufferImpl());
11212:                                if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_2) != 0) {
11213:                                    count = texBuffer.limit() / 2;
11214:                                } else if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0) {
11215:                                    count = texBuffer.limit() / 3;
11216:                                } else if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_4) != 0) {
11217:                                    count = texBuffer.limit() / 4;
11218:                                }
11219:                            }
11220:                        } else {
11221:                            count = interleavedFloatBufferImpl.limit() / stride;
11222:                        }
11223:                    }
11224:                }
11225:                return count;
11226:            }
11227:
11228:            // NOTE: we don't need a getNumVertexAttrCount method, since getNum*Count
11229:            // is only called by Morph, which doesn't support vertex attrs
11230:
11231:            // Found the min distance from center to the point/line/tri/quad
11232:            // form by dist[]
11233:            void computeMinDistance(Point3d coordinates[], Point3d center,
11234:                    Vector3d normal, double dist[], Point3d iPnt) {
11235:                double x, y, z;
11236:                int i, j;
11237:
11238:                if (coordinates.length == 1) {
11239:                    // a point
11240:                    iPnt.x = coordinates[0].x;
11241:                    iPnt.y = coordinates[0].y;
11242:                    iPnt.z = coordinates[0].z;
11243:                    x = iPnt.x - center.x;
11244:                    y = iPnt.y - center.y;
11245:                    z = iPnt.z - center.z;
11246:                    dist[0] = Math.sqrt(x * x + y * y + z * z);
11247:                    return;
11248:                }
11249:
11250:                if (coordinates.length == 2) {
11251:                    // a line
11252:                    dist[0] = Math.sqrt(Distance.pointToSegment(center,
11253:                            coordinates[0], coordinates[1], iPnt, null));
11254:                    return;
11255:                }
11256:
11257:                double normalLen = 0;
11258:
11259:                if (normal == null) {
11260:                    Vector3d vec0 = new Vector3d();
11261:                    Vector3d vec1 = new Vector3d();
11262:                    normal = new Vector3d();
11263:                    // compute plane normal for coordinates.
11264:                    for (i = 0; i < coordinates.length - 1;) {
11265:                        vec0.x = coordinates[i + 1].x - coordinates[i].x;
11266:                        vec0.y = coordinates[i + 1].y - coordinates[i].y;
11267:                        vec0.z = coordinates[i + 1].z - coordinates[i++].z;
11268:                        if (vec0.length() > 0.0)
11269:                            break;
11270:                    }
11271:
11272:                    for (j = i; j < coordinates.length - 1; j++) {
11273:                        vec1.x = coordinates[j + 1].x - coordinates[j].x;
11274:                        vec1.y = coordinates[j + 1].y - coordinates[j].y;
11275:                        vec1.z = coordinates[j + 1].z - coordinates[j].z;
11276:                        if (vec1.length() > 0.0)
11277:                            break;
11278:                    }
11279:
11280:                    if (j == (coordinates.length - 1)) {
11281:                        // Degenerate polygon, check with edge only
11282:                        normal = null;
11283:                    } else {
11284:                        normal.cross(vec0, vec1);
11285:                    }
11286:                }
11287:
11288:                if (normal != null) {
11289:                    normalLen = normal.length();
11290:                    if (normalLen == 0.0) {
11291:                        // Degenerate polygon, check with edge only
11292:                        normal = null;
11293:                    }
11294:                }
11295:
11296:                if (coordinates.length == 3) {
11297:                    // a triangle
11298:                    if (normal != null) {
11299:                        double d = -(normal.x * coordinates[0].x + normal.y
11300:                                * coordinates[0].y + normal.z
11301:                                * coordinates[0].z);
11302:                        dist[0] = (normal.x * center.x + normal.y * center.y
11303:                                + normal.z * center.z + d)
11304:                                / normalLen;
11305:                        iPnt.x = center.x - dist[0] * normal.x / normalLen;
11306:                        iPnt.y = center.y - dist[0] * normal.y / normalLen;
11307:                        iPnt.z = center.z - dist[0] * normal.z / normalLen;
11308:
11309:                        if (pointInTri(iPnt, coordinates[0], coordinates[1],
11310:                                coordinates[2], normal)) {
11311:                            return;
11312:                        }
11313:                    }
11314:
11315:                    // checking point to line distance
11316:                    double minDist;
11317:                    Point3d minPnt = new Point3d();
11318:
11319:                    dist[0] = Distance.pointToSegment(center, coordinates[0],
11320:                            coordinates[1], iPnt, null);
11321:                    minDist = Distance.pointToSegment(center, coordinates[1],
11322:                            coordinates[2], minPnt, null);
11323:                    if (minDist < dist[0]) {
11324:                        dist[0] = minDist;
11325:                        iPnt.x = minPnt.x;
11326:                        iPnt.y = minPnt.y;
11327:                        iPnt.z = minPnt.z;
11328:                    }
11329:                    minDist = Distance.pointToSegment(center, coordinates[2],
11330:                            coordinates[0], minPnt, null);
11331:                    if (minDist < dist[0]) {
11332:                        dist[0] = minDist;
11333:                        iPnt.x = minPnt.x;
11334:                        iPnt.y = minPnt.y;
11335:                        iPnt.z = minPnt.z;
11336:                    }
11337:                    dist[0] = Math.sqrt(dist[0]);
11338:                    return;
11339:                }
11340:
11341:                // a quad
11342:                if (normal != null) {
11343:                    double d = -(normal.x * coordinates[0].x + normal.y
11344:                            * coordinates[0].y + normal.z * coordinates[0].z);
11345:                    dist[0] = (normal.x * center.x + normal.y * center.y
11346:                            + normal.z * center.z + d)
11347:                            / normalLen;
11348:                    iPnt.x = center.x - dist[0] * normal.x / normalLen;
11349:                    iPnt.y = center.y - dist[0] * normal.y / normalLen;
11350:                    iPnt.z = center.z - dist[0] * normal.z / normalLen;
11351:
11352:                    if (pointInTri(iPnt, coordinates[0], coordinates[1],
11353:                            coordinates[2], normal)
11354:                            || pointInTri(iPnt, coordinates[1], coordinates[2],
11355:                                    coordinates[3], normal)) {
11356:                        return;
11357:                    }
11358:                }
11359:
11360:                // checking point to line distance
11361:                double minDist;
11362:                Point3d minPnt = new Point3d();
11363:
11364:                dist[0] = Distance.pointToSegment(center, coordinates[0],
11365:                        coordinates[1], iPnt, null);
11366:                minDist = Distance.pointToSegment(center, coordinates[1],
11367:                        coordinates[2], minPnt, null);
11368:                if (minDist < dist[0]) {
11369:                    dist[0] = minDist;
11370:                    iPnt.x = minPnt.x;
11371:                    iPnt.y = minPnt.y;
11372:                    iPnt.z = minPnt.z;
11373:                }
11374:                minDist = Distance.pointToSegment(center, coordinates[2],
11375:                        coordinates[3], minPnt, null);
11376:                if (minDist < dist[0]) {
11377:                    dist[0] = minDist;
11378:                    iPnt.x = minPnt.x;
11379:                    iPnt.y = minPnt.y;
11380:                    iPnt.z = minPnt.z;
11381:                }
11382:
11383:                minDist = Distance.pointToSegment(center, coordinates[3],
11384:                        coordinates[0], minPnt, null);
11385:                if (minDist < dist[0]) {
11386:                    dist[0] = minDist;
11387:                    iPnt.x = minPnt.x;
11388:                    iPnt.y = minPnt.y;
11389:                    iPnt.z = minPnt.z;
11390:                }
11391:
11392:                dist[0] = Math.sqrt(dist[0]);
11393:            }
11394:
11395:            void handleFrequencyChange(int bit) {
11396:                int mask = 0;
11397:                if ((vertexFormat & GeometryArray.BY_REFERENCE) == 0) {
11398:                    if ((bit == GeometryArray.ALLOW_COORDINATE_WRITE)
11399:                            || (((vertexFormat & GeometryArray.COLOR) != 0) && bit == GeometryArray.ALLOW_COLOR_WRITE)
11400:                            || (((vertexFormat & GeometryArray.NORMALS) != 0) && bit == GeometryArray.ALLOW_NORMAL_WRITE)
11401:                            || (((vertexFormat & GeometryArray.TEXTURE_COORDINATE) != 0) && bit == GeometryArray.ALLOW_TEXCOORD_WRITE)
11402:                            || (((vertexFormat & GeometryArray.VERTEX_ATTRIBUTES) != 0) && bit == GeometryArray.ALLOW_VERTEX_ATTR_WRITE)
11403:                            || (bit == GeometryArray.ALLOW_COUNT_WRITE)) {
11404:                        mask = 1;
11405:                    }
11406:                } else {
11407:                    if (bit == GeometryArray.ALLOW_REF_DATA_WRITE)
11408:                        mask = 1;
11409:                }
11410:                if (mask != 0) {
11411:                    setFrequencyChangeMask(bit, mask);
11412:                }
11413:            }
11414:
11415:            int getTexCoordType() {
11416:                return texCoordType;
11417:            }
11418:
11419:            int getVertexAttrType() {
11420:                return vertexAttrType;
11421:            }
11422:
11423:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.