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