📄 geometrydecompressor.java
字号:
} else { // get normal header, process current position opcode nextHeader = getBits(6, "normal") ; mbp = processDecompressionOpcode(0) ; currentHeader = nextHeader | GC_SET_NORM ; // get color header, process current normal opcode nextHeader = getBits(6, "color") ; processDecompressionOpcode(mbp) ; currentHeader = nextHeader | GC_SET_COLOR ; // get next opcode, process current color opcode nextHeader = getBits(8, "header") ; processDecompressionOpcode(mbp) ; } // Send out the complete vertex. outputVertex(curPos, curNorm, curColor, repCode) ; if (benchmark) vertexCount++ ; // meshState bits get turned off in the setColor and setNormal // routines in order to keep track of what data a mesh buffer // reference should use. meshState |= USE_MESH_NORMAL ; meshState |= USE_MESH_COLOR ; } else { // Non-vertex case: get next opcode, then process current opcode. nextHeader = getBits(8, "header") ; processDecompressionOpcode(0) ; } } // // Decode the opcode in currentHeader, and dispatch to the appropriate // processing method. // private int processDecompressionOpcode(int mbp) { if ((currentHeader & 0xC0) == GC_SET_NORM) processSetNormal(mbp) ; else if ((currentHeader & 0xC0) == GC_SET_COLOR) processSetColor(mbp) ; else if ((currentHeader & 0xC0) == GC_VERTEX) // Return the state of the mesh buffer push bit // when processing a vertex. return processVertex() ; else if ((currentHeader & 0xE0) == GC_MESH_B_R) { processMeshBR() ; // Send out the complete vertex. outputVertex(curPos, curNorm, curColor, repCode) ; if (benchmark) vertexCount++ ; // meshState bits get turned off in the setColor and setNormal // routines in order to keep track of what data a mesh buffer // reference should use. meshState |= USE_MESH_NORMAL ; meshState |= USE_MESH_COLOR ; } else if ((currentHeader & 0xF8) == GC_SET_STATE) processSetState() ; else if ((currentHeader & 0xF8) == GC_SET_TABLE) processSetTable() ; else if ((currentHeader & 0xFF) == GC_EOS) processEos() ; else if ((currentHeader & 0xFF) == GC_V_NO_OP) processVNoop() ; else if ((currentHeader & 0xFF) == GC_PASS_THROUGH) processPassThrough() ; else if ((currentHeader & 0xFF) == GC_SKIP_8) processSkip8() ; return 0 ; } // // Process a set state opcode. // private void processSetState() { int ii ; if (debug) System.err.println("GeometryDecompressor.processSetState") ; ii = getBits(3, "bundling") ; bundlingNorm = ((currentHeader & 0x1) != 0) ; bundlingColor = (((ii >>> 2) & 0x1) != 0) ; doingAlpha = (((ii >>> 1) & 0x1) != 0) ; if (debug) System.err.println(" bundling normal: " + bundlingNorm + " bundling color: " + bundlingColor + " alpha present: " + doingAlpha) ; // Call the abstract output implementation. outputVertexFormat(bundlingNorm, bundlingColor, doingAlpha) ; } // // Process a set decompression table opcode. // // Extract the parameters of the table set command, // and set the approprate table entries. // private void processSetTable() { HuffmanTableEntry gct[] ; int i, adr, tagLength, dataLength, rightShift, absolute ; int ii, index ; if (debug) System.err.println("GeometryDecompressor.processSetTable") ; // Get reference to approprate 64 entry table. index = (currentHeader & 0x6) >>> 1 ; gct = gctables[index] ; // Get the remaining bits of the set table command. ii = getBits(15, "set table") ; // Extract the individual fields from the two bit strings. adr = ((currentHeader & 0x1) << 6) | ((ii >>> 9) & 0x3F) ; // Get data length. For positions and colors, 0 really means 16, as 0 // lengths are meaningless for them. Normal components are allowed to // have lengths of 0. dataLength = (ii >>> 5) & 0x0F ; if (dataLength == 0 && index != 2) dataLength = 16 ; rightShift = ii & 0x0F ; absolute = (ii >>> 4) & 0x1 ; // // Decode the tag length from the address field by finding the // first set 1 from the left in the bitfield. // for (tagLength = 6 ; tagLength > 0 ; tagLength--) { if ((adr >> tagLength) != 0) break ; } // Shift the address bits up into place, and off the leading 1. adr = (adr << (6 - tagLength)) & 0x3F ; if (debug) System.err.println(" table " + ((currentHeader & 0x6) >>> 1) + " address " + adr + " tag length " + tagLength + " data length " + dataLength + " shift " + rightShift + " absolute " + absolute) ; // Fill in the table fields with the specified values. for (i = 0 ; i < (1 << (6 - tagLength)) ; i++) { gct[adr+i].tagLength = tagLength ; gct[adr+i].dataLength = dataLength ; gct[adr+i].rightShift = rightShift ; gct[adr+i].absolute = absolute ; } } // // Process a vertex opcode. Any bundled normal and/or color will be // processed by separate methods. Return the mesh buffer push indicator. // private int processVertex() { HuffmanTableEntry gct ; float fX, fY, fZ ; short dx, dy, dz ; int mbp, x, y, z, dataLen ; int ii ; // If the next command is a mesh buffer reference // then use colors and normals from the mesh buffer. meshState = 0 ; // Get a reference to the approprate tag table entry. gct = gctables[0][currentHeader & 0x3F] ; if (debug) System.err.println("GeometryDecompressor.processVertex\n" + gct.toString()) ; // Get the true length of the data. dataLen = gct.dataLength - gct.rightShift ; // Read in the replace code and mesh buffer push bits, // if they're not in the current header. if (6 - (3 * dataLen) - gct.tagLength > 0) { int numBits = 6 - (3 * dataLen) - gct.tagLength ; int jj ; jj = currentHeader & BMASK[numBits] ; ii = getBits(3 - numBits, "repcode/mbp") ; ii |= (jj << (3 - numBits)) ; } else ii = getBits(3, "repcode/mbp") ; repCode = ii >>> 1 ; mbp = ii & 0x1 ; // Read in x, y, and z components. x = currentHeader & BMASK[6-gct.tagLength] ; if (gct.tagLength + dataLen == 6) { y = getBits(dataLen, "y") ; z = getBits(dataLen, "z") ; } else if (gct.tagLength + dataLen < 6) { x = x >> (6 - gct.tagLength - dataLen) ; y = currentHeader & BMASK[6 - gct.tagLength - dataLen] ; if (gct.tagLength + 2*dataLen == 6) { z = getBits(dataLen, "z") ; } else if (gct.tagLength + 2*dataLen < 6) { y = y >> (6 - gct.tagLength - 2*dataLen) ; z = currentHeader & BMASK[6 - gct.tagLength - 2*dataLen] ; if (gct.tagLength + 3*dataLen < 6) { z = z >> (6 - gct.tagLength - 3*dataLen) ; } else if (gct.tagLength + 3*dataLen > 6) { ii = getBits(dataLen - (6 - gct.tagLength - 2*dataLen), "z") ; z = (z << (dataLen - (6 - gct.tagLength - 2*dataLen))) | ii ; } } else { ii = getBits(dataLen - (6 - gct.tagLength - dataLen), "y") ; y = (y << (dataLen - (6 - gct.tagLength - dataLen))) | ii ; z = getBits(dataLen, "z") ; } } else { ii = getBits(dataLen - (6 - gct.tagLength), "x") ; x = (x << (dataLen - (6 - gct.tagLength))) | ii ; y = getBits(dataLen, "y") ; z = getBits(dataLen, "z") ; } // Sign extend delta x y z components. x = x << (32 - dataLen) ; x = x >> (32 - dataLen) ; y = y << (32 - dataLen) ; y = y >> (32 - dataLen) ; z = z << (32 - dataLen) ; z = z >> (32 - dataLen) ; // Normalize values. dx = (short)(x << gct.rightShift) ; dy = (short)(y << gct.rightShift) ; dz = (short)(z << gct.rightShift) ; // Update current position, first adding deltas if in relative mode. if (gct.absolute != 0) { curX = dx ; curY = dy ; curZ = dz ; if (debug) System.err.println(" absolute position: " + curX + " " + curY + " " + curZ) ; } else { curX += dx ; curY += dy ; curZ += dz ; if (debug) System.err.println(" delta position: " + dx + " " + dy + " " + dz) ; } // Do optional mesh buffer push. if (mbp != 0) { // Increment to next position (meshIndex is initialized to 15). meshIndex = (meshIndex + 1) & 0xF ; meshBuffer[meshIndex].x = curX ; meshBuffer[meshIndex].y = curY ; meshBuffer[meshIndex].z = curZ ; if (debug) System.err.println(" pushed position into mesh buffer at " + meshIndex) ; } // Convert point back to [-1..1] floating point. fX = curX ; fX /= 32768.0 ; fY = curY ; fY /= 32768.0 ; fZ = curZ ; fZ /= 32768.0 ; if (debug) System.err.println(" result position " + fX + " " + fY + " " + fZ) ; curPos.set(fX, fY, fZ) ; return mbp ; } // // Process a set current normal opcode. // private void processSetNormal(int mbp) { HuffmanTableEntry gct ; int index, du, dv, n, dataLength ; int ii ; // if next command is a mesh buffer reference, use this normal meshState &= ~USE_MESH_NORMAL ; // use table 2 for normals gct = gctables[2][currentHeader & 0x3F] ; if (debug) System.err.println("GeometryDecompressor.processSetNormal\n" + gct.toString()) ; // subtract up-shift amount to get true data (u, v) length dataLength = gct.dataLength - gct.rightShift ; if (gct.absolute != 0) { // // Absolute normal case. Extract index from 6-bit tag. // index = currentHeader & BMASK[6-gct.tagLength] ; if (gct.tagLength != 0) { // read in the rest of the 6-bit sex/oct pair (index) ii = getBits(6 - (6 - gct.tagLength), "sex/oct") ; index = (index << (6 - (6 - gct.tagLength))) | ii ; } // read in u and v data curU = getBits(dataLength, "u") ; curV = getBits(dataLength, "v") ; // normalize u, v, sextant, and octant curU = curU << gct.rightShift ; curV = curV << gct.rightShift ; curSex = (index >> 3) & 0x7 ; curOct = index & 0x7 ; if (debug) { if (curSex < 6) System.err.println(" absolute normal: sex " + curSex + " oct " + curOct + " u " + curU + " v " + curV) ; else System.err.println(" special normal: sex " + curSex + " oct " + curOct) ; } } else { // // Relative normal case. Extract du from 6-bit tag. // du = currentHeader & BMASK[6-gct.tagLength] ; if (gct.tagLength + dataLength < 6) { // normalize du, get dv du = du >> (6 - gct.tagLength - dataLength) ; dv = currentHeader & BMASK[6 - gct.tagLength - dataLength] ; if (gct.tagLength + 2*dataLength < 6) { // normalize dv dv = dv >> (6 - gct.tagLength - 2*dataLength) ; } else if (gct.tagLength + 2*dataLength > 6) { // read in rest of dv and normalize it ii = getBits(dataLength - (6 - gct.tagLength - dataLength), "dv") ; dv = (dv << (dataLength - (6 - gct.tagLength - dataLength))) | ii ; } } else if (gct.tagLength + dataLength > 6) { // read in rest of du and normalize it ii = getBits(dataLength - (6 - gct.tagLength), "du") ; du = (du << (dataLength - (6 - gct.tagLength))) | ii ; // read in dv dv = getBits(dataLength, "dv") ; } else { // read in dv dv = getBits(dataLength, "dv") ; } // Sign extend delta uv components. du = du << (32 - dataLength) ; du = du >> (32 - dataLength) ; dv = dv << (32 - dataLength) ; dv = dv >> (32 - dataLength) ; // normalize values du = du << gct.rightShift ; dv = dv << gct.rightShift ; // un-delta curU += du ; curV += dv ; if (debug) System.err.println(" delta normal: du " + du + " dv " + dv) ; // // Check for normal wrap. // if (! ((curU >= 0) && (curV >= 0) && (curU + curV <= 64))) if ((curU < 0) && (curV >= 0)) { // wrap on u, same octant, different sextant curU = -curU ; switch (curSex) { case 0: curSex = 4 ; break ; case 1: curSex = 5 ; break ; case 2: curSex = 3 ; break ; case 3: curSex = 2 ; break ; case 4: curSex = 0 ; break ; case 5: curSex = 1 ; break ; } } else if ((curU >= 0) && (curV < 0)) { // wrap on v, same sextant, different octant curV = -curV ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -