Source Code Cross Referenced for GeometryInfo.java in  » 6.0-JDK-Modules » java-3d » com » sun » j3d » utils » geometry » 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 » com.sun.j3d.utils.geometry 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * $RCSfile: GeometryInfo.java,v $
0003:         *
0004:         * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved.
0005:         *
0006:         * Redistribution and use in source and binary forms, with or without
0007:         * modification, are permitted provided that the following conditions
0008:         * are met:
0009:         *
0010:         * - Redistribution of source code must retain the above copyright
0011:         *   notice, this list of conditions and the following disclaimer.
0012:         *
0013:         * - Redistribution in binary form must reproduce the above copyright
0014:         *   notice, this list of conditions and the following disclaimer in
0015:         *   the documentation and/or other materials provided with the
0016:         *   distribution.
0017:         *
0018:         * Neither the name of Sun Microsystems, Inc. or the names of
0019:         * contributors may be used to endorse or promote products derived
0020:         * from this software without specific prior written permission.
0021:         *
0022:         * This software is provided "AS IS," without a warranty of any
0023:         * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
0024:         * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
0025:         * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
0026:         * EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL
0027:         * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF
0028:         * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
0029:         * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR
0030:         * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
0031:         * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
0032:         * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
0033:         * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
0034:         * POSSIBILITY OF SUCH DAMAGES.
0035:         *
0036:         * You acknowledge that this software is not designed, licensed or
0037:         * intended for use in the design, construction, operation or
0038:         * maintenance of any nuclear facility.
0039:         *
0040:         * $Revision: 1.4 $
0041:         * $Date: 2007/02/09 17:20:19 $
0042:         * $State: Exp $
0043:         */
0044:
0045:        package com.sun.j3d.utils.geometry;
0046:
0047:        import com.sun.j3d.utils.geometry.Triangulator;
0048:        import java.io.*;
0049:        import javax.media.j3d.*;
0050:        import javax.vecmath.*;
0051:        import com.sun.j3d.internal.J3dUtilsI18N;
0052:        import java.util.HashMap;
0053:        import com.sun.j3d.utils.geometry.GeometryInfoGenerator;
0054:        import com.sun.j3d.internal.BufferWrapper;
0055:        import com.sun.j3d.internal.ByteBufferWrapper;
0056:        import com.sun.j3d.internal.FloatBufferWrapper;
0057:        import com.sun.j3d.internal.DoubleBufferWrapper;
0058:        import com.sun.j3d.internal.ByteOrderWrapper;
0059:        import javax.media.j3d.J3DBuffer;
0060:
0061:        /**
0062:         * The GeometryInfo object holds data for processing by the Java3D geometry
0063:         * utility tools.<p><blockquote>
0064:         * 
0065:         *         The NormalGenerator adds normals to geometry without normals.<p>
0066:         * 
0067:         *         The Stripifier combines adjacent triangles into triangle strips for
0068:         *         more efficent rendering.<p></blockquote>
0069:         * 
0070:         * Also, the GeometryCompressor can take a set of GeometryInfo objects in a
0071:         * CompressionSteam and generate a CompressedGeometry object from the
0072:         * geometry.<p>
0073:         *         Geometry is loaded into a GeometryInfo in a manner similar to the
0074:         * <a href="../../../../../javax/media/j3d/GeometryArray.html">
0075:         * GeometryArray</a> methods.  The constructor for the GeometryInfo takes a flag
0076:         * that specifies the kind of data being loaded.  The vertex data is
0077:         * specified using methods that are similar to the GeometryArray methods, but
0078:         * with fewer variations.<p>
0079:         *         The major difference between GeometryInfo and GeometryArray is
0080:         * that the number of vertices, vertex format, and other data are specified
0081:         * implictly, rather than as part of the constructor.  The number of verticies
0082:         * comes from the number of coordinates passed to the setCoordinates()
0083:         * method.  The format comes from the set of data components that are
0084:         * specified.  For example, calling the setCoordinates(), setColors3() and
0085:         * setTextureCoordinatesParames(1, 2) methods implies a
0086:         * format of COORDINATES | COLOR_3
0087:         * | TEXTURE_COORDINATE_2.  Indexed representation is specified by calling
0088:         * the methods that specify the indices, for example
0089:         * setCoordinateIndices().<p>
0090:         *         Stripped primitives are loaded using the TRIANGLE_FAN_ARRAY or
0091:         * TRIANGLE_STRIP_ARRAY flags to the constructor.  The setStripCounts()
0092:         * method specifies the length of each strip.<p>
0093:         *         A set of complex polygons is loaded using the POLYGON_ARRAY
0094:         * flag to the constructor.  The setStripCounts() method specifies the length
0095:         * of each contour of the polygons.  The setContourCounts() method specifies
0096:         * the number of countours in each polygon. For example, a triangle with a
0097:         * triangular hole would have strip counts [3, 3] (indicating two contours of
0098:         * three points) and contour counts [2] (indicating a single polygon with two
0099:         * contours).<p>
0100:         *         GeometryInfo itelf contains some simple utilities, such as
0101:         * calculating indices for non-indexed data ("indexifying") and getting rid
0102:         * of unused data in your indexed geometry ("compacting").<p>
0103:         *         The geometry utility tools modify the contents of the
0104:         * GeometryInfo.  After processing, the resulting geometry can be extracted
0105:         * from the GeometryInfo by calling getGeometryArray().  If multiple tools
0106:         * are used, the order of processing should be: generate normals, then
0107:         * stripify.  For example, to convert a general mesh of polygons without
0108:         * normals into an optimized mesh call:
0109:         * <pre><blockquote>
0110:         *         GeometryInfo gi = new GeometryInfo(GeometryInfo.POLYGON_ARRAY);
0111:         *         // initialize the geometry info here
0112:         *         // generate normals
0113:         *         NormalGenerator ng = new NormalGenerator();
0114:         *         ng.generateNormals(gi);
0115:         *         // stripify
0116:         *         Stripifier st = new Stripifier();
0117:         *         st.stripify(gi);
0118:         *         GeometryArray result = gi.getGeometryArray();
0119:         * </blockquote></pre>
0120:         * 
0121:         * @see NormalGenerator
0122:         * @see Stripifier
0123:         * @see com.sun.j3d.utils.compression.CompressionStream
0124:         * @see com.sun.j3d.utils.compression.GeometryCompressor
0125:         * @see javax.media.j3d.GeometryArray
0126:         */
0127:
0128:        public class GeometryInfo {
0129:
0130:            /**
0131:             * Send to the constructor to inform that the data will be arranged so
0132:             * that each set of three vertices form an independent triangle
0133:             */
0134:            public static final int TRIANGLE_ARRAY = 1;
0135:
0136:            /**
0137:             * Send to the constructor to inform that the data will be arranged so
0138:             * that each set of four vertices form an independent quad
0139:             */
0140:            public static final int QUAD_ARRAY = 2;
0141:
0142:            /**
0143:             * Send to the constructor to inform that the data will be arranged so
0144:             * that the stripCounts array indicates how many vertices to use
0145:             * for each triangle fan.
0146:             */
0147:            public static final int TRIANGLE_FAN_ARRAY = 3;
0148:
0149:            /**
0150:             * Send to the constructor to inform that the data will be arranged so
0151:             * that the stripCounts array indicates how many vertices to use
0152:             * for each triangle strip.
0153:             */
0154:            public static final int TRIANGLE_STRIP_ARRAY = 4;
0155:
0156:            /**
0157:             * Send to the constructor to inform that the data is arranged as
0158:             * possibly multi-contour, possible non-planar polygons.
0159:             * The stripCounts array indicates how many vertices to use
0160:             * for each contour, and the contourCounts array indicates how many
0161:             * stripCounts entries to use for each polygon.  The first 
0162:             * contour is the bounding polygon, and subsequent contours are
0163:             * "holes."  If contourCounts is left null, the default is
0164:             * one contour per polygon.
0165:             */
0166:            public static final int POLYGON_ARRAY = 5;
0167:
0168:            private int prim;
0169:
0170:            // 1 Show indexification details
0171:            private static final int DEBUG = 0;
0172:
0173:            private Point3f coordinates[] = null;
0174:            private Color3f colors3[] = null;
0175:            private Color4f colors4[] = null;
0176:            private Vector3f normals[] = null;
0177:            private Object texCoordSets[][] = null;
0178:
0179:            private int coordinateIndices[] = null;
0180:            private int colorIndices[] = null;
0181:            private int normalIndices[] = null;
0182:            private int texCoordIndexSets[][] = null;
0183:
0184:            private int[] texCoordSetMap = null;
0185:            private int texCoordSetCount = 0;
0186:            private int texCoordDim = 0;
0187:
0188:            private int stripCounts[] = null;
0189:            private int contourCounts[] = null;
0190:
0191:            private Triangulator tr = null;
0192:            private NormalGenerator ng = null;
0193:
0194:            private int oldPrim = 0;
0195:            private int oldStripCounts[] = null;
0196:
0197:            private boolean coordOnly = false;
0198:
0199:            /**
0200:             * Constructor.
0201:             * Creates an empty GeometryInfo object.  
0202:             * @param primitive Tells the GeometryInfo object the type of
0203:             * primitive data to be stored
0204:             * in it, so it will know the format of the data. It can be one of
0205:             * TRIANGLE_ARRAY, 
0206:             * QUAD_ARRAY, TRIANGLE_FAN_ARRAY, TRIANGLE_STRIP_ARRAY, or POLYGON_ARRAY.
0207:             */
0208:            public GeometryInfo(int primitive) {
0209:                if ((primitive >= TRIANGLE_ARRAY)
0210:                        && (primitive <= POLYGON_ARRAY)) {
0211:                    prim = primitive;
0212:                } else {
0213:                    throw new IllegalArgumentException(J3dUtilsI18N
0214:                            .getString("GeometryInfo0"));
0215:                }
0216:            } // End of GeometryInfo(int)
0217:
0218:            /**
0219:             * Contructor.  Populates the GeometryInfo with the geometry from
0220:             * the GeometryArray.<p>
0221:             * If the GeometryArray uses the <code>Initial</code> and 
0222:             * <code>Valid</code> GeometryArray methods (<code>
0223:             * setInitialVertexIndex()</code> and <code>setValidVertexCount()
0224:             * </code> and their cousins) then only the needed geometry
0225:             * is copied into the GeometryInfo.
0226:             */
0227:            public GeometryInfo(GeometryArray ga) {
0228:                GeometryInfoGenerator.create(this , ga);
0229:            } // End of GeometryInfo(GeometryArray)
0230:
0231:            /**
0232:             * Removes all data from the GeometryInfo and resets the primitive.
0233:             * After a call to reset(), the GeometryInfo object will be just like
0234:             * it was when it was newly constructed.
0235:             * @param primitive Either TRIANGLE_ARRAY, QUAD_ARRAY,
0236:             * TRIANGLE_FAN_ARRAY, TRIANGLE_STRIP_ARRAY, or POLYGON_ARRAY.
0237:             * Tells the GeometryInfo object the type of primitive data to be stored
0238:             * in it, so it will know the format of the data.
0239:             */
0240:            public void reset(int primitive) {
0241:                if ((primitive >= TRIANGLE_ARRAY)
0242:                        && (primitive <= POLYGON_ARRAY)) {
0243:                    prim = primitive;
0244:                } else {
0245:                    throw new IllegalArgumentException(J3dUtilsI18N
0246:                            .getString("GeometryInfo0"));
0247:                }
0248:
0249:                coordinates = null;
0250:                colors3 = null;
0251:                colors4 = null;
0252:                normals = null;
0253:
0254:                coordinateIndices = null;
0255:                colorIndices = null;
0256:                normalIndices = null;
0257:
0258:                stripCounts = null;
0259:                contourCounts = null;
0260:
0261:                oldPrim = 0;
0262:                oldStripCounts = null;
0263:
0264:                texCoordDim = 0;
0265:                texCoordSetCount = 0;
0266:                texCoordSets = null;
0267:                texCoordIndexSets = null;
0268:                texCoordSetMap = null;
0269:
0270:                coordOnly = false;
0271:
0272:            } // End of reset(int)
0273:
0274:            /**
0275:             * Removes all data from this GeometryInfo and populates it with
0276:             * the geometry from the GeometryArray.
0277:             */
0278:            public void reset(GeometryArray ga) {
0279:                GeometryInfoGenerator.create(this , ga);
0280:            } // End of reset(GeometryArray)
0281:
0282:            // This method takes an indexed quad array and expands it to
0283:            // a list of indexed triangles.  It is used for the Coordinate
0284:            // indices as well as the color and texture indices.
0285:            private int[] expandQuad(int indices[]) {
0286:                int triangles[] = new int[indices.length / 4 * 6];
0287:
0288:                for (int i = 0; i < indices.length / 4; i++) {
0289:                    triangles[i * 6 + 0] = indices[i * 4];
0290:                    triangles[i * 6 + 1] = indices[i * 4 + 1];
0291:                    triangles[i * 6 + 2] = indices[i * 4 + 2];
0292:                    triangles[i * 6 + 3] = indices[i * 4];
0293:                    triangles[i * 6 + 4] = indices[i * 4 + 2];
0294:                    triangles[i * 6 + 5] = indices[i * 4 + 3];
0295:                }
0296:
0297:                return triangles;
0298:            } // End of expandQuad
0299:
0300:            // This method takes an indexed triangle fan and expands it to
0301:            // a list of indexed triangles.  It is used for the Coordinate
0302:            // indices as well as the color and texture indices.
0303:            private int[] expandTriFan(int numTris, int indices[]) {
0304:                int triangles[] = new int[numTris * 3];
0305:                int p = 0;
0306:                int base = 0;
0307:                for (int f = 0; f < stripCounts.length; f++) {
0308:                    for (int t = 0; t < stripCounts[f] - 2; t++) {
0309:                        triangles[p++] = indices[base];
0310:                        triangles[p++] = indices[base + t + 1];
0311:                        triangles[p++] = indices[base + t + 2];
0312:                    }
0313:                    base += stripCounts[f];
0314:                }
0315:                return triangles;
0316:            } // End of expandTriFan
0317:
0318:            // This method takes an indexed triangle strip and expands it to
0319:            // a list of indexed triangles.  It is used for the Coordinate
0320:            // indices as well as the color and texture indices.
0321:            private int[] expandTriStrip(int numTris, int indices[]) {
0322:                int triangles[] = new int[numTris * 3];
0323:
0324:                int p = 0;
0325:                int base = 0;
0326:                for (int s = 0; s < stripCounts.length; s++) {
0327:                    for (int t = 0; t < stripCounts[s] - 2; t++) {
0328:
0329:                        // Use a ping-ponging algorithm to reverse order on every other
0330:                        // triangle to preserve winding
0331:                        if (t % 2 == 0) {
0332:                            triangles[p++] = indices[base + t + 0];
0333:                            triangles[p++] = indices[base + t + 1];
0334:                            triangles[p++] = indices[base + t + 2];
0335:                        } else {
0336:                            triangles[p++] = indices[base + t + 0];
0337:                            triangles[p++] = indices[base + t + 2];
0338:                            triangles[p++] = indices[base + t + 1];
0339:                        }
0340:                    }
0341:                    base += stripCounts[s];
0342:                }
0343:
0344:                return triangles;
0345:            } // End of expandTriStrip
0346:
0347:            // Used by the NormalGenerator utility.  Informs the GeometryInfo object
0348:            // to remember its current primitive and stripCounts arrays so that
0349:            // they can be used to convert the object back to its original 
0350:            // primitive
0351:            void rememberOldPrim() {
0352:                oldPrim = prim;
0353:                oldStripCounts = stripCounts;
0354:            } // End of rememberOldPrim
0355:
0356:            // The NormalGenerator needs to know the original primitive for
0357:            // facet normal generation for quads
0358:            int getOldPrim() {
0359:                return oldPrim;
0360:            } // End of getOldPrim
0361:
0362:            // Used by the Utility libraries other than the NormalGenerator.
0363:            // Informs the GeometryInfo object that the geometry need not
0364:            // be converted back to the original primitive before returning.
0365:            // For example, if a list of Fans is sent, converted to Triangles
0366:            // for normal generation, and then stripified by the Stripifyer,
0367:            // we want to make sure that GeometryInfo doesn't convert the
0368:            // geometry *back* to fans before creating the output GeometryArray.
0369:            void forgetOldPrim() {
0370:                oldPrim = 0;
0371:                oldStripCounts = null;
0372:            } // End of forgetOldPrim
0373:
0374:            // We have changed the user's data from their original primitive
0375:            // type to TRIANGLE_ARRAY.  If this method is being called, it
0376:            // means we need to change it back (to try and hide from the user
0377:            // the fact that we've converted).  This usually happens when
0378:            // the user has used GeometryInfo for generating normals, but
0379:            // they are not Stripifying or Triangulating.  The function is
0380:            // called from getGeometryArray before creating the output data.
0381:            private void changeBackToOldPrim() {
0382:                if (oldPrim != 0) {
0383:                    convertToIndexedTriangles();
0384:                    if (ng == null)
0385:                        ng = new NormalGenerator();
0386:                    ng.convertBackToOldPrim(this , oldPrim, oldStripCounts);
0387:                    oldPrim = 0;
0388:                    oldStripCounts = null;
0389:                }
0390:            } // End of changeBackToOldPrim
0391:
0392:            /**
0393:             * Convert the GeometryInfo object to have primitive type TRIANGLE_ARRAY
0394:             * and be indexed.
0395:             * @throws IllegalArgumentException if coordinate data is missing,
0396:             * if the index lists aren't all the
0397:             * same length, if an index list is set and the corresponding data
0398:             * list isn't set, if a data list is set and the corresponding
0399:             * index list is unset (unless all index lists are unset or in
0400:             * USE_COORD_INDEX_ONLY format),
0401:             * if StripCounts or ContourCounts is inconsistent with the current
0402:             * primitive, if the sum of the contourCounts array doesn't equal
0403:             * the length of the StripCounts array, or if the number of vertices
0404:             * isn't a multiple of three (for triangles) or four (for quads).
0405:             */
0406:            public void convertToIndexedTriangles() {
0407:                int triangles = 0;
0408:
0409:                // This calls checkForBadData
0410:                indexify();
0411:
0412:                if (prim == TRIANGLE_ARRAY)
0413:                    return;
0414:
0415:                switch (prim) {
0416:
0417:                case QUAD_ARRAY:
0418:
0419:                    coordinateIndices = expandQuad(coordinateIndices);
0420:                    if (colorIndices != null)
0421:                        colorIndices = expandQuad(colorIndices);
0422:                    if (normalIndices != null)
0423:                        normalIndices = expandQuad(normalIndices);
0424:                    for (int i = 0; i < texCoordSetCount; i++)
0425:                        texCoordIndexSets[i] = expandQuad(texCoordIndexSets[i]);
0426:                    break;
0427:
0428:                case TRIANGLE_FAN_ARRAY:
0429:                    // Count how many triangles are in the object
0430:                    for (int i = 0; i < stripCounts.length; i++) {
0431:                        triangles += stripCounts[i] - 2;
0432:                    }
0433:
0434:                    coordinateIndices = expandTriFan(triangles,
0435:                            coordinateIndices);
0436:                    if (colorIndices != null)
0437:                        colorIndices = expandTriFan(triangles, colorIndices);
0438:                    if (normalIndices != null)
0439:                        normalIndices = expandTriFan(triangles, normalIndices);
0440:                    for (int i = 0; i < texCoordSetCount; i++)
0441:                        texCoordIndexSets[i] = expandTriFan(triangles,
0442:                                texCoordIndexSets[i]);
0443:                    break;
0444:
0445:                case TRIANGLE_STRIP_ARRAY:
0446:                    // Count how many triangles are in the object
0447:                    for (int i = 0; i < stripCounts.length; i++) {
0448:                        triangles += stripCounts[i] - 2;
0449:                    }
0450:
0451:                    coordinateIndices = expandTriStrip(triangles,
0452:                            coordinateIndices);
0453:                    if (colorIndices != null)
0454:                        colorIndices = expandTriStrip(triangles, colorIndices);
0455:                    if (normalIndices != null)
0456:                        normalIndices = expandTriStrip(triangles, normalIndices);
0457:                    for (int i = 0; i < texCoordSetCount; i++)
0458:                        texCoordIndexSets[i] = expandTriStrip(triangles,
0459:                                texCoordIndexSets[i]);
0460:                    break;
0461:
0462:                case POLYGON_ARRAY:
0463:                    if (tr == null)
0464:                        tr = new Triangulator();
0465:                    tr.triangulate(this );
0466:                    break;
0467:                }
0468:
0469:                prim = TRIANGLE_ARRAY;
0470:                stripCounts = null;
0471:            } // End of convertToIndexedTriangles
0472:
0473:            /**
0474:             * Get the current primitive.  Some of the utilities may change the
0475:             * primitive type of the data stored in the GeometryInfo object
0476:             * (for example, the stripifyer will change it to TRIANGLE_STRIP_ARRAY).
0477:             */
0478:            public int getPrimitive() {
0479:                return prim;
0480:            } // End of getPrimitive()
0481:
0482:            /**
0483:             * Set the current primitive.  Some of the utilities may change the
0484:             * primitive type of the data stored in the GeometryInfo object
0485:             * (for example, the stripifyer will change it to TRIANGLE_STRIP_ARRAY).
0486:             * But the user can't change the primitive type - it is set in the 
0487:             * constructor.  Therefore, this method has package scope.
0488:             */
0489:            void setPrimitive(int primitive) {
0490:                if ((prim >= TRIANGLE_ARRAY) && (prim <= POLYGON_ARRAY)) {
0491:                    prim = primitive;
0492:                } else {
0493:                    throw new IllegalArgumentException(J3dUtilsI18N
0494:                            .getString("GeometryInfo0"));
0495:                }
0496:            } // End of setPrimitive()
0497:
0498:            /**
0499:             * Sets the coordinates array.  
0500:             * No data copying is done because a reference to user data is used.
0501:             */
0502:            public void setCoordinates(Point3f coordinates[]) {
0503:                this .coordinates = coordinates;
0504:            } // End of setCoordinates
0505:
0506:            /**
0507:             * Sets the coordinates array.
0508:             * The points are copied into the GeometryInfo object.
0509:             */
0510:            public void setCoordinates(Point3d coordinates[]) {
0511:                if (coordinates == null)
0512:                    this .coordinates = null;
0513:                else {
0514:                    this .coordinates = new Point3f[coordinates.length];
0515:                    for (int i = 0; i < coordinates.length; i++) {
0516:                        this .coordinates[i] = new Point3f(
0517:                                (float) (coordinates[i].x),
0518:                                (float) (coordinates[i].y),
0519:                                (float) (coordinates[i].z));
0520:                    }
0521:                }
0522:            } // End of setCoordinates
0523:
0524:            /**
0525:             * Sets the coordinates array.
0526:             * The points are copied into the GeometryInfo object.
0527:             */
0528:            public void setCoordinates(float coordinates[]) {
0529:                if (coordinates == null)
0530:                    this .coordinates = null;
0531:                else {
0532:                    this .coordinates = new Point3f[coordinates.length / 3];
0533:                    for (int i = 0; i < this .coordinates.length; i++) {
0534:                        this .coordinates[i] = new Point3f(coordinates[i * 3],
0535:                                coordinates[i * 3 + 1], coordinates[i * 3 + 2]);
0536:                    }
0537:                }
0538:            } // End of setCoordinates
0539:
0540:            /**
0541:             * Sets the coordinates array.
0542:             * The points are copied into the GeometryInfo object.
0543:             */
0544:            public void setCoordinates(double coordinates[]) {
0545:                if (coordinates == null)
0546:                    this .coordinates = null;
0547:                else {
0548:                    this .coordinates = new Point3f[coordinates.length / 3];
0549:                    for (int i = 0; i < coordinates.length / 3; i++) {
0550:                        this .coordinates[i] = new Point3f(
0551:                                (float) coordinates[i * 3],
0552:                                (float) coordinates[i * 3 + 1],
0553:                                (float) coordinates[i * 3 + 2]);
0554:                    }
0555:                }
0556:            } // End of setCoordinates
0557:
0558:            /**
0559:             * Retrieves a reference to the coordinate array.
0560:             */
0561:            public Point3f[] getCoordinates() {
0562:                return coordinates;
0563:            } // End of getCoordinates
0564:
0565:            /**
0566:             * Sets the colors array.
0567:             * No data copying is done because a reference to
0568:             * user data is used.
0569:             */
0570:            public void setColors(Color3f colors[]) {
0571:                colors3 = colors;
0572:                colors4 = null;
0573:            } // End of setColors
0574:
0575:            /**
0576:             * Sets the colors array.
0577:             * No data copying is done because a reference to
0578:             * user data is used.
0579:             */
0580:            public void setColors(Color4f colors[]) {
0581:                colors3 = null;
0582:                colors4 = colors;
0583:            } // End of setColors
0584:
0585:            /**
0586:             * Sets the colors array.
0587:             * The points are copied into the GeometryInfo object.
0588:             */
0589:            public void setColors(Color3b colors[]) {
0590:                if (colors == null) {
0591:                    colors3 = null;
0592:                    colors4 = null;
0593:                } else {
0594:                    colors3 = new Color3f[colors.length];
0595:                    colors4 = null;
0596:                    for (int i = 0; i < colors.length; i++) {
0597:                        colors3[i] = new Color3f(
0598:                                (float) (colors[i].x & 0xff) / 255.0f,
0599:                                (float) (colors[i].y & 0xff) / 255.0f,
0600:                                (float) (colors[i].z & 0xff) / 255.0f);
0601:                    }
0602:                }
0603:            } // End of setColors
0604:
0605:            /**
0606:             * Sets the colors array.
0607:             * The points are copied into the GeometryInfo object.
0608:             */
0609:            public void setColors(Color4b colors[]) {
0610:                if (colors == null) {
0611:                    colors3 = null;
0612:                    colors4 = null;
0613:                } else {
0614:                    colors3 = null;
0615:                    colors4 = new Color4f[colors.length];
0616:                    for (int i = 0; i < colors.length; i++) {
0617:                        colors4[i] = new Color4f(
0618:                                (float) (colors[i].x & 0xff) / 255.0f,
0619:                                (float) (colors[i].y & 0xff) / 255.0f,
0620:                                (float) (colors[i].z & 0xff) / 255.0f,
0621:                                (float) (colors[i].w & 0xff) / 255.0f);
0622:                    }
0623:                }
0624:            } // End of setColors
0625:
0626:            /**
0627:             * Sets the colors array.
0628:             * The points are copied into the GeometryInfo object, assuming
0629:             * 3 components (R, G, and B) per vertex.
0630:             */
0631:            public void setColors3(float colors[]) {
0632:                if (colors == null) {
0633:                    colors3 = null;
0634:                    colors4 = null;
0635:                } else {
0636:                    colors3 = new Color3f[colors.length / 3];
0637:                    colors4 = null;
0638:                    for (int i = 0; i < colors.length / 3; i++) {
0639:                        colors3[i] = new Color3f(colors[i * 3],
0640:                                colors[i * 3 + 1], colors[i * 3 + 2]);
0641:                    }
0642:                }
0643:            } // End of setColors3
0644:
0645:            /**
0646:             * Sets the colors array.
0647:             * The points are copied into the GeometryInfo object, assuming
0648:             * 4 components (R, G, B, and A) per vertex.
0649:             */
0650:            public void setColors4(float colors[]) {
0651:                if (colors == null) {
0652:                    colors3 = null;
0653:                    colors4 = null;
0654:                } else {
0655:                    colors3 = null;
0656:                    colors4 = new Color4f[colors.length / 4];
0657:                    for (int i = 0; i < colors.length / 4; i++) {
0658:                        colors4[i] = new Color4f(colors[i * 4],
0659:                                colors[i * 4 + 1], colors[i * 4 + 2],
0660:                                colors[i * 4 + 3]);
0661:                    }
0662:                }
0663:            } // End of setColors4
0664:
0665:            /**
0666:             * Sets the colors array.
0667:             * The points are copied into the GeometryInfo object, assuming
0668:             * 3 components (R, G, and B) per vertex.
0669:             */
0670:            public void setColors3(byte colors[]) {
0671:                if (colors == null) {
0672:                    colors3 = null;
0673:                    colors4 = null;
0674:                } else {
0675:                    colors3 = new Color3f[colors.length / 3];
0676:                    colors4 = null;
0677:                    for (int i = 0; i < colors.length / 3; i++) {
0678:                        colors3[i] = new Color3f(
0679:                                (float) (colors[i * 3] & 0xff) / 255.0f,
0680:                                (float) (colors[i * 3 + 1] & 0xff) / 255.0f,
0681:                                (float) (colors[i * 3 + 2] & 0xff) / 255.0f);
0682:                    }
0683:                }
0684:            } // End of setColors3
0685:
0686:            /**
0687:             * Sets the colors array.
0688:             * The points are copied into the GeometryInfo object, assuming
0689:             * 4 components (R, G, B, and A) per vertex.
0690:             */
0691:            public void setColors4(byte colors[]) {
0692:                if (colors == null) {
0693:                    colors3 = null;
0694:                    colors4 = null;
0695:                } else {
0696:                    colors3 = null;
0697:                    colors4 = new Color4f[colors.length / 4];
0698:                    for (int i = 0; i < colors.length / 4; i++) {
0699:                        colors4[i] = new Color4f(
0700:                                (float) (colors[i * 4] & 0xff) / 255.0f,
0701:                                (float) (colors[i * 4 + 1] & 0xff) / 255.0f,
0702:                                (float) (colors[i * 4 + 2] & 0xff) / 255.0f,
0703:                                (float) (colors[i * 4 + 3] & 0xff) / 255.0f);
0704:                    }
0705:                }
0706:            } // End of setColors4
0707:
0708:            /**
0709:             * Retrieves a reference to the colors array.  Will be either
0710:             * <code>Color3f[]</code> or <code>Color4f[]</code> depending on
0711:             * the type of the input data.  Call
0712:             * getNumColorComponents() to find out which version is returned.
0713:             */
0714:            public Object[] getColors() {
0715:                if (colors3 != null)
0716:                    return colors3;
0717:                else
0718:                    return colors4;
0719:            } // End of getColors
0720:
0721:            /**
0722:             * Returns the number of color data components stored per vertex
0723:             * in the current GeometryInfo object (3 for RGB or 4 for RGBA).
0724:             * If no colors are currently defined, 0 is returned.
0725:             */
0726:            public int getNumColorComponents() {
0727:                if (colors3 != null)
0728:                    return 3;
0729:                else if (colors4 != null)
0730:                    return 4;
0731:                else
0732:                    return 0;
0733:            } // End of getNumColorComponents
0734:
0735:            /**
0736:             * Sets the normals array.
0737:             * No data copying is done because a reference to
0738:             * user data is used.
0739:             */
0740:            public void setNormals(Vector3f normals[]) {
0741:                this .normals = normals;
0742:            } // End of setNormals
0743:
0744:            /**
0745:             * Sets the normals array.
0746:             * The points are copied into the GeometryInfo object.
0747:             */
0748:            public void setNormals(float normals[]) {
0749:                if (normals == null)
0750:                    this .normals = null;
0751:                else {
0752:                    this .normals = new Vector3f[normals.length / 3];
0753:                    for (int i = 0; i < this .normals.length; i++) {
0754:                        this .normals[i] = new Vector3f(normals[i * 3],
0755:                                normals[i * 3 + 1], normals[i * 3 + 2]);
0756:                    }
0757:                }
0758:            } // End of setNormals(float[])
0759:
0760:            /**
0761:             * Retrieves a reference to the normal array.
0762:             */
0763:            public Vector3f[] getNormals() {
0764:                return normals;
0765:            } // End of getNormals
0766:
0767:            /**
0768:             * This method is used to specify the number of texture coordinate sets  
0769:             * and the dimensionality of the texture coordinates.
0770:             * The number of texture coordinate sets must be specified to the GeometryInfo
0771:             * class before any of the sets are specified. The dimensionality of the 
0772:             * texture coordinates may be 2, 3, or 4, corresponding to 2D, 3D, or 4D 
0773:             * texture coordinates respectively.(All sets must have the same 
0774:             * dimensionality.) The default is zero, 2D texture coordinate sets. 
0775:             * This method should be called before any texture coordinate sets are 
0776:             * specified because <b>calling this method will delete all previously
0777:             * specified texture coordinate and texture coordinate index arrays</b> 
0778:             * associated with this GeometryInfo.  For example: 
0779:             * <blockquote><pre>
0780:             *	geomInfo.setTextureCoordinateParams(2, 3);
0781:             *	geomInfo.setTextureCoordinates(0, tex0);
0782:             *	geomInfo.setTextureCoordinates(1, tex1);
0783:             *	geomInfo.setTextureCoordinateParams(1, 2);
0784:             *	geomInfo.getTexCoordSetCount();
0785:             * </blockquote></pre>
0786:             * The second call to <code>setTextureCoordinateParams</code> will erase all 
0787:             * the texture coordinate arrays, so the subsequent call to <code>
0788:             * getTexCoordSetCount</code> will return 1.
0789:             * @param numSets The number of texture coordinate sets that will be 
0790:             * specified for this GeometryInfo object.
0791:             * @param dim The dimensionality of the texture coordinates. Has to be 2, 3 
0792:             * or 4.
0793:             * @throws IllegalArgumentException if the dimensionality of the texture 
0794:             * coordinates is not one of 2, 3 or 4.
0795:             */
0796:            public void setTextureCoordinateParams(int numSets, int dim) {
0797:                if (dim == 2) {
0798:                    texCoordSets = new TexCoord2f[numSets][];
0799:                } else if (dim == 3) {
0800:                    texCoordSets = new TexCoord3f[numSets][];
0801:                } else if (dim == 4) {
0802:                    texCoordSets = new TexCoord4f[numSets][];
0803:                } else {
0804:                    throw new IllegalArgumentException(J3dUtilsI18N
0805:                            .getString("GeometryInfo9"));
0806:                }
0807:                texCoordIndexSets = new int[numSets][];
0808:                texCoordDim = dim;
0809:                texCoordSetCount = numSets;
0810:            } // End of setTextureCoordinateParams
0811:
0812:            /**
0813:             * Returns the number of texture coordinate sets in this GeometryInfo.
0814:             * This value is set with setTextureCoordinateParams().
0815:             * If setTextureCoordinateParams()
0816:             * has not been called, 0 is returned unless one of the deprecated
0817:             * texture coordinate methods has been called.  Calling one of the
0818:             * deprecated texture coordinate methods sets the count to 1.
0819:             * The deprecated texture coordinate methods are those that don't
0820:             * take texCoordSet as the first parameter.
0821:             * @return the number of texture coordinate sets in this
0822:             * GeometryInfo.
0823:             */
0824:            public int getTexCoordSetCount() {
0825:                return texCoordSetCount;
0826:            }
0827:
0828:            /**
0829:             * Returns the number of texture coordinate components that are stored
0830:             * per vertex.  Returns 2 for ST (2D), 3 for STR (3D),
0831:             * or 4 for STRQ (4D), aslo known as the "dimensionality" of the
0832:             * coordinates.  This value is set with 
0833:             * setTextureCoordinateParams().  If setTextureCoordinateParams()
0834:             * has not been called, 0 is returned unless one of the deprecated
0835:             * texture coordinate methods has been called.  Calling one of the
0836:             * deprecated texture coordinate methods sets the dimensionality
0837:             * explicitly (if you called setTextureCoordinates(Point2f[]) then
0838:             * 2 is returned).
0839:             * The deprecated texture coordinate methods are those that don't
0840:             * take texCoordSet as the first parameter.
0841:             */
0842:            public int getNumTexCoordComponents() {
0843:                return texCoordDim;
0844:            } // End of getNumTexCoordComponents
0845:
0846:            /**
0847:             * Sets the mapping between texture coordinate sets and texture units.
0848:             * See the 
0849:             * <a href="../../../../../javax/media/j3d/GeometryArray.html#texCoordSetMap">
0850:             * GeometryArray constructor </a> for further details.
0851:             * <p> <b>Note:</b> If the texCoordSetMap is not set, multi-texturing is 
0852:             * turned off. Only the texture coordinate set at index 0 (if set) will be 
0853:             * used. Any other sets specified by the GeometryInfo.setTextureCoordinate* 
0854:             * methods will be ignored.
0855:             */
0856:            public void setTexCoordSetMap(int map[]) {
0857:                texCoordSetMap = map;
0858:            }
0859:
0860:            /**
0861:             * Returns a reference to the texture coordinate set map.
0862:             * See the 
0863:             * <a href="../../../../../javax/media/j3d/GeometryArray.html#texCoordSetMap">
0864:             * GeometryArray constructor </a> for further details.
0865:             */
0866:            public int[] getTexCoordSetMap() {
0867:                return texCoordSetMap;
0868:            }
0869:
0870:            /**
0871:             * Sets the 2D texture coordinates for the specified set.
0872:             * No data copying is done - a reference to user data is used. 
0873:             * @param texCoordSet The texture coordinate set for which these 
0874:             * coordinates are being specified.
0875:             * @param texCoords Array of 2D texture coordinates.
0876:             * @throws IllegalArgumentException if <code>texCoordSet </code> < 0 or
0877:             * <code>texCoordSet >= texCoordSetCount</code>,
0878:             * or the texture coordinate parameters were not previously set by
0879:             * calling <code>setTextureCoordinateParams(texCoordSetCount, 2)</code>.
0880:             */
0881:            public void setTextureCoordinates(int texCoordSet,
0882:                    TexCoord2f texCoords[]) {
0883:                if (texCoordDim != 2)
0884:                    throw new IllegalArgumentException(J3dUtilsI18N
0885:                            .getString("GeometryInfo15"));
0886:                if ((texCoordSet >= texCoordSetCount) || (texCoordSet < 0))
0887:                    throw new IllegalArgumentException(J3dUtilsI18N
0888:                            .getString("GeometryInfo18"));
0889:
0890:                texCoordSets[texCoordSet] = texCoords;
0891:            } // End of setTextureCoordinates(int, TexCoord3f[])
0892:
0893:            /**
0894:             * Sets the TextureCoordinates array by copying the data
0895:             * into the GeometryInfo object.
0896:             * This method sets the number of texture coordinate sets to 1,
0897:             * sets the dimensionality of the texture coordinates to 2,
0898:             * and sets the coordinates for texture coordinate set 0.
0899:             * @deprecated As of Java 3D 1.3 replaced by 
0900:             * <code>setTextureCoordinates(int texCoordSet, TexCoord2f coords[])</code>
0901:             */
0902:            public void setTextureCoordinates(Point2f texCoords[]) {
0903:                texCoordSetCount = 1;
0904:                texCoordDim = 2;
0905:                texCoordSets = new TexCoord2f[1][];
0906:                if (texCoords != null) {
0907:                    TexCoord2f[] tex = new TexCoord2f[texCoords.length];
0908:                    for (int i = 0; i < texCoords.length; i++)
0909:                        tex[i] = new TexCoord2f(texCoords[i]);
0910:                    texCoordSets[0] = tex;
0911:                }
0912:            } // End of setTextureCoordinates(Point2f[])
0913:
0914:            /**
0915:             * Sets the texture coordinates array for the specified set.
0916:             * No data copying is done - a reference to user data is used. 
0917:             * @param texCoordSet The texture coordinate set for which these coordinates 
0918:             * are being specified.
0919:             * @param texCoords Array of 3D texture coordinates.
0920:             * @throws IllegalArgumentException if <code> texCoordSet </code> < 0 or
0921:             * <code>texCoordSet >= texCoordSetCount</code>,
0922:             * or the texture coordinate parameters were not previously set by
0923:             * calling <code>setTextureCoordinateParams(texCoordSetCount, 3)</code>.
0924:             */
0925:            public void setTextureCoordinates(int texCoordSet,
0926:                    TexCoord3f texCoords[]) {
0927:                if (texCoordDim != 3)
0928:                    throw new IllegalArgumentException(J3dUtilsI18N
0929:                            .getString("GeometryInfo16"));
0930:                if ((texCoordSet >= texCoordSetCount) || (texCoordSet < 0))
0931:                    throw new IllegalArgumentException(J3dUtilsI18N
0932:                            .getString("GeometryInfo18"));
0933:
0934:                texCoordSets[texCoordSet] = texCoords;
0935:            } // End of setTextureCoordinates(int, TexCoord3f[])
0936:
0937:            /**
0938:             * Sets the TextureCoordinates array by copying the data
0939:             * into the GeometryInfo object.
0940:             * This method sets the number of texture coordinate sets to 1,
0941:             * sets the dimensionality of the texture coordinates to 3,
0942:             * and sets the coordinates for texture coordinate set 0.
0943:             * @deprecated As of Java 3D 1.3 replaced by 
0944:             * <code>setTextureCoordinates(int texCoordSet, TexCoord3f coords[])</code>
0945:             */
0946:            public void setTextureCoordinates(Point3f texCoords[]) {
0947:                texCoordSetCount = 1;
0948:                texCoordDim = 3;
0949:                texCoordSets = new TexCoord3f[1][];
0950:                if (texCoords != null) {
0951:                    TexCoord3f[] tex = new TexCoord3f[texCoords.length];
0952:                    for (int i = 0; i < texCoords.length; i++)
0953:                        tex[i] = new TexCoord3f(texCoords[i]);
0954:                    texCoordSets[0] = tex;
0955:                }
0956:            } // End of setTextureCoordinates(Point3f[])
0957:
0958:            /**
0959:             * Sets the texture coordinates array for the specified set.
0960:             * No data copying is done - a reference to user data is used. 
0961:             * @param texCoordSet The texture coordinate set for which these coordinates 
0962:             * are being specified.
0963:             * @param texCoords Array of 4D texture coordinates.
0964:             * @throws IllegalArgumentException if <code> texCoordSet </code> < 0 or
0965:             * <code>texCoordSet >= texCoordSetCount</code>,
0966:             * or the texture coordinate parameters were not previously set by
0967:             * calling <code>setTextureCoordinateParams(texCoordSetCount, 4)</code>.
0968:             */
0969:            public void setTextureCoordinates(int texCoordSet,
0970:                    TexCoord4f texCoords[]) {
0971:                if (texCoordDim != 4)
0972:                    throw new IllegalArgumentException(J3dUtilsI18N
0973:                            .getString("GeometryInfo17"));
0974:                if ((texCoordSet >= texCoordSetCount) || (texCoordSet < 0))
0975:                    throw new IllegalArgumentException(J3dUtilsI18N
0976:                            .getString("GeometryInfo18"));
0977:
0978:                texCoordSets[texCoordSet] = texCoords;
0979:            } // End of setTextureCoordinates(int, TexCoord4f[])
0980:
0981:            /**
0982:             * Sets the texture coordinates array by copying the data into the
0983:             * GeometryInfo object.  The number of sets and dimensionality of
0984:             * the sets must have been set previously with 
0985:             * setTextureCoordinateParams(texCoordSetCount, dim).
0986:             * @param texCoordSet The texture coordinate set for which these coordinates 
0987:             * are being specified.
0988:             * @param texCoords The float array of texture coordinates. For n texture 
0989:             * coordinates with dimensionality d, there must be d*n floats in the array.
0990:             * @throws IllegalArgumentException if <code>texCoordSet </code> < 0 or
0991:             * <code>texCoordSet >= texCoordSetCount</code>,
0992:             * or the texture coordinate parameters were not previously set by
0993:             * calling <code>setTextureCoordinateParams</code>.
0994:             */
0995:            public void setTextureCoordinates(int texCoordSet,
0996:                    float texCoords[]) {
0997:                if ((texCoords.length % texCoordDim) != 0)
0998:                    throw new IllegalArgumentException(J3dUtilsI18N
0999:                            .getString("GeometryInfo2"));
1000:
1001:                // Copy the texCoords into this GeometryInfo object
1002:                if (texCoordDim == 2) {
1003:                    TexCoord2f tcoords[] = new TexCoord2f[texCoords.length / 2];
1004:                    for (int i = 0; i < tcoords.length; i++)
1005:                        tcoords[i] = new TexCoord2f(texCoords[i * 2],
1006:                                texCoords[i * 2 + 1]);
1007:                    setTextureCoordinates(texCoordSet, tcoords);
1008:                } else if (texCoordDim == 3) {
1009:                    TexCoord3f tcoords[] = new TexCoord3f[texCoords.length / 3];
1010:                    for (int i = 0; i < tcoords.length; i++)
1011:                        tcoords[i] = new TexCoord3f(texCoords[i * 3],
1012:                                texCoords[i * 3 + 1], texCoords[i * 3 + 2]);
1013:                    setTextureCoordinates(texCoordSet, tcoords);
1014:                } else if (texCoordDim == 4) {
1015:                    TexCoord4f tcoords[] = new TexCoord4f[texCoords.length / 4];
1016:                    for (int i = 0; i < tcoords.length; i++)
1017:                        tcoords[i] = new TexCoord4f(texCoords[i * 4],
1018:                                texCoords[i * 4 + 1], texCoords[i * 4 + 2],
1019:                                texCoords[i * 4 + 3]);
1020:                    setTextureCoordinates(texCoordSet, tcoords);
1021:                } else {
1022:                    throw new IllegalArgumentException(J3dUtilsI18N
1023:                            .getString("GeometryInfo21"));
1024:                }
1025:            } // End of setTextureCoordinates(int, float[])
1026:
1027:            /**
1028:             * Sets the texture coordinates array by copying the data
1029:             * into the GeometryInfo object, assuming two numbers
1030:             * (S and T) per vertex.
1031:             * This method sets the number of texture coordinate sets to 1,
1032:             * sets the dimensionality of the texture coordinates to 2,
1033:             * and sets the coordinates for texture coordinate set 0.
1034:             * @deprecated As of Java 3D 1.3 replaced by 
1035:             * <code>setTextureCoordinates(int texCoordSet, float texCoords[])</code>
1036:             */
1037:            public void setTextureCoordinates2(float texCoords[]) {
1038:                texCoordSetCount = 1;
1039:                texCoordDim = 2;
1040:                texCoordSets = new TexCoord2f[1][];
1041:                setTextureCoordinates(0, texCoords);
1042:            } // End of setTextureCoordinates2(float[])
1043:
1044:            /**
1045:             * Sets the TextureCoordinates array by copying the data
1046:             * into the GeometryInfo object, assuming three numbers
1047:             * (S, T, &amp; R) per vertex.
1048:             * This method sets the number of texture coordinate sets to 1,
1049:             * sets the dimensionality of the texture coordinates to 3,
1050:             * and sets the coordinates for texture coordinate set 0.
1051:             * @deprecated As of Java 3D 1.3 replaced by 
1052:             * <code>setTextureCoordinates(int texCoordSet, float texCoords[])</code>
1053:             */
1054:            public void setTextureCoordinates3(float texCoords[]) {
1055:                texCoordSetCount = 1;
1056:                texCoordDim = 3;
1057:                texCoordSets = new TexCoord3f[1][];
1058:                setTextureCoordinates(0, texCoords);
1059:            } // End of setTextureCoordinates3(float[])
1060:
1061:            /**
1062:             * Returns a reference to the indicated texture coordinate array.
1063:             * The return type will be <code>TexCoord2f[]</code>, <code>TexCoord3f[]
1064:             * </code>, or <code>TexCoord4f[]</code> depending on the 
1065:             * current dimensionality of the texture coordinates in the GeometryInfo
1066:             * object.  Use <code>getNumTexCoordComponents()</code> to find out which 
1067:             * version is returned.
1068:             * @param texCoordSet The index of the texture coordinate set to
1069:             * retrieve.
1070:             * @return An array of texture coordinates at the specified index
1071:             * @throws IllegalArgumentException If <code> texCoordSet</code> < 0
1072:             * or <code>texCoordSet >= texCoordSetCount</code>
1073:             */
1074:            public Object[] getTextureCoordinates(int texCoordSet) {
1075:                if ((texCoordSet >= texCoordSetCount) || (texCoordSet < 0))
1076:                    throw new IllegalArgumentException(J3dUtilsI18N
1077:                            .getString("GeometryInfo18"));
1078:                return texCoordSets[texCoordSet];
1079:            } // End of getTextureCoordinates(int)
1080:
1081:            /**
1082:             * Retrieves a reference to texture coordinate set 0.
1083:             * The return type will be <code>TexCoord2f[]</code>, <code>TexCoord3f[]
1084:             * </code>, or <code>TexCoord4f[]</code> depending on the 
1085:             * current dimensionality of the texture coordinates in the GeometryInfo
1086:             * object.  Use <code>getNumTexCoordComponents()</code> to find out which 
1087:             * version is returned.  Equivalent to <code>getTextureCoordinates(0)</code>.
1088:             * @return An array of texture coordinates for set 0.
1089:             * @deprecated As of Java 3D 1.3 replaced by 
1090:             * <code>getTextureCoordinates(int texCoordSet)</code>
1091:             */
1092:            public Object[] getTextureCoordinates() {
1093:                return texCoordSets[0];
1094:            } // End of getTextureCoordinates()
1095:
1096:            /**
1097:             * Sets the array of indices into the Coordinate array.
1098:             * No data copying is done - a reference to user data is used. 
1099:             */
1100:            public void setCoordinateIndices(int coordinateIndices[]) {
1101:                this .coordinateIndices = coordinateIndices;
1102:            } // End of setCoordinateIndices
1103:
1104:            /**
1105:             * Retrieves a reference to the array of indices into the
1106:             * coordinate array.</p>
1107:             *
1108:             * This method should be considered for advanced users only.
1109:             * Novice users should just use getGeometryArray() to retrieve
1110:             * their data so that the internal format of GeometryInfo is
1111:             * of no concern.</p>
1112:             *
1113:             * Depending on which of the utility routines you've called
1114:             * on your GeometryInfo object, the results may not be what you
1115:             * expect.  If you've called the Stripifier, your GeometryInfo
1116:             * object's Primitive has been changed to indexed TRIANGLE_STRIP_ARRAY
1117:             * and your data will be formatted accordingly.  Similarly, if
1118:             * you've called the Triangulator, your data is in indexed
1119:             * TRIANGLE_ARRAY format.  Generating normals with the NormalGenerator
1120:             * utility will convert your data to indexed TRIANGLE_ARRAY also,
1121:             * but if you call getGeometryArray without calling the Stripifier or
1122:             * Triangulator, your data will be converted back to the original
1123:             * primitive type when creating the GeometryArray object to pass
1124:             * back.  However, if your creaseAngle was not Math.PI (no creases -
1125:             * smooth shading), then the introduction of
1126:             * creases into your model may have split primitives, lengthening 
1127:             * the StripCounts and index arrays from your original data.
1128:             */
1129:            public int[] getCoordinateIndices() {
1130:                return coordinateIndices;
1131:            } // End of getCoordinateIndices
1132:
1133:            /**
1134:             * Sets the array of indices into the Color array.
1135:             * No data copying is done - a reference to user data is used. 
1136:             */
1137:            public void setColorIndices(int colorIndices[]) {
1138:                this .colorIndices = colorIndices;
1139:            } // End of setColorIndices
1140:
1141:            /**
1142:             * Retrieves a reference to the array of indices into the
1143:             * color array.</p>
1144:             *
1145:             * This method should be considered for advanced users only.
1146:             * Novice users should just use getGeometryArray() to retrieve
1147:             * their data so that the internal format of GeometryInfo is
1148:             * of no concern.</p>
1149:             *
1150:             * Depending on which of the utility routines you've called
1151:             * on your GeometryInfo object, the results may not be what you
1152:             * expect.  If you've called the Stripifier, your GeometryInfo
1153:             * object's Primitive has been changed to indexed TRIANGLE_STRIP_ARRAY
1154:             * and your data will be formatted accordingly.  Similarly, if
1155:             * you've called the Triangulator, your data is in indexed
1156:             * TRIANGLE_ARRAY format.  Generating normals with the NormalGenerator
1157:             * utility will convert your data to indexed TRIANGLE_ARRAY also,
1158:             * but if you call getGeometryArray without calling the Stripifier or
1159:             * Triangulator, your data will be converted back to the original
1160:             * primitive type when creating the GeometryArray object to pass
1161:             * back.  However, if your creaseAngle was not Math.PI (no creases -
1162:             * smooth shading), then the introduction of
1163:             * creases into your model may have split primitives, lengthening
1164:             * the StripCounts and index arrays from your original data.
1165:             */
1166:            public int[] getColorIndices() {
1167:                return colorIndices;
1168:            } // End of getColorIndices
1169:
1170:            /**
1171:             * Sets the array of indices into the Normal array.
1172:             * No data copying is done - a reference to user data is used. 
1173:             */
1174:            public void setNormalIndices(int normalIndices[]) {
1175:                this .normalIndices = normalIndices;
1176:
1177:            } // End of setNormalIndices
1178:
1179:            /**
1180:             * Retrieves a reference to the array of indices into the
1181:             * Normal array.</p>
1182:             *
1183:             * This method should be considered for advanced users only.
1184:             * Novice users should just use getGeometryArray() to retrieve
1185:             * their data so that the internal format of GeometryInfo is
1186:             * of no concern.</p>
1187:             *
1188:             * Depending on which of the utility routines you've called
1189:             * on your GeometryInfo object, the results may not be what you
1190:             * expect.  If you've called the Stripifier, your GeometryInfo
1191:             * object's Primitive has been changed to indexed TRIANGLE_STRIP_ARRAY
1192:             * and your data will be formatted accordingly.  Similarly, if
1193:             * you've called the Triangulator, your data is in indexed
1194:             * TRIANGLE_ARRAY format.  Generating normals with the NormalGenerator
1195:             * utility will convert your data to indexed TRIANGLE_ARRAY also,
1196:             * but if you call getGeometryArray without calling the Stripifier or
1197:             * Triangulator, your data will be converted back to the original
1198:             * primitive type when creating the GeometryArray object to pass
1199:             * back.  However, if your creaseAngle was not Math.PI (no creases -
1200:             * smooth shading), then the introduction of
1201:             * creases into your model may have split primitives, lengthening
1202:             * the StripCounts and index arrays from your original data.
1203:             */
1204:            public int[] getNormalIndices() {
1205:                return normalIndices;
1206:            } // End of getNormalIndices
1207:
1208:            /**
1209:             * Sets one of the texture coordinate index arrays.
1210:             * No data copying is done - a reference to user data is used. 
1211:             * @param texCoordSet The texture coordinate set for which these coordinate 
1212:             * indices are being specified.
1213:             * @param texIndices The integer array of indices into the specified texture 
1214:             * coordinate set
1215:             * @throws IllegalArgumentException If <code> texCoordSet</code> < 0 or
1216:             * <code>texCoordSet >= texCoordSetCount</code>.
1217:             */
1218:            public void setTextureCoordinateIndices(int texCoordSet,
1219:                    int texIndices[]) {
1220:                if ((texCoordSet >= texCoordSetCount) || (texCoordSet < 0))
1221:                    throw new IllegalArgumentException(J3dUtilsI18N
1222:                            .getString("GeometryInfo18"));
1223:
1224:                // Texture coordinates are indexed 
1225:                texCoordIndexSets[texCoordSet] = texIndices;
1226:            } // End of setTextureCoordinateIndices(int, int[])
1227:
1228:            /**
1229:             * Sets the array of indices into texture coordinate set 0.  Do not
1230:             * call this method if you are using more than one set of texture
1231:             * coordinates.
1232:             * No data is copied - a reference to the user data is used.
1233:             * @deprecated As of Java 3D 1.3 replaced by 
1234:             * <code>setTextureCoordinateIndices(int texCoordSet, int indices[])</code>
1235:             * @throws IllegalArgumentException If <code>texCoordSetCount > 1</code>.
1236:             */
1237:            public void setTextureCoordinateIndices(int texIndices[]) {
1238:                if (texCoordSetCount > 1)
1239:                    throw new IllegalArgumentException(J3dUtilsI18N
1240:                            .getString("GeometryInfo1"));
1241:                texCoordIndexSets = new int[1][];
1242:                texCoordIndexSets[0] = texIndices;
1243:            } // End of setTextureCoordinateIndices(int[])
1244:
1245:            /**
1246:             * Retrieves a reference to the specified array of texture
1247:             * coordinate indices.<p>
1248:             *
1249:             * This method should be considered for advanced users only.
1250:             * Novice users should just use getGeometryArray() to retrieve
1251:             * their data so that the internal format of GeometryInfo is
1252:             * of no concern.</p>
1253:             *
1254:             * Depending on which of the utility routines you've called
1255:             * on your GeometryInfo object, the results may not be what you
1256:             * expect.  If you've called the Stripifier, your GeometryInfo
1257:             * object's Primitive has been changed to indexed TRIANGLE_STRIP_ARRAY
1258:             * and your data will be formatted accordingly.  Similarly, if
1259:             * you've called the Triangulator, your data is in indexed
1260:             * TRIANGLE_ARRAY format.  Generating normals with the NormalGenerator
1261:             * utility will convert your data to indexed TRIANGLE_ARRAY also,
1262:             * but if you call getGeometryArray without calling the Stripifier or
1263:             * Triangulator, your data will be converted back to the original
1264:             * primitive type when creating the GeometryArray object to pass
1265:             * back.  However, if your creaseAngle was not Math.PI (no creases -
1266:             * smooth shading), then the introduction of
1267:             * creases into your model may have split primitives, lengthening
1268:             * the StripCounts and index arrays from your original data.
1269:             * @param texCoordSet The texture coordinate index set to be
1270:             * retrieved.
1271:             * @return Integer array of the texture coordinate indices for the specified
1272:             * set.
1273:             */
1274:            public int[] getTextureCoordinateIndices(int texCoordSet) {
1275:                return texCoordIndexSets[texCoordSet];
1276:            }
1277:
1278:            /**
1279:             * Returns a reference to texture coordinate index set 0.
1280:             * Equivalent to
1281:             * <code>getTextureCoordinateIndices(0)</code>.
1282:             * @deprecated As of Java 3D 1.3 replaced by 
1283:             * <code>int[] getTextureCoordinateIndices(int texCoordSet) </code>
1284:             * @return Integer array of the texture coordinate indices for set 0
1285:             */
1286:            public int[] getTextureCoordinateIndices() {
1287:                if (texCoordIndexSets == null)
1288:                    return null;
1289:                return texCoordIndexSets[0];
1290:            } // End of getTextureCoordinateIndices()
1291:
1292:            /**
1293:             * Sets the array of strip counts.  If index lists have been set for
1294:             * this GeomteryInfo object then the data is indexed and the stripCounts
1295:             * are like stripIndexCounts.  If no index lists have been set then
1296:             * the data is non-indexed and the stripCounts are like 
1297:             * stripVertexCounts.
1298:             * @see GeometryStripArray#GeometryStripArray(int, int,
1299:             * int[] stripVertexCounts)
1300:             * @see IndexedGeometryStripArray#IndexedGeometryStripArray(int, int, int,
1301:             * int[] stripIndexCounts)
1302:             */
1303:            public void setStripCounts(int stripCounts[]) {
1304:                this .stripCounts = stripCounts;
1305:            } // End of setStripCounts
1306:
1307:            /**
1308:             * Retrieves a reference to the array of stripCounts.</p>
1309:             *
1310:             * This method should be considered for advanced users only.
1311:             * Novice users should just use getGeometryArray() to retrieve
1312:             * their data so that the internal format of GeometryInfo is
1313:             * of no concern.</p>
1314:             *
1315:             * Depending on which of the utility routines you've called
1316:             * on your GeometryInfo object, the results may not be what you
1317:             * expect.  If you've called the Stripifier, your GeometryInfo
1318:             * object's Primitive has been changed to indexed TRIANGLE_STRIP_ARRAY
1319:             * and your data will be formatted accordingly.  Similarly, if
1320:             * you've called the Triangulator, your data is in indexed
1321:             * TRIANGLE_ARRAY format.  Generating normals with the NormalGenerator
1322:             * utility will convert your data to indexed TRIANGLE_ARRAY also,
1323:             * but if you call getGeometryArray without calling the Stripifier or
1324:             * Triangulator, your data will be converted back to the original
1325:             * primitive type when creating the GeometryArray object to pass
1326:             * back.  However, if your creaseAngle was not Math.PI (no creases -
1327:             * smooth shading), then the introduction of
1328:             * creases into your model may have split primitives, lengthening
1329:             * the StripCounts and index arrays from your original data.
1330:             */
1331:            public int[] getStripCounts() {
1332:                return stripCounts;
1333:            } // End of getStripCounts
1334:
1335:            /**
1336:             * Sets the list of contour counts.  Only used with the POLYGON_ARRAY
1337:             * primitive.  Polygons can be made of several vertex lists 
1338:             * called contours.  The first list is the polygon, and 
1339:             * subsequent lists are "holes" that are removed from the
1340:             * polygon.  All of the holes must be contained entirely
1341:             * within the polygon.
1342:             */
1343:            public void setContourCounts(int contourCounts[]) {
1344:                this .contourCounts = contourCounts;
1345:            } // End of setContourCounts
1346:
1347:            /**
1348:             * Retrieves a reference to the array of contourCounts.
1349:             */
1350:            public int[] getContourCounts() {
1351:                return contourCounts;
1352:            } // End of getContourCounts
1353:
1354:            /*
1355:             * This routine will return an index list for any array of objects.
1356:             */
1357:            int[] getListIndices(Object list[]) {
1358:                // Create list of indices to return
1359:                int indices[] = new int[list.length];
1360:
1361:                // Create hash table with initial capacity equal to the number
1362:                // of components (assuming about half will be duplicates)
1363:                HashMap table = new HashMap(list.length);
1364:
1365:                Integer idx;
1366:                for (int i = 0; i < list.length; i++) {
1367:
1368:                    // Find index associated with this object
1369:                    idx = (Integer) table.get(list[i]);
1370:
1371:                    if (idx == null) {
1372:                        // We haven't seen this object before
1373:                        indices[i] = i;
1374:
1375:                        // Put into hash table and remember the index
1376:                        table.put(list[i], new Integer(i));
1377:
1378:                    } else {
1379:                        // We've seen this object
1380:                        indices[i] = idx.intValue();
1381:                    }
1382:                }
1383:
1384:                return indices;
1385:            } // End of getListIndices
1386:
1387:            // Class to hash 'size' integers
1388:            private class IndexRow {
1389:                int[] val;
1390:                int size;
1391:                private static final int HASHCONST = 0xBABEFACE;
1392:
1393:                public int hashCode() {
1394:                    int bits = 0;
1395:                    for (int i = 0; i < size; i++) {
1396:                        bits ^= (bits * HASHCONST) << 2;
1397:                    }
1398:                    return bits;
1399:                } // End of IndexRow.hashCode
1400:
1401:                public boolean equals(Object obj) {
1402:                    for (int i = 0; i < size; i++) {
1403:                        if (((IndexRow) obj).get(i) != val[i])
1404:                            return false;
1405:                    }
1406:                    return true;
1407:                } // End of IndexRow.equals()
1408:
1409:                public int get(int index) {
1410:                    return val[index];
1411:                } // End of IndexRow.get
1412:
1413:                public void set(int index, int value) {
1414:                    val[index] = value;
1415:                } // End of IndexRow.set
1416:
1417:                IndexRow(int numColumns) {
1418:                    size = numColumns;
1419:                    val = new int[size];
1420:                } // End of IndexRow constructor
1421:            } // End of class IndexRow
1422:
1423:            /**
1424:             * Create index lists for all data lists.
1425:             * Identical data entries are guaranteed to
1426:             * use the same index value.  Does not remove unused data values
1427:             * from the object - call compact() to do this.
1428:             * @param useCoordIndexOnly Reformat the data into the
1429:             * GeometryArray.USE_COORD_INDEX_ONLY format where there is only
1430:             * one index list.  If the data is already in the USE_COORD_INDEX_ONLY
1431:             * format, sending false (or calling indexify()) will change
1432:             * it to the normal indexed format.
1433:             * @throws IllegalArgumentException if coordinate data is missing,
1434:             * if the index lists aren't all the
1435:             * same length, if an index list is set and the corresponding data
1436:             * list isn't set, if a data list is set and the corresponding
1437:             * index list is unset (unless all index lists are unset or in
1438:             * USE_COORD_INDEX_ONLY format),
1439:             * if StripCounts or ContourCounts is inconsistent with the current
1440:             * primitive, if the sum of the contourCounts array doesn't equal
1441:             * the length of the StripCounts array, or if the number of vertices
1442:             * isn't a multiple of three (for triangles) or four (for quads).
1443:             */
1444:            public void indexify(boolean useCoordIndexOnly) {
1445:                checkForBadData();
1446:
1447:                if (useCoordIndexOnly) {
1448:                    // Return if already in this format
1449:                    if (coordOnly)
1450:                        return;
1451:
1452:                    // Start from normal indexed format
1453:                    indexify(false);
1454:
1455:                    // Reformat data to USE_COORD_INDEX_ONLY format
1456:                    // Need to make an index into the index lists using each
1457:                    // row of indexes as one value
1458:
1459:                    // First, find out how many index lists there are;
1460:                    int numLists = 1; // Always have coordinates
1461:                    if (colorIndices != null)
1462:                        numLists++;
1463:                    if (normalIndices != null)
1464:                        numLists++;
1465:                    numLists += texCoordSetCount;
1466:
1467:                    // Make single array containing all indices
1468:                    int n = coordinateIndices.length;
1469:                    IndexRow[] ir = new IndexRow[n];
1470:                    int j;
1471:                    for (int i = 0; i < n; i++) {
1472:                        ir[i] = new IndexRow(numLists);
1473:                        j = 0;
1474:                        ir[i].set(j++, coordinateIndices[i]);
1475:                        if (colorIndices != null)
1476:                            ir[i].set(j++, colorIndices[i]);
1477:                        if (normalIndices != null)
1478:                            ir[i].set(j++, normalIndices[i]);
1479:                        for (int k = 0; k < texCoordSetCount; k++) {
1480:                            ir[i].set(j++, texCoordIndexSets[k][i]);
1481:                        }
1482:                    }
1483:
1484:                    // Get index into that array
1485:                    int[] coordOnlyIndices = getListIndices(ir);
1486:
1487:                    // Get rid of duplicate rows
1488:                    int newInd[] = new int[coordOnlyIndices.length];
1489:                    ir = (IndexRow[]) compactData(coordOnlyIndices, ir, newInd);
1490:                    coordOnlyIndices = newInd;
1491:
1492:                    // Reformat data lists to correspond to new index
1493:
1494:                    // Allocate arrays to hold reformatted data
1495:                    Point3f[] newCoords = new Point3f[ir.length];
1496:                    Color3f[] newColors3 = null;
1497:                    Color4f[] newColors4 = null;
1498:                    Vector3f[] newNormals = null;
1499:                    Object newTexCoordSets[][] = null;
1500:                    if (colors3 != null)
1501:                        newColors3 = new Color3f[ir.length];
1502:                    else if (colors4 != null)
1503:                        newColors4 = new Color4f[ir.length];
1504:                    if (normals != null)
1505:                        newNormals = new Vector3f[ir.length];
1506:                    for (int i = 0; i < texCoordSetCount; i++) {
1507:                        if (texCoordDim == 2) {
1508:                            if (i == 0)
1509:                                newTexCoordSets = new TexCoord2f[texCoordSetCount][];
1510:                            newTexCoordSets[i] = new TexCoord2f[ir.length];
1511:                        } else if (texCoordDim == 3) {
1512:                            if (i == 0)
1513:                                newTexCoordSets = new TexCoord3f[texCoordSetCount][];
1514:                            newTexCoordSets[i] = new TexCoord3f[ir.length];
1515:                        } else if (texCoordDim == 4) {
1516:                            if (i == 0)
1517:                                newTexCoordSets = new TexCoord4f[texCoordSetCount][];
1518:                            newTexCoordSets[i] = new TexCoord4f[ir.length];
1519:                        }
1520:                    }
1521:
1522:                    // Copy data into new arrays
1523:                    n = ir.length;
1524:                    for (int i = 0; i < n; i++) {
1525:                        j = 0;
1526:                        newCoords[i] = coordinates[(ir[i]).get(j++)];
1527:                        if (colors3 != null) {
1528:                            newColors3[i] = colors3[(ir[i]).get(j++)];
1529:                        } else if (colors4 != null) {
1530:                            newColors4[i] = colors4[(ir[i]).get(j++)];
1531:                        }
1532:                        if (normals != null)
1533:                            newNormals[i] = normals[(ir[i]).get(j++)];
1534:                        for (int k = 0; k < texCoordSetCount; k++) {
1535:                            newTexCoordSets[k][i] = texCoordSets[k][(ir[i])
1536:                                    .get(j++)];
1537:                        }
1538:                    }
1539:
1540:                    // Replace old arrays with new arrays
1541:                    coordinates = newCoords;
1542:                    colors3 = newColors3;
1543:                    colors4 = newColors4;
1544:                    normals = newNormals;
1545:                    texCoordSets = newTexCoordSets;
1546:                    coordinateIndices = coordOnlyIndices;
1547:                    colorIndices = null;
1548:                    normalIndices = null;
1549:                    texCoordIndexSets = new int[texCoordSetCount][];
1550:
1551:                    coordOnly = true;
1552:                } else if (coordOnly) {
1553:                    // Need to change from useCoordIndexOnly format to normal
1554:                    // indexed format.  Should make a more efficient implementation
1555:                    // later.
1556:
1557:                    int n = coordinateIndices.length;
1558:                    if ((colors3 != null) || (colors4 != null)) {
1559:                        colorIndices = new int[n];
1560:                        for (int i = 0; i < n; i++)
1561:                            colorIndices[i] = coordinateIndices[i];
1562:                    }
1563:                    if (normals != null) {
1564:                        normalIndices = new int[n];
1565:                        for (int i = 0; i < n; i++)
1566:                            normalIndices[i] = coordinateIndices[i];
1567:                    }
1568:                    texCoordIndexSets = new int[texCoordSetCount][];
1569:                    for (int i = 0; i < texCoordSetCount; i++) {
1570:                        texCoordIndexSets[i] = new int[n];
1571:                        for (int j = 0; j < n; j++) {
1572:                            texCoordIndexSets[i][j] = coordinateIndices[j];
1573:                        }
1574:                    }
1575:                    coordOnly = false;
1576:                } else {
1577:
1578:                    // No need to indexify if already indexed
1579:                    if (coordinateIndices != null)
1580:                        return;
1581:
1582:                    coordinateIndices = getListIndices(coordinates);
1583:
1584:                    if (colors3 != null)
1585:                        colorIndices = getListIndices(colors3);
1586:                    else if (colors4 != null)
1587:                        colorIndices = getListIndices(colors4);
1588:
1589:                    if (normals != null)
1590:                        normalIndices = getListIndices(normals);
1591:
1592:                    texCoordIndexSets = new int[texCoordSetCount][];
1593:                    for (int i = 0; i < texCoordSetCount; i++) {
1594:                        texCoordIndexSets[i] = getListIndices(texCoordSets[i]);
1595:                    }
1596:
1597:                    coordOnly = false;
1598:                }
1599:
1600:                if ((DEBUG & 1) == 1) {
1601:                    System.out.println("Coordinate Array:");
1602:                    for (int i = 0; i < coordinates.length; i++) {
1603:                        System.out.println("  " + i + " " + coordinates[i]
1604:                                + " " + coordinates[i].hashCode());
1605:                    }
1606:                    System.out.println("Index array:");
1607:                    for (int i = 0; i < coordinateIndices.length; i++) {
1608:                        System.out.println("  " + i + " "
1609:                                + coordinateIndices[i]);
1610:                    }
1611:                }
1612:
1613:            } // End of indexify
1614:
1615:            public void indexify() {
1616:                indexify(false);
1617:            } // End of indexify()
1618:
1619:            /**
1620:             * Allocates an array of the same type as the input type. This allows us to 
1621:             * use a generic compactData method.
1622:             *
1623:             * @param data Array of coordinate, color, normal or texture coordinate data
1624:             * The data can be in one of the following formats - Point3f, Color3f, 
1625:             * Color4f, TexCoord2f, TexCoord3f, TexCoord4f.
1626:             *
1627:             * @param num The size of the array to be allocated
1628:             *
1629:             * @return An array of size num of the same type as the input type 
1630:             *
1631:             * @exception IllegalArgumentException if the input array is not one of the 
1632:             * types listed above.
1633:             */
1634:            Object[] allocateArray(Object data[], int num) {
1635:                Object newData[] = null;
1636:                if (data instanceof  javax.vecmath.Point3f[]) {
1637:                    newData = new Point3f[num];
1638:                } else if (data instanceof  javax.vecmath.Vector3f[]) {
1639:                    newData = new Vector3f[num];
1640:                } else if (data instanceof  javax.vecmath.Color3f[]) {
1641:                    newData = new Color3f[num];
1642:                } else if (data instanceof  javax.vecmath.Color4f[]) {
1643:                    newData = new Color4f[num];
1644:                } else if (data instanceof  javax.vecmath.TexCoord2f[]) {
1645:                    newData = new TexCoord2f[num];
1646:                } else if (data instanceof  javax.vecmath.TexCoord3f[]) {
1647:                    newData = new TexCoord3f[num];
1648:                } else if (data instanceof  javax.vecmath.TexCoord4f[]) {
1649:                    newData = new TexCoord4f[num];
1650:                } else if (data instanceof  IndexRow[]) {
1651:                    // Hack so we can use compactData for coordIndexOnly
1652:                    newData = new IndexRow[num];
1653:                } else
1654:                    throw new IllegalArgumentException(J3dUtilsI18N
1655:                            .getString("GeometryInfo9"));
1656:                return newData;
1657:            } // End of allocateArray
1658:
1659:            /**
1660:             * Generic method that compacts (ie removes unreferenced/duplicate data)
1661:             * any type of indexed data. 
1662:             * Used to compact coordinate, color, normal and texture coordinate data.
1663:             * @param indices Array of indices
1664:             * @param data Array of coordinate, color, normal or texture coordinate data
1665:             * The data can be in one of the following formats - Point3f, Color3f, 
1666:             * Color4f, TexCoord2f, TexCoord3f, TexCoord4f. 
1667:             * @param newInd The new array of indexes after the data has been compacted.
1668:             * This must be allocated by the calling method. On return, this array will 
1669:             * contain the new index data. The size of this array must be equal to 
1670:             * indices.length
1671:             * @return Array of the data with unreferenced and duplicate entries removed. 
1672:             * The return type will be the same as the type that was passed in data. 
1673:             */
1674:            // TODO:  Remove duplicate entries in data lists.
1675:            private Object[] compactData(int indices[], Object data[],
1676:                    int newInd[]) {
1677:                Object newData[] = null;
1678:                /*
1679:                 * This is a three step process.
1680:                 * First, find out how many unique indexes are used.  This
1681:                 * will be the size of the new data array.
1682:                 */
1683:                int numUnique = 0;
1684:                int translationTable[] = new int[data.length];
1685:                for (int i = 0; i < indices.length; i++) {
1686:                    if (translationTable[indices[i]] == 0) {
1687:
1688:                        numUnique++;
1689:                        translationTable[indices[i]] = 1;
1690:                    }
1691:                }
1692:                /*
1693:                 * Second, build the new data list.  Remember the new indexes so
1694:                 * we can use the table to translate the old indexes to the new
1695:                 */
1696:                newData = allocateArray(data, numUnique);
1697:                int newIdx = 0;
1698:                for (int i = 0; i < translationTable.length; i++) {
1699:                    if (translationTable[i] != 0) {
1700:                        newData[newIdx] = data[i];
1701:                        translationTable[i] = newIdx++;
1702:                    }
1703:                }
1704:                /*
1705:                 * Third, make the new index list
1706:                 */
1707:                for (int i = 0; i < indices.length; i++) {
1708:                    newInd[i] = translationTable[indices[i]];
1709:                }
1710:                return newData;
1711:            } // End of compactData
1712:
1713:            /**
1714:             * Remove unused data from an indexed dataset.
1715:             * Indexed data may contain data entries that are never referenced by
1716:             * the dataset.  This routine will remove those entries where 
1717:             * appropriate and renumber the indices to match the new values.
1718:             * @throws IllegalArgumentException if coordinate data is missing,
1719:             * if the index lists aren't all the
1720:             * same length, if an index list is set and the corresponding data
1721:             * list isn't set, if a data list is set and the corresponding
1722:             * index list is unset (unless all index lists are unset or in
1723:             * USE_COORD_INDEX_ONLY format),
1724:             * if StripCounts or ContourCounts is inconsistent with the current
1725:             * primitive, if the sum of the contourCounts array doesn't equal
1726:             * the length of the StripCounts array, or if the number of vertices
1727:             * isn't a multiple of three (for triangles) or four (for quads).
1728:             */
1729:            public void compact() {
1730:                checkForBadData();
1731:
1732:                // Only usable on indexed data
1733:                if (coordinateIndices == null)
1734:                    return;
1735:
1736:                // USE_COORD_INDEX_ONLY never has unused data
1737:                if (coordOnly)
1738:                    return;
1739:
1740:                int newInd[] = new int[coordinateIndices.length];
1741:                coordinates = (Point3f[]) compactData(coordinateIndices,
1742:                        coordinates, newInd);
1743:                coordinateIndices = newInd;
1744:
1745:                if (colorIndices != null) {
1746:                    newInd = new int[colorIndices.length];
1747:                    if (colors3 != null)
1748:                        colors3 = (Color3f[]) compactData(colorIndices,
1749:                                colors3, newInd);
1750:                    else if (colors4 != null)
1751:                        colors4 = (Color4f[]) compactData(colorIndices,
1752:                                colors4, newInd);
1753:                    colorIndices = newInd;
1754:                }
1755:
1756:                if (normalIndices != null) {
1757:                    newInd = new int[normalIndices.length];
1758:                    normals = (Vector3f[]) compactData(normalIndices, normals,
1759:                            newInd);
1760:                    normalIndices = newInd;
1761:                }
1762:
1763:                for (int i = 0; i < texCoordSetCount; i++) {
1764:                    newInd = new int[texCoordIndexSets[i].length];
1765:                    texCoordSets[i] = compactData(texCoordIndexSets[i],
1766:                            texCoordSets[i], newInd);
1767:                    texCoordIndexSets[i] = newInd;
1768:                }
1769:            } // End of compact
1770:
1771:            /**
1772:             * Check the data to make sure everything's consistent.
1773:             */
1774:            private void checkForBadData() {
1775:                boolean badData = false;
1776:
1777:                //
1778:                // Coordinates are required
1779:                //
1780:                if (coordinates == null) {
1781:                    throw new IllegalArgumentException(J3dUtilsI18N
1782:                            .getString("GeometryInfo3"));
1783:                }
1784:
1785:                //
1786:                // Check for indices with no data
1787:                //
1788:                if ((colors3 == null) && (colors4 == null)
1789:                        && (colorIndices != null))
1790:                    throw new IllegalArgumentException(J3dUtilsI18N
1791:                            .getString("GeometryInfo4"));
1792:                if ((normals == null) && (normalIndices != null))
1793:                    throw new IllegalArgumentException(J3dUtilsI18N
1794:                            .getString("GeometryInfo11"));
1795:
1796:                //
1797:                // Make sure all TextureCoordinate data is set (indices or not)
1798:                //
1799:                for (int i = 0; i < texCoordSetCount; i++) {
1800:                    if (texCoordSets[i] == null)
1801:                        throw new IllegalArgumentException(J3dUtilsI18N
1802:                                .getString("GeometryInfo10"));
1803:                }
1804:
1805:                //
1806:                // Check for Missing Index lists
1807:                //
1808:                boolean texInds = false; // Indicates whether we have texcoord indices
1809:                if (texCoordIndexSets != null) {
1810:                    for (int i = 0; i < texCoordSetCount; i++) {
1811:                        if (texCoordIndexSets[i] != null)
1812:                            texInds = true;
1813:                    }
1814:                }
1815:                if ((coordinateIndices != null) || (colorIndices != null)
1816:                        || (normalIndices != null) || texInds) {
1817:                    // At least one index list is present, so they all must be
1818:                    // present (unless coordOnly)
1819:                    if (coordinateIndices == null)
1820:                        badData = true;
1821:                    else if (coordOnly) {
1822:                        if ((colorIndices != null) || (normalIndices != null)
1823:                                || (texInds == true)) {
1824:                            throw new IllegalArgumentException(J3dUtilsI18N
1825:                                    .getString("GeometryInfo20"));
1826:                        }
1827:                    } else if (((colors3 != null) || (colors4 != null))
1828:                            && (colorIndices == null))
1829:                        badData = true;
1830:                    else if ((normals != null) && (normalIndices == null))
1831:                        badData = true;
1832:                    else if ((texCoordSetCount > 0) && !texInds)
1833:                        badData = true;
1834:                    if (badData)
1835:                        throw new IllegalArgumentException(J3dUtilsI18N
1836:                                .getString("GeometryInfo19"));
1837:                }
1838:
1839:                //
1840:                // Make sure index lists are all the same length
1841:                //
1842:                if ((coordinateIndices != null) && (!coordOnly)) {
1843:                    if (((colors3 != null) || (colors4 != null))
1844:                            && (colorIndices.length != coordinateIndices.length))
1845:                        badData = true;
1846:                    else if ((normals != null)
1847:                            && (normalIndices.length != coordinateIndices.length))
1848:                        badData = true;
1849:                    else {
1850:                        //Check all texCoord indices have the same length
1851:                        for (int i = 0; i < texCoordSetCount; i++) {
1852:                            if (texCoordIndexSets[i].length != coordinateIndices.length) {
1853:                                badData = true;
1854:                                break;
1855:                            }
1856:                        }
1857:                    }
1858:                    if (badData) {
1859:                        throw new IllegalArgumentException(J3dUtilsI18N
1860:                                .getString("GeometryInfo5"));
1861:                    }
1862:                }
1863:
1864:                //
1865:                // For stripped primitives, make sure we have strip counts
1866:                //
1867:                if ((prim == TRIANGLE_STRIP_ARRAY)
1868:                        || (prim == TRIANGLE_FAN_ARRAY)
1869:                        || (prim == POLYGON_ARRAY)) {
1870:                    if (stripCounts == null)
1871:                        badData = true;
1872:                } else if (stripCounts != null)
1873:                    badData = true;
1874:                if (badData) {
1875:                    throw new IllegalArgumentException(J3dUtilsI18N
1876:                            .getString("GeometryInfo6"));
1877:                }
1878:
1879:                // Find out how much data we have
1880:                int count;
1881:                if (coordinateIndices == null)
1882:                    count = coordinates.length;
1883:                else
1884:                    count = coordinateIndices.length;
1885:
1886:                //
1887:                // Make sure sum of strip counts equals indexCount (or vertexCount)
1888:                // and check to make sure triangles and quads have the right number
1889:                // of vertices
1890:                //
1891:                if ((prim == TRIANGLE_STRIP_ARRAY)
1892:                        || (prim == TRIANGLE_FAN_ARRAY)
1893:                        || (prim == POLYGON_ARRAY)) {
1894:                    int sum = 0;
1895:                    for (int i = 0; i < stripCounts.length; i++) {
1896:                        sum += stripCounts[i];
1897:                    }
1898:                    if (sum != count) {
1899:                        throw new IllegalArgumentException(J3dUtilsI18N
1900:                                .getString("GeometryInfo7"));
1901:                    }
1902:                } else if (prim == TRIANGLE_ARRAY) {
1903:                    if (count % 3 != 0) {
1904:                        throw new IllegalArgumentException(J3dUtilsI18N
1905:                                .getString("GeometryInfo12"));
1906:                    }
1907:                } else if (prim == QUAD_ARRAY) {
1908:                    if (count % 4 != 0) {
1909:                        throw new IllegalArgumentException(J3dUtilsI18N
1910:                                .getString("GeometryInfo13"));
1911:                    }
1912:                }
1913:
1914:                //
1915:                // For polygons, make sure the contours add up.
1916:                //
1917:                if (prim == POLYGON_ARRAY) {
1918:                    if (contourCounts != null) {
1919:                        int c = 0;
1920:                        for (int i = 0; i < contourCounts.length; i++)
1921:                            c += contourCounts[i];
1922:                        if (c != stripCounts.length) {
1923:                            throw new IllegalArgumentException(J3dUtilsI18N
1924:                                    .getString("GeometryInfo8"));
1925:                        }
1926:                    }
1927:                } else {
1928:                    if (contourCounts != null) {
1929:                        throw new IllegalArgumentException(J3dUtilsI18N
1930:                                .getString("GeometryInfo14"));
1931:                    }
1932:                }
1933:            } // End of checkForBadData
1934:
1935:            /**
1936:             * Get rid of index lists by reorganizing data into an un-indexed
1937:             * format.  Does nothing if no index lists are set.
1938:             * @throws IllegalArgumentException if coordinate data is missing,
1939:             * if the index lists aren't all the
1940:             * same length, if an index list is set and the corresponding data
1941:             * list isn't set, if a data list is set and the corresponding
1942:             * index list is unset (unless all index lists are unset or in
1943:             * USE_COORD_INDEX_ONLY format),
1944:             * if StripCounts or ContourCounts is inconsistent with the current
1945:             * primitive, if the sum of the contourCounts array doesn't equal
1946:             * the length of the StripCounts array, or if the number of vertices
1947:             * isn't a multiple of three (for triangles) or four (for quads).
1948:             */
1949:            public void unindexify() {
1950:                checkForBadData();
1951:                if (coordinateIndices != null) {
1952:                    // Switch from USE_COORD_INDEX_ONLY format
1953:                    if (coordOnly)
1954:                        indexify(false);
1955:
1956:                    coordinates = (Point3f[]) unindexifyData(coordinates,
1957:                            coordinateIndices);
1958:                    coordinateIndices = null;
1959:
1960:                    if (colors3 != null) {
1961:                        colors3 = (Color3f[]) unindexifyData(colors3,
1962:                                colorIndices);
1963:                    } else if (colors4 != null) {
1964:                        colors4 = (Color4f[]) unindexifyData(colors4,
1965:                                colorIndices);
1966:                    }
1967:                    colorIndices = null;
1968:
1969:                    if (normals != null) {
1970:                        normals = (Vector3f[]) unindexifyData(normals,
1971:                                normalIndices);
1972:                        normalIndices = null;
1973:                    }
1974:
1975:                    for (int i = 0; i < texCoordSetCount; i++)
1976:                        texCoordSets[i] = unindexifyData(texCoordSets[i],
1977:                                texCoordIndexSets[i]);
1978:                    texCoordIndexSets = new int[texCoordSetCount][];
1979:                }
1980:            } // End of unindexify
1981:
1982:            /**
1983:             * Generic unindexify method. Can unindex data in any of the following 
1984:             * formats Point3f, Color3f, Color4f, Vector3f, TexCoord2f, TexCoord3f, 
1985:             * TexCoord4f.
1986:             */
1987:            private Object[] unindexifyData(Object data[], int index[]) {
1988:                Object newData[] = allocateArray(data, index.length);
1989:                for (int i = 0; i < index.length; i++) {
1990:                    newData[i] = data[index[i]];
1991:                }
1992:                return newData;
1993:            } // End of unindexifyData
1994:
1995:            /**
1996:             * Calculate vertexFormat based on data.
1997:             */
1998:            private int getVertexFormat() {
1999:                int vertexFormat = GeometryArray.COORDINATES;
2000:
2001:                if (colors3 != null)
2002:                    vertexFormat |= GeometryArray.COLOR_3;
2003:                else if (colors4 != null)
2004:                    vertexFormat |= GeometryArray.COLOR_4;
2005:
2006:                if (normals != null)
2007:                    vertexFormat |= GeometryArray.NORMALS;
2008:
2009:                if (texCoordDim == 2)
2010:                    vertexFormat |= GeometryArray.TEXTURE_COORDINATE_2;
2011:                else if (texCoordDim == 3)
2012:                    vertexFormat |= GeometryArray.TEXTURE_COORDINATE_3;
2013:                else if (texCoordDim == 4)
2014:                    vertexFormat |= GeometryArray.TEXTURE_COORDINATE_4;
2015:
2016:                return vertexFormat;
2017:            } // End of getVertexFormat
2018:
2019:            /**
2020:             * Calculate vertexCount based on data
2021:             */
2022:            private int getVertexCount() {
2023:                int vertexCount = coordinates.length;
2024:
2025:                if (colors3 != null) {
2026:                    if (colors3.length > vertexCount)
2027:                        vertexCount = colors3.length;
2028:                } else if (colors4 != null) {
2029:                    if (colors4.length > vertexCount)
2030:                        vertexCount = colors4.length;
2031:                }
2032:
2033:                if (normals != null) {
2034:                    if (normals.length > vertexCount)
2035:                        vertexCount = normals.length;
2036:                }
2037:
2038:                // Find max length tex coord set
2039:                for (int i = 0; i < texCoordSetCount; i++) {
2040:                    if (texCoordSets[i].length > vertexCount)
2041:                        vertexCount = texCoordSets[i].length;
2042:                }
2043:
2044:                return vertexCount;
2045:            } // End of getVertexCount
2046:
2047:            /**
2048:             * Converts an array of Tuple2f, Tuple3f, or Tuple4f values into
2049:             * an array of floats.  Assumes array is not null.  Returns null
2050:             * if array is not Tuple2f, Tuple3f, or Tuple4f.  Used by fillIn()
2051:             * for BY_REFERENCE not INTERLEAVED geometry.
2052:             */
2053:            private float[] vecmathToFloat(Object[] ar) {
2054:                if (ar[0] instanceof  Tuple2f) {
2055:                    float[] p = new float[ar.length * 2];
2056:                    Tuple2f[] a = (Tuple2f[]) ar;
2057:                    for (int i = 0; i < ar.length; i++) {
2058:                        p[i * 2] = a[i].x;
2059:                        p[i * 2 + 1] = a[i].y;
2060:                    }
2061:                    return p;
2062:                } else if (ar[0] instanceof  Tuple3f) {
2063:                    float[] p = new float[ar.length * 3];
2064:                    Tuple3f[] a = (Tuple3f[]) ar;
2065:                    for (int i = 0; i < ar.length; i++) {
2066:                        p[i * 3] = a[i].x;
2067:                        p[i * 3 + 1] = a[i].y;
2068:                        p[i * 3 + 2] = a[i].z;
2069:                    }
2070:                    return p;
2071:                } else if (ar[0] instanceof  Tuple4f) {
2072:                    float[] p = new float[ar.length * 4];
2073:                    Tuple4f[] a = (Tuple4f[]) ar;
2074:                    for (int i = 0; i < ar.length; i++) {
2075:                        p[i * 4] = a[i].x;
2076:                        p[i * 4 + 1] = a[i].y;
2077:                        p[i * 4 + 2] = a[i].z;
2078:                        p[i * 4 + 3] = a[i].w;
2079:                    }
2080:                    return p;
2081:                }
2082:                return null;
2083:            } // End of vecmathToFloat
2084:
2085:            /**
2086:             * Fill in the GeometryArray object.  Used by getGeometryArray and
2087:             * getIndexedGeometryArray.  checkForBadData has already been called.
2088:             */
2089:            private void fillIn(GeometryArray ga, boolean byRef,
2090:                    boolean interleaved, boolean nio) {
2091:                if (interleaved) {
2092:                    // Calculate number of words per vertex
2093:                    int wpv = 3; // Always have coordinate data
2094:                    if (normals != null)
2095:                        wpv += 3;
2096:                    if (colors3 != null)
2097:                        wpv += 3;
2098:                    else if (colors4 != null)
2099:                        wpv += 4;
2100:                    wpv += (texCoordSetCount * texCoordDim);
2101:
2102:                    // Build array of interleaved data
2103:                    float[] d = new float[wpv * coordinates.length];
2104:
2105:                    // Fill in the array
2106:                    int offset = 0;
2107:                    for (int i = 0; i < coordinates.length; i++) {
2108:                        if (texCoordDim == 2) {
2109:                            for (int j = 0; j < texCoordSetCount; j++) {
2110:                                d[offset++] = ((TexCoord2f) texCoordSets[j][i]).x;
2111:                                d[offset++] = ((TexCoord2f) texCoordSets[j][i]).y;
2112:                            }
2113:                        } else if (texCoordDim == 3) {
2114:                            for (int j = 0; j < texCoordSetCount; j++) {
2115:                                d[offset++] = ((TexCoord3f) texCoordSets[j][i]).x;
2116:                                d[offset++] = ((TexCoord3f) texCoordSets[j][i]).y;
2117:                                d[offset++] = ((TexCoord3f) texCoordSets[j][i]).z;
2118:                            }
2119:                        } else if (texCoordDim == 4) {
2120:                            for (int j = 0; j < texCoordSetCount; j++) {
2121:                                d[offset++] = ((TexCoord4f) texCoordSets[j][i]).x;
2122:                                d[offset++] = ((TexCoord4f) texCoordSets[j][i]).y;
2123:                                d[offset++] = ((TexCoord4f) texCoordSets[j][i]).z;
2124:                                d[offset++] = ((TexCoord4f) texCoordSets[j][i]).w;
2125:                            }
2126:                        }
2127:
2128:                        if (colors3 != null) {
2129:                            d[offset++] = colors3[i].x;
2130:                            d[offset++] = colors3[i].y;
2131:                            d[offset++] = colors3[i].z;
2132:                        } else if (colors4 != null) {
2133:                            d[offset++] = colors4[i].x;
2134:                            d[offset++] = colors4[i].y;
2135:                            d[offset++] = colors4[i].z;
2136:                            d[offset++] = colors4[i].w;
2137:                        }
2138:
2139:                        if (normals != null) {
2140:                            d[offset++] = normals[i].x;
2141:                            d[offset++] = normals[i].y;
2142:                            d[offset++] = normals[i].z;
2143:                        }
2144:
2145:                        d[offset++] = coordinates[i].x;
2146:                        d[offset++] = coordinates[i].y;
2147:                        d[offset++] = coordinates[i].z;
2148:                    }
2149:                    // Register reference to array of interleaved data
2150:                    if (nio) {
2151:                        ByteBufferWrapper b = ByteBufferWrapper
2152:                                .allocateDirect(d.length * 4);
2153:                        FloatBufferWrapper f = b.order(
2154:                                ByteOrderWrapper.nativeOrder()).asFloatBuffer();
2155:                        f.put(d);
2156:                        ga.setInterleavedVertexBuffer(f.getJ3DBuffer());
2157:                    } else
2158:                        ga.setInterleavedVertices(d);
2159:                } else if (nio) {
2160:
2161:                    ByteBufferWrapper b = ByteBufferWrapper
2162:                            .allocateDirect(coordinates.length * 4 * 3);
2163:                    FloatBufferWrapper f = b.order(
2164:                            ByteOrderWrapper.nativeOrder()).asFloatBuffer();
2165:                    f.put(vecmathToFloat(coordinates));
2166:                    ga.setCoordRefBuffer(f.getJ3DBuffer());
2167:
2168:                    if (colors3 != null) {
2169:                        b = ByteBufferWrapper
2170:                                .allocateDirect(colors3.length * 4 * 3);
2171:                        f = b.order(ByteOrderWrapper.nativeOrder())
2172:                                .asFloatBuffer();
2173:                        f.put(vecmathToFloat(colors3));
2174:                        ga.setColorRefBuffer(f.getJ3DBuffer());
2175:                    } else if (colors4 != null) {
2176:                        b = ByteBufferWrapper
2177:                                .allocateDirect(colors4.length * 4 * 4);
2178:                        f = b.order(ByteOrderWrapper.nativeOrder())
2179:                                .asFloatBuffer();
2180:                        f.put(vecmathToFloat(colors4));
2181:                        ga.setColorRefBuffer(f.getJ3DBuffer());
2182:                    }
2183:
2184:                    if (normals != null) {
2185:                        b = ByteBufferWrapper
2186:                                .allocateDirect(normals.length * 4 * 3);
2187:                        f = b.order(ByteOrderWrapper.nativeOrder())
2188:                                .asFloatBuffer();
2189:                        f.put(vecmathToFloat(normals));
2190:                        ga.setNormalRefBuffer(f.getJ3DBuffer());
2191:                    }
2192:
2193:                    for (int i = 0; i < texCoordSetCount; i++) {
2194:                        b = ByteBufferWrapper
2195:                                .allocateDirect(texCoordSets[i].length * 4
2196:                                        * texCoordDim);
2197:                        f = b.order(ByteOrderWrapper.nativeOrder())
2198:                                .asFloatBuffer();
2199:                        f.put(vecmathToFloat(texCoordSets[i]));
2200:                        ga.setTexCoordRefBuffer(i, f.getJ3DBuffer());
2201:                    }
2202:                } else if (byRef) {
2203:                    // Need to copy the data into float arrays - GeometryArray
2204:                    // prefers them over the vecmath types
2205:                    ga.setCoordRefFloat(vecmathToFloat(coordinates));
2206:                    if (colors3 != null)
2207:                        ga.setColorRefFloat(vecmathToFloat(colors3));
2208:                    else if (colors4 != null)
2209:                        ga.setColorRefFloat(vecmathToFloat(colors4));
2210:                    if (normals != null)
2211:                        ga.setNormalRefFloat(vecmathToFloat(normals));
2212:                    for (int i = 0; i < texCoordSetCount; i++) {
2213:                        ga.setTexCoordRefFloat(i,
2214:                                vecmathToFloat(texCoordSets[i]));
2215:                    }
2216:                } else {
2217:                    ga.setCoordinates(0, coordinates);
2218:                    if (colors3 != null)
2219:                        ga.setColors(0, colors3);
2220:                    else if (colors4 != null)
2221:                        ga.setColors(0, colors4);
2222:                    if (normals != null)
2223:                        ga.setNormals(0, normals);
2224:                    for (int i = 0; i < texCoordSetCount; i++) {
2225:                        if (texCoordDim == 2) {
2226:                            ga.setTextureCoordinates(i, 0,
2227:                                    (TexCoord2f[]) texCoordSets[i]);
2228:                        } else if (texCoordDim == 3) {
2229:                            ga.setTextureCoordinates(i, 0,
2230:                                    (TexCoord3f[]) texCoordSets[i]);
2231:                        } else if (texCoordDim == 4) {
2232:                            ga.setTextureCoordinates(i, 0,
2233:                                    (TexCoord4f[]) texCoordSets[i]);
2234:                        }
2235:                    }
2236:                }
2237:
2238:                if (coordinateIndices != null) {
2239:                    IndexedGeometryArray iga = null;
2240:                    iga = (IndexedGeometryArray) ga;
2241:                    iga.setCoordinateIndices(0, coordinateIndices);
2242:                    if (!coordOnly) {
2243:                        if (colorIndices != null)
2244:                            iga.setColorIndices(0, colorIndices);
2245:                        if (normalIndices != null)
2246:                            iga.setNormalIndices(0, normalIndices);
2247:                        for (int i = 0; i < texCoordSetCount; i++)
2248:                            iga.setTextureCoordinateIndices(i, 0,
2249:                                    texCoordIndexSets[i]);
2250:                    }
2251:                }
2252:            } // End of fillIn
2253:
2254:            /**
2255:             * Redo indexes to guarantee connection information.
2256:             * Use this routine if your original data is in indexed format, but
2257:             * you don't trust that the indexing is correct.  After this 
2258:             * routine it is guaranteed that two points with the same
2259:             * position will have the same coordinate index (for example).  
2260:             * Try this if you see
2261:             * glitches in your normals or stripification, to rule out
2262:             * bad indexing as the source of the problem.  Works with normal
2263:             * indexed format or USE_COORD_INDEX_ONLY format.
2264:             * @throws IllegalArgumentException if coordinate data is missing,
2265:             * if the index lists aren't all the
2266:             * same length, if an index list is set and the corresponding data
2267:             * list isn't set, if a data list is set and the corresponding
2268:             * index list is unset (unless all index lists are unset or in
2269:             * USE_COORD_INDEX_ONLY format),
2270:             * if StripCounts or ContourCounts is inconsistent with the current
2271:             * primitive, if the sum of the contourCounts array doesn't equal
2272:             * the length of the StripCounts array, or if the number of vertices
2273:             * isn't a multiple of three (for triangles) or four (for quads).
2274:             */
2275:            public void recomputeIndices() {
2276:                boolean remember = coordOnly;
2277:
2278:                // Can make more efficient implementation later
2279:                unindexify();
2280:                indexify(remember);
2281:            } // End of recomputeIndices
2282:
2283:            /**
2284:             * Reverse the order of an array of ints (computer class homework
2285:             * problem).
2286:             */
2287:            private void reverseList(int list[]) {
2288:                int t;
2289:
2290:                if (list == null)
2291:                    return;
2292:
2293:                for (int i = 0; i < list.length / 2; i++) {
2294:                    t = list[i];
2295:                    list[i] = list[list.length - i - 1];
2296:                    list[list.length - i - 1] = t;
2297:                }
2298:            } // End of reverseList
2299:
2300:            /**
2301:             * Reverse the order of all lists.  If your polygons are formatted with 
2302:             * clockwise winding, you will always see the back and never the front.
2303:             * (Java 3D always wants vertices specified with a counter-clockwise
2304:             * winding.)
2305:             * This method will (in effect) reverse the winding of your data by
2306:             * inverting all of the index lists and the stripCounts
2307:             * and contourCounts lists.
2308:             * @throws IllegalArgumentException if coordinate data is missing,
2309:             * if the index lists aren't all the
2310:             * same length, if an index list is set and the corresponding data
2311:             * list isn't set, if a data list is set and the corresponding
2312:             * index list is unset (unless all index lists are unset or in
2313:             * USE_COORD_INDEX_ONLY format),
2314:             * if StripCounts or ContourCounts is inconsistent with the current
2315:             * primitive, if the sum of the contourCounts array doesn't equal
2316:             * the length of the StripCounts array, or if the number of vertices
2317:             * isn't a multiple of three (for triangles) or four (for quads).
2318:             */
2319:            public void reverse() {
2320:                indexify();
2321:                reverseList(stripCounts);
2322:                reverseList(oldStripCounts);
2323:                reverseList(contourCounts);
2324:                reverseList(coordinateIndices);
2325:                reverseList(colorIndices);
2326:                reverseList(normalIndices);
2327:                for (int i = 0; i < texCoordSetCount; i++)
2328:                    reverseList(texCoordIndexSets[i]);
2329:            } // End of reverse
2330:
2331:            /**
2332:             * Returns true if the data in this GeometryInfo is currently 
2333:             * formatted in the USE_COORD_INDEX_ONLY format where a single
2334:             * index list is used to index into all data lists.
2335:             * @see GeometryInfo#indexify(boolean)
2336:             * @see GeometryInfo#getIndexedGeometryArray(boolean, boolean, boolean,
2337:             * boolean, boolean)
2338:             */
2339:            public boolean getUseCoordIndexOnly() {
2340:                return coordOnly;
2341:            } // End of getUseCoordIndexOnly
2342:
2343:            /**
2344:             * Tells the GeometryInfo that its data is formatted in the
2345:             * USE_COORD_INDEX_ONLY format with a single index list
2346:             * (the coordinate index list) that indexes into all data
2347:             * lists (coordinates, normals, colors, and texture 
2348:             * coordinates).  NOTE: this will not convert the data
2349:             * for you.  This method is for when you are sending in
2350:             * data useng the setCoordinates, setNormals, setColors,
2351:             * and/or setTextureCoordinates methods, and you are only
2352:             * setting one index using setCoordinateIndices().  If
2353:             * you want GeometryInfo to convert your data to the
2354:             * USE_COORD_INDEX_ONLY format, use indexify(true) or
2355:             * getIndexedGeometryArray with the useCoordIndexOnly
2356:             * parameter set to true.
2357:             * @see GeometryInfo#indexify(boolean)
2358:             * @see GeometryInfo#getIndexedGeometryArray(boolean, boolean, boolean,
2359:             * boolean, boolean)
2360:             */
2361:            public void setUseCoordIndexOnly(boolean useCoordIndexOnly) {
2362:                coordOnly = useCoordIndexOnly;
2363:            } // End of setUseCoordIndexOnly
2364:
2365:            /**
2366:             * Creates and returns a non-indexed Java 3D GeometryArray object
2367:             * based on the data in the GeometryInfo object.  This object is
2368:             * suitable to be attached to a Shape3D node for rendering.
2369:             * @param byRef Use geometry BY_REFERENCE
2370:             * @param interleaved Use INTERLEAVED geometry.  Implies byRef is
2371:             * true as well.
2372:             * @param nio Create GeometryArray using java.nio.Buffer for
2373:             * geometry arrays.  Only usable on JDK 1.4 or higher.  Implies
2374:             * byRef is true as well.
2375:             * @throws IllegalArgumentException if coordinate data is missing,
2376:             * if the index lists aren't all the
2377:             * same length, if an index list is set and the corresponding data
2378:             * list isn't set, if a data list is set and the corresponding
2379:             * index list is unset (unless all index lists are unset or in
2380:             * USE_COORD_INDEX_ONLY format),
2381:             * if StripCounts or ContourCounts is inconsistent with the current
2382:             * primitive, if the sum of the contourCounts array doesn't equal
2383:             * the length of the StripCounts array, or if the number of vertices
2384:             * isn't a multiple of three (for triangles) or four (for quads).
2385:             */
2386:            public GeometryArray getGeometryArray(boolean byRef,
2387:                    boolean interleaved, boolean nio) {
2388:                checkForBadData();
2389:
2390:                if (prim == POLYGON_ARRAY) {
2391:                    if (tr == null)
2392:                        tr = new Triangulator();
2393:                    tr.triangulate(this );
2394:                } else
2395:                    changeBackToOldPrim();
2396:
2397:                unindexify();
2398:
2399:                int vertexFormat = getVertexFormat();
2400:                if (nio)
2401:                    vertexFormat |= (GeometryArray.BY_REFERENCE | GeometryArray.USE_NIO_BUFFER);
2402:                if (interleaved)
2403:                    vertexFormat |= (GeometryArray.BY_REFERENCE | GeometryArray.INTERLEAVED);
2404:                if (byRef)
2405:                    vertexFormat |= GeometryArray.BY_REFERENCE;
2406:
2407:                int vertexCount = coordinates.length;
2408:
2409:                // If the texCoordSetMap hasn't been set, assume one set of 
2410:                // texture coordinates only and one texture state unit 
2411:                if ((texCoordSetCount > 0) && (texCoordSetMap == null)) {
2412:                    texCoordSetCount = 1;
2413:                    texCoordSetMap = new int[1];
2414:                    texCoordSetMap[0] = 0;
2415:                }
2416:
2417:                // Create the GeometryArray object
2418:                GeometryArray ga = null;
2419:                switch (prim) {
2420:                case TRIANGLE_ARRAY:
2421:                    TriangleArray ta = new TriangleArray(vertexCount,
2422:                            vertexFormat, texCoordSetCount, texCoordSetMap);
2423:                    ga = (GeometryArray) ta;
2424:                    break;
2425:
2426:                case QUAD_ARRAY:
2427:                    QuadArray qa = new QuadArray(vertexCount, vertexFormat,
2428:                            texCoordSetCount, texCoordSetMap);
2429:                    ga = (GeometryArray) qa;
2430:                    break;
2431:
2432:                case TRIANGLE_STRIP_ARRAY:
2433:                    TriangleStripArray tsa = new TriangleStripArray(
2434:                            vertexCount, vertexFormat, texCoordSetCount,
2435:                            texCoordSetMap, stripCounts);
2436:                    ga = (GeometryArray) tsa;
2437:                    break;
2438:
2439:                case TRIANGLE_FAN_ARRAY:
2440:                    TriangleFanArray tfa = new TriangleFanArray(vertexCount,
2441:                            vertexFormat, texCoordSetCount, texCoordSetMap,
2442:                            stripCounts);
2443:                    ga = (GeometryArray) tfa;
2444:                    break;
2445:                }
2446:
2447:                fillIn(ga, byRef, interleaved, nio);
2448:
2449:                return ga;
2450:            } // End of getGeometryArray(int, int)
2451:
2452:            /**
2453:             * Creates and returns a non-indexed Java 3D GeometryArray object
2454:             * based on the data in the GeometryInfo object.  This object is
2455:             * suitable to be attached to a Shape3D node for rendering.
2456:             * The geometry is <b>not</b> created using data BY_REFERENCE,
2457:             * INTERLEAVED, or USE_NIO_BUFFER.
2458:             * @throws IllegalArgumentException if coordinate data is missing,
2459:             * if the index lists aren't all the
2460:             * same length, if an index list is set and the corresponding data
2461:             * list isn't set, if a data list is set and the corresponding
2462:             * index list is unset (unless all index lists are unset or in
2463:             * USE_COORD_INDEX_ONLY format),
2464:             * if StripCounts or ContourCounts is inconsistent with the current
2465:             * primitive, if the sum of the contourCounts array doesn't equal
2466:             * the length of the StripCounts array, or if the number of vertices
2467:             * isn't a multiple of three (for triangles) or four (for quads).
2468:             */
2469:            public GeometryArray getGeometryArray() {
2470:                return getGeometryArray(false, false, false);
2471:            } // End of getGeometryArray()
2472:
2473:            /**
2474:             * Creates and returns a IndexedGeometryArray
2475:             * based on the data in the GeometryInfo object.  This object is
2476:             * suitable to be attached to a Shape3D node for rendering.
2477:             * @param compact Remove Coordinates, Colors, Normals, and 
2478:             * TextureCoordinates that aren't referenced by any indices.
2479:             * @param byRef Create the IndexedGeometryArray using geometry
2480:             * BY_REFERENCE.
2481:             * @param interleaved Use INTERLEAVED geometry.  Implies byRef is
2482:             * true as well.
2483:             * @param nio Create GeometryArray using java.nio.Buffer for
2484:             * geometry arrays.  Only usable on JDK 1.4 or higher.  Implies
2485:             * byRef is true as well.
2486:             * @param useCoordIndexOnly Create the IndexedGeometryArray using
2487:             * USE_COORD_INDEX_ONLY.  Values from the coordinate index array
2488:             * are used as a single set of indices into all vertex 
2489:             * component arrays (coord, color, normal, and texCoord).
2490:             * @throws IllegalArgumentException if coordinate data is missing,
2491:             * if the index lists aren't all the
2492:             * same length, if an index list is set and the corresponding data
2493:             * list isn't set, if a data list is set and the corresponding
2494:             * index list is unset (unless all index lists are unset or in
2495:             * USE_COORD_INDEX_ONLY format),
2496:             * if StripCounts or ContourCounts is inconsistent with the current
2497:             * primitive, if the sum of the contourCounts array doesn't equal
2498:             * the length of the StripCounts array, or if the number of vertices
2499:             * isn't a multiple of three (for triangles) or four (for quads).
2500:             */
2501:            public IndexedGeometryArray getIndexedGeometryArray(
2502:                    boolean compact, boolean byRef, boolean interleaved,
2503:                    boolean useCoordIndexOnly, boolean nio) {
2504:                indexify(useCoordIndexOnly);
2505:
2506:                if (compact)
2507:                    compact();
2508:
2509:                if (prim == POLYGON_ARRAY) {
2510:                    if (tr == null)
2511:                        tr = new Triangulator();
2512:                    tr.triangulate(this );
2513:                } else
2514:                    changeBackToOldPrim();
2515:
2516:                if (useCoordIndexOnly && coordOnly == false) {
2517:                    // Check to see if we can optimize for USE_COORD_INDEX_ONLY
2518:                    int i, j;
2519:                    boolean canUseCoordIndexOnly = true;
2520:
2521:                    if (coordinateIndices != null) {
2522:                        // See if all the array lengths are the same
2523:                        if (colorIndices != null
2524:                                && colorIndices.length != coordinateIndices.length) {
2525:                            canUseCoordIndexOnly = false;
2526:                        }
2527:                        if (normalIndices != null
2528:                                && normalIndices.length != coordinateIndices.length) {
2529:                            canUseCoordIndexOnly = false;
2530:                        }
2531:                        for (i = 0; i < texCoordSetCount; i++) {
2532:                            if (texCoordIndexSets[i] != null
2533:                                    && texCoordIndexSets[i].length != coordinateIndices.length) {
2534:                                canUseCoordIndexOnly = false;
2535:                                break;
2536:                            }
2537:                        }
2538:                        if (canUseCoordIndexOnly
2539:                                && ((colorIndices != null)
2540:                                        || (normalIndices != null) || (texCoordSetCount > 0))) {
2541:                            // All array lengths are the same.  Check their contents
2542:
2543:                            for (i = 0; i < coordinateIndices.length; i++) {
2544:                                int indexValue = coordinateIndices[i];
2545:
2546:                                if (colorIndices != null
2547:                                        && colorIndices[i] != indexValue) {
2548:                                    canUseCoordIndexOnly = false;
2549:                                    break;
2550:                                }
2551:                                if (normalIndices != null
2552:                                        && normalIndices[i] != indexValue) {
2553:                                    canUseCoordIndexOnly = false;
2554:                                    break;
2555:                                }
2556:                                for (j = 0; j < texCoordSetCount; j++) {
2557:                                    if (texCoordIndexSets[j] != null
2558:                                            && texCoordIndexSets[j][i] != indexValue) {
2559:                                        canUseCoordIndexOnly = false;
2560:                                        break;
2561:                                    }
2562:                                }
2563:                            }
2564:                        }
2565:                    }
2566:                    coordOnly = canUseCoordIndexOnly;
2567:                }
2568:
2569:                int vertexFormat = getVertexFormat();
2570:                if (nio)
2571:                    vertexFormat |= (GeometryArray.BY_REFERENCE | GeometryArray.USE_NIO_BUFFER);
2572:                if (interleaved)
2573:                    vertexFormat |= (GeometryArray.BY_REFERENCE | GeometryArray.INTERLEAVED);
2574:                if (byRef)
2575:                    vertexFormat |= GeometryArray.BY_REFERENCE;
2576:                if (coordOnly)
2577:                    vertexFormat |= GeometryArray.USE_COORD_INDEX_ONLY;
2578:
2579:                int vertexCount = getVertexCount();
2580:
2581:                if ((texCoordSetCount > 0) && (texCoordSetMap == null)) {
2582:                    texCoordSetCount = 1;
2583:                    texCoordSetMap = new int[1];
2584:                    texCoordSetMap[0] = 0;
2585:                }
2586:
2587:                //
2588:                // Create the IndexedGeometryArray object
2589:                //
2590:
2591:                IndexedGeometryArray ga = null;
2592:
2593:                switch (prim) {
2594:                case TRIANGLE_ARRAY:
2595:                    IndexedTriangleArray ta = new IndexedTriangleArray(
2596:                            vertexCount, vertexFormat, texCoordSetCount,
2597:                            texCoordSetMap, coordinateIndices.length);
2598:                    ga = (IndexedGeometryArray) ta;
2599:                    break;
2600:
2601:                case QUAD_ARRAY:
2602:                    IndexedQuadArray qa = new IndexedQuadArray(vertexCount,
2603:                            vertexFormat, texCoordSetCount, texCoordSetMap,
2604:                            coordinateIndices.length);
2605:                    ga = (IndexedGeometryArray) qa;
2606:                    break;
2607:                case TRIANGLE_STRIP_ARRAY:
2608:                    IndexedTriangleStripArray tsa = new IndexedTriangleStripArray(
2609:                            vertexCount, vertexFormat, texCoordSetCount,
2610:                            texCoordSetMap, coordinateIndices.length,
2611:                            stripCounts);
2612:                    ga = (IndexedGeometryArray) tsa;
2613:                    break;
2614:
2615:                case TRIANGLE_FAN_ARRAY:
2616:                    IndexedTriangleFanArray tfa = new IndexedTriangleFanArray(
2617:                            vertexCount, vertexFormat, texCoordSetCount,
2618:                            texCoordSetMap, coordinateIndices.length,
2619:                            stripCounts);
2620:                    ga = (IndexedGeometryArray) tfa;
2621:                    break;
2622:                }
2623:
2624:                // Fill in the GeometryArray object
2625:                fillIn(ga, byRef, interleaved, nio);
2626:
2627:                return ga;
2628:            } // End of getIndexedGeometryArray(bool, bool, bool, bool, bool)
2629:
2630:            /**
2631:             * Creates and returns an IndexedGeometryArray
2632:             * based on the data in the GeometryInfo object.  This object is
2633:             * suitable to be attached to a Shape3D node for rendering.
2634:             * Equivalent to <code>getIndexedGeometryArray(compact, false, 
2635:             * false, false, false)</code>.
2636:             * @param compact Remove Coordinates, Colors, Normals, and 
2637:             * TextureCoordinates that aren't referenced by any indices.
2638:             * @throws IllegalArgumentException if coordinate data is missing,
2639:             * if the index lists aren't all the
2640:             * same length, if an index list is set and the corresponding data
2641:             * list isn't set, if a data list is set and the corresponding
2642:             * index list is unset (unless all index lists are unset or in
2643:             * USE_COORD_INDEX_ONLY format),
2644:             * if StripCounts or ContourCounts is inconsistent with the current
2645:             * primitive, if the sum of the contourCounts array doesn't equal
2646:             * the length of the StripCounts array, or if the number of vertices
2647:             * isn't a multiple of three (for triangles) or four (for quads).
2648:             */
2649:            public IndexedGeometryArray getIndexedGeometryArray(boolean compact) {
2650:                return getIndexedGeometryArray(compact, false, false, false,
2651:                        false);
2652:            } // End of getIndexedGeometryArray(boolean)
2653:
2654:            /**
2655:             * Creates and returns an IndexedGeometryArray
2656:             * based on the data in the GeometryInfo object.  This object is
2657:             * suitable to be attached to a Shape3D node for rendering.
2658:             * Equivalent to <code>getIndexedGeometryArray(false, false, 
2659:             * false, false, false)</code>.
2660:             * @throws IllegalArgumentException if coordinate data is missing,
2661:             * if the index lists aren't all the
2662:             * same length, if an index list is set and the corresponding data
2663:             * list isn't set, if a data list is set and the corresponding
2664:             * index list is unset (unless all index lists are unset or in
2665:             * USE_COORD_INDEX_ONLY format),
2666:             * if StripCounts or ContourCounts is inconsistent with the current
2667:             * primitive, if the sum of the contourCounts array doesn't equal
2668:             * the length of the StripCounts array, or if the number of vertices
2669:             * isn't a multiple of three (for triangles) or four (for quads).
2670:             */
2671:            public IndexedGeometryArray getIndexedGeometryArray() {
2672:                return getIndexedGeometryArray(false, false, false, false,
2673:                        false);
2674:            } // End of getIndexedGeometryArray()
2675:
2676:        } // End of class GeometryInfo
2677:
2678:        // End of file GeometryInfo.java
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.