1 /* 2 * $RCSfile: CompressedGeometryRetained.java,v $ 3 * 4 * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * - Redistribution of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * - Redistribution in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * 18 * Neither the name of Sun Microsystems, Inc. or the names of 19 * contributors may be used to endorse or promote products derived 20 * from this software without specific prior written permission. 21 * 22 * This software is provided "AS IS," without a warranty of any 23 * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND 24 * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, 25 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY 26 * EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL 27 * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF 28 * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS 29 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR 30 * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, 31 * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND 32 * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR 33 * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE 34 * POSSIBILITY OF SUCH DAMAGES. 35 * 36 * You acknowledge that this software is not designed, licensed or 37 * intended for use in the design, construction, operation or 38 * maintenance of any nuclear facility. 39 * 40 * $Revision: 1.3 $ 41 * $Date: 2007/02/09 17:20:21 $ 42 * $State: Exp $ 43 */ 44 45 package com.sun.j3d.utils.geometry.compression; 46 47 import javax.media.j3d.BoundingBox; 48 import javax.media.j3d.Bounds; 49 import javax.media.j3d.Canvas3D; 50 import javax.media.j3d.GeometryArray; 51 import javax.media.j3d.PickInfo; 52 import javax.media.j3d.PickShape; 53 import javax.media.j3d.Transform3D; 54 import javax.vecmath.Point3d; 55 56 /** 57 * The compressed geometry object is used to store geometry in a 58 * compressed format. Using compressed geometry reduces the amount 59 * of memory needed by a Java 3D application and increases the speed 60 * objects can be sent over the network. Once geometry decompression 61 * hardware support becomes available, increased rendering performance 62 * will also result from the use of compressed geometry. 63 */ 64 class CompressedGeometryRetained extends Object { 65 66 // If not in by-reference mode, a 48-byte header as defined by the 67 // GL_SUNX_geometry_compression OpenGL extension is always concatenated to 68 // the beginning of the compressed geometry data and copied along with the 69 // it into a contiguous array. This allows hardware decompression using 70 // the obsolete experimental GL_SUNX_geometry_compression extension if 71 // that is all that is available. 72 // 73 // This is completely distinct and not to be confused with the cgHeader 74 // field on the non-retained side, although much of the data is 75 // essentially the same. 76 private static final int HEADER_LENGTH = 48 ; 77 78 // These are the header locations examined. 79 private static final int HEADER_MAJOR_VERSION_OFFSET = 0 ; 80 private static final int HEADER_MINOR_VERSION_OFFSET = 1 ; 81 private static final int HEADER_MINOR_MINOR_VERSION_OFFSET = 2 ; 82 private static final int HEADER_BUFFER_TYPE_OFFSET = 3 ; 83 private static final int HEADER_BUFFER_DATA_OFFSET = 4 ; 84 85 // The OpenGL compressed geometry extensions use bits instead of 86 // enumerations to represent the type of compressed geometry. 87 static final byte TYPE_POINT = 1 ; 88 static final byte TYPE_LINE = 2 ; 89 static final byte TYPE_TRIANGLE = 4 ; 90 91 // Version number of this compressed geometry object. 92 int majorVersionNumber ; 93 int minorVersionNumber ; 94 int minorMinorVersionNumber ; 95 96 // These fields are used by the native execute() method. 97 int packedVersion ; 98 int bufferType ; 99 int bufferContents ; 100 int renderFlags ; 101 int offset ; 102 int size ; 103 byte[] compressedGeometry ; 104 105 // A reference to the original byte array with which this object was 106 // created. If hardware decompression is available but it doesn't support 107 // by-reference semantics, then an internal copy of the original byte array 108 // is made even when by-reference semantics have been requested. 109 private byte[] originalCompressedGeometry = null ; 110 111 // Geometric bounds 112 private BoundingBox geoBounds = new BoundingBox(); 113 114 // True if by-reference data access mode is in effect. 115 private boolean byReference = false ; 116 117 /** 118 * The package-scoped constructor. 119 */ CompressedGeometryRetained()120 CompressedGeometryRetained() { 121 // Compressed geometry is always bounded by [-1..1] on each axis, so 122 // set that as the initial bounding box. 123 geoBounds.setUpper( 1.0, 1.0, 1.0) ; 124 geoBounds.setLower(-1.0,-1.0,-1.0) ; 125 } 126 127 /** 128 * Return true if the data access mode is by-reference. 129 */ isByReference()130 boolean isByReference() { 131 return this.byReference ; 132 } 133 createByCopy(byte[] geometry)134 private void createByCopy(byte[] geometry) { 135 // Always copy a header along with the compressed geometry into a 136 // contiguous array in order to support hardware acceleration with the 137 // GL_SUNX_geometry_compression extension. The header is unnecessary 138 // if only the newer GL_SUN_geometry_compression API needs support. 139 compressedGeometry = new byte[HEADER_LENGTH + this.size] ; 140 141 compressedGeometry[HEADER_MAJOR_VERSION_OFFSET] = 142 (byte)this.majorVersionNumber ; 143 144 compressedGeometry[HEADER_MINOR_VERSION_OFFSET] = 145 (byte)this.minorVersionNumber ; 146 147 compressedGeometry[HEADER_MINOR_MINOR_VERSION_OFFSET] = 148 (byte)this.minorMinorVersionNumber ; 149 150 compressedGeometry[HEADER_BUFFER_TYPE_OFFSET] = 151 (byte)this.bufferType ; 152 153 compressedGeometry[HEADER_BUFFER_DATA_OFFSET] = 154 (byte)this.bufferContents ; 155 156 System.arraycopy(geometry, this.offset, 157 compressedGeometry, HEADER_LENGTH, this.size) ; 158 159 this.offset = HEADER_LENGTH ; 160 } 161 162 /** 163 * Creates the retained compressed geometry data. Data from the header is 164 * always copied; the compressed geometry is copied as well if the data 165 * access mode is not by-reference. 166 * 167 * @param hdr the compressed geometry header 168 * @param geometry the compressed geometry 169 * @param byReference if true then by-reference semantics requested 170 */ createCompressedGeometry(CompressedGeometryData.Header hdr, byte[] geometry, boolean byReference)171 void createCompressedGeometry(CompressedGeometryData.Header hdr, 172 byte[] geometry, boolean byReference) { 173 174 this.byReference = byReference ; 175 176 if (hdr.lowerBound != null) 177 this.geoBounds.setLower(hdr.lowerBound) ; 178 179 if (hdr.upperBound != null) 180 this.geoBounds.setUpper(hdr.upperBound) ; 181 182 //// this.centroid.set(geoBounds.getCenter()); 183 //// recompCentroid = false; 184 this.majorVersionNumber = hdr.majorVersionNumber ; 185 this.minorVersionNumber = hdr.minorVersionNumber ; 186 this.minorMinorVersionNumber = hdr.minorMinorVersionNumber ; 187 188 this.packedVersion = 189 (hdr.majorVersionNumber << 24) | 190 (hdr.minorVersionNumber << 16) | 191 (hdr.minorMinorVersionNumber << 8) ; 192 193 switch(hdr.bufferType) { 194 case CompressedGeometryData.Header.POINT_BUFFER: 195 this.bufferType = TYPE_POINT ; 196 break ; 197 case CompressedGeometryData.Header.LINE_BUFFER: 198 this.bufferType = TYPE_LINE ; 199 break ; 200 case CompressedGeometryData.Header.TRIANGLE_BUFFER: 201 this.bufferType = TYPE_TRIANGLE ; 202 break ; 203 } 204 205 this.bufferContents = hdr.bufferDataPresent ; 206 this.renderFlags = 0 ; 207 208 this.size = hdr.size ; 209 this.offset = hdr.start ; 210 211 if (byReference) { 212 // Assume we can use the given reference, but maintain a second 213 // reference in case a copy is later needed. 214 this.compressedGeometry = geometry; 215 this.originalCompressedGeometry = geometry; 216 } else { 217 // Copy the original data into a format that can be used by both 218 // the software and native hardware decompressors. 219 createByCopy(geometry); 220 this.originalCompressedGeometry = null; 221 } 222 } 223 224 /** 225 * Return a vertex format mask that's compatible with GeometryArray 226 * objects. 227 */ getVertexFormat()228 int getVertexFormat() { 229 int vertexFormat = GeometryArray.COORDINATES; 230 231 if ((bufferContents & CompressedGeometryData.Header.NORMAL_IN_BUFFER) != 0) { 232 vertexFormat |= GeometryArray.NORMALS; 233 } 234 235 if ((bufferContents & CompressedGeometryData.Header.COLOR_IN_BUFFER) != 0) { 236 if ((bufferContents & CompressedGeometryData.Header.ALPHA_IN_BUFFER) != 0) { 237 vertexFormat |= GeometryArray.COLOR_4; 238 } else { 239 vertexFormat |= GeometryArray.COLOR_3; 240 } 241 } 242 243 return vertexFormat ; 244 } 245 246 /** 247 * Return a buffer type that's compatible with CompressedGeometryData.Header. 248 */ getBufferType()249 int getBufferType() { 250 switch(this.bufferType) { 251 case TYPE_POINT: 252 return CompressedGeometryData.Header.POINT_BUFFER ; 253 case TYPE_LINE: 254 return CompressedGeometryData.Header.LINE_BUFFER ; 255 default: 256 case TYPE_TRIANGLE: 257 return CompressedGeometryData.Header.TRIANGLE_BUFFER ; 258 } 259 } 260 261 /** 262 * Copies compressed geometry data into the given array of bytes. 263 * The internal header information is not copied. 264 * 265 * @param buff array of bytes into which to copy compressed geometry 266 */ copy(byte[] buff)267 void copy(byte[] buff) { 268 System.arraycopy(compressedGeometry, offset, buff, 0, size) ; 269 } 270 271 /** 272 * Returns a reference to the original compressed geometry byte array, 273 * which may have been copied even if by-reference semantics have been 274 * requested. It will be null if byCopy is in effect. 275 * 276 * @return reference to array of bytes containing the compressed geometry. 277 */ getReference()278 byte[] getReference() { 279 return originalCompressedGeometry ; 280 } 281 282 } 283