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


0001:        /*
0002:         * $RCSfile: CompressionStream.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.5 $
0041:         * $Date: 2007/02/09 17:20:16 $
0042:         * $State: Exp $
0043:         */
0044:
0045:        package com.sun.j3d.utils.compression;
0046:
0047:        import com.sun.j3d.internal.BufferWrapper;
0048:        import com.sun.j3d.internal.ByteBufferWrapper;
0049:        import com.sun.j3d.internal.DoubleBufferWrapper;
0050:        import com.sun.j3d.internal.FloatBufferWrapper;
0051:        import com.sun.j3d.utils.geometry.GeometryInfo;
0052:        import java.util.Collection;
0053:        import java.util.Iterator;
0054:        import java.util.LinkedList;
0055:        import javax.media.j3d.Appearance;
0056:        import javax.media.j3d.CompressedGeometryHeader;
0057:        import javax.media.j3d.Geometry;
0058:        import javax.media.j3d.GeometryArray;
0059:        import javax.media.j3d.GeometryStripArray;
0060:        import javax.media.j3d.IndexedGeometryArray;
0061:        import javax.media.j3d.IndexedGeometryStripArray;
0062:        import javax.media.j3d.IndexedLineArray;
0063:        import javax.media.j3d.IndexedLineStripArray;
0064:        import javax.media.j3d.IndexedQuadArray;
0065:        import javax.media.j3d.IndexedTriangleArray;
0066:        import javax.media.j3d.IndexedTriangleFanArray;
0067:        import javax.media.j3d.IndexedTriangleStripArray;
0068:        import javax.media.j3d.J3DBuffer;
0069:        import javax.media.j3d.LineArray;
0070:        import javax.media.j3d.LineStripArray;
0071:        import javax.media.j3d.Material;
0072:        import javax.media.j3d.QuadArray;
0073:        import javax.media.j3d.Shape3D;
0074:        import javax.media.j3d.TriangleArray;
0075:        import javax.media.j3d.TriangleFanArray;
0076:        import javax.media.j3d.TriangleStripArray;
0077:        import javax.vecmath.Color3f;
0078:        import javax.vecmath.Color4f;
0079:        import javax.vecmath.Point3d;
0080:        import javax.vecmath.Point3f;
0081:        import javax.vecmath.Point3i;
0082:        import javax.vecmath.Vector3f;
0083:
0084:        /**
0085:         * This class is used as input to a geometry compressor.  It collects elements
0086:         * such as vertices, normals, colors, mesh references, and quantization
0087:         * parameters in an ordered stream.  This stream is then traversed during
0088:         * the compression process and used to build the compressed output buffer.
0089:         *
0090:         * @see GeometryCompressor
0091:         *
0092:         * @deprecated As of Java 3D 1.5, replaced by
0093:         * com.sun.j3d.utils.geometry.compression.{@link com.sun.j3d.utils.geometry.compression.CompressionStream}.
0094:         */
0095:        public class CompressionStream {
0096:            //
0097:            // NOTE: For now, copies are made of all GeometryArray vertex components
0098:            // even when by-reference access is available.
0099:            //
0100:            // TODO: Retrofit all CompressionStreamElements and MeshBuffer to handle
0101:            // offsets to vertex data array references so that vertex components don't
0102:            // have to be copied.  New CompressionStreamElements could be defined to
0103:            // set the current array reference during the quantization pass, or the
0104:            // reference could be included in every CompressionStreamElement along
0105:            // with the data offsets.
0106:            //
0107:            // TODO: Quantize on-the-fly when adding GeometryArray vertex data so that
0108:            // CompressionStreamElements don't need references to the original float,
0109:            // double, or byte data.  Quantization is currently a separate pass since
0110:            // the 1st pass adds vertex data and gets the total object bounds, but
0111:            // this can be computed by merging the bounds of each GeometryArray
0112:            // compressed into a single object.  The 2nd pass quantization is still
0113:            // needed for vertex data which isn't retrieved from a GeometryArray; for
0114:            // example, apps that might use the addVertex() methods directly instead
0115:            // of addGeometryArray().
0116:            //
0117:            // TODO: To further optimize memory, create new subclasses of
0118:            // CompressionStream{Color, Normal} for bundled attributes and add them as
0119:            // explicit stream elements.  Then CompressionStreamVertex won't need to
0120:            // carry references to them.  This memory savings might be negated by the
0121:            // extra overhead of adding more elements to the stream, however.
0122:            //
0123:            // TODO: Keep the absolute quantized values in the mesh buffer mirror so
0124:            // that unmeshed CompressionStreamElements don't need to carry them.
0125:            //
0126:            // TODO: Support texture coordinate compression even though Level II is
0127:            // not supported by any hardware decompressor on any graphics card.
0128:            // Software decompression is still useful for applications interested in
0129:            // minimizing file space, transmission time, and object loading time.
0130:            //
0131:            private static final boolean debug = false;
0132:            private static final boolean benchmark = false;
0133:
0134:            // Mesh buffer normal substitution is unavailable in Level I.
0135:            private static final boolean noMeshNormalSubstitution = true;
0136:
0137:            /**
0138:             * This flag indicates that a vertex starts a new triangle or line strip.
0139:             */
0140:            static final int RESTART = 1;
0141:
0142:            /**
0143:             * This flag indicates that the next triangle in the strip is defined by
0144:             * replacing the middle vertex of the previous triangle in the strip.
0145:             * Equivalent to REPLACE_OLDEST for line strips.
0146:             */
0147:            static final int REPLACE_MIDDLE = 2;
0148:
0149:            /**
0150:             * This flag indicates that the next triangle in the strip is defined by
0151:             * replacing the oldest vertex of the previous triangle in the strip.
0152:             * Equivalent to REPLACE_MIDDLE for line strips.
0153:             */
0154:            static final int REPLACE_OLDEST = 3;
0155:
0156:            /**
0157:             * This flag indicates that a vertex is to be pushed into the mesh buffer.
0158:             */
0159:            static final int MESH_PUSH = 1;
0160:
0161:            /**
0162:             * This flag indicates that a vertex does not use the mesh buffer.
0163:             */
0164:            static final int NO_MESH_PUSH = 0;
0165:
0166:            /**
0167:             * Byte to float scale factor for scaling byte color components.
0168:             */
0169:            static final float ByteToFloatScale = 1.0f / 255.0f;
0170:
0171:            /**
0172:             * Type of this stream, either CompressedGeometryHeader.POINT_BUFFER,
0173:             * CompressedGeometryHeader.LINE_BUFFER, or
0174:             * CompressedGeometryHeader.TRIANGLE_BUFFER
0175:             */
0176:            int streamType;
0177:
0178:            /**
0179:             * A mask indicating which components are present in each vertex, as
0180:             * defined by GeometryArray.
0181:             */
0182:            int vertexComponents;
0183:
0184:            /**
0185:             * Boolean indicating colors are bundled with the vertices.
0186:             */
0187:            boolean vertexColors;
0188:
0189:            /**
0190:             * Boolean indicating RGB colors are bundled with the vertices.
0191:             */
0192:            boolean vertexColor3;
0193:
0194:            /**
0195:             * Boolean indicating RGBA colors are bundled with the vertices.
0196:             */
0197:            boolean vertexColor4;
0198:
0199:            /**
0200:             * Boolean indicating normals are bundled with the vertices.
0201:             */
0202:            boolean vertexNormals;
0203:
0204:            /**
0205:             * Boolean indicating texture coordinates are present.
0206:             */
0207:            boolean vertexTextures;
0208:
0209:            /**
0210:             * Boolean indicating that 2D texture coordinates are used.
0211:             * Currently only used to skip over textures in interleaved data.
0212:             */
0213:            boolean vertexTexture2;
0214:
0215:            /**
0216:             * Boolean indicating that 3D texture coordinates are used.
0217:             * Currently only used to skip over textures in interleaved data.
0218:             */
0219:            boolean vertexTexture3;
0220:
0221:            /**
0222:             * Boolean indicating that 4D texture coordinates are used.
0223:             * Currently only used to skip over textures in interleaved data.
0224:             */
0225:            boolean vertexTexture4;
0226:
0227:            /**
0228:             * Axes-aligned box enclosing all vertices in model coordinates.
0229:             */
0230:            Point3d mcBounds[] = new Point3d[2];
0231:
0232:            /**
0233:             * Axes-aligned box enclosing all vertices in normalized coordinates.
0234:             */
0235:            Point3d ncBounds[] = new Point3d[2];
0236:
0237:            /**
0238:             * Axes-aligned box enclosing all vertices in quantized coordinates.
0239:             */
0240:            Point3i qcBounds[] = new Point3i[2];
0241:
0242:            /**
0243:             * Center for normalizing positions to the unit cube.
0244:             */
0245:            double center[] = new double[3];
0246:
0247:            /**
0248:             * Maximum position range along the 3 axes.
0249:             */
0250:            double positionRangeMaximum;
0251:
0252:            /**
0253:             * Scale for normalizing positions to the unit cube.
0254:             */
0255:            double scale;
0256:
0257:            /**
0258:             * Current position component (X, Y, and Z) quantization value.  This can
0259:             * range from 1 to 16 bits and has a default of 16.<p>
0260:             *
0261:             * At 1 bit of quantization it is not possible to express positive
0262:             * absolute or delta positions.
0263:             */
0264:            int positionQuant;
0265:
0266:            /**
0267:             * Current color component (R, G, B, A) quantization value.  This can
0268:             * range from 2 to 16 bits and has a default of 9.<p>
0269:             *
0270:             * A color component is represented with a signed fixed-point value in
0271:             * order to be able express negative deltas; the default of 9 bits
0272:             * corresponds to the 8-bit color component range of the graphics hardware
0273:             * commonly available.  Colors must be non-negative, so the lower limit of
0274:             * quantization is 2 bits.
0275:             */
0276:            int colorQuant;
0277:
0278:            /**
0279:             * Current normal component (U and V) quantization value.  This can range
0280:             * from 0 to 6 bits and has a default of 6.<p>
0281:             *
0282:             * At 0 bits of quantization normals are represented only as 6 bit
0283:             * sextant/octant pairs and 14 specially encoded normals (the 6 axis
0284:             * normals and the 8 octant midpoint normals); since U and V can only be 0
0285:             * at the minimum quantization, the totally number of unique normals is 
0286:             * 12 + 14 = 26.
0287:             */
0288:            int normalQuant;
0289:
0290:            /**
0291:             * Flag indicating position quantization change.
0292:             */
0293:            boolean positionQuantChanged;
0294:
0295:            /**
0296:             * Flag indicating color quantization change.
0297:             */
0298:            boolean colorQuantChanged;
0299:
0300:            /**
0301:             * Flag indicating normal quantization change.
0302:             */
0303:            boolean normalQuantChanged;
0304:
0305:            /**
0306:             * Last quantized position.
0307:             */
0308:            int lastPosition[] = new int[3];
0309:
0310:            /**
0311:             * Last quantized color.
0312:             */
0313:            int lastColor[] = new int[4];
0314:
0315:            /**
0316:             * Last quantized normal's sextant.
0317:             */
0318:            int lastSextant;
0319:
0320:            /**
0321:             * Last quantized normal's octant.
0322:             */
0323:            int lastOctant;
0324:
0325:            /**
0326:             * Last quantized normal's U encoding parameter.
0327:             */
0328:            int lastU;
0329:
0330:            /**
0331:             * Last quantized normal's V encoding parameter.
0332:             */
0333:            int lastV;
0334:
0335:            /**
0336:             * Flag indicating last normal used a special encoding.
0337:             */
0338:            boolean lastSpecialNormal;
0339:
0340:            /**
0341:             * Flag indicating the first position in this stream.
0342:             */
0343:            boolean firstPosition;
0344:
0345:            /**
0346:             * Flag indicating the first color in this stream.
0347:             */
0348:            boolean firstColor;
0349:
0350:            /**
0351:             * Flag indicating the first normal in this stream.
0352:             */
0353:            boolean firstNormal;
0354:
0355:            /**
0356:             * The total number of bytes used to create the uncompressed geometric
0357:             * elements in this stream, useful for performance analysis.  This
0358:             * excludes mesh buffer references.
0359:             */
0360:            int byteCount;
0361:
0362:            /**
0363:             * The number of vertices created for this stream, excluding mesh buffer
0364:             * references.
0365:             */
0366:            int vertexCount;
0367:
0368:            /**
0369:             * The number of mesh buffer references created for this stream.
0370:             */
0371:            int meshReferenceCount;
0372:
0373:            /**
0374:             * Mesh buffer mirror used for computing deltas during quantization pass
0375:             * and a limited meshing algorithm for unstripped data.
0376:             */
0377:            MeshBuffer meshBuffer = new MeshBuffer();
0378:
0379:            // Collection which holds the elements of this stream.
0380:            private Collection stream;
0381:
0382:            // True if preceding stream elements were colors or normals.  Used to flag
0383:            // color and normal mesh buffer substitution when computing deltas during
0384:            // quantization pass.
0385:            private boolean lastElementColor = false;
0386:            private boolean lastLastElementColor = false;
0387:            private boolean lastElementNormal = false;
0388:            private boolean lastLastElementNormal = false;
0389:
0390:            // Some convenient temporary holding variables.
0391:            private Point3f p3f = new Point3f();
0392:            private Color3f c3f = new Color3f();
0393:            private Color4f c4f = new Color4f();
0394:            private Vector3f n3f = new Vector3f();
0395:
0396:            // Private constructor for common initializations.
0397:            private CompressionStream() {
0398:                this .stream = new LinkedList();
0399:
0400:                byteCount = 0;
0401:                vertexCount = 0;
0402:                meshReferenceCount = 0;
0403:
0404:                mcBounds[0] = new Point3d(Double.POSITIVE_INFINITY,
0405:                        Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY);
0406:                mcBounds[1] = new Point3d(Double.NEGATIVE_INFINITY,
0407:                        Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY);
0408:
0409:                qcBounds[0] = new Point3i(Integer.MAX_VALUE, Integer.MAX_VALUE,
0410:                        Integer.MAX_VALUE);
0411:                qcBounds[1] = new Point3i(Integer.MIN_VALUE, Integer.MIN_VALUE,
0412:                        Integer.MIN_VALUE);
0413:
0414:                /* normalized bounds computed from quantized bounds */
0415:                ncBounds[0] = new Point3d();
0416:                ncBounds[1] = new Point3d();
0417:            }
0418:
0419:            /**
0420:             * Creates a new CompressionStream for the specified geometry type and
0421:             * vertex format.<p>
0422:             *
0423:             * @param streamType type of data in this stream, either
0424:             * CompressedGeometryHeader.POINT_BUFFER,
0425:             * CompressedGeometryHeader.LINE_BUFFER, or
0426:             * CompressedGeometryHeader.TRIANGLE_BUFFER
0427:             *
0428:             * @param vertexComponents a mask indicating which components are present
0429:             * in each vertex, as defined by GeometryArray: COORDINATES, NORMALS, and
0430:             * COLOR_3 or COLOR_4.
0431:             *
0432:             * @see GeometryCompressor
0433:             * @see GeometryArray
0434:             */
0435:            CompressionStream(int streamType, int vertexComponents) {
0436:                this ();
0437:                this .streamType = streamType;
0438:                this .vertexComponents = getVertexComponents(vertexComponents);
0439:            }
0440:
0441:            // See what vertex geometry components are present.  The byReference,
0442:            // interleaved, useNIOBuffer, and useCoordIndexOnly flags are not
0443:            // examined.
0444:            private int getVertexComponents(int vertexFormat) {
0445:                int components = 0;
0446:
0447:                vertexColors = vertexColor3 = vertexColor4 = vertexNormals = vertexTextures = vertexTexture2 = vertexTexture3 = vertexTexture4 = false;
0448:
0449:                if ((vertexFormat & GeometryArray.NORMALS) != 0) {
0450:                    vertexNormals = true;
0451:                    components &= GeometryArray.NORMALS;
0452:                    if (debug)
0453:                        System.out.println("vertexNormals");
0454:                }
0455:
0456:                if ((vertexFormat & GeometryArray.COLOR_3) != 0) {
0457:                    vertexColors = true;
0458:
0459:                    if ((vertexFormat & GeometryArray.COLOR_4) != 0) {
0460:                        vertexColor4 = true;
0461:                        components &= GeometryArray.COLOR_4;
0462:                        if (debug)
0463:                            System.out.println("vertexColor4");
0464:                    } else {
0465:                        vertexColor3 = true;
0466:                        components &= GeometryArray.COLOR_3;
0467:                        if (debug)
0468:                            System.out.println("vertexColor3");
0469:                    }
0470:                }
0471:
0472:                if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_2) != 0) {
0473:                    vertexTextures = true;
0474:                    vertexTexture2 = true;
0475:                    components &= GeometryArray.TEXTURE_COORDINATE_2;
0476:                    if (debug)
0477:                        System.out.println("vertexTexture2");
0478:                } else if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0) {
0479:                    vertexTextures = true;
0480:                    vertexTexture3 = true;
0481:                    components &= GeometryArray.TEXTURE_COORDINATE_3;
0482:                    if (debug)
0483:                        System.out.println("vertexTexture3");
0484:                } else if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_4) != 0) {
0485:                    vertexTextures = true;
0486:                    vertexTexture4 = true;
0487:                    components &= GeometryArray.TEXTURE_COORDINATE_4;
0488:                    if (debug)
0489:                        System.out.println("vertexTexture4");
0490:                }
0491:
0492:                if (vertexTextures)
0493:                    // Throw exception for now until texture is supported.
0494:                    throw new UnsupportedOperationException(
0495:                            "\ncompression of texture coordinates is not supported");
0496:
0497:                return components;
0498:            }
0499:
0500:            // Get the streamType associated with a GeometryArray instance.
0501:            private int getStreamType(GeometryArray ga) {
0502:                if (ga instanceof  TriangleStripArray
0503:                        || ga instanceof  IndexedTriangleStripArray
0504:                        || ga instanceof  TriangleFanArray
0505:                        || ga instanceof  IndexedTriangleFanArray
0506:                        || ga instanceof  TriangleArray
0507:                        || ga instanceof  IndexedTriangleArray
0508:                        || ga instanceof  QuadArray
0509:                        || ga instanceof  IndexedQuadArray)
0510:
0511:                    return CompressedGeometryHeader.TRIANGLE_BUFFER;
0512:
0513:                else if (ga instanceof  LineArray
0514:                        || ga instanceof  IndexedLineArray
0515:                        || ga instanceof  LineStripArray
0516:                        || ga instanceof  IndexedLineStripArray)
0517:
0518:                    return CompressedGeometryHeader.LINE_BUFFER;
0519:
0520:                else
0521:                    return CompressedGeometryHeader.POINT_BUFFER;
0522:            }
0523:
0524:            /**
0525:             * Iterates across all compression stream elements and applies
0526:             * quantization parameters, encoding consecutive vertices as delta values
0527:             * whenever possible.  Each geometric element is mapped to a HuffmanNode
0528:             * object containing its resulting bit length, right shift (trailing 0
0529:             * count), and absolute or relative status.<p>
0530:             * 
0531:             * Positions are normalized to span a unit cube via an offset and a
0532:             * uniform scale factor that maps the midpoint of the object extents along
0533:             * each dimension to the origin, and the longest dimension of the object to
0534:             * the open interval (-1.0 .. +1.0).  The geometric endpoints along that
0535:             * dimension are both one quantum away from unity; for example, at a
0536:             * position quantization of 6 bits, an object would be normalized so that
0537:             * its most negative dimension is at (-1 + 1/64) and the most positive is
0538:             * at (1 - 1/64).<p>
0539:             * 
0540:             * Normals are assumed to be of unit length.  Color components are clamped
0541:             * to the [0..1) range, where the right endpoint is one quantum less
0542:             * than 1.0.<p>
0543:             *
0544:             * @param huffmanTable Table which will map geometric compression stream
0545:             * elements to HuffmanNode objects describing each element's data
0546:             * representation.  This table can then be processed with Huffman's
0547:             * algorithm to optimize the bit length of descriptor tags according to
0548:             * the number of geometric elements mapped to each tag.
0549:             */
0550:            void quantize(HuffmanTable huffmanTable) {
0551:                // Set up default initial quantization parameters.  The position and
0552:                // color parameters specify the number of bits for each X, Y, Z, R, G,
0553:                // B, or A component.  The normal quantization parameter specifies the
0554:                // number of bits for each U and V component.
0555:                positionQuant = 16;
0556:                colorQuant = 9;
0557:                normalQuant = 6;
0558:
0559:                // Compute position center and scaling for normalization to the unit
0560:                // cube.  This is a volume bounded by the open intervals (-1..1) on
0561:                // each axis.
0562:                center[0] = (mcBounds[1].x + mcBounds[0].x) / 2.0;
0563:                center[1] = (mcBounds[1].y + mcBounds[0].y) / 2.0;
0564:                center[2] = (mcBounds[1].z + mcBounds[0].z) / 2.0;
0565:
0566:                double xRange = mcBounds[1].x - mcBounds[0].x;
0567:                double yRange = mcBounds[1].y - mcBounds[0].y;
0568:                double zRange = mcBounds[1].z - mcBounds[0].z;
0569:
0570:                if (xRange > yRange)
0571:                    positionRangeMaximum = xRange;
0572:                else
0573:                    positionRangeMaximum = yRange;
0574:
0575:                if (zRange > positionRangeMaximum)
0576:                    positionRangeMaximum = zRange;
0577:
0578:                // Adjust the range of the unit cube to match the default
0579:                // quantization.
0580:                //
0581:                // This scale factor along with the center values computed above will
0582:                // produce 16-bit integer representations of the floating point
0583:                // position coordinates ranging symmetrically about 0 from -32767 to
0584:                // +32767.  -32768 is not used and the normalized floating point
0585:                // position coordinates of -1.0 as well as +1.0 will not be
0586:                // represented.
0587:                //
0588:                // Applications which wish to seamlessly stitch together compressed
0589:                // objects will need to be aware that the range of normalized
0590:                // positions will be one quantum away from the [-1..1] endpoints of
0591:                // the unit cube and should adjust scale factors accordingly.
0592:                scale = (2.0 / positionRangeMaximum) * (32767.0 / 32768.0);
0593:
0594:                // Flag quantization change.
0595:                positionQuantChanged = colorQuantChanged = normalQuantChanged = true;
0596:
0597:                // Flag first position, color, and normal.
0598:                firstPosition = firstColor = firstNormal = true;
0599:
0600:                // Apply quantization.
0601:                Iterator i = stream.iterator();
0602:                while (i.hasNext()) {
0603:                    Object o = i.next();
0604:
0605:                    if (o instanceof  CompressionStreamElement) {
0606:                        ((CompressionStreamElement) o).quantize(this ,
0607:                                huffmanTable);
0608:
0609:                        // Keep track of whether last two elements were colors or
0610:                        // normals for mesh buffer component substitution semantics.
0611:                        lastLastElementColor = lastElementColor;
0612:                        lastLastElementNormal = lastElementNormal;
0613:                        lastElementColor = lastElementNormal = false;
0614:
0615:                        if (o instanceof  CompressionStreamColor)
0616:                            lastElementColor = true;
0617:                        else if (o instanceof  CompressionStreamNormal)
0618:                            lastElementNormal = true;
0619:                    }
0620:                }
0621:
0622:                // Compute the bounds in normalized coordinates.
0623:                ncBounds[0].x = (double) qcBounds[0].x / 32768.0;
0624:                ncBounds[0].y = (double) qcBounds[0].y / 32768.0;
0625:                ncBounds[0].z = (double) qcBounds[0].z / 32768.0;
0626:
0627:                ncBounds[1].x = (double) qcBounds[1].x / 32768.0;
0628:                ncBounds[1].y = (double) qcBounds[1].y / 32768.0;
0629:                ncBounds[1].z = (double) qcBounds[1].z / 32768.0;
0630:            }
0631:
0632:            /**
0633:             * Iterates across all compression stream elements and builds the
0634:             * compressed geometry command stream output.<p>
0635:             *
0636:             * @param huffmanTable Table which maps geometric elements in this stream
0637:             * to tags describing the encoding parameters (length, shift, and
0638:             * absolute/relative status) to be used for their representations in the
0639:             * compressed output.  All tags must be 6 bits or less in length, and the
0640:             * sum of the number of bits in the tag plus the number of bits in the
0641:             * data it describes must be at least 6 bits in length.
0642:             *
0643:             * @param outputBuffer CommandStream to use for collecting the compressed
0644:             * bits.
0645:             */
0646:            void outputCommands(HuffmanTable huffmanTable,
0647:                    CommandStream outputBuffer) {
0648:                //
0649:                // The first command output is setState to indicate what data is
0650:                // bundled with each vertex.  Although the semantics of geometry
0651:                // decompression allow setState to appear anywhere in the stream, this
0652:                // cannot be handled by the current Java 3D software decompressor,
0653:                // which internally decompresses an entire compressed buffer into a
0654:                // single retained object sharing a single consistent vertex format.
0655:                // This limitation may be removed in subsequent releases of Java 3D.
0656:                //
0657:                int bnv = (vertexNormals ? 1 : 0);
0658:                int bcv = ((vertexColor3 || vertexColor4) ? 1 : 0);
0659:                int cap = (vertexColor4 ? 1 : 0);
0660:
0661:                int command = CommandStream.SET_STATE | bnv;
0662:                long data = (bcv << 2) | (cap << 1);
0663:
0664:                // Output the setState command.
0665:                outputBuffer.addCommand(command, 8, data, 3);
0666:
0667:                // Output the Huffman table commands.
0668:                huffmanTable.outputCommands(outputBuffer);
0669:
0670:                // Output each compression stream element's data.
0671:                Iterator i = stream.iterator();
0672:                while (i.hasNext()) {
0673:                    Object o = i.next();
0674:                    if (o instanceof  CompressionStreamElement)
0675:                        ((CompressionStreamElement) o).outputCommand(
0676:                                huffmanTable, outputBuffer);
0677:                }
0678:
0679:                // Finish the header-forwarding interleave and long-word align.
0680:                outputBuffer.end();
0681:            }
0682:
0683:            /**
0684:             * Retrieve the total size of the uncompressed geometric data in bytes,
0685:             * excluding mesh buffer references.
0686:             * @return uncompressed byte count
0687:             */
0688:            int getByteCount() {
0689:                return byteCount;
0690:            }
0691:
0692:            /**
0693:             * Retrieve the the number of vertices created for this stream, excluding
0694:             * mesh buffer references.
0695:             * @return vertex count
0696:             */
0697:            int getVertexCount() {
0698:                return vertexCount;
0699:            }
0700:
0701:            /**
0702:             * Retrieve the number of mesh buffer references created for this stream. 
0703:             * @return mesh buffer reference count
0704:             */
0705:            int getMeshReferenceCount() {
0706:                return meshReferenceCount;
0707:            }
0708:
0709:            /**
0710:             * Stream element that sets position quantization during quantize pass.
0711:             */
0712:            private class PositionQuant extends CompressionStreamElement {
0713:                int value;
0714:
0715:                PositionQuant(int value) {
0716:                    this .value = value;
0717:                }
0718:
0719:                void quantize(CompressionStream s, HuffmanTable t) {
0720:                    positionQuant = value;
0721:                    positionQuantChanged = true;
0722:
0723:                    // Adjust range of unit cube scaling to match quantization.
0724:                    scale = (2.0 / positionRangeMaximum)
0725:                            * (((double) ((1 << (value - 1)) - 1)) / ((double) (1 << (value - 1))));
0726:                }
0727:
0728:                public String toString() {
0729:                    return "positionQuant: " + value;
0730:                }
0731:            }
0732:
0733:            /**
0734:             * Stream element that sets normal quantization during quantize pass.
0735:             */
0736:            private class NormalQuant extends CompressionStreamElement {
0737:                int value;
0738:
0739:                NormalQuant(int value) {
0740:                    this .value = value;
0741:                }
0742:
0743:                void quantize(CompressionStream s, HuffmanTable t) {
0744:                    normalQuant = value;
0745:                    normalQuantChanged = true;
0746:                }
0747:
0748:                public String toString() {
0749:                    return "normalQuant: " + value;
0750:                }
0751:            }
0752:
0753:            /**
0754:             * Stream element that sets color quantization during quantize pass.
0755:             */
0756:            private class ColorQuant extends CompressionStreamElement {
0757:                int value;
0758:
0759:                ColorQuant(int value) {
0760:                    this .value = value;
0761:                }
0762:
0763:                void quantize(CompressionStream s, HuffmanTable t) {
0764:                    colorQuant = value;
0765:                    colorQuantChanged = true;
0766:                }
0767:
0768:                public String toString() {
0769:                    return "colorQuant: " + value;
0770:                }
0771:            }
0772:
0773:            /**
0774:             * Stream element that references the mesh buffer.
0775:             */
0776:            private class MeshReference extends CompressionStreamElement {
0777:                int stripFlag, meshIndex;
0778:
0779:                MeshReference(int stripFlag, int meshIndex) {
0780:                    this .stripFlag = stripFlag;
0781:                    this .meshIndex = meshIndex;
0782:                    meshReferenceCount++;
0783:                }
0784:
0785:                void quantize(CompressionStream s, HuffmanTable t) {
0786:                    // Retrieve the vertex from the mesh buffer mirror and set up the
0787:                    // data needed for the next stream element to compute its deltas.
0788:                    CompressionStreamVertex v = meshBuffer.getVertex(meshIndex);
0789:                    lastPosition[0] = v.xAbsolute;
0790:                    lastPosition[1] = v.yAbsolute;
0791:                    lastPosition[2] = v.zAbsolute;
0792:
0793:                    // Set up last color data if it exists and previous elements
0794:                    // don't override it.
0795:                    if (v.color != null && !lastElementColor
0796:                            && !(lastElementNormal && lastLastElementColor)) {
0797:                        lastColor[0] = v.color.rAbsolute;
0798:                        lastColor[1] = v.color.gAbsolute;
0799:                        lastColor[2] = v.color.bAbsolute;
0800:                        lastColor[3] = v.color.aAbsolute;
0801:                    }
0802:
0803:                    // Set up last normal data if it exists and previous element
0804:                    // doesn't override it.
0805:                    if (v.normal != null && !lastElementNormal
0806:                            && !(lastElementColor && lastLastElementNormal)) {
0807:                        lastSextant = v.normal.sextant;
0808:                        lastOctant = v.normal.octant;
0809:                        lastU = v.normal.uAbsolute;
0810:                        lastV = v.normal.vAbsolute;
0811:                        lastSpecialNormal = v.normal.specialNormal;
0812:                    }
0813:                }
0814:
0815:                void outputCommand(HuffmanTable t, CommandStream outputBuffer) {
0816:                    int command = CommandStream.MESH_B_R;
0817:                    long data = stripFlag & 0x1;
0818:
0819:                    command |= (((meshIndex & 0xf) << 1) | (stripFlag >> 1));
0820:                    outputBuffer.addCommand(command, 8, data, 1);
0821:                }
0822:
0823:                public String toString() {
0824:                    return "meshReference: stripFlag " + stripFlag
0825:                            + " meshIndex " + meshIndex;
0826:                }
0827:            }
0828:
0829:            /**
0830:             * Copy vertex data and add it to the end of this stream.
0831:             * @param pos position data
0832:             * @param stripFlag vertex replacement flag, either RESTART,
0833:             * REPLACE_OLDEST, or REPLACE_MIDDLE
0834:             */
0835:            void addVertex(Point3f pos, int stripFlag) {
0836:                stream.add(new CompressionStreamVertex(this , pos,
0837:                        (Vector3f) null, (Color3f) null, stripFlag,
0838:                        NO_MESH_PUSH));
0839:            }
0840:
0841:            /**
0842:             * Copy vertex data and add it to the end of this stream.
0843:             * @param pos position data
0844:             * @param norm normal data
0845:             * @param stripFlag vertex replacement flag, either RESTART,
0846:             * REPLACE_OLDEST, or REPLACE_MIDDLE
0847:             */
0848:            void addVertex(Point3f pos, Vector3f norm, int stripFlag) {
0849:                stream.add(new CompressionStreamVertex(this , pos, norm,
0850:                        (Color3f) null, stripFlag, NO_MESH_PUSH));
0851:            }
0852:
0853:            /**
0854:             * Copy vertex data and add it to the end of this stream.
0855:             * @param pos position data
0856:             * @param color color data
0857:             * @param stripFlag vertex replacement flag, either RESTART,
0858:             * REPLACE_OLDEST, or REPLACE_MIDDLE
0859:             */
0860:            void addVertex(Point3f pos, Color3f color, int stripFlag) {
0861:                stream.add(new CompressionStreamVertex(this , pos,
0862:                        (Vector3f) null, color, stripFlag, NO_MESH_PUSH));
0863:            }
0864:
0865:            /**
0866:             * Copy vertex data and add it to the end of this stream.
0867:             * @param pos position data
0868:             * @param color color data
0869:             * @param stripFlag vertex replacement flag, either RESTART,
0870:             * REPLACE_OLDEST, or REPLACE_MIDDLE
0871:             */
0872:            void addVertex(Point3f pos, Color4f color, int stripFlag) {
0873:                stream.add(new CompressionStreamVertex(this , pos,
0874:                        (Vector3f) null, color, stripFlag, NO_MESH_PUSH));
0875:            }
0876:
0877:            /**
0878:             * Copy vertex data and add it to the end of this stream.
0879:             * @param pos position data
0880:             * @param norm normal data
0881:             * @param color color data
0882:             * @param stripFlag vertex replacement flag, either RESTART,
0883:             * REPLACE_OLDEST, or REPLACE_MIDDLE
0884:             */
0885:            void addVertex(Point3f pos, Vector3f norm, Color3f color,
0886:                    int stripFlag) {
0887:                stream.add(new CompressionStreamVertex(this , pos, norm, color,
0888:                        stripFlag, NO_MESH_PUSH));
0889:            }
0890:
0891:            /**
0892:             * Copy vertex data and add it to the end of this stream.
0893:             * @param pos position data
0894:             * @param norm normal data
0895:             * @param color color data
0896:             * @param stripFlag vertex replacement flag, either RESTART,
0897:             * REPLACE_OLDEST, or REPLACE_MIDDLE
0898:             */
0899:            void addVertex(Point3f pos, Vector3f norm, Color4f color,
0900:                    int stripFlag) {
0901:                stream.add(new CompressionStreamVertex(this , pos, norm, color,
0902:                        stripFlag, NO_MESH_PUSH));
0903:            }
0904:
0905:            /**
0906:             * Copy vertex data and add it to the end of this stream.
0907:             * @param pos position data
0908:             * @param stripFlag vertex replacement flag, either RESTART, REPLACE_OLDEST,
0909:             * or REPLACE_MIDDLE
0910:             * @param meshFlag if MESH_PUSH the vertex is pushed into the mesh buffer
0911:             */
0912:            void addVertex(Point3f pos, int stripFlag, int meshFlag) {
0913:                stream.add(new CompressionStreamVertex(this , pos,
0914:                        (Vector3f) null, (Color3f) null, stripFlag, meshFlag));
0915:            }
0916:
0917:            /**
0918:             * Copy vertex data and add it to the end of this stream.
0919:             * @param pos position data
0920:             * @param norm normal data
0921:             * @param stripFlag vertex replacement flag, either RESTART, REPLACE_OLDEST,
0922:             * or REPLACE_MIDDLE
0923:             * @param meshFlag if MESH_PUSH the vertex is pushed into the mesh buffer
0924:             */
0925:            void addVertex(Point3f pos, Vector3f norm, int stripFlag,
0926:                    int meshFlag) {
0927:                stream.add(new CompressionStreamVertex(this , pos, norm,
0928:                        (Color3f) null, stripFlag, meshFlag));
0929:            }
0930:
0931:            /**
0932:             * Copy vertex data and add it to the end of this stream.
0933:             * @param pos position data
0934:             * @param color color data
0935:             * @param stripFlag vertex replacement flag, either RESTART, REPLACE_OLDEST,
0936:             * or REPLACE_MIDDLE
0937:             * @param meshFlag if MESH_PUSH the vertex is pushed into the mesh buffer
0938:             */
0939:            void addVertex(Point3f pos, Color3f color, int stripFlag,
0940:                    int meshFlag) {
0941:                stream.add(new CompressionStreamVertex(this , pos,
0942:                        (Vector3f) null, color, stripFlag, meshFlag));
0943:            }
0944:
0945:            /**
0946:             * Copy vertex data and add it to the end of this stream.
0947:             * @param pos position data
0948:             * @param color color data
0949:             * @param stripFlag vertex replacement flag, either RESTART, REPLACE_OLDEST,
0950:             * or REPLACE_MIDDLE
0951:             * @param meshFlag if MESH_PUSH the vertex is pushed into the mesh buffer
0952:             */
0953:            void addVertex(Point3f pos, Color4f color, int stripFlag,
0954:                    int meshFlag) {
0955:                stream.add(new CompressionStreamVertex(this , pos,
0956:                        (Vector3f) null, color, stripFlag, meshFlag));
0957:            }
0958:
0959:            /**
0960:             * Copy vertex data and add it to the end of this stream.
0961:             * @param pos position data
0962:             * @param norm normal data
0963:             * @param color color data
0964:             * @param stripFlag vertex replacement flag, either RESTART, REPLACE_OLDEST,
0965:             * or REPLACE_MIDDLE
0966:             * @param meshFlag if MESH_PUSH the vertex is pushed into the mesh buffer
0967:             */
0968:            void addVertex(Point3f pos, Vector3f norm, Color3f color,
0969:                    int stripFlag, int meshFlag) {
0970:                stream.add(new CompressionStreamVertex(this , pos, norm, color,
0971:                        stripFlag, meshFlag));
0972:            }
0973:
0974:            /**
0975:             * Copy vertex data and add it to the end of this stream.
0976:             * @param pos position data
0977:             * @param norm normal data
0978:             * @param color color data
0979:             * @param stripFlag vertex replacement flag, either RESTART, REPLACE_OLDEST,
0980:             * or REPLACE_MIDDLE
0981:             * @param meshFlag if MESH_PUSH the vertex is pushed into the mesh buffer
0982:             */
0983:            void addVertex(Point3f pos, Vector3f norm, Color4f color,
0984:                    int stripFlag, int meshFlag) {
0985:                stream.add(new CompressionStreamVertex(this , pos, norm, color,
0986:                        stripFlag, meshFlag));
0987:            }
0988:
0989:            /**
0990:             * Copy vertex data and add it to the end of this stream.
0991:             * @param pos position data
0992:             * @param norm normal data
0993:             * @param color color data, either Color3f or Color4f, determined by
0994:             * current vertex format
0995:             * @param stripFlag vertex replacement flag, either RESTART, REPLACE_OLDEST,
0996:             * or REPLACE_MIDDLE
0997:             * @param meshFlag if MESH_PUSH the vertex is pushed into the mesh buffer
0998:             */
0999:            void addVertex(Point3f pos, Vector3f norm, Object color,
1000:                    int stripFlag, int meshFlag) {
1001:
1002:                if (vertexColor3)
1003:                    stream.add(new CompressionStreamVertex(this , pos, norm,
1004:                            (Color3f) color, stripFlag, meshFlag));
1005:                else
1006:                    stream.add(new CompressionStreamVertex(this , pos, norm,
1007:                            (Color4f) color, stripFlag, meshFlag));
1008:            }
1009:
1010:            /**
1011:             * Add a mesh buffer reference to this stream.
1012:             * @param stripFlag vertex replacement flag, either RESTART, REPLACE_OLDEST,
1013:             * or REPLACE_MIDDLE
1014:             * @param meshIndex index of vertex to retrieve from the mesh buffer
1015:             */
1016:            void addMeshReference(int stripFlag, int meshIndex) {
1017:                stream.add(new MeshReference(stripFlag, meshIndex));
1018:            }
1019:
1020:            /**
1021:             * Copy the given color to the end of this stream and use it as a global
1022:             * state change that applies to all subsequent vertices.
1023:             */
1024:            void addColor(Color3f c3f) {
1025:                stream.add(new CompressionStreamColor(this , c3f));
1026:            }
1027:
1028:            /**
1029:             * Copy the given color to the end of this stream and use it as a global
1030:             * state change that applies to all subsequent vertices.
1031:             */
1032:            void addColor(Color4f c4f) {
1033:                stream.add(new CompressionStreamColor(this , c4f));
1034:            }
1035:
1036:            /**
1037:             * Copy the given normal to the end of this stream and use it as a global
1038:             * state change that applies to all subsequent vertices.
1039:             */
1040:            void addNormal(Vector3f n) {
1041:                stream.add(new CompressionStreamNormal(this , n));
1042:            }
1043:
1044:            /**
1045:             * Add a new position quantization value to the end of this stream that
1046:             * will apply to all subsequent vertex positions.
1047:             *
1048:             * @param value number of bits to quantize each position's X, Y,
1049:             * and Z components, ranging from 1 to 16 with a default of 16
1050:             */
1051:            void addPositionQuantization(int value) {
1052:                stream.add(new PositionQuant(value));
1053:            }
1054:
1055:            /**
1056:             * Add a new color quantization value to the end of this stream that will
1057:             * apply to all subsequent colors.
1058:             *
1059:             * @param value number of bits to quantize each color's R, G, B, and
1060:             * alpha components, ranging from 2 to 16 with a default of 9
1061:             */
1062:            void addColorQuantization(int value) {
1063:                stream.add(new ColorQuant(value));
1064:            }
1065:
1066:            /**
1067:             * Add a new normal quantization value to the end of this stream that will
1068:             * apply to all subsequent normals.  This value specifies the number of
1069:             * bits for each normal's U and V components.
1070:             *
1071:             * @param value number of bits for quantizing U and V, ranging from 0 to
1072:             * 6 with a default of 6
1073:             */
1074:            void addNormalQuantization(int value) {
1075:                stream.add(new NormalQuant(value));
1076:            }
1077:
1078:            /**
1079:             * Interface to access GeometryArray vertex components and add them to the
1080:             * compression stream.
1081:             * 
1082:             * A processVertex() implementation retrieves vertex components using the
1083:             * appropriate access semantics of a particular GeometryArray, and adds
1084:             * them to the compression stream.
1085:             * 
1086:             * The implementation always pushes vertices into the mesh buffer unless
1087:             * they match ones already there; if they do, it generates mesh buffer
1088:             * references instead.  This reduces the number of vertices when
1089:             * non-stripped abutting facets are added to the stream.
1090:             * 
1091:             * Note: Level II geometry compression semantics allow the mesh buffer
1092:             * normals to be substituted with the value of an immediately
1093:             * preceding SetNormal command, but this is unavailable in Level I.
1094:             *
1095:             * @param index vertex offset from the beginning of its data array
1096:             * @param stripFlag RESTART, REPLACE_MIDDLE, or REPLACE_OLDEST
1097:             */
1098:            private interface GeometryAccessor {
1099:                void processVertex(int index, int stripFlag);
1100:            }
1101:
1102:            /**
1103:             * This class implements the GeometryAccessor interface for geometry
1104:             * arrays accessed with by-copy semantics.
1105:             */
1106:            private class ByCopyGeometry implements  GeometryAccessor {
1107:                Point3f[] positions = null;
1108:                Vector3f[] normals = null;
1109:                Color3f[] colors3 = null;
1110:                Color4f[] colors4 = null;
1111:
1112:                ByCopyGeometry(GeometryArray ga) {
1113:                    this (ga, ga.getInitialVertexIndex(), ga
1114:                            .getValidVertexCount());
1115:                }
1116:
1117:                ByCopyGeometry(GeometryArray ga, int firstVertex,
1118:                        int validVertexCount) {
1119:                    int i;
1120:                    positions = new Point3f[validVertexCount];
1121:                    for (i = 0; i < validVertexCount; i++)
1122:                        positions[i] = new Point3f();
1123:
1124:                    ga.getCoordinates(firstVertex, positions);
1125:
1126:                    if (vertexNormals) {
1127:                        normals = new Vector3f[validVertexCount];
1128:                        for (i = 0; i < validVertexCount; i++)
1129:                            normals[i] = new Vector3f();
1130:
1131:                        ga.getNormals(firstVertex, normals);
1132:                    }
1133:
1134:                    if (vertexColor3) {
1135:                        colors3 = new Color3f[validVertexCount];
1136:                        for (i = 0; i < validVertexCount; i++)
1137:                            colors3[i] = new Color3f();
1138:
1139:                        ga.getColors(firstVertex, colors3);
1140:                    } else if (vertexColor4) {
1141:                        colors4 = new Color4f[validVertexCount];
1142:                        for (i = 0; i < validVertexCount; i++)
1143:                            colors4[i] = new Color4f();
1144:
1145:                        ga.getColors(firstVertex, colors4);
1146:                    }
1147:                }
1148:
1149:                public void processVertex(int v, int stripFlag) {
1150:                    Point3f p = positions[v];
1151:                    int r = meshBuffer.getMeshReference(p);
1152:
1153:                    if ((r == meshBuffer.NOT_FOUND)
1154:                            || (vertexNormals && noMeshNormalSubstitution && (!normals[v]
1155:                                    .equals(meshBuffer.getNormal(r))))) {
1156:
1157:                        Vector3f n = vertexNormals ? normals[v] : null;
1158:                        Object c = vertexColor3 ? (Object) colors3[v]
1159:                                : vertexColor4 ? (Object) colors4[v] : null;
1160:
1161:                        addVertex(p, n, c, stripFlag, MESH_PUSH);
1162:                        meshBuffer.push(p, c, n);
1163:                    } else {
1164:                        if (vertexNormals
1165:                                && !noMeshNormalSubstitution
1166:                                && (!normals[v].equals(meshBuffer.getNormal(r))))
1167:                            addNormal(normals[v]);
1168:
1169:                        if (vertexColor3
1170:                                && (!colors3[v].equals(meshBuffer.getColor3(r))))
1171:                            addColor(colors3[v]);
1172:
1173:                        else if (vertexColor4
1174:                                && (!colors4[v].equals(meshBuffer.getColor4(r))))
1175:                            addColor(colors4[v]);
1176:
1177:                        addMeshReference(stripFlag, r);
1178:                    }
1179:                }
1180:            }
1181:
1182:            /**
1183:             * Class which holds index array references for a geometry array.
1184:             */
1185:            private static class IndexArrays {
1186:                int colorIndices[] = null;
1187:                int normalIndices[] = null;
1188:                int positionIndices[] = null;
1189:            }
1190:
1191:            /**
1192:             * Retrieves index array references for the specified IndexedGeometryArray.
1193:             * Index arrays are copied starting from initialIndexIndex.
1194:             */
1195:            private void getIndexArrays(GeometryArray ga, IndexArrays ia) {
1196:                IndexedGeometryArray iga = (IndexedGeometryArray) ga;
1197:
1198:                int initialIndexIndex = iga.getInitialIndexIndex();
1199:                int indexCount = iga.getValidIndexCount();
1200:                int vertexFormat = iga.getVertexFormat();
1201:
1202:                boolean useCoordIndexOnly = false;
1203:                if ((vertexFormat & GeometryArray.USE_COORD_INDEX_ONLY) != 0) {
1204:                    if (debug)
1205:                        System.out.println("useCoordIndexOnly");
1206:                    useCoordIndexOnly = true;
1207:                }
1208:
1209:                ia.positionIndices = new int[indexCount];
1210:                iga.getCoordinateIndices(initialIndexIndex, ia.positionIndices);
1211:
1212:                if (vertexNormals) {
1213:                    if (useCoordIndexOnly) {
1214:                        ia.normalIndices = ia.positionIndices;
1215:                    } else {
1216:                        ia.normalIndices = new int[indexCount];
1217:                        iga.getNormalIndices(initialIndexIndex,
1218:                                ia.normalIndices);
1219:                    }
1220:                }
1221:                if (vertexColor3 || vertexColor4) {
1222:                    if (useCoordIndexOnly) {
1223:                        ia.colorIndices = ia.positionIndices;
1224:                    } else {
1225:                        ia.colorIndices = new int[indexCount];
1226:                        iga.getColorIndices(initialIndexIndex, ia.colorIndices);
1227:                    }
1228:                }
1229:            }
1230:
1231:            /**
1232:             * Class which holds indices for a specific vertex of an
1233:             * IndexedGeometryArray. 
1234:             */
1235:            private static class VertexIndices {
1236:                int pi, ni, ci;
1237:            }
1238:
1239:            /**
1240:             * Retrieves vertex indices for a specific vertex in an
1241:             * IndexedGeometryArray.
1242:             */
1243:            private void getVertexIndices(int v, IndexArrays ia,
1244:                    VertexIndices vi) {
1245:                vi.pi = ia.positionIndices[v];
1246:                if (vertexNormals)
1247:                    vi.ni = ia.normalIndices[v];
1248:                if (vertexColors)
1249:                    vi.ci = ia.colorIndices[v];
1250:            }
1251:
1252:            /**
1253:             * This class implements the GeometryAccessor interface for indexed
1254:             * geometry arrays accessed with by-copy semantics.
1255:             */
1256:            private class IndexedByCopyGeometry extends ByCopyGeometry {
1257:                IndexArrays ia = new IndexArrays();
1258:                VertexIndices vi = new VertexIndices();
1259:
1260:                IndexedByCopyGeometry(GeometryArray ga) {
1261:                    super (ga, 0, ga.getVertexCount());
1262:                    getIndexArrays(ga, ia);
1263:                }
1264:
1265:                public void processVertex(int v, int stripFlag) {
1266:                    getVertexIndices(v, ia, vi);
1267:                    int r = meshBuffer.getMeshReference(vi.pi);
1268:
1269:                    if ((r == meshBuffer.NOT_FOUND)
1270:                            || (vertexNormals && noMeshNormalSubstitution && (vi.ni != meshBuffer
1271:                                    .getNormalIndex(r)))) {
1272:
1273:                        Point3f p = positions[vi.pi];
1274:                        Vector3f n = vertexNormals ? normals[vi.ni] : null;
1275:                        Object c = vertexColor3 ? (Object) colors3[vi.ci]
1276:                                : vertexColor4 ? (Object) colors4[vi.ci] : null;
1277:
1278:                        addVertex(p, n, c, stripFlag, MESH_PUSH);
1279:                        meshBuffer.push(vi.pi, vi.ci, vi.ni);
1280:                    } else {
1281:                        if (vertexNormals && !noMeshNormalSubstitution
1282:                                && vi.ni != meshBuffer.getNormalIndex(r))
1283:                            addNormal(normals[vi.ni]);
1284:
1285:                        if (vertexColor3
1286:                                && vi.ci != meshBuffer.getColorIndex(r))
1287:                            addColor(colors3[vi.ci]);
1288:
1289:                        else if (vertexColor4
1290:                                && vi.ci != meshBuffer.getColorIndex(r))
1291:                            addColor(colors4[vi.ci]);
1292:
1293:                        addMeshReference(stripFlag, r);
1294:                    }
1295:                }
1296:            }
1297:
1298:            //
1299:            // NOTE: For now, copies are made of all GeometryArray vertex components
1300:            // even when by-reference access is available.  
1301:            //
1302:            private static class VertexCopy {
1303:                Object c = null;
1304:                Point3f p = null;
1305:                Vector3f n = null;
1306:                Color3f c3 = null;
1307:                Color4f c4 = null;
1308:            }
1309:
1310:            private void processVertexCopy(VertexCopy vc, int stripFlag) {
1311:                int r = meshBuffer.getMeshReference(vc.p);
1312:
1313:                if ((r == meshBuffer.NOT_FOUND)
1314:                        || (vertexNormals && noMeshNormalSubstitution && (!vc.n
1315:                                .equals(meshBuffer.getNormal(r))))) {
1316:
1317:                    addVertex(vc.p, vc.n, vc.c, stripFlag, MESH_PUSH);
1318:                    meshBuffer.push(vc.p, vc.c, vc.n);
1319:                } else {
1320:                    if (vertexNormals && !noMeshNormalSubstitution
1321:                            && (!vc.n.equals(meshBuffer.getNormal(r))))
1322:                        addNormal(vc.n);
1323:
1324:                    if (vertexColor3
1325:                            && (!vc.c3.equals(meshBuffer.getColor3(r))))
1326:                        addColor(vc.c3);
1327:
1328:                    else if (vertexColor4
1329:                            && (!vc.c4.equals(meshBuffer.getColor4(r))))
1330:                        addColor(vc.c4);
1331:
1332:                    addMeshReference(stripFlag, r);
1333:                }
1334:            }
1335:
1336:            private void processIndexedVertexCopy(VertexCopy vc,
1337:                    VertexIndices vi, int stripFlag) {
1338:
1339:                int r = meshBuffer.getMeshReference(vi.pi);
1340:
1341:                if ((r == meshBuffer.NOT_FOUND)
1342:                        || (vertexNormals && noMeshNormalSubstitution && (vi.ni != meshBuffer
1343:                                .getNormalIndex(r)))) {
1344:
1345:                    addVertex(vc.p, vc.n, vc.c, stripFlag, MESH_PUSH);
1346:                    meshBuffer.push(vi.pi, vi.ci, vi.ni);
1347:                } else {
1348:                    if (vertexNormals && !noMeshNormalSubstitution
1349:                            && vi.ni != meshBuffer.getNormalIndex(r))
1350:                        addNormal(vc.n);
1351:
1352:                    if (vertexColor3 && vi.ci != meshBuffer.getColorIndex(r))
1353:                        addColor(vc.c3);
1354:
1355:                    else if (vertexColor4
1356:                            && vi.ci != meshBuffer.getColorIndex(r))
1357:                        addColor(vc.c4);
1358:
1359:                    addMeshReference(stripFlag, r);
1360:                }
1361:            }
1362:
1363:            /**
1364:             * This abstract class implements the GeometryAccessor interface for
1365:             * concrete subclasses which handle float and NIO interleaved geometry
1366:             * arrays.
1367:             */
1368:            private abstract class InterleavedGeometry implements 
1369:                    GeometryAccessor {
1370:                VertexCopy vc = new VertexCopy();
1371:
1372:                int vstride = 0;
1373:                int coffset = 0;
1374:                int noffset = 0;
1375:                int poffset = 0;
1376:                int tstride = 0;
1377:                int tcount = 0;
1378:
1379:                InterleavedGeometry(GeometryArray ga) {
1380:                    if (vertexTextures) {
1381:                        if (vertexTexture2)
1382:                            tstride = 2;
1383:                        else if (vertexTexture3)
1384:                            tstride = 3;
1385:                        else if (vertexTexture4)
1386:                            tstride = 4;
1387:
1388:                        tcount = ga.getTexCoordSetCount();
1389:                        vstride += tcount * tstride;
1390:                    }
1391:
1392:                    if (vertexColors) {
1393:                        coffset = vstride;
1394:                        if (vertexColor3)
1395:                            vstride += 3;
1396:                        else
1397:                            vstride += 4;
1398:                    }
1399:
1400:                    if (vertexNormals) {
1401:                        noffset = vstride;
1402:                        vstride += 3;
1403:                    }
1404:
1405:                    poffset = vstride;
1406:                    vstride += 3;
1407:                }
1408:
1409:                abstract void copyVertex(int pi, int ni, int ci, VertexCopy vc);
1410:
1411:                public void processVertex(int v, int stripFlag) {
1412:                    copyVertex(v, v, v, vc);
1413:                    processVertexCopy(vc, stripFlag);
1414:                }
1415:            }
1416:
1417:            /**
1418:             * This class implements the GeometryAccessor interface for float
1419:             * interleaved geometry arrays.
1420:             */
1421:            private class InterleavedGeometryFloat extends InterleavedGeometry {
1422:                float[] vdata = null;
1423:
1424:                InterleavedGeometryFloat(GeometryArray ga) {
1425:                    super (ga);
1426:                    vdata = ga.getInterleavedVertices();
1427:                }
1428:
1429:                void copyVertex(int pi, int ni, int ci, VertexCopy vc) {
1430:                    int voffset;
1431:                    voffset = pi * vstride;
1432:                    vc.p = new Point3f(vdata[voffset + poffset + 0],
1433:                            vdata[voffset + poffset + 1], vdata[voffset
1434:                                    + poffset + 2]);
1435:
1436:                    if (vertexNormals) {
1437:                        voffset = ni * vstride;
1438:                        vc.n = new Vector3f(vdata[voffset + noffset + 0],
1439:                                vdata[voffset + noffset + 1], vdata[voffset
1440:                                        + noffset + 2]);
1441:                    }
1442:                    if (vertexColor3) {
1443:                        voffset = ci * vstride;
1444:                        vc.c3 = new Color3f(vdata[voffset + coffset + 0],
1445:                                vdata[voffset + coffset + 1], vdata[voffset
1446:                                        + coffset + 2]);
1447:                        vc.c = vc.c3;
1448:                    } else if (vertexColor4) {
1449:                        voffset = ci * vstride;
1450:                        vc.c4 = new Color4f(vdata[voffset + coffset + 0],
1451:                                vdata[voffset + coffset + 1], vdata[voffset
1452:                                        + coffset + 2], vdata[voffset + coffset
1453:                                        + 3]);
1454:                        vc.c = vc.c4;
1455:                    }
1456:                }
1457:            }
1458:
1459:            /**
1460:             * This class implements the GeometryAccessor interface for indexed
1461:             * interleaved geometry arrays.
1462:             */
1463:            private class IndexedInterleavedGeometryFloat extends
1464:                    InterleavedGeometryFloat {
1465:
1466:                IndexArrays ia = new IndexArrays();
1467:                VertexIndices vi = new VertexIndices();
1468:
1469:                IndexedInterleavedGeometryFloat(GeometryArray ga) {
1470:                    super (ga);
1471:                    getIndexArrays(ga, ia);
1472:                }
1473:
1474:                public void processVertex(int v, int stripFlag) {
1475:                    getVertexIndices(v, ia, vi);
1476:                    copyVertex(vi.pi, vi.ni, vi.ci, vc);
1477:                    processIndexedVertexCopy(vc, vi, stripFlag);
1478:                }
1479:            }
1480:
1481:            /**
1482:             * This class implements the GeometryAccessor interface for 
1483:             * interleaved NIO geometry arrays.
1484:             */
1485:            private class InterleavedGeometryNIO extends InterleavedGeometry {
1486:                FloatBufferWrapper fbw = null;
1487:
1488:                InterleavedGeometryNIO(GeometryArray ga) {
1489:                    super (ga);
1490:                    J3DBuffer buffer = ga.getInterleavedVertexBuffer();
1491:                    if (BufferWrapper.getBufferType(buffer) == BufferWrapper.TYPE_FLOAT) {
1492:                        fbw = new FloatBufferWrapper(buffer);
1493:                    } else {
1494:                        throw new IllegalArgumentException(
1495:                                "\ninterleaved vertex buffer must be FloatBuffer");
1496:                    }
1497:                }
1498:
1499:                void copyVertex(int pi, int ni, int ci, VertexCopy vc) {
1500:                    int voffset;
1501:                    voffset = pi * vstride;
1502:                    vc.p = new Point3f(fbw.get(voffset + poffset + 0), fbw
1503:                            .get(voffset + poffset + 1), fbw.get(voffset
1504:                            + poffset + 2));
1505:
1506:                    if (vertexNormals) {
1507:                        voffset = ni * vstride;
1508:                        vc.n = new Vector3f(fbw.get(voffset + noffset + 0), fbw
1509:                                .get(voffset + noffset + 1), fbw.get(voffset
1510:                                + noffset + 2));
1511:                    }
1512:                    if (vertexColor3) {
1513:                        voffset = ci * vstride;
1514:                        vc.c3 = new Color3f(fbw.get(voffset + coffset + 0), fbw
1515:                                .get(voffset + coffset + 1), fbw.get(voffset
1516:                                + coffset + 2));
1517:                        vc.c = vc.c3;
1518:                    } else if (vertexColor4) {
1519:                        voffset = ci * vstride;
1520:                        vc.c4 = new Color4f(fbw.get(voffset + coffset + 0), fbw
1521:                                .get(voffset + coffset + 1), fbw.get(voffset
1522:                                + coffset + 2), fbw.get(voffset + coffset + 3));
1523:                        vc.c = vc.c4;
1524:                    }
1525:                }
1526:            }
1527:
1528:            /**
1529:             * This class implements the GeometryAccessor interface for indexed
1530:             * interleaved NIO geometry arrays.
1531:             */
1532:            private class IndexedInterleavedGeometryNIO extends
1533:                    InterleavedGeometryNIO {
1534:                IndexArrays ia = new IndexArrays();
1535:                VertexIndices vi = new VertexIndices();
1536:
1537:                IndexedInterleavedGeometryNIO(GeometryArray ga) {
1538:                    super (ga);
1539:                    getIndexArrays(ga, ia);
1540:                }
1541:
1542:                public void processVertex(int v, int stripFlag) {
1543:                    getVertexIndices(v, ia, vi);
1544:                    copyVertex(vi.pi, vi.ni, vi.ci, vc);
1545:                    processIndexedVertexCopy(vc, vi, stripFlag);
1546:                }
1547:            }
1548:
1549:            /**
1550:             * This class implements the GeometryAccessor interface for
1551:             * non-interleaved geometry arrays accessed with by-reference semantics.
1552:             */
1553:            private class ByRefGeometry implements  GeometryAccessor {
1554:                VertexCopy vc = new VertexCopy();
1555:
1556:                byte[] colorsB = null;
1557:                float[] colorsF = null;
1558:                float[] normals = null;
1559:                float[] positionsF = null;
1560:                double[] positionsD = null;
1561:
1562:                int initialPositionIndex = 0;
1563:                int initialNormalIndex = 0;
1564:                int initialColorIndex = 0;
1565:
1566:                ByRefGeometry(GeometryArray ga) {
1567:                    positionsF = ga.getCoordRefFloat();
1568:                    if (debug && positionsF != null)
1569:                        System.out.println("float positions");
1570:
1571:                    positionsD = ga.getCoordRefDouble();
1572:                    if (debug && positionsD != null)
1573:                        System.out.println("double positions");
1574:
1575:                    if (positionsF == null && positionsD == null)
1576:                        throw new UnsupportedOperationException(
1577:                                "\nby-reference access to Point3{d,f} arrays");
1578:
1579:                    initialPositionIndex = ga.getInitialCoordIndex();
1580:
1581:                    if (vertexColors) {
1582:                        colorsB = ga.getColorRefByte();
1583:                        if (debug && colorsB != null)
1584:                            System.out.println("byte colors");
1585:
1586:                        colorsF = ga.getColorRefFloat();
1587:                        if (debug && colorsF != null)
1588:                            System.out.println("float colors");
1589:
1590:                        if (colorsB == null && colorsF == null)
1591:                            throw new UnsupportedOperationException(
1592:                                    "\nby-reference access to Color{3b,3f,4b,4f} arrays");
1593:
1594:                        initialColorIndex = ga.getInitialColorIndex();
1595:                    }
1596:
1597:                    if (vertexNormals) {
1598:                        normals = ga.getNormalRefFloat();
1599:                        if (debug && normals != null)
1600:                            System.out.println("float normals");
1601:
1602:                        if (normals == null)
1603:                            throw new UnsupportedOperationException(
1604:                                    "\nby-reference access to Normal3f array");
1605:
1606:                        initialNormalIndex = ga.getInitialNormalIndex();
1607:                    }
1608:                }
1609:
1610:                void copyVertex(int pi, int ni, int ci, VertexCopy vc) {
1611:                    pi *= 3;
1612:                    if (positionsF != null) {
1613:                        vc.p = new Point3f(positionsF[pi + 0],
1614:                                positionsF[pi + 1], positionsF[pi + 2]);
1615:                    } else {
1616:                        vc.p = new Point3f((float) positionsD[pi + 0],
1617:                                (float) positionsD[pi + 1],
1618:                                (float) positionsD[pi + 2]);
1619:                    }
1620:
1621:                    ni *= 3;
1622:                    if (vertexNormals) {
1623:                        vc.n = new Vector3f(normals[ni + 0], normals[ni + 1],
1624:                                normals[ni + 2]);
1625:                    }
1626:
1627:                    if (vertexColor3) {
1628:                        ci *= 3;
1629:                        if (colorsB != null) {
1630:                            vc.c3 = new Color3f(
1631:                                    (colorsB[ci + 0] & 0xff) * ByteToFloatScale,
1632:                                    (colorsB[ci + 1] & 0xff) * ByteToFloatScale,
1633:                                    (colorsB[ci + 2] & 0xff) * ByteToFloatScale);
1634:                        } else {
1635:                            vc.c3 = new Color3f(colorsF[ci + 0],
1636:                                    colorsF[ci + 1], colorsF[ci + 2]);
1637:                        }
1638:                        vc.c = vc.c3;
1639:                    } else if (vertexColor4) {
1640:                        ci *= 4;
1641:                        if (colorsB != null) {
1642:                            vc.c4 = new Color4f(
1643:                                    (colorsB[ci + 0] & 0xff) * ByteToFloatScale,
1644:                                    (colorsB[ci + 1] & 0xff) * ByteToFloatScale,
1645:                                    (colorsB[ci + 2] & 0xff) * ByteToFloatScale,
1646:                                    (colorsB[ci + 3] & 0xff) * ByteToFloatScale);
1647:                        } else {
1648:                            vc.c4 = new Color4f(colorsF[ci + 0],
1649:                                    colorsF[ci + 1], colorsF[ci + 2],
1650:                                    colorsF[ci + 3]);
1651:                        }
1652:                        vc.c = vc.c4;
1653:                    }
1654:                }
1655:
1656:                public void processVertex(int v, int stripFlag) {
1657:                    copyVertex(v + initialPositionIndex,
1658:                            v + initialNormalIndex, v + initialColorIndex, vc);
1659:
1660:                    processVertexCopy(vc, stripFlag);
1661:                }
1662:            }
1663:
1664:            /**
1665:             * This class implements the GeometryAccessor interface for indexed
1666:             * non-interleaved geometry arrays accessed with by-reference semantics.
1667:             */
1668:            private class IndexedByRefGeometry extends ByRefGeometry {
1669:                IndexArrays ia = new IndexArrays();
1670:                VertexIndices vi = new VertexIndices();
1671:
1672:                IndexedByRefGeometry(GeometryArray ga) {
1673:                    super (ga);
1674:                    getIndexArrays(ga, ia);
1675:                }
1676:
1677:                public void processVertex(int v, int stripFlag) {
1678:                    getVertexIndices(v, ia, vi);
1679:                    copyVertex(vi.pi, vi.ni, vi.ci, vc);
1680:                    processIndexedVertexCopy(vc, vi, stripFlag);
1681:                }
1682:            }
1683:
1684:            /**
1685:             * This class implements the GeometryAccessor interface for
1686:             * non-interleaved geometry arrays accessed with NIO.
1687:             */
1688:            private class ByRefGeometryNIO implements  GeometryAccessor {
1689:                VertexCopy vc = new VertexCopy();
1690:
1691:                ByteBufferWrapper colorsB = null;
1692:                FloatBufferWrapper colorsF = null;
1693:                FloatBufferWrapper normals = null;
1694:                FloatBufferWrapper positionsF = null;
1695:                DoubleBufferWrapper positionsD = null;
1696:
1697:                int initialPositionIndex = 0;
1698:                int initialNormalIndex = 0;
1699:                int initialColorIndex = 0;
1700:
1701:                ByRefGeometryNIO(GeometryArray ga) {
1702:                    J3DBuffer buffer;
1703:                    buffer = ga.getCoordRefBuffer();
1704:                    initialPositionIndex = ga.getInitialCoordIndex();
1705:
1706:                    switch (BufferWrapper.getBufferType(buffer)) {
1707:                    case BufferWrapper.TYPE_FLOAT:
1708:                        positionsF = new FloatBufferWrapper(buffer);
1709:                        if (debug)
1710:                            System.out.println("float positions buffer");
1711:                        break;
1712:                    case BufferWrapper.TYPE_DOUBLE:
1713:                        positionsD = new DoubleBufferWrapper(buffer);
1714:                        if (debug)
1715:                            System.out.println("double positions buffer");
1716:                        break;
1717:                    default:
1718:                        throw new IllegalArgumentException(
1719:                                "\nposition buffer must be FloatBuffer or DoubleBuffer");
1720:                    }
1721:
1722:                    if (vertexColors) {
1723:                        buffer = ga.getColorRefBuffer();
1724:                        initialColorIndex = ga.getInitialColorIndex();
1725:
1726:                        switch (BufferWrapper.getBufferType(buffer)) {
1727:                        case BufferWrapper.TYPE_BYTE:
1728:                            colorsB = new ByteBufferWrapper(buffer);
1729:                            if (debug)
1730:                                System.out.println("byte colors buffer");
1731:                            break;
1732:                        case BufferWrapper.TYPE_FLOAT:
1733:                            colorsF = new FloatBufferWrapper(buffer);
1734:                            if (debug)
1735:                                System.out.println("float colors buffer");
1736:                            break;
1737:                        default:
1738:                            throw new IllegalArgumentException(
1739:                                    "\ncolor buffer must be ByteBuffer or FloatBuffer");
1740:                        }
1741:                    }
1742:
1743:                    if (vertexNormals) {
1744:                        buffer = ga.getNormalRefBuffer();
1745:                        initialNormalIndex = ga.getInitialNormalIndex();
1746:
1747:                        switch (BufferWrapper.getBufferType(buffer)) {
1748:                        case BufferWrapper.TYPE_FLOAT:
1749:                            normals = new FloatBufferWrapper(buffer);
1750:                            if (debug)
1751:                                System.out.println("float normals buffer");
1752:                            break;
1753:                        default:
1754:                            throw new IllegalArgumentException(
1755:                                    "\nnormal buffer must be FloatBuffer");
1756:                        }
1757:                    }
1758:                }
1759:
1760:                void copyVertex(int pi, int ni, int ci, VertexCopy vc) {
1761:                    pi *= 3;
1762:                    if (positionsF != null) {
1763:                        vc.p = new Point3f(positionsF.get(pi + 0), positionsF
1764:                                .get(pi + 1), positionsF.get(pi + 2));
1765:                    } else {
1766:                        vc.p = new Point3f((float) positionsD.get(pi + 0),
1767:                                (float) positionsD.get(pi + 1),
1768:                                (float) positionsD.get(pi + 2));
1769:                    }
1770:
1771:                    ni *= 3;
1772:                    if (vertexNormals) {
1773:                        vc.n = new Vector3f(normals.get(ni + 0), normals
1774:                                .get(ni + 1), normals.get(ni + 2));
1775:                    }
1776:
1777:                    if (vertexColor3) {
1778:                        ci *= 3;
1779:                        if (colorsB != null) {
1780:                            vc.c3 = new Color3f((colorsB.get(ci + 0) & 0xff)
1781:                                    * ByteToFloatScale,
1782:                                    (colorsB.get(ci + 1) & 0xff)
1783:                                            * ByteToFloatScale, (colorsB
1784:                                            .get(ci + 2) & 0xff)
1785:                                            * ByteToFloatScale);
1786:                        } else {
1787:                            vc.c3 = new Color3f(colorsF.get(ci + 0), colorsF
1788:                                    .get(ci + 1), colorsF.get(ci + 2));
1789:                        }
1790:                        vc.c = vc.c3;
1791:                    } else if (vertexColor4) {
1792:                        ci *= 4;
1793:                        if (colorsB != null) {
1794:                            vc.c4 = new Color4f((colorsB.get(ci + 0) & 0xff)
1795:                                    * ByteToFloatScale,
1796:                                    (colorsB.get(ci + 1) & 0xff)
1797:                                            * ByteToFloatScale, (colorsB
1798:                                            .get(ci + 2) & 0xff)
1799:                                            * ByteToFloatScale, (colorsB
1800:                                            .get(ci + 3) & 0xff)
1801:                                            * ByteToFloatScale);
1802:                        } else {
1803:                            vc.c4 = new Color4f(colorsF.get(ci + 0), colorsF
1804:                                    .get(ci + 1), colorsF.get(ci + 2), colorsF
1805:                                    .get(ci + 3));
1806:                        }
1807:                        vc.c = vc.c4;
1808:                    }
1809:                }
1810:
1811:                public void processVertex(int v, int stripFlag) {
1812:                    copyVertex(v + initialPositionIndex,
1813:                            v + initialNormalIndex, v + initialColorIndex, vc);
1814:
1815:                    processVertexCopy(vc, stripFlag);
1816:                }
1817:            }
1818:
1819:            /**
1820:             * This class implements the GeometryAccessor interface for
1821:             * non-interleaved indexed geometry arrays accessed with NIO.
1822:             */
1823:            private class IndexedByRefGeometryNIO extends ByRefGeometryNIO {
1824:                IndexArrays ia = new IndexArrays();
1825:                VertexIndices vi = new VertexIndices();
1826:
1827:                IndexedByRefGeometryNIO(GeometryArray ga) {
1828:                    super (ga);
1829:                    getIndexArrays(ga, ia);
1830:                }
1831:
1832:                public void processVertex(int v, int stripFlag) {
1833:                    getVertexIndices(v, ia, vi);
1834:                    copyVertex(vi.pi, vi.ni, vi.ci, vc);
1835:                    processIndexedVertexCopy(vc, vi, stripFlag);
1836:                }
1837:            }
1838:
1839:            /**
1840:             * Convert a GeometryArray to compression stream elements and add them to
1841:             * this stream.
1842:             *
1843:             * @param ga GeometryArray to convert
1844:             * @exception IllegalArgumentException if GeometryArray has a
1845:             * dimensionality or vertex format inconsistent with the CompressionStream
1846:             */
1847:            void addGeometryArray(GeometryArray ga) {
1848:                int firstVertex = 0;
1849:                int validVertexCount = 0;
1850:                int vertexFormat = ga.getVertexFormat();
1851:                GeometryAccessor geometryAccessor = null;
1852:
1853:                if (streamType != getStreamType(ga))
1854:                    throw new IllegalArgumentException(
1855:                            "GeometryArray has inconsistent dimensionality");
1856:
1857:                if (vertexComponents != getVertexComponents(vertexFormat))
1858:                    throw new IllegalArgumentException(
1859:                            "GeometryArray has inconsistent vertex components");
1860:
1861:                // Set up for vertex data access semantics.
1862:                boolean NIO = (vertexFormat & GeometryArray.USE_NIO_BUFFER) != 0;
1863:                boolean byRef = (vertexFormat & GeometryArray.BY_REFERENCE) != 0;
1864:                boolean interleaved = (vertexFormat & GeometryArray.INTERLEAVED) != 0;
1865:                boolean indexedGeometry = ga instanceof  IndexedGeometryArray;
1866:
1867:                if (indexedGeometry) {
1868:                    if (debug)
1869:                        System.out.println("indexed");
1870:                    // Index arrays will be copied such that valid indices start at
1871:                    // offset 0 in the copied arrays.
1872:                    firstVertex = 0;
1873:                    validVertexCount = ((IndexedGeometryArray) ga)
1874:                            .getValidIndexCount();
1875:                }
1876:
1877:                if (!byRef) {
1878:                    if (debug)
1879:                        System.out.println("by-copy");
1880:                    if (indexedGeometry) {
1881:                        geometryAccessor = new IndexedByCopyGeometry(ga);
1882:                    } else {
1883:                        firstVertex = 0;
1884:                        validVertexCount = ga.getValidVertexCount();
1885:                        geometryAccessor = new ByCopyGeometry(ga);
1886:                    }
1887:                } else if (interleaved && NIO) {
1888:                    if (debug)
1889:                        System.out.println("interleaved NIO");
1890:                    if (indexedGeometry) {
1891:                        geometryAccessor = new IndexedInterleavedGeometryNIO(ga);
1892:                    } else {
1893:                        firstVertex = ga.getInitialVertexIndex();
1894:                        validVertexCount = ga.getValidVertexCount();
1895:                        geometryAccessor = new InterleavedGeometryNIO(ga);
1896:                    }
1897:                } else if (interleaved && !NIO) {
1898:                    if (debug)
1899:                        System.out.println("interleaved");
1900:                    if (indexedGeometry) {
1901:                        geometryAccessor = new IndexedInterleavedGeometryFloat(
1902:                                ga);
1903:                    } else {
1904:                        firstVertex = ga.getInitialVertexIndex();
1905:                        validVertexCount = ga.getValidVertexCount();
1906:                        geometryAccessor = new InterleavedGeometryFloat(ga);
1907:                    }
1908:                } else if (!interleaved && NIO) {
1909:                    if (debug)
1910:                        System.out.println("non-interleaved NIO");
1911:                    if (indexedGeometry) {
1912:                        geometryAccessor = new IndexedByRefGeometryNIO(ga);
1913:                    } else {
1914:                        firstVertex = 0;
1915:                        validVertexCount = ga.getValidVertexCount();
1916:                        geometryAccessor = new ByRefGeometryNIO(ga);
1917:                    }
1918:                } else if (!interleaved && !NIO) {
1919:                    if (debug)
1920:                        System.out.println("non-interleaved by-ref");
1921:                    if (indexedGeometry) {
1922:                        geometryAccessor = new IndexedByRefGeometry(ga);
1923:                    } else {
1924:                        firstVertex = 0;
1925:                        validVertexCount = ga.getValidVertexCount();
1926:                        geometryAccessor = new ByRefGeometry(ga);
1927:                    }
1928:                }
1929:
1930:                // Set up for topology.
1931:                int stripCount = 0;
1932:                int stripCounts[] = null;
1933:                int constantStripLength = 0;
1934:                int replaceCode = RESTART;
1935:                boolean strips = false;
1936:                boolean implicitStrips = false;
1937:
1938:                if (ga instanceof  TriangleStripArray
1939:                        || ga instanceof  IndexedTriangleStripArray
1940:                        || ga instanceof  LineStripArray
1941:                        || ga instanceof  IndexedLineStripArray) {
1942:
1943:                    strips = true;
1944:                    replaceCode = REPLACE_OLDEST;
1945:                    if (debug)
1946:                        System.out.println("strips");
1947:                } else if (ga instanceof  TriangleFanArray
1948:                        || ga instanceof  IndexedTriangleFanArray) {
1949:
1950:                    strips = true;
1951:                    replaceCode = REPLACE_MIDDLE;
1952:                    if (debug)
1953:                        System.out.println("fans");
1954:                } else if (ga instanceof  QuadArray
1955:                        || ga instanceof  IndexedQuadArray) {
1956:
1957:                    // Handled as fan arrays with 4 vertices per fan.
1958:                    implicitStrips = true;
1959:                    constantStripLength = 4;
1960:                    replaceCode = REPLACE_MIDDLE;
1961:                    if (debug)
1962:                        System.out.println("quads");
1963:                }
1964:
1965:                // Get strip counts.
1966:                if (strips) {
1967:                    if (indexedGeometry) {
1968:                        IndexedGeometryStripArray igsa;
1969:                        igsa = (IndexedGeometryStripArray) ga;
1970:
1971:                        stripCount = igsa.getNumStrips();
1972:                        stripCounts = new int[stripCount];
1973:                        igsa.getStripIndexCounts(stripCounts);
1974:
1975:                    } else {
1976:                        GeometryStripArray gsa;
1977:                        gsa = (GeometryStripArray) ga;
1978:
1979:                        stripCount = gsa.getNumStrips();
1980:                        stripCounts = new int[stripCount];
1981:                        gsa.getStripVertexCounts(stripCounts);
1982:                    }
1983:                }
1984:
1985:                // Build the compression stream for this shape's geometry.
1986:                int v = firstVertex;
1987:                if (strips) {
1988:                    for (int i = 0; i < stripCount; i++) {
1989:                        geometryAccessor.processVertex(v++, RESTART);
1990:                        for (int j = 1; j < stripCounts[i]; j++) {
1991:                            geometryAccessor.processVertex(v++, replaceCode);
1992:                        }
1993:                    }
1994:                } else if (implicitStrips) {
1995:                    while (v < firstVertex + validVertexCount) {
1996:                        geometryAccessor.processVertex(v++, RESTART);
1997:                        for (int j = 1; j < constantStripLength; j++) {
1998:                            geometryAccessor.processVertex(v++, replaceCode);
1999:                        }
2000:                    }
2001:                } else {
2002:                    while (v < firstVertex + validVertexCount) {
2003:                        geometryAccessor.processVertex(v++, RESTART);
2004:                    }
2005:                }
2006:            }
2007:
2008:            /**
2009:             * Print the stream to standard output.
2010:             */
2011:            void print() {
2012:                System.out
2013:                        .println("\nstream has " + stream.size() + " entries");
2014:                System.out.println("uncompressed size " + byteCount + " bytes");
2015:                System.out.println("upper position bound: "
2016:                        + mcBounds[1].toString());
2017:                System.out.println("lower position bound: "
2018:                        + mcBounds[0].toString());
2019:                System.out.println("X, Y, Z centers (" + ((float) center[0])
2020:                        + " " + ((float) center[1]) + " " + ((float) center[2])
2021:                        + ")\n" + "scale " + ((float) scale) + "\n");
2022:
2023:                Iterator i = stream.iterator();
2024:                while (i.hasNext()) {
2025:                    System.out.println(i.next().toString() + "\n");
2026:                }
2027:            }
2028:
2029:            ////////////////////////////////////////////////////////////////////////////
2030:            //									      //
2031:            // The following constructors and methods are currently the only public   //
2032:            // members of this class.  All other members are subject to revision.     //
2033:            //									      //
2034:            ////////////////////////////////////////////////////////////////////////////
2035:
2036:            /**
2037:             * Creates a CompressionStream from an array of Shape3D scene graph
2038:             * objects.  These Shape3D objects may only consist of a GeometryArray
2039:             * component and an optional Appearance component.  The resulting stream
2040:             * may be used as input to the GeometryCompressor methods.<p>
2041:             *
2042:             * Each Shape3D in the array must be of the same dimensionality (point,
2043:             * line, or surface) and have the same vertex format as the others.
2044:             * Texture coordinates are ignored.<p>
2045:             *
2046:             * If a color is specified in the material attributes for a Shape3D then
2047:             * that color is added to the CompressionStream as the current global
2048:             * color.  Subsequent colors as well as any colors bundled with vertices
2049:             * will override it.  Only the material diffuse colors are used; all other
2050:             * appearance attributes are ignored.<p>
2051:             *
2052:             * @param positionQuant
2053:             * number of bits to quantize each position's X, Y,
2054:             * and Z components, ranging from 1 to 16
2055:             *
2056:             * @param colorQuant
2057:             * number of bits to quantize each color's R, G, B, and
2058:             * alpha components, ranging from 2 to 16
2059:             *
2060:             * @param normalQuant
2061:             * number of bits for quantizing each normal's U and V components, ranging
2062:             * from 0 to 6
2063:             *
2064:             * @param shapes
2065:             * an array of Shape3D scene graph objects containing
2066:             * GeometryArray objects, all with the same vertex format and
2067:             * dimensionality
2068:             *
2069:             * @exception IllegalArgumentException if any Shape3D has an inconsistent
2070:             * dimensionality or vertex format, or if any Shape3D contains a geometry
2071:             * component that is not a GeometryArray
2072:             *
2073:             * @see Shape3D
2074:             * @see GeometryArray
2075:             * @see GeometryCompressor
2076:             */
2077:            public CompressionStream(int positionQuant, int colorQuant,
2078:                    int normalQuant, Shape3D shapes[]) {
2079:                this ();
2080:                if (debug)
2081:                    System.out.println("CompressionStream(Shape3D[]):");
2082:
2083:                if (shapes == null)
2084:                    throw new IllegalArgumentException("null Shape3D array");
2085:
2086:                if (shapes.length == 0)
2087:                    throw new IllegalArgumentException(
2088:                            "zero-length Shape3D array");
2089:
2090:                if (shapes[0] == null)
2091:                    throw new IllegalArgumentException(
2092:                            "Shape3D at index 0 is null");
2093:
2094:                long startTime = 0;
2095:                if (benchmark)
2096:                    startTime = System.currentTimeMillis();
2097:
2098:                Geometry g = shapes[0].getGeometry();
2099:                if (!(g instanceof  GeometryArray))
2100:                    throw new IllegalArgumentException(
2101:                            "Shape3D at index 0 is not a GeometryArray");
2102:
2103:                GeometryArray ga = (GeometryArray) g;
2104:                this .streamType = getStreamType(ga);
2105:                this .vertexComponents = getVertexComponents(ga
2106:                        .getVertexFormat());
2107:
2108:                // Add global quantization parameters to the start of the stream.
2109:                addPositionQuantization(positionQuant);
2110:                addColorQuantization(colorQuant);
2111:                addNormalQuantization(normalQuant);
2112:
2113:                // Loop through all shapes.
2114:                for (int s = 0; s < shapes.length; s++) {
2115:                    if (debug)
2116:                        System.out.println("\nShape3D " + s + ":");
2117:
2118:                    g = shapes[s].getGeometry();
2119:                    if (!(g instanceof  GeometryArray))
2120:                        throw new IllegalArgumentException("Shape3D at index "
2121:                                + s + " is not a GeometryArray");
2122:
2123:                    // Check for material color and add it to the stream if it exists.
2124:                    Appearance a = shapes[s].getAppearance();
2125:                    if (a != null) {
2126:                        Material m = a.getMaterial();
2127:                        if (m != null) {
2128:                            m.getDiffuseColor(c3f);
2129:                            if (vertexColor4) {
2130:                                c4f.set(c3f.x, c3f.y, c3f.z, 1.0f);
2131:                                addColor(c4f);
2132:                            } else
2133:                                addColor(c3f);
2134:                        }
2135:                    }
2136:
2137:                    // Add the geometry array to the stream.
2138:                    addGeometryArray((GeometryArray) g);
2139:                }
2140:
2141:                if (benchmark) {
2142:                    long t = System.currentTimeMillis() - startTime;
2143:                    System.out.println("\nCompressionStream:\n" + shapes.length
2144:                            + " shapes in " + (t / 1000f) + " sec");
2145:                }
2146:            }
2147:
2148:            /**
2149:             * Creates a CompressionStream from an array of Shape3D scene graph
2150:             * objects.  These Shape3D objects may only consist of a GeometryArray
2151:             * component and an optional Appearance component.  The resulting stream
2152:             * may be used as input to the GeometryCompressor methods.<p>
2153:             *
2154:             * Each Shape3D in the array must be of the same dimensionality (point,
2155:             * line, or surface) and have the same vertex format as the others.
2156:             * Texture coordinates are ignored.<p>
2157:             *
2158:             * If a color is specified in the material attributes for a Shape3D then
2159:             * that color is added to the CompressionStream as the current global
2160:             * color.  Subsequent colors as well as any colors bundled with vertices
2161:             * will override it.  Only the material diffuse colors are used; all other
2162:             * appearance attributes are ignored.<p>
2163:             *
2164:             * Defaults of 16, 9, and 6 bits are used as the quantization values for
2165:             * positions, colors, and normals respectively.  These are the maximum
2166:             * resolution values defined for positions and normals; the default of 9
2167:             * for color is the equivalent of the 8 bits of RGBA component resolution
2168:             * commonly available in graphics frame buffers.<p>
2169:             *
2170:             * @param shapes
2171:             * an array of Shape3D scene graph objects containing
2172:             * GeometryArray objects, all with the same vertex format and
2173:             * dimensionality.
2174:             *
2175:             * @exception IllegalArgumentException if any Shape3D has an inconsistent
2176:             * dimensionality or vertex format, or if any Shape3D contains a geometry
2177:             * component that is not a GeometryArray
2178:             *
2179:             * @see Shape3D
2180:             * @see GeometryArray
2181:             * @see GeometryCompressor
2182:             */
2183:            public CompressionStream(Shape3D shapes[]) {
2184:                this (16, 9, 6, shapes);
2185:            }
2186:
2187:            /**
2188:             * Creates a CompressionStream from an array of GeometryInfo objects.  The
2189:             * resulting stream may be used as input to the GeometryCompressor
2190:             * methods.<p>
2191:             *
2192:             * Each GeometryInfo in the array must be of the same dimensionality
2193:             * (point, line, or surface) and have the same vertex format as the
2194:             * others.  Texture coordinates are ignored.<p>
2195:             *
2196:             * @param positionQuant
2197:             * number of bits to quantize each position's X, Y,
2198:             * and Z components, ranging from 1 to 16
2199:             *
2200:             * @param colorQuant
2201:             * number of bits to quantize each color's R, G, B, and
2202:             * alpha components, ranging from 2 to 16
2203:             *
2204:             * @param normalQuant
2205:             * number of bits for quantizing each normal's U and V components, ranging
2206:             * from 0 to 6
2207:             *
2208:             * @param geometry
2209:             * an array of GeometryInfo objects, all with the same
2210:             * vertex format and dimensionality
2211:             *
2212:             * @exception IllegalArgumentException if any GeometryInfo object has an
2213:             * inconsistent dimensionality or vertex format
2214:             *
2215:             * @see GeometryInfo
2216:             * @see GeometryCompressor
2217:             */
2218:            public CompressionStream(int positionQuant, int colorQuant,
2219:                    int normalQuant, GeometryInfo geometry[]) {
2220:                this ();
2221:                if (debug)
2222:                    System.out.println("CompressionStream(GeometryInfo[])");
2223:
2224:                if (geometry == null)
2225:                    throw new IllegalArgumentException(
2226:                            "null GeometryInfo array");
2227:
2228:                if (geometry.length == 0)
2229:                    throw new IllegalArgumentException(
2230:                            "zero-length GeometryInfo array");
2231:
2232:                if (geometry[0] == null)
2233:                    throw new IllegalArgumentException(
2234:                            "GeometryInfo at index 0 is null");
2235:
2236:                long startTime = 0;
2237:                if (benchmark)
2238:                    startTime = System.currentTimeMillis();
2239:
2240:                GeometryArray ga = geometry[0].getGeometryArray();
2241:                this .streamType = getStreamType(ga);
2242:                this .vertexComponents = getVertexComponents(ga
2243:                        .getVertexFormat());
2244:
2245:                // Add global quantization parameters to the start of the stream.
2246:                addPositionQuantization(positionQuant);
2247:                addColorQuantization(colorQuant);
2248:                addNormalQuantization(normalQuant);
2249:
2250:                // Loop through all GeometryInfo objects and add them to the stream.
2251:                for (int i = 0; i < geometry.length; i++) {
2252:                    if (debug)
2253:                        System.out.println("\nGeometryInfo " + i + ":");
2254:                    addGeometryArray(geometry[i].getGeometryArray());
2255:                }
2256:
2257:                if (benchmark) {
2258:                    long t = System.currentTimeMillis() - startTime;
2259:                    System.out.println("\nCompressionStream:\n"
2260:                            + geometry.length + " GeometryInfo objects in "
2261:                            + (t / 1000f) + " sec");
2262:                }
2263:            }
2264:
2265:            /**
2266:             * Creates a CompressionStream from an array of GeometryInfo objects.  The
2267:             * resulting stream may be used as input to the GeometryCompressor
2268:             * methods.<p>
2269:             *
2270:             * Each GeometryInfo in the array must be of the same dimensionality
2271:             * (point, line, or surface) and have the same vertex format as the
2272:             * others.  Texture coordinates are ignored.<p>
2273:             *
2274:             * Defaults of 16, 9, and 6 bits are used as the quantization values for
2275:             * positions, colors, and normals respectively.  These are the maximum
2276:             * resolution values defined for positions and normals; the default of 9
2277:             * for color is the equivalent of the 8 bits of RGBA component resolution
2278:             * commonly available in graphics frame buffers.<p>
2279:             *
2280:             * @param geometry
2281:             * an array of GeometryInfo objects, all with the same
2282:             * vertex format and dimensionality
2283:             *
2284:             * @exception IllegalArgumentException if any GeometryInfo object has an
2285:             * inconsistent dimensionality or vertex format
2286:             *
2287:             * @see GeometryInfo
2288:             * @see GeometryCompressor
2289:             */
2290:            public CompressionStream(GeometryInfo geometry[]) {
2291:                this (16, 9, 6, geometry);
2292:            }
2293:
2294:            /**
2295:             * Get the original bounds of the coordinate data, in modeling coordinates.
2296:             * Coordinate data is positioned and scaled to a normalized cube after
2297:             * compression.  
2298:             * 
2299:             * @return Point3d array of length 2, where the 1st Point3d is the lower
2300:             * bounds and the 2nd Point3d is the upper bounds.
2301:             * @since Java 3D 1.3
2302:             */
2303:            public Point3d[] getModelBounds() {
2304:                Point3d[] bounds = new Point3d[2];
2305:                bounds[0] = new Point3d(mcBounds[0]);
2306:                bounds[1] = new Point3d(mcBounds[1]);
2307:                return bounds;
2308:            }
2309:
2310:            /**
2311:             * Get the bounds of the compressed object in normalized coordinates.
2312:             * These have an maximum bounds by [-1.0 .. +1.0] across each axis.
2313:             * 
2314:             * @return Point3d array of length 2, where the 1st Point3d is the lower
2315:             * bounds and the 2nd Point3d is the upper bounds.
2316:             * @since Java 3D 1.3
2317:             */
2318:            public Point3d[] getNormalizedBounds() {
2319:                Point3d[] bounds = new Point3d[2];
2320:                bounds[0] = new Point3d(ncBounds[0]);
2321:                bounds[1] = new Point3d(ncBounds[1]);
2322:                return bounds;
2323:            }
2324:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.