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


0001:        /*
0002:         * $RCSfile: GeometryDecompressor.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.3 $
0041:         * $Date: 2007/02/09 17:20:22 $
0042:         * $State: Exp $
0043:         */
0044:
0045:        package com.sun.j3d.utils.geometry.compression;
0046:
0047:        import com.sun.j3d.internal.J3dUtilsI18N;
0048:        import javax.vecmath.Color4f;
0049:        import javax.vecmath.Point3f;
0050:        import javax.vecmath.Vector3f;
0051:
0052:        /**
0053:         * This abstract class provides the base methods needed to create a geometry
0054:         * decompressor.  Subclasses must implement a backend to handle the output,
0055:         * consisting of a generalized triangle strip, line strip, or point array,
0056:         * along with possible global color and normal changes.
0057:         */
0058:        abstract class GeometryDecompressor {
0059:            private static final boolean debug = false;
0060:            private static final boolean benchmark = false;
0061:
0062:            /**
0063:             * Compressed geometry format version supported.
0064:             */
0065:            static final int majorVersionNumber = 1;
0066:            static final int minorVersionNumber = 0;
0067:            static final int minorMinorVersionNumber = 2;
0068:
0069:            /**
0070:             * This method is called when a SetState command is encountered in the
0071:             * decompression stream.  
0072:             *
0073:             * @param bundlingNorm true indicates normals are bundled with vertices
0074:             * @param bundlingColor true indicates colors are bundled with vertices
0075:             * @param doingAlpha true indicates alpha values are bundled with vertices
0076:             */
0077:            abstract void outputVertexFormat(boolean bundlingNorm,
0078:                    boolean bundlingColor, boolean doingAlpha);
0079:
0080:            /**
0081:             * This method captures the vertex output of the decompressor.  The normal
0082:             * or color references may be null if the corresponding data is not
0083:             * bundled with the vertices in the compressed geometry buffer.  Alpha
0084:             * values may be included in the color.  
0085:             * 
0086:             * @param position The coordinates of the vertex.
0087:             * @param normal The normal bundled with the vertex.  May be null.
0088:             * @param color The color bundled with the vertex.  May be null.  
0089:             * Alpha may be present.
0090:             * @param vertexReplaceCode Specifies the generalized strip flag
0091:             * that is bundled with each vertex.
0092:             * @see GeneralizedStripFlags
0093:             * @see CompressedGeometryHeader
0094:             */
0095:            abstract void outputVertex(Point3f position, Vector3f normal,
0096:                    Color4f color, int vertexReplaceCode);
0097:
0098:            /**
0099:             * This method captures the global color output of the decompressor.  It
0100:             * is only invoked if colors are not bundled with the vertex data.  The
0101:             * global color applies to all succeeding vertices until the next time the
0102:             * method is invoked.
0103:             *
0104:             * @param color The current global color.
0105:             */
0106:            abstract void outputColor(Color4f color);
0107:
0108:            /**
0109:             * This method captures the global normal output of the decompressor.  It
0110:             * is only invoked if normals are not bundled with the vertex data.  The
0111:             * global normal applies to all succeeding vertices until the next time the
0112:             * method is invoked.
0113:             *
0114:             * @param normal The current global normal.
0115:             */
0116:            abstract void outputNormal(Vector3f normal);
0117:
0118:            // Geometry compression opcodes.
0119:            private static final int GC_VERTEX = 0x40;
0120:            private static final int GC_SET_NORM = 0xC0;
0121:            private static final int GC_SET_COLOR = 0x80;
0122:            private static final int GC_MESH_B_R = 0x20;
0123:            private static final int GC_SET_STATE = 0x18;
0124:            private static final int GC_SET_TABLE = 0x10;
0125:            private static final int GC_PASS_THROUGH = 0x08;
0126:            private static final int GC_EOS = 0x00;
0127:            private static final int GC_V_NO_OP = 0x01;
0128:            private static final int GC_SKIP_8 = 0x07;
0129:
0130:            // Three 64-entry decompression tables are used: gctables[0] for
0131:            // positions, gctables[1] for colors, and gctables[2] for normals.
0132:            private HuffmanTableEntry gctables[][];
0133:
0134:            /**
0135:             * Decompression table entry.
0136:             */
0137:            static class HuffmanTableEntry {
0138:                int tagLength, dataLength;
0139:                int rightShift, absolute;
0140:
0141:                public String toString() {
0142:                    return " tag length: " + tagLength + " data length: "
0143:                            + dataLength + " shift: " + rightShift
0144:                            + " abs/rel: " + absolute;
0145:                }
0146:            }
0147:
0148:            // A 16-entry mesh buffer is used.
0149:            private MeshBufferEntry meshBuffer[];
0150:            private int meshIndex = 15;
0151:            private int meshState;
0152:
0153:            // meshState values.  These are needed to determine if colors and/or
0154:            // normals should come from meshBuffer or from SetColor or SetNormal.
0155:            private static final int USE_MESH_NORMAL = 0x1;
0156:            private static final int USE_MESH_COLOR = 0x2;
0157:
0158:            /**
0159:             * Mesh buffer entry containing position, normal, and color.
0160:             */
0161:            static class MeshBufferEntry {
0162:                short x, y, z;
0163:                short octant, sextant, u, v;
0164:                short r, g, b, a;
0165:            }
0166:
0167:            // Geometry compression state variables.
0168:            private short curX, curY, curZ;
0169:            private short curR, curG, curB, curA;
0170:            private int curSex, curOct, curU, curV;
0171:
0172:            // Current vertex data.
0173:            private Point3f curPos;
0174:            private Vector3f curNorm;
0175:            private Color4f curColor;
0176:            private int repCode;
0177:
0178:            // Flags indicating what data is bundled with the vertex.
0179:            private boolean bundlingNorm;
0180:            private boolean bundlingColor;
0181:            private boolean doingAlpha;
0182:
0183:            // Internal decompression buffering variables.
0184:            private int currentHeader = 0;
0185:            private int nextHeader = 0;
0186:            private int bitBuffer = 0;
0187:            private int bitBufferCount = 32;
0188:
0189:            // Used for benchmarking if so configured.
0190:            private long startTime;
0191:            private int vertexCount;
0192:
0193:            // Bit-field masks: BMASK[i] = (1<<i)-1
0194:            private static final int BMASK[] = { 0x0, 0x1, 0x3, 0x7, 0xF, 0x1F,
0195:                    0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF,
0196:                    0x3FFF, 0x7FFF, 0xFFFF, 0x1FFFF, 0x3FFFF, 0x7FFFF, 0xFFFFF,
0197:                    0x1FFFFF, 0x3FFFFF, 0x7FFFFF, 0xFFFFFF, 0x1FFFFFF,
0198:                    0x3FFFFFF, 0x7FFFFFF, 0xFFFFFFF, 0x1FFFFFFF, 0x3FFFFFFF,
0199:                    0x7FFFFFFF, 0xFFFFFFFF, };
0200:
0201:            // A reference to the compressed data and the current offset.
0202:            private byte gcData[];
0203:            private int gcIndex;
0204:
0205:            // The normals table for decoding 6-bit [u,v] spherical sextant coordinates.
0206:            private static final double gcNormals[][][];
0207:            private static final double NORMAL_MAX_Y_ANG = 0.615479709;
0208:            private static final boolean printNormalTable = false;
0209:
0210:            /**
0211:             * Initialize the normals table.
0212:             */
0213:            static {
0214:                int i, j, inx, iny, inz;
0215:                double th, psi, qnx, qny, qnz;
0216:
0217:                gcNormals = new double[65][65][3];
0218:
0219:                for (i = 0; i < 65; i++) {
0220:                    for (j = 0; j < 65; j++) {
0221:                        if (i + j > 64)
0222:                            continue;
0223:
0224:                        psi = NORMAL_MAX_Y_ANG * (i / 64.0);
0225:                        th = Math.asin(Math.tan(NORMAL_MAX_Y_ANG
0226:                                * ((64 - j) / 64.0)));
0227:
0228:                        qnx = Math.cos(th) * Math.cos(psi);
0229:                        qny = Math.sin(psi);
0230:                        qnz = Math.sin(th) * Math.cos(psi);
0231:
0232:                        //  Convert the floating point normal to s1.14 bit notation,
0233:                        //  then back again.
0234:                        qnx = qnx * 16384.0;
0235:                        inx = (int) qnx;
0236:                        qnx = (double) inx;
0237:                        qnx = qnx / 16384.0;
0238:
0239:                        qny = qny * 16384.0;
0240:                        iny = (int) qny;
0241:                        qny = (double) iny;
0242:                        qny = qny / 16384.0;
0243:
0244:                        qnz = qnz * 16384.0;
0245:                        inz = (int) qnz;
0246:                        qnz = (double) inz;
0247:                        qnz = qnz / 16384.0;
0248:
0249:                        gcNormals[i][j][0] = qnx;
0250:                        gcNormals[i][j][1] = qny;
0251:                        gcNormals[i][j][2] = qnz;
0252:                    }
0253:                }
0254:
0255:                if (printNormalTable) {
0256:                    System.out.println("struct {");
0257:                    System.out.println("    double nx, ny, nz ;");
0258:                    System.out.println("} gcNormals[65][65] = {");
0259:                    for (i = 0; i <= 64; i++) {
0260:                        System.out.println("{");
0261:                        for (j = 0; j <= 64; j++) {
0262:                            if (j + i > 64)
0263:                                continue;
0264:                            System.out.println("{ " + gcNormals[i][j][0] + ", "
0265:                                    + gcNormals[i][j][1] + ", "
0266:                                    + gcNormals[i][j][2] + " }");
0267:                        }
0268:                        System.out.println("},");
0269:                    }
0270:                    System.out.println("}");
0271:                }
0272:            }
0273:
0274:            //
0275:            // The constructor.
0276:            //
0277:            GeometryDecompressor() {
0278:                curPos = new Point3f();
0279:                curNorm = new Vector3f();
0280:                curColor = new Color4f();
0281:                gctables = new HuffmanTableEntry[3][64];
0282:
0283:                for (int i = 0; i < 64; i++) {
0284:                    gctables[0][i] = new HuffmanTableEntry();
0285:                    gctables[1][i] = new HuffmanTableEntry();
0286:                    gctables[2][i] = new HuffmanTableEntry();
0287:                }
0288:
0289:                meshBuffer = new MeshBufferEntry[16];
0290:                for (int i = 0; i < 16; i++)
0291:                    meshBuffer[i] = new MeshBufferEntry();
0292:            }
0293:
0294:            /**
0295:             * Check version numbers and return true if compatible.
0296:             */
0297:            boolean checkVersion(int majorVersionNumber, int minorVersionNumber) {
0298:                return ((majorVersionNumber < this .majorVersionNumber) || ((majorVersionNumber == this .majorVersionNumber) && (minorVersionNumber <= this .minorVersionNumber)));
0299:            }
0300:
0301:            /**
0302:             * Decompress data and invoke abstract output methods.
0303:             *
0304:             * @param start byte offset to start of compressed geometry in data array
0305:             * @param length size of compressed geometry in bytes
0306:             * @param data array containing compressed geometry buffer of the
0307:             * specified length at the given offset from the start of the array
0308:             * @exception ArrayIndexOutOfBoundsException if start+length > data size
0309:             */
0310:            void decompress(int start, int length, byte data[]) {
0311:                if (debug)
0312:                    System.out.println("GeometryDecompressor.decompress\n"
0313:                            + " start: " + start + " length: " + length
0314:                            + " data array size: " + data.length);
0315:                if (benchmark)
0316:                    benchmarkStart(length);
0317:
0318:                if (start + length > data.length)
0319:                    throw new ArrayIndexOutOfBoundsException(J3dUtilsI18N
0320:                            .getString("GeometryDecompressor0"));
0321:
0322:                // Set reference to compressed data and skip to start of data.
0323:                gcData = data;
0324:                gcIndex = start;
0325:
0326:                // Initialize state.
0327:                bitBufferCount = 0;
0328:                meshState = 0;
0329:                bundlingNorm = false;
0330:                bundlingColor = false;
0331:                doingAlpha = false;
0332:                repCode = 0;
0333:
0334:                // Headers are interleaved for hardware implementations, so the
0335:                // first is always a nullop.
0336:                nextHeader = GC_V_NO_OP;
0337:
0338:                // Enter decompression loop.
0339:                while (gcIndex < start + length)
0340:                    processDecompression();
0341:
0342:                // Finish out any bits left in bitBuffer.
0343:                while (bitBufferCount > 0)
0344:                    processDecompression();
0345:
0346:                if (benchmark)
0347:                    benchmarkPrint(length);
0348:            }
0349:
0350:            //
0351:            // Return the next bitCount bits of compressed data.
0352:            //
0353:            private int getBits(int bitCount, String d) {
0354:                int bits;
0355:
0356:                if (debug)
0357:                    System.out.print(" getBits(" + bitCount + ") " + d + ", "
0358:                            + bitBufferCount + " available at gcIndex "
0359:                            + gcIndex);
0360:
0361:                if (bitCount == 0) {
0362:                    if (debug)
0363:                        System.out.println(": got 0x0");
0364:                    return 0;
0365:                }
0366:
0367:                if (bitBufferCount == 0) {
0368:                    bitBuffer = (((gcData[gcIndex++] & 0xff) << 24)
0369:                            | ((gcData[gcIndex++] & 0xff) << 16)
0370:                            | ((gcData[gcIndex++] & 0xff) << 8) | ((gcData[gcIndex++] & 0xff)));
0371:
0372:                    bitBufferCount = 32;
0373:                }
0374:
0375:                if (bitBufferCount >= bitCount) {
0376:                    bits = (bitBuffer >>> (32 - bitCount)) & BMASK[bitCount];
0377:                    bitBuffer = bitBuffer << bitCount;
0378:                    bitBufferCount -= bitCount;
0379:                } else {
0380:                    bits = (bitBuffer >>> (32 - bitCount)) & BMASK[bitCount];
0381:                    bits = bits >>> (bitCount - bitBufferCount);
0382:                    bits = bits << (bitCount - bitBufferCount);
0383:
0384:                    bitBuffer = (((gcData[gcIndex++] & 0xff) << 24)
0385:                            | ((gcData[gcIndex++] & 0xff) << 16)
0386:                            | ((gcData[gcIndex++] & 0xff) << 8) | ((gcData[gcIndex++] & 0xff)));
0387:
0388:                    bits = bits
0389:                            | ((bitBuffer >>> (32 - (bitCount - bitBufferCount))) & BMASK[bitCount
0390:                                    - bitBufferCount]);
0391:
0392:                    bitBuffer = bitBuffer << (bitCount - bitBufferCount);
0393:                    bitBufferCount = 32 - (bitCount - bitBufferCount);
0394:                }
0395:
0396:                if (debug)
0397:                    System.out.println(": got 0x" + Integer.toHexString(bits));
0398:
0399:                return bits;
0400:            }
0401:
0402:            //
0403:            // Shuffle interleaved headers and opcodes.
0404:            //
0405:            private void processDecompression() {
0406:                int mbp;
0407:                currentHeader = nextHeader;
0408:
0409:                if ((currentHeader & 0xC0) == GC_VERTEX) {
0410:                    // Process a vertex.
0411:                    if (!bundlingNorm && !bundlingColor) {
0412:                        // get next opcode, process current position opcode
0413:                        nextHeader = getBits(8, "header");
0414:                        mbp = processDecompressionOpcode(0);
0415:
0416:                    } else if (bundlingNorm && !bundlingColor) {
0417:                        // get normal header, process current position opcode
0418:                        nextHeader = getBits(6, "normal");
0419:                        mbp = processDecompressionOpcode(0);
0420:                        currentHeader = nextHeader | GC_SET_NORM;
0421:
0422:                        // get next opcode, process current normal opcode
0423:                        nextHeader = getBits(8, "header");
0424:                        processDecompressionOpcode(mbp);
0425:
0426:                    } else if (!bundlingNorm && bundlingColor) {
0427:                        // get color header, process current position opcode
0428:                        nextHeader = getBits(6, "color");
0429:                        mbp = processDecompressionOpcode(0);
0430:                        currentHeader = nextHeader | GC_SET_COLOR;
0431:
0432:                        // get next opcode, process current color opcode
0433:                        nextHeader = getBits(8, "header");
0434:                        processDecompressionOpcode(mbp);
0435:
0436:                    } else {
0437:                        // get normal header, process current position opcode
0438:                        nextHeader = getBits(6, "normal");
0439:                        mbp = processDecompressionOpcode(0);
0440:                        currentHeader = nextHeader | GC_SET_NORM;
0441:
0442:                        // get color header, process current normal opcode
0443:                        nextHeader = getBits(6, "color");
0444:                        processDecompressionOpcode(mbp);
0445:                        currentHeader = nextHeader | GC_SET_COLOR;
0446:
0447:                        // get next opcode, process current color opcode
0448:                        nextHeader = getBits(8, "header");
0449:                        processDecompressionOpcode(mbp);
0450:                    }
0451:
0452:                    // Send out the complete vertex.
0453:                    outputVertex(curPos, curNorm, curColor, repCode);
0454:                    if (benchmark)
0455:                        vertexCount++;
0456:
0457:                    // meshState bits get turned off in the setColor and setNormal
0458:                    // routines in order to keep track of what data a mesh buffer
0459:                    // reference should use.
0460:                    meshState |= USE_MESH_NORMAL;
0461:                    meshState |= USE_MESH_COLOR;
0462:
0463:                } else {
0464:                    // Non-vertex case: get next opcode, then process current opcode.
0465:                    nextHeader = getBits(8, "header");
0466:                    processDecompressionOpcode(0);
0467:                }
0468:            }
0469:
0470:            //
0471:            // Decode the opcode in currentHeader, and dispatch to the appropriate
0472:            // processing method.  
0473:            //
0474:            private int processDecompressionOpcode(int mbp) {
0475:                if ((currentHeader & 0xC0) == GC_SET_NORM)
0476:                    processSetNormal(mbp);
0477:                else if ((currentHeader & 0xC0) == GC_SET_COLOR)
0478:                    processSetColor(mbp);
0479:                else if ((currentHeader & 0xC0) == GC_VERTEX)
0480:                    // Return the state of the mesh buffer push bit
0481:                    // when processing a vertex.
0482:                    return processVertex();
0483:                else if ((currentHeader & 0xE0) == GC_MESH_B_R) {
0484:                    processMeshBR();
0485:
0486:                    // Send out the complete vertex.
0487:                    outputVertex(curPos, curNorm, curColor, repCode);
0488:                    if (benchmark)
0489:                        vertexCount++;
0490:
0491:                    // meshState bits get turned off in the setColor and setNormal
0492:                    // routines in order to keep track of what data a mesh buffer
0493:                    // reference should use.
0494:                    meshState |= USE_MESH_NORMAL;
0495:                    meshState |= USE_MESH_COLOR;
0496:                } else if ((currentHeader & 0xF8) == GC_SET_STATE)
0497:                    processSetState();
0498:                else if ((currentHeader & 0xF8) == GC_SET_TABLE)
0499:                    processSetTable();
0500:                else if ((currentHeader & 0xFF) == GC_EOS)
0501:                    processEos();
0502:                else if ((currentHeader & 0xFF) == GC_V_NO_OP)
0503:                    processVNoop();
0504:                else if ((currentHeader & 0xFF) == GC_PASS_THROUGH)
0505:                    processPassThrough();
0506:                else if ((currentHeader & 0xFF) == GC_SKIP_8)
0507:                    processSkip8();
0508:
0509:                return 0;
0510:            }
0511:
0512:            //
0513:            //  Process a set state opcode.
0514:            //
0515:            private void processSetState() {
0516:                int ii;
0517:                if (debug)
0518:                    System.out.println("GeometryDecompressor.processSetState");
0519:
0520:                ii = getBits(3, "bundling");
0521:
0522:                bundlingNorm = ((currentHeader & 0x1) != 0);
0523:                bundlingColor = (((ii >>> 2) & 0x1) != 0);
0524:                doingAlpha = (((ii >>> 1) & 0x1) != 0);
0525:
0526:                if (debug)
0527:                    System.out.println(" bundling normal: " + bundlingNorm
0528:                            + " bundling color: " + bundlingColor
0529:                            + " alpha present: " + doingAlpha);
0530:
0531:                // Call the abstract output implementation.
0532:                outputVertexFormat(bundlingNorm, bundlingColor, doingAlpha);
0533:            }
0534:
0535:            //
0536:            // Process a set decompression table opcode.
0537:            //
0538:            // Extract the parameters of the table set command,
0539:            // and set the approprate table entries.
0540:            //
0541:            private void processSetTable() {
0542:                HuffmanTableEntry gct[];
0543:                int i, adr, tagLength, dataLength, rightShift, absolute;
0544:                int ii, index;
0545:
0546:                if (debug)
0547:                    System.out.println("GeometryDecompressor.processSetTable");
0548:
0549:                // Get reference to approprate 64 entry table.
0550:                index = (currentHeader & 0x6) >>> 1;
0551:                gct = gctables[index];
0552:
0553:                // Get the remaining bits of the set table command.
0554:                ii = getBits(15, "set table");
0555:
0556:                // Extract the individual fields from the two bit strings.
0557:                adr = ((currentHeader & 0x1) << 6) | ((ii >>> 9) & 0x3F);
0558:
0559:                // Get data length.  For positions and colors, 0 really means 16, as 0
0560:                // lengths are meaningless for them.  Normal components are allowed to
0561:                // have lengths of 0.
0562:                dataLength = (ii >>> 5) & 0x0F;
0563:                if (dataLength == 0 && index != 2)
0564:                    dataLength = 16;
0565:
0566:                rightShift = ii & 0x0F;
0567:                absolute = (ii >>> 4) & 0x1;
0568:
0569:                //
0570:                // Decode the tag length from the address field by finding the
0571:                // first set 1 from the left in the bitfield.
0572:                //
0573:                for (tagLength = 6; tagLength > 0; tagLength--) {
0574:                    if ((adr >> tagLength) != 0)
0575:                        break;
0576:                }
0577:
0578:                // Shift the address bits up into place, and off the leading 1.
0579:                adr = (adr << (6 - tagLength)) & 0x3F;
0580:
0581:                if (debug)
0582:                    System.out.println(" table "
0583:                            + ((currentHeader & 0x6) >>> 1) + " address " + adr
0584:                            + " tag length " + tagLength + " data length "
0585:                            + dataLength + " shift " + rightShift
0586:                            + " absolute " + absolute);
0587:
0588:                // Fill in the table fields with the specified values.
0589:                for (i = 0; i < (1 << (6 - tagLength)); i++) {
0590:                    gct[adr + i].tagLength = tagLength;
0591:                    gct[adr + i].dataLength = dataLength;
0592:                    gct[adr + i].rightShift = rightShift;
0593:                    gct[adr + i].absolute = absolute;
0594:                }
0595:            }
0596:
0597:            //
0598:            // Process a vertex opcode.  Any bundled normal and/or color will be
0599:            // processed by separate methods.  Return the mesh buffer push indicator.
0600:            //
0601:            private int processVertex() {
0602:                HuffmanTableEntry gct;
0603:                float fX, fY, fZ;
0604:                short dx, dy, dz;
0605:                int mbp, x, y, z, dataLen;
0606:                int ii;
0607:
0608:                // If the next command is a mesh buffer reference
0609:                // then use colors and normals from the mesh buffer.
0610:                meshState = 0;
0611:
0612:                // Get a reference to the approprate tag table entry.
0613:                gct = gctables[0][currentHeader & 0x3F];
0614:
0615:                if (debug)
0616:                    System.out.println("GeometryDecompressor.processVertex\n"
0617:                            + gct.toString());
0618:
0619:                // Get the true length of the data.
0620:                dataLen = gct.dataLength - gct.rightShift;
0621:
0622:                // Read in the replace code and mesh buffer push bits,
0623:                // if they're not in the current header.
0624:                if (6 - (3 * dataLen) - gct.tagLength > 0) {
0625:                    int numBits = 6 - (3 * dataLen) - gct.tagLength;
0626:                    int jj;
0627:
0628:                    jj = currentHeader & BMASK[numBits];
0629:                    ii = getBits(3 - numBits, "repcode/mbp");
0630:                    ii |= (jj << (3 - numBits));
0631:                } else
0632:                    ii = getBits(3, "repcode/mbp");
0633:
0634:                repCode = ii >>> 1;
0635:                mbp = ii & 0x1;
0636:
0637:                // Read in x, y, and z components.
0638:                x = currentHeader & BMASK[6 - gct.tagLength];
0639:
0640:                if (gct.tagLength + dataLen == 6) {
0641:                    y = getBits(dataLen, "y");
0642:                    z = getBits(dataLen, "z");
0643:                } else if (gct.tagLength + dataLen < 6) {
0644:                    x = x >> (6 - gct.tagLength - dataLen);
0645:
0646:                    y = currentHeader & BMASK[6 - gct.tagLength - dataLen];
0647:                    if (gct.tagLength + 2 * dataLen == 6) {
0648:                        z = getBits(dataLen, "z");
0649:                    } else if (gct.tagLength + 2 * dataLen < 6) {
0650:                        y = y >> (6 - gct.tagLength - 2 * dataLen);
0651:
0652:                        z = currentHeader
0653:                                & BMASK[6 - gct.tagLength - 2 * dataLen];
0654:                        if (gct.tagLength + 3 * dataLen < 6) {
0655:                            z = z >> (6 - gct.tagLength - 3 * dataLen);
0656:                        } else if (gct.tagLength + 3 * dataLen > 6) {
0657:                            ii = getBits(dataLen
0658:                                    - (6 - gct.tagLength - 2 * dataLen), "z");
0659:                            z = (z << (dataLen - (6 - gct.tagLength - 2 * dataLen)))
0660:                                    | ii;
0661:                        }
0662:                    } else {
0663:                        ii = getBits(dataLen - (6 - gct.tagLength - dataLen),
0664:                                "y");
0665:                        y = (y << (dataLen - (6 - gct.tagLength - dataLen)))
0666:                                | ii;
0667:                        z = getBits(dataLen, "z");
0668:                    }
0669:                } else {
0670:                    ii = getBits(dataLen - (6 - gct.tagLength), "x");
0671:                    x = (x << (dataLen - (6 - gct.tagLength))) | ii;
0672:                    y = getBits(dataLen, "y");
0673:                    z = getBits(dataLen, "z");
0674:                }
0675:
0676:                // Sign extend delta x y z components.
0677:                x = x << (32 - dataLen);
0678:                x = x >> (32 - dataLen);
0679:                y = y << (32 - dataLen);
0680:                y = y >> (32 - dataLen);
0681:                z = z << (32 - dataLen);
0682:                z = z >> (32 - dataLen);
0683:
0684:                // Normalize values.
0685:                dx = (short) (x << gct.rightShift);
0686:                dy = (short) (y << gct.rightShift);
0687:                dz = (short) (z << gct.rightShift);
0688:
0689:                // Update current position, first adding deltas if in relative mode.
0690:                if (gct.absolute != 0) {
0691:                    curX = dx;
0692:                    curY = dy;
0693:                    curZ = dz;
0694:                    if (debug)
0695:                        System.out.println(" absolute position: " + curX + " "
0696:                                + curY + " " + curZ);
0697:                } else {
0698:                    curX += dx;
0699:                    curY += dy;
0700:                    curZ += dz;
0701:                    if (debug)
0702:                        System.out.println(" delta position: " + dx + " " + dy
0703:                                + " " + dz);
0704:                }
0705:
0706:                // Do optional mesh buffer push.
0707:                if (mbp != 0) {
0708:                    // Increment to next position (meshIndex is initialized to 15).
0709:                    meshIndex = (meshIndex + 1) & 0xF;
0710:                    meshBuffer[meshIndex].x = curX;
0711:                    meshBuffer[meshIndex].y = curY;
0712:                    meshBuffer[meshIndex].z = curZ;
0713:                    if (debug)
0714:                        System.out
0715:                                .println(" pushed position into mesh buffer at "
0716:                                        + meshIndex);
0717:                }
0718:
0719:                // Convert point back to [-1..1] floating point.
0720:                fX = curX;
0721:                fX /= 32768.0;
0722:                fY = curY;
0723:                fY /= 32768.0;
0724:                fZ = curZ;
0725:                fZ /= 32768.0;
0726:                if (debug)
0727:                    System.out.println(" result position " + fX + " " + fY
0728:                            + " " + fZ);
0729:
0730:                curPos.set(fX, fY, fZ);
0731:                return mbp;
0732:            }
0733:
0734:            //
0735:            // Process a set current normal opcode.
0736:            //
0737:            private void processSetNormal(int mbp) {
0738:                HuffmanTableEntry gct;
0739:                int index, du, dv, n, dataLength;
0740:                int ii;
0741:
0742:                // if next command is a mesh buffer reference, use this normal
0743:                meshState &= ~USE_MESH_NORMAL;
0744:
0745:                // use table 2 for normals
0746:                gct = gctables[2][currentHeader & 0x3F];
0747:
0748:                if (debug)
0749:                    System.out
0750:                            .println("GeometryDecompressor.processSetNormal\n"
0751:                                    + gct.toString());
0752:
0753:                // subtract up-shift amount to get true data (u, v) length
0754:                dataLength = gct.dataLength - gct.rightShift;
0755:
0756:                if (gct.absolute != 0) {
0757:                    //
0758:                    // Absolute normal case.  Extract index from 6-bit tag.
0759:                    //
0760:                    index = currentHeader & BMASK[6 - gct.tagLength];
0761:
0762:                    if (gct.tagLength != 0) {
0763:                        // read in the rest of the 6-bit sex/oct pair (index)
0764:                        ii = getBits(6 - (6 - gct.tagLength), "sex/oct");
0765:                        index = (index << (6 - (6 - gct.tagLength))) | ii;
0766:                    }
0767:
0768:                    // read in u and v data
0769:                    curU = getBits(dataLength, "u");
0770:                    curV = getBits(dataLength, "v");
0771:
0772:                    // normalize u, v, sextant, and octant
0773:                    curU = curU << gct.rightShift;
0774:                    curV = curV << gct.rightShift;
0775:
0776:                    curSex = (index >> 3) & 0x7;
0777:                    curOct = index & 0x7;
0778:
0779:                    if (debug) {
0780:                        if (curSex < 6)
0781:                            System.out.println(" absolute normal: sex "
0782:                                    + curSex + " oct " + curOct + " u " + curU
0783:                                    + " v " + curV);
0784:                        else
0785:                            System.out.println(" special normal: sex " + curSex
0786:                                    + " oct " + curOct);
0787:                    }
0788:                } else {
0789:                    //
0790:                    // Relative normal case.  Extract du from 6-bit tag.
0791:                    //
0792:                    du = currentHeader & BMASK[6 - gct.tagLength];
0793:
0794:                    if (gct.tagLength + dataLength < 6) {
0795:                        // normalize du, get dv
0796:                        du = du >> (6 - gct.tagLength - dataLength);
0797:                        dv = currentHeader
0798:                                & BMASK[6 - gct.tagLength - dataLength];
0799:
0800:                        if (gct.tagLength + 2 * dataLength < 6) {
0801:                            // normalize dv
0802:                            dv = dv >> (6 - gct.tagLength - 2 * dataLength);
0803:                        } else if (gct.tagLength + 2 * dataLength > 6) {
0804:                            // read in rest of dv and normalize it
0805:                            ii = getBits(dataLength
0806:                                    - (6 - gct.tagLength - dataLength), "dv");
0807:                            dv = (dv << (dataLength - (6 - gct.tagLength - dataLength)))
0808:                                    | ii;
0809:                        }
0810:                    } else if (gct.tagLength + dataLength > 6) {
0811:                        // read in rest of du and normalize it
0812:                        ii = getBits(dataLength - (6 - gct.tagLength), "du");
0813:                        du = (du << (dataLength - (6 - gct.tagLength))) | ii;
0814:                        // read in dv
0815:                        dv = getBits(dataLength, "dv");
0816:                    } else {
0817:                        // read in dv
0818:                        dv = getBits(dataLength, "dv");
0819:                    }
0820:
0821:                    // Sign extend delta uv components.
0822:                    du = du << (32 - dataLength);
0823:                    du = du >> (32 - dataLength);
0824:                    dv = dv << (32 - dataLength);
0825:                    dv = dv >> (32 - dataLength);
0826:
0827:                    // normalize values
0828:                    du = du << gct.rightShift;
0829:                    dv = dv << gct.rightShift;
0830:
0831:                    // un-delta
0832:                    curU += du;
0833:                    curV += dv;
0834:
0835:                    if (debug)
0836:                        System.out.println(" delta normal: du " + du + " dv "
0837:                                + dv);
0838:
0839:                    //
0840:                    // Check for normal wrap.
0841:                    //
0842:                    if (!((curU >= 0) && (curV >= 0) && (curU + curV <= 64)))
0843:                        if ((curU < 0) && (curV >= 0)) {
0844:                            // wrap on u, same octant, different sextant
0845:                            curU = -curU;
0846:                            switch (curSex) {
0847:                            case 0:
0848:                                curSex = 4;
0849:                                break;
0850:                            case 1:
0851:                                curSex = 5;
0852:                                break;
0853:                            case 2:
0854:                                curSex = 3;
0855:                                break;
0856:                            case 3:
0857:                                curSex = 2;
0858:                                break;
0859:                            case 4:
0860:                                curSex = 0;
0861:                                break;
0862:                            case 5:
0863:                                curSex = 1;
0864:                                break;
0865:                            }
0866:                        } else if ((curU >= 0) && (curV < 0)) {
0867:                            // wrap on v, same sextant, different octant
0868:                            curV = -curV;
0869:                            switch (curSex) {
0870:                            case 1:
0871:                            case 5:
0872:                                curOct = curOct ^ 4; // invert x axis
0873:                                break;
0874:                            case 0:
0875:                            case 4:
0876:                                curOct = curOct ^ 2; // invert y axis
0877:                                break;
0878:                            case 2:
0879:                            case 3:
0880:                                curOct = curOct ^ 1; // invert z axis
0881:                                break;
0882:                            }
0883:                        } else if (curU + curV > 64) {
0884:                            // wrap on uv, same octant, different sextant
0885:                            curU = 64 - curU;
0886:                            curV = 64 - curV;
0887:                            switch (curSex) {
0888:                            case 0:
0889:                                curSex = 2;
0890:                                break;
0891:                            case 1:
0892:                                curSex = 3;
0893:                                break;
0894:                            case 2:
0895:                                curSex = 0;
0896:                                break;
0897:                            case 3:
0898:                                curSex = 1;
0899:                                break;
0900:                            case 4:
0901:                                curSex = 5;
0902:                                break;
0903:                            case 5:
0904:                                curSex = 4;
0905:                                break;
0906:                            }
0907:                        } else {
0908:                            throw new IllegalArgumentException(J3dUtilsI18N
0909:                                    .getString("GeometryDecompressor1"));
0910:                        }
0911:                }
0912:
0913:                // do optional mesh buffer push
0914:                if (mbp != 0) {
0915:                    if (debug)
0916:                        System.out
0917:                                .println(" pushing normal into mesh buffer at "
0918:                                        + meshIndex);
0919:
0920:                    meshBuffer[meshIndex].sextant = (short) curSex;
0921:                    meshBuffer[meshIndex].octant = (short) curOct;
0922:                    meshBuffer[meshIndex].u = (short) curU;
0923:                    meshBuffer[meshIndex].v = (short) curV;
0924:                }
0925:
0926:                // convert normal back to [-1..1] floating point
0927:                indexNormal(curSex, curOct, curU, curV, curNorm);
0928:
0929:                // a set normal opcode when normals aren't bundled with the vertices
0930:                // is a global normal change.
0931:                if (!bundlingNorm)
0932:                    outputNormal(curNorm);
0933:            }
0934:
0935:            //
0936:            // Get the floating point normal from its sextant, octant, u, and v.
0937:            //
0938:            private void indexNormal(int sex, int oct, int u, int v, Vector3f n) {
0939:                float nx, ny, nz, t;
0940:
0941:                if (debug)
0942:                    System.out.println(" sextant " + sex + " octant " + oct
0943:                            + " u " + u + " v " + v);
0944:                if (sex > 5) {
0945:                    // special normals
0946:                    switch (oct & 0x1) {
0947:                    case 0: // six coordinate axes
0948:                        switch (((sex & 0x1) << 1) | ((oct & 0x4) >> 2)) {
0949:                        case 0:
0950:                            nx = 1.0f;
0951:                            ny = nz = 0.0f;
0952:                            break;
0953:                        case 1:
0954:                            ny = 1.0f;
0955:                            nx = nz = 0.0f;
0956:                            break;
0957:                        default:
0958:                        case 2:
0959:                            nz = 1.0f;
0960:                            nx = ny = 0.0f;
0961:                            break;
0962:                        }
0963:                        sex = 0;
0964:                        oct = (oct & 0x2) >> 1;
0965:                        oct = (oct << 2) | (oct << 1) | oct;
0966:                        break;
0967:                    case 1: // eight mid
0968:                    default:
0969:                        oct = ((sex & 0x1) << 2) | (oct >> 1);
0970:                        sex = 0;
0971:                        nx = ny = nz = (float) (1.0 / Math.sqrt(3.0));
0972:                        break;
0973:                    }
0974:                    if ((oct & 0x1) != 0)
0975:                        nz = -nz;
0976:                    if ((oct & 0x2) != 0)
0977:                        ny = -ny;
0978:                    if ((oct & 0x4) != 0)
0979:                        nx = -nx;
0980:
0981:                } else {
0982:                    // regular normals
0983:                    nx = (float) gcNormals[v][u][0];
0984:                    ny = (float) gcNormals[v][u][1];
0985:                    nz = (float) gcNormals[v][u][2];
0986:
0987:                    // reverse the swap 
0988:                    if ((sex & 0x4) != 0) {
0989:                        t = nx;
0990:                        nx = nz;
0991:                        nz = t;
0992:                    }
0993:                    if ((sex & 0x2) != 0) {
0994:                        t = ny;
0995:                        ny = nz;
0996:                        nz = t;
0997:                    }
0998:                    if ((sex & 0x1) != 0) {
0999:                        t = nx;
1000:                        nx = ny;
1001:                        ny = t;
1002:                    }
1003:
1004:                    // reverse the sign flip 
1005:                    if ((oct & 0x1) != 0)
1006:                        nz = -nz;
1007:                    if ((oct & 0x2) != 0)
1008:                        ny = -ny;
1009:                    if ((oct & 0x4) != 0)
1010:                        nx = -nx;
1011:                }
1012:
1013:                // return resulting normal
1014:                n.set(nx, ny, nz);
1015:                if (debug)
1016:                    System.out.println(" result normal: " + nx + " " + ny + " "
1017:                            + nz);
1018:            }
1019:
1020:            //
1021:            // Process a set current color command.
1022:            //
1023:            private void processSetColor(int mbp) {
1024:                HuffmanTableEntry gct;
1025:                short dr, dg, db, da;
1026:                float fR, fG, fB, fA;
1027:                int r, g, b, a, index, dataLength;
1028:                int ii;
1029:
1030:                // If the next command is a mesh buffer reference, use this color.
1031:                meshState &= ~USE_MESH_COLOR;
1032:
1033:                // Get the huffman table entry.
1034:                gct = gctables[1][currentHeader & 0x3F];
1035:
1036:                if (debug)
1037:                    System.out.println("GeometryDecompressor.processSetColor\n"
1038:                            + gct.toString());
1039:
1040:                // Get the true length of the data.
1041:                dataLength = gct.dataLength - gct.rightShift;
1042:
1043:                // Read in red, green, blue, and possibly alpha.
1044:                r = currentHeader & BMASK[6 - gct.tagLength];
1045:                a = 0;
1046:
1047:                if (gct.tagLength + dataLength == 6) {
1048:                    g = getBits(dataLength, "g");
1049:                    b = getBits(dataLength, "b");
1050:                    if (doingAlpha)
1051:                        a = getBits(dataLength, "a");
1052:                } else if (gct.tagLength + dataLength < 6) {
1053:                    r = r >> (6 - gct.tagLength - dataLength);
1054:
1055:                    g = currentHeader & BMASK[6 - gct.tagLength - dataLength];
1056:                    if (gct.tagLength + 2 * dataLength == 6) {
1057:                        b = getBits(dataLength, "b");
1058:                        if (doingAlpha)
1059:                            a = getBits(dataLength, "a");
1060:                    } else if (gct.tagLength + 2 * dataLength < 6) {
1061:                        g = g >> (6 - gct.tagLength - 2 * dataLength);
1062:
1063:                        b = currentHeader
1064:                                & BMASK[6 - gct.tagLength - 2 * dataLength];
1065:                        if (gct.tagLength + 3 * dataLength == 6) {
1066:                            if (doingAlpha)
1067:                                a = getBits(dataLength, "a");
1068:                        } else if (gct.tagLength + 3 * dataLength < 6) {
1069:                            b = b >> (6 - gct.tagLength - 3 * dataLength);
1070:
1071:                            if (doingAlpha) {
1072:                                a = currentHeader
1073:                                        & BMASK[6 - gct.tagLength - 4
1074:                                                * dataLength];
1075:                                if (gct.tagLength + 4 * dataLength < 6) {
1076:                                    a = a >> (6 - gct.tagLength - 3 * dataLength);
1077:                                } else if (gct.tagLength + 4 * dataLength > 6) {
1078:                                    ii = getBits(
1079:                                            dataLength
1080:                                                    - (6 - gct.tagLength - 3 * dataLength),
1081:                                            "a");
1082:                                    a = (a << (dataLength - (6 - gct.tagLength - 3 * dataLength)))
1083:                                            | ii;
1084:                                }
1085:                            }
1086:                        } else {
1087:                            ii = getBits(dataLength
1088:                                    - (6 - gct.tagLength - 2 * dataLength), "b");
1089:                            b = (b << (dataLength - (6 - gct.tagLength - 2 * dataLength)))
1090:                                    | ii;
1091:                            if (doingAlpha)
1092:                                a = getBits(dataLength, "a");
1093:                        }
1094:                    } else {
1095:                        ii = getBits(dataLength
1096:                                - (6 - gct.tagLength - dataLength), "g");
1097:                        g = (g << (dataLength - (6 - gct.tagLength - dataLength)))
1098:                                | ii;
1099:                        b = getBits(dataLength, "b");
1100:                        if (doingAlpha)
1101:                            a = getBits(dataLength, "a");
1102:                    }
1103:                } else {
1104:                    ii = getBits(dataLength - (6 - gct.tagLength), "r");
1105:                    r = (r << (dataLength - (6 - gct.tagLength))) | ii;
1106:                    g = getBits(dataLength, "g");
1107:                    b = getBits(dataLength, "b");
1108:                    if (doingAlpha)
1109:                        a = getBits(dataLength, "a");
1110:                }
1111:
1112:                // Sign extend delta x y z components.
1113:                r <<= (32 - dataLength);
1114:                r >>= (32 - dataLength);
1115:                g <<= (32 - dataLength);
1116:                g >>= (32 - dataLength);
1117:                b <<= (32 - dataLength);
1118:                b >>= (32 - dataLength);
1119:                a <<= (32 - dataLength);
1120:                a >>= (32 - dataLength);
1121:
1122:                // Normalize values.
1123:                dr = (short) (r << gct.rightShift);
1124:                dg = (short) (g << gct.rightShift);
1125:                db = (short) (b << gct.rightShift);
1126:                da = (short) (a << gct.rightShift);
1127:
1128:                // Update current position, first adding deltas if in relative mode.
1129:                if (gct.absolute != 0) {
1130:                    curR = dr;
1131:                    curG = dg;
1132:                    curB = db;
1133:                    if (doingAlpha)
1134:                        curA = da;
1135:                    if (debug)
1136:                        System.out.println(" absolute color: r " + curR + " g "
1137:                                + curG + " b " + curB + " a " + curA);
1138:                } else {
1139:                    curR += dr;
1140:                    curG += dg;
1141:                    curB += db;
1142:                    if (doingAlpha)
1143:                        curA += da;
1144:                    if (debug)
1145:                        System.out.println(" delta color: dr " + dr + " dg "
1146:                                + dg + " db " + db + " da " + da);
1147:                }
1148:
1149:                // Do optional mesh buffer push.
1150:                if (mbp != 0) {
1151:                    if (debug)
1152:                        System.out
1153:                                .println(" pushing color into mesh buffer at "
1154:                                        + meshIndex);
1155:
1156:                    meshBuffer[meshIndex].r = curR;
1157:                    meshBuffer[meshIndex].g = curG;
1158:                    meshBuffer[meshIndex].b = curB;
1159:                    meshBuffer[meshIndex].a = curA;
1160:                }
1161:
1162:                // Convert point back to [-1..1] floating point.
1163:                fR = curR;
1164:                fR /= 32768.0;
1165:                fG = curG;
1166:                fG /= 32768.0;
1167:                fB = curB;
1168:                fB /= 32768.0;
1169:                fA = curA;
1170:                fA /= 32768.0;
1171:
1172:                curColor.set(fR, fG, fB, fA);
1173:                if (debug)
1174:                    System.out.println(" result color: " + fR + " " + fG + " "
1175:                            + fB + " " + fA);
1176:
1177:                // A set color opcode when colors aren't bundled with the vertices
1178:                // is a global color change.
1179:                if (!bundlingColor)
1180:                    outputColor(curColor);
1181:            }
1182:
1183:            //
1184:            // Process a mesh buffer reference command.
1185:            //
1186:            private void processMeshBR() {
1187:                MeshBufferEntry entry;
1188:                int index, normal;
1189:                int ii;
1190:
1191:                if (debug)
1192:                    System.out.println("GeometryDecompressor.processMeshBR");
1193:
1194:                ii = getBits(1, "mbr");
1195:
1196:                index = (currentHeader >>> 1) & 0xF;
1197:                repCode = ((currentHeader & 0x1) << 1) | ii;
1198:
1199:                // Adjust index to proper place in fifo.
1200:                index = (meshIndex - index) & 0xf;
1201:                if (debug)
1202:                    System.out.println(" using index " + index);
1203:
1204:                // Get reference to mesh buffer entry.
1205:                entry = meshBuffer[index];
1206:                curX = entry.x;
1207:                curY = entry.y;
1208:                curZ = entry.z;
1209:
1210:                // Convert point back to [-1..1] floating point.
1211:                curPos.set(((float) curX) / 32768.0f,
1212:                        ((float) curY) / 32768.0f, ((float) curZ) / 32768.0f);
1213:
1214:                if (debug)
1215:                    System.out.println(" retrieved position " + curPos.x + " "
1216:                            + curPos.y + " " + curPos.z + " replace code "
1217:                            + repCode);
1218:
1219:                // Get mesh buffer normal if previous opcode was not a setNormal.
1220:                if (bundlingNorm && ((meshState & USE_MESH_NORMAL) != 0)) {
1221:                    curSex = entry.sextant;
1222:                    curOct = entry.octant;
1223:                    curU = entry.u;
1224:                    curV = entry.v;
1225:
1226:                    // Convert normal back to -1.0 - 1.0 floating point from index.
1227:                    normal = (curSex << 15) | (curOct << 12) | (curU << 6)
1228:                            | curV;
1229:
1230:                    if (debug)
1231:                        System.out.println(" retrieving normal");
1232:                    indexNormal(curSex, curOct, curU, curV, curNorm);
1233:                }
1234:
1235:                // Get mesh buffer color if previous opcode was not a setColor.
1236:                if (bundlingColor && ((meshState & USE_MESH_COLOR) != 0)) {
1237:                    curR = entry.r;
1238:                    curG = entry.g;
1239:                    curB = entry.b;
1240:
1241:                    // Convert point back to -1.0 - 1.0 floating point.
1242:                    curColor.x = curR;
1243:                    curColor.x /= 32768.0;
1244:                    curColor.y = curG;
1245:                    curColor.y /= 32768.0;
1246:                    curColor.z = curB;
1247:                    curColor.z /= 32768.0;
1248:
1249:                    if (doingAlpha) {
1250:                        curA = entry.a;
1251:                        curColor.w = curA;
1252:                        curColor.w /= 32768.0;
1253:                    }
1254:                    if (debug)
1255:                        System.out.println(" retrieved color " + curColor.x
1256:                                + " " + curColor.y + " " + curColor.z + " "
1257:                                + curColor.w);
1258:                }
1259:
1260:                // Reset meshState.
1261:                meshState = 0;
1262:            }
1263:
1264:            // Process a end-of-stream opcode.
1265:            private void processEos() {
1266:                if (debug)
1267:                    System.out.println("GeometryDecompressor.processEos");
1268:            }
1269:
1270:            // Process a variable length no-op opcode.
1271:            private void processVNoop() {
1272:                int ii, ct;
1273:                if (debug)
1274:                    System.out.println("GeometryDecompressor.processVNoop");
1275:
1276:                ct = getBits(5, "noop count");
1277:                ii = getBits(ct, "noop bits");
1278:            }
1279:
1280:            // Process a pass-through opcode.
1281:            private void processPassThrough() {
1282:                int ignore;
1283:                if (debug)
1284:                    System.out
1285:                            .println("GeometryDecompressor.processPassThrough");
1286:
1287:                ignore = getBits(24, "passthrough");
1288:                ignore = getBits(32, "passthrough");
1289:            }
1290:
1291:            // Process a skip-8 opcode.
1292:            private void processSkip8() {
1293:                int skip;
1294:                if (debug)
1295:                    System.out.println("GeometryDecompressor.processSkip8");
1296:
1297:                skip = getBits(8, "skip8");
1298:            }
1299:
1300:            private void benchmarkStart(int length) {
1301:                vertexCount = 0;
1302:                System.out.println(" GeometryDecompressor: decompressing "
1303:                        + length + " bytes...");
1304:                startTime = System.currentTimeMillis();
1305:            }
1306:
1307:            private void benchmarkPrint(int length) {
1308:                float t = (System.currentTimeMillis() - startTime) / 1000.0f;
1309:                System.out.println("  done in " + t + " sec." + "\n"
1310:                        + "  decompressed " + vertexCount + " vertices at "
1311:                        + (vertexCount / t) + " vertices/sec\n");
1312:
1313:                System.out.print("  vertex data present: coords");
1314:                int floatVertexSize = 12;
1315:                if (bundlingNorm) {
1316:                    System.out.print(" normals");
1317:                    floatVertexSize += 12;
1318:                }
1319:                if (bundlingColor) {
1320:                    System.out.println(" colors");
1321:                    floatVertexSize += 12;
1322:                }
1323:                if (doingAlpha) {
1324:                    System.out.println(" alpha");
1325:                    floatVertexSize += 4;
1326:                }
1327:                System.out.println();
1328:
1329:                System.out
1330:                        .println("  bytes of data in generalized strip output: "
1331:                                + (vertexCount * floatVertexSize)
1332:                                + "\n"
1333:                                + "  compression ratio: "
1334:                                + (length / (float) (vertexCount * floatVertexSize))
1335:                                + "\n");
1336:            }
1337:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.