📄 compressionstream.java
字号:
Integer.MIN_VALUE) ; /* normalized bounds computed from quantized bounds */ ncBounds[0] = new Point3d() ; ncBounds[1] = new Point3d() ; } /** * Creates a new CompressionStream for the specified geometry type and * vertex format.<p> * * @param streamType type of data in this stream, either * CompressedGeometryData.Header.POINT_BUFFER, * CompressedGeometryData.Header.LINE_BUFFER, or * CompressedGeometryData.Header.TRIANGLE_BUFFER * @param vertexComponents a mask indicating which components are present * in each vertex, as defined by GeometryArray: COORDINATES, NORMALS, and * COLOR_3 or COLOR_4. * @see GeometryCompressor * @see GeometryArray */ CompressionStream(int streamType, int vertexComponents) { this() ; this.streamType = streamType ; this.vertexComponents = getVertexComponents(vertexComponents) ; } // See what vertex geometry components are present. The byReference, // interleaved, useNIOBuffer, and useCoordIndexOnly flags are not // examined. private int getVertexComponents(int vertexFormat) { int components = 0 ; vertexColors = vertexColor3 = vertexColor4 = vertexNormals = vertexTextures = vertexTexture2 = vertexTexture3 = vertexTexture4 = false ; if ((vertexFormat & GeometryArray.NORMALS) != 0) { vertexNormals = true ; components &= GeometryArray.NORMALS ; if (debug) System.out.println("vertexNormals") ; } if ((vertexFormat & GeometryArray.COLOR_3) != 0) { vertexColors = true ; if ((vertexFormat & GeometryArray.COLOR_4) != 0) { vertexColor4 = true ; components &= GeometryArray.COLOR_4 ; if (debug) System.out.println("vertexColor4") ; } else { vertexColor3 = true ; components &= GeometryArray.COLOR_3 ; if (debug) System.out.println("vertexColor3") ; } } if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_2) != 0) { vertexTextures = true ; vertexTexture2 = true ; components &= GeometryArray.TEXTURE_COORDINATE_2 ; if (debug) System.out.println("vertexTexture2") ; } else if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_3) != 0) { vertexTextures = true ; vertexTexture3 = true ; components &= GeometryArray.TEXTURE_COORDINATE_3 ; if (debug) System.out.println("vertexTexture3") ; } else if ((vertexFormat & GeometryArray.TEXTURE_COORDINATE_4) != 0) { vertexTextures = true ; vertexTexture4 = true ; components &= GeometryArray.TEXTURE_COORDINATE_4 ; if (debug) System.out.println("vertexTexture4") ; } if (vertexTextures) // Throw exception for now until texture is supported. throw new UnsupportedOperationException ("\ncompression of texture coordinates is not supported") ; return components ; } // Get the streamType associated with a GeometryArray instance. private int getStreamType(GeometryArray ga) { if (ga instanceof TriangleStripArray || ga instanceof IndexedTriangleStripArray || ga instanceof TriangleFanArray || ga instanceof IndexedTriangleFanArray || ga instanceof TriangleArray || ga instanceof IndexedTriangleArray || ga instanceof QuadArray || ga instanceof IndexedQuadArray) return CompressedGeometryData.Header.TRIANGLE_BUFFER ; else if (ga instanceof LineArray || ga instanceof IndexedLineArray || ga instanceof LineStripArray || ga instanceof IndexedLineStripArray) return CompressedGeometryData.Header.LINE_BUFFER ; else return CompressedGeometryData.Header.POINT_BUFFER ; } /** * Iterates across all compression stream elements and applies * quantization parameters, encoding consecutive vertices as delta values * whenever possible. Each geometric element is mapped to a HuffmanNode * object containing its resulting bit length, right shift (trailing 0 * count), and absolute or relative status.<p> * * Positions are normalized to span a unit cube via an offset and a * uniform scale factor that maps the midpoint of the object extents along * each dimension to the origin, and the longest dimension of the object to * the open interval (-1.0 .. +1.0). The geometric endpoints along that * dimension are both one quantum away from unity; for example, at a * position quantization of 6 bits, an object would be normalized so that * its most negative dimension is at (-1 + 1/64) and the most positive is * at (1 - 1/64).<p> * * Normals are assumed to be of unit length. Color components are clamped * to the [0..1) range, where the right endpoint is one quantum less * than 1.0.<p> * * @param huffmanTable Table which will map geometric compression stream * elements to HuffmanNode objects describing each element's data * representation. This table can then be processed with Huffman's * algorithm to optimize the bit length of descriptor tags according to * the number of geometric elements mapped to each tag. */ void quantize(HuffmanTable huffmanTable) { // Set up default initial quantization parameters. The position and // color parameters specify the number of bits for each X, Y, Z, R, G, // B, or A component. The normal quantization parameter specifies the // number of bits for each U and V component. positionQuant = 16 ; colorQuant = 9 ; normalQuant = 6 ; // Compute position center and scaling for normalization to the unit // cube. This is a volume bounded by the open intervals (-1..1) on // each axis. center[0] = (mcBounds[1].x + mcBounds[0].x) / 2.0 ; center[1] = (mcBounds[1].y + mcBounds[0].y) / 2.0 ; center[2] = (mcBounds[1].z + mcBounds[0].z) / 2.0 ; double xRange = mcBounds[1].x - mcBounds[0].x ; double yRange = mcBounds[1].y - mcBounds[0].y ; double zRange = mcBounds[1].z - mcBounds[0].z ; if (xRange > yRange) positionRangeMaximum = xRange ; else positionRangeMaximum = yRange ; if (zRange > positionRangeMaximum) positionRangeMaximum = zRange ; // Adjust the range of the unit cube to match the default // quantization. // // This scale factor along with the center values computed above will // produce 16-bit integer representations of the floating point // position coordinates ranging symmetrically about 0 from -32767 to // +32767. -32768 is not used and the normalized floating point // position coordinates of -1.0 as well as +1.0 will not be // represented. // // Applications which wish to seamlessly stitch together compressed // objects will need to be aware that the range of normalized // positions will be one quantum away from the [-1..1] endpoints of // the unit cube and should adjust scale factors accordingly. scale = (2.0 / positionRangeMaximum) * (32767.0 / 32768.0) ; // Flag quantization change. positionQuantChanged = colorQuantChanged = normalQuantChanged = true ; // Flag first position, color, and normal. firstPosition = firstColor = firstNormal = true ; // Apply quantization. Iterator i = stream.iterator() ; while (i.hasNext()) { Object o = i.next() ; if (o instanceof CompressionStreamElement) { ((CompressionStreamElement)o).quantize(this, huffmanTable) ; // Keep track of whether last two elements were colors or // normals for mesh buffer component substitution semantics. lastLastElementColor = lastElementColor ; lastLastElementNormal = lastElementNormal ; lastElementColor = lastElementNormal = false ; if (o instanceof CompressionStreamColor) lastElementColor = true ; else if (o instanceof CompressionStreamNormal) lastElementNormal = true ; } } // Compute the bounds in normalized coordinates. ncBounds[0].x = (double)qcBounds[0].x / 32768.0 ; ncBounds[0].y = (double)qcBounds[0].y / 32768.0 ; ncBounds[0].z = (double)qcBounds[0].z / 32768.0 ; ncBounds[1].x = (double)qcBounds[1].x / 32768.0 ; ncBounds[1].y = (double)qcBounds[1].y / 32768.0 ; ncBounds[1].z = (double)qcBounds[1].z / 32768.0 ; } /** * Iterates across all compression stream elements and builds the * compressed geometry command stream output.<p> * * @param huffmanTable Table which maps geometric elements in this stream * to tags describing the encoding parameters (length, shift, and * absolute/relative status) to be used for their representations in the * compressed output. All tags must be 6 bits or less in length, and the * sum of the number of bits in the tag plus the number of bits in the * data it describes must be at least 6 bits in length. * * @param outputBuffer CommandStream to use for collecting the compressed * bits. */ void outputCommands(HuffmanTable huffmanTable, CommandStream outputBuffer) { // // The first command output is setState to indicate what data is // bundled with each vertex. Although the semantics of geometry // decompression allow setState to appear anywhere in the stream, this // cannot be handled by the current Java 3D software decompressor, // which internally decompresses an entire compressed buffer into a // single retained object sharing a single consistent vertex format. // This limitation may be removed in subsequent releases of Java 3D. // int bnv = (vertexNormals? 1 : 0) ; int bcv = ((vertexColor3 || vertexColor4)? 1 : 0) ; int cap = (vertexColor4? 1 : 0) ; int command = CommandStream.SET_STATE | bnv ; long data = (bcv << 2) | (cap << 1) ; // Output the setState command. outputBuffer.addCommand(command, 8, data, 3) ; // Output the Huffman table commands. huffmanTable.outputCommands(outputBuffer) ; // Output each compression stream element's data. Iterator i = stream.iterator() ; while (i.hasNext()) { Object o = i.next() ; if (o instanceof CompressionStreamElement) ((CompressionStreamElement)o).outputCommand(huffmanTable, outputBuffer) ; } // Finish the header-forwarding interleave and long-word align. outputBuffer.end() ; } /** * Retrieve the total size of the uncompressed geometric data in bytes, * excluding mesh buffer references. * @return uncompressed byte count */ int getByteCount() { return byteCount ; } /** * Retrieve the the number of vertices created for this stream, excluding * mesh buffer references. * @return vertex count */ int getVertexCount() { return vertexCount ; } /** * Retrieve the number of mesh buffer references created for this stream. * @return mesh buffer reference count */ int getMeshReferenceCount() { return meshReferenceCount ; } /** * Stream element that sets position quantization during quantize pass. */ private class PositionQuant extends CompressionStreamElement { int value ; PositionQuant(int value) { this.value = value ; } void quantize(CompressionStream s, HuffmanTable t) { positionQuant = value ; positionQuantChanged = true ; // Adjust range of unit cube scaling to match quantization. scale = (2.0 / positionRangeMaximum) * (((double)((1 << (value-1)) - 1))/((double)(1 << (value-1)))) ; } public String toString() { return "positionQuant: " + value ; } } /** * Stream element that sets normal quantization during quantize pass. */ private class NormalQuant extends CompressionStreamElement { int value ; NormalQuant(int value) { this.value = value ; } void quantize(CompressionStream s, HuffmanTable t) { normalQuant = value ; normalQuantChanged = true ; } public String toString() { return "normalQuant: " + value ; } } /** * Stream element that sets color quantization during quantize pass. */ private class ColorQuant extends CompressionStreamElement { int value ; ColorQuant(int value) { this.value = value ; } void quantize(CompressionStream s, HuffmanTable t) { colorQuant = value ; colorQuantChanged = true ; } public String toString() { return "colorQuant: " + value ; } } /** * Stream element that references the mesh buffer. */ private class MeshReference extends CompressionStreamElement { int stripFlag, meshIndex ; MeshReference(int stripFlag, int meshIndex) { this.stripFlag = stripFlag ; this.meshIndex = meshIndex ; meshReferenceCount++ ; } void quantize(CompressionStream s, HuffmanTable t) { // Retrieve the vertex from the mesh buffer mirror and set up the // data needed for the next stream element to compute its deltas. CompressionStreamVertex v = meshBuffer.getVertex(meshIndex) ; lastPosition[0] = v.xAbsolute ; lastPosition[1] = v.yAbsolute ; lastPosition[2] = v.zAbsolute ; // Set up last color data if it exists and previous elements // don't override it. if (v.color != null && !lastElementColor && !(lastElementNormal && lastLastElementColor)) { lastColor[0] = v.color.rAbsolute ; lastColor[1] = v.color.gAbsolute ; lastColor[2] = v.color.bAbsolute ; lastColor[3] = v.color.aAbsolute ; } // Set up last normal data if it exists and previous element // doesn't override it. if (v.normal != null && !lastElementNormal && !(lastElementColor && lastLastElementNormal)) { lastSextant = v.normal.sextant ; lastOctant = v.normal.octant ; lastU = v.normal.uAbsolute ; lastV = v.normal.vAbsolute ; lastSpecialNormal = v.normal.specialNormal ; } } void outputCommand(HuffmanTable t, CommandStream outputBuffer) { int command = CommandStream.MESH_B_R ; long data = stripFlag & 0x1 ; command |= (((meshIndex & 0xf) << 1) | (stripFlag >> 1)) ; outputBuffer.addCommand(command, 8, data, 1) ; } public String toString() { return "meshReference: stripFlag " + stripFlag + " meshIndex " + meshIndex ; } } /**
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -