aboutsummaryrefslogtreecommitdiffstats
path: root/src/javax/media/j3d/CompressedGeometryRetained.java
diff options
context:
space:
mode:
authorJulien Gouesse <[email protected]>2015-11-19 20:45:53 +0100
committerJulien Gouesse <[email protected]>2015-11-19 20:45:53 +0100
commita18c3b0789bfc24b49dbaf41c2390159bc683afc (patch)
treeb5236ff2570178de356eab569225108948eb4d30 /src/javax/media/j3d/CompressedGeometryRetained.java
parent264608060948a634b53a13ee96ed07527eb07340 (diff)
parent7a2e20caac9db6f789a7b3fab344b9758af45335 (diff)
Gets Harvey's changes
Diffstat (limited to 'src/javax/media/j3d/CompressedGeometryRetained.java')
-rw-r--r--src/javax/media/j3d/CompressedGeometryRetained.java470
1 files changed, 470 insertions, 0 deletions
diff --git a/src/javax/media/j3d/CompressedGeometryRetained.java b/src/javax/media/j3d/CompressedGeometryRetained.java
new file mode 100644
index 0000000..aba0277
--- /dev/null
+++ b/src/javax/media/j3d/CompressedGeometryRetained.java
@@ -0,0 +1,470 @@
+/*
+ * Copyright 1998-2008 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ */
+
+package javax.media.j3d ;
+import javax.vecmath.Point3d;
+
+/**
+ * The compressed geometry object is used to store geometry in a
+ * compressed format. Using compressed geometry reduces the amount
+ * of memory needed by a Java 3D application and increases the speed
+ * objects can be sent over the network. Once geometry decompression
+ * hardware support becomes available, increased rendering performance
+ * will also result from the use of compressed geometry.
+ */
+class CompressedGeometryRetained extends GeometryRetained {
+
+ // If not in by-reference mode, a 48-byte header as defined by the
+ // GL_SUNX_geometry_compression OpenGL extension is always concatenated to
+ // the beginning of the compressed geometry data and copied along with the
+ // it into a contiguous array. This allows hardware decompression using
+ // the obsolete experimental GL_SUNX_geometry_compression extension if
+ // that is all that is available.
+ //
+ // This is completely distinct and not to be confused with the cgHeader
+ // field on the non-retained side, although much of the data is
+ // essentially the same.
+ private static final int HEADER_LENGTH = 48 ;
+
+ // These are the header locations examined.
+ private static final int HEADER_MAJOR_VERSION_OFFSET = 0 ;
+ private static final int HEADER_MINOR_VERSION_OFFSET = 1 ;
+ private static final int HEADER_MINOR_MINOR_VERSION_OFFSET = 2 ;
+ private static final int HEADER_BUFFER_TYPE_OFFSET = 3 ;
+ private static final int HEADER_BUFFER_DATA_OFFSET = 4 ;
+
+ // The OpenGL compressed geometry extensions use bits instead of
+ // enumerations to represent the type of compressed geometry.
+ static final byte TYPE_POINT = 1 ;
+ static final byte TYPE_LINE = 2 ;
+ static final byte TYPE_TRIANGLE = 4 ;
+
+ // Version number of this compressed geometry object.
+ int majorVersionNumber ;
+ int minorVersionNumber ;
+ int minorMinorVersionNumber ;
+
+ // These fields are used by the native execute() method.
+ int packedVersion ;
+ int bufferType ;
+ int bufferContents ;
+ int renderFlags ;
+ int offset ;
+ int size ;
+ byte[] compressedGeometry ;
+
+ // True if by-reference data access mode is in effect.
+ private boolean byReference = false ;
+
+ // A reference to the original byte array with which this object was
+ // created. If hardware decompression is available but it doesn't support
+ // by-reference semantics, then an internal copy of the original byte array
+ // is made even when by-reference semantics have been requested.
+ private byte[] originalCompressedGeometry = null ;
+
+ // True if the platform supports hardware decompression.
+ private static boolean hardwareDecompression = false ;
+
+ // This field retains a reference to the GeometryRetained object used for
+ // geometry-based picking. It is normally the same reference as the
+ // mirror geometry used for rendering unless hardware decompression is
+ // supported.
+ private GeometryRetained pickGeometry = null ;
+
+ /**
+ * Formerly native method that returns availability of a native by-reference
+ * rendering API for compressed geometry.
+ */
+ private boolean decompressByRef(Context ctx) {
+ return false;
+ }
+
+ /**
+ * Formerly native method that returns availability of hardware
+ * rendering (and acceleration) for compressed geometry of the
+ * given version.
+ */
+ private boolean decompressHW(Context ctx, int majorVersion, int minorVersion) {
+ return false;
+ }
+
+ /**
+ * Formerly native method that does HW compressed geometry rendering
+ */
+ private void execute(Context ctx, int version, int bufferType,
+ int bufferContents, int renderFlags,
+ int offset, int size, byte[] geometry) {
+
+ assert false : "This method should never be called!";
+ }
+
+ /**
+ * Method for calling native execute() method on behalf of the J3D renderer.
+ */
+ @Override
+ void execute(Canvas3D cv, RenderAtom ra, boolean isNonUniformScale,
+ boolean updateAlpha, float alpha,
+ int screen, boolean ignoreVertexColors) {
+
+ // XXXX: alpha udpate
+ execute(cv.ctx, packedVersion, bufferType, bufferContents,
+ renderFlags, offset, size, compressedGeometry) ;
+ }
+
+ /**
+ * The package-scoped constructor.
+ */
+ CompressedGeometryRetained() {
+ this.geoType = GEO_TYPE_COMPRESSED ;
+
+ // Compressed geometry is always bounded by [-1..1] on each axis, so
+ // set that as the initial bounding box.
+ geoBounds.setUpper( 1.0, 1.0, 1.0) ;
+ geoBounds.setLower(-1.0,-1.0,-1.0) ;
+ }
+
+ /**
+ * Compressed geometry is immutable so this method does nothing.
+ */
+ @Override
+ void computeBoundingBox() {
+ }
+
+ /**
+ * Update this object. Compressed geometry is immutable so there's
+ * nothing to do.
+ */
+ @Override
+ void update() {
+ isDirty = 0 ;
+ }
+
+ /**
+ * Return true if the data access mode is by-reference.
+ */
+ boolean isByReference() {
+ return this.byReference ;
+ }
+
+ private void createByCopy(byte[] geometry) {
+ // Always copy a header along with the compressed geometry into a
+ // contiguous array in order to support hardware acceleration with the
+ // GL_SUNX_geometry_compression extension. The header is unnecessary
+ // if only the newer GL_SUN_geometry_compression API needs support.
+ compressedGeometry = new byte[HEADER_LENGTH + this.size] ;
+
+ compressedGeometry[HEADER_MAJOR_VERSION_OFFSET] =
+ (byte)this.majorVersionNumber ;
+
+ compressedGeometry[HEADER_MINOR_VERSION_OFFSET] =
+ (byte)this.minorVersionNumber ;
+
+ compressedGeometry[HEADER_MINOR_MINOR_VERSION_OFFSET] =
+ (byte)this.minorMinorVersionNumber ;
+
+ compressedGeometry[HEADER_BUFFER_TYPE_OFFSET] =
+ (byte)this.bufferType ;
+
+ compressedGeometry[HEADER_BUFFER_DATA_OFFSET] =
+ (byte)this.bufferContents ;
+
+ System.arraycopy(geometry, this.offset,
+ compressedGeometry, HEADER_LENGTH, this.size) ;
+
+ this.offset = HEADER_LENGTH ;
+ }
+
+ /**
+ * Creates the retained compressed geometry data. Data from the header is
+ * always copied; the compressed geometry is copied as well if the data
+ * access mode is not by-reference.
+ *
+ * @param hdr the compressed geometry header
+ * @param geometry the compressed geometry
+ * @param byReference if true then by-reference semantics requested
+ */
+ void createCompressedGeometry(CompressedGeometryHeader hdr,
+ byte[] geometry, boolean byReference) {
+
+ this.byReference = byReference ;
+
+ if (hdr.lowerBound != null)
+ this.geoBounds.setLower(hdr.lowerBound) ;
+
+ if (hdr.upperBound != null)
+ this.geoBounds.setUpper(hdr.upperBound) ;
+
+ geoBounds.getCenter(this.centroid);
+ recompCentroid = false;
+ this.majorVersionNumber = hdr.majorVersionNumber ;
+ this.minorVersionNumber = hdr.minorVersionNumber ;
+ this.minorMinorVersionNumber = hdr.minorMinorVersionNumber ;
+
+ this.packedVersion =
+ (hdr.majorVersionNumber << 24) |
+ (hdr.minorVersionNumber << 16) |
+ (hdr.minorMinorVersionNumber << 8) ;
+
+ switch(hdr.bufferType) {
+ case CompressedGeometryHeader.POINT_BUFFER:
+ this.bufferType = TYPE_POINT ;
+ break ;
+ case CompressedGeometryHeader.LINE_BUFFER:
+ this.bufferType = TYPE_LINE ;
+ break ;
+ case CompressedGeometryHeader.TRIANGLE_BUFFER:
+ this.bufferType = TYPE_TRIANGLE ;
+ break ;
+ }
+
+ this.bufferContents = hdr.bufferDataPresent ;
+ this.renderFlags = 0 ;
+
+ this.size = hdr.size ;
+ this.offset = hdr.start ;
+
+ if (byReference) {
+ // Assume we can use the given reference, but maintain a second
+ // reference in case a copy is later needed.
+ this.compressedGeometry = geometry ;
+ this.originalCompressedGeometry = geometry ;
+ } else {
+ // Copy the original data into a format that can be used by both
+ // the software and native hardware decompressors.
+ createByCopy(geometry) ;
+ this.originalCompressedGeometry = null ;
+ }
+ }
+
+ /**
+ * Decompress this object into a GeometryArrayRetained if hardware
+ * decompression is not available. Once decompressed the resulting
+ * geometry replaces the geometry reference in the associated RenderAtom
+ * as well as the mirror geometry reference in this object.
+ */
+ GeometryRetained getGeometry(boolean forceDecompression, Canvas3D cv ) {
+
+ if (forceDecompression) {
+ // forceDecompression is set to true if lighting is disabled and
+ // ignoreVertexColors is true, since there is no way for openGL to
+ // ignore vertexColors in this case.
+ GeometryDecompressorRetained gdr =
+ new GeometryDecompressorRetained() ;
+
+ mirrorGeometry = gdr.decompress(this) ;
+ gdr.getBoundingBox(geoBounds) ;
+ pickGeometry = mirrorGeometry ;
+ }
+ else {
+ // Return this object if hardware decompression is available.
+ if (hardwareDecompression)
+ return this;
+
+ // Check to see if hardware decompression is available.
+ if (decompressHW(cv.ctx, majorVersionNumber, minorVersionNumber)) {
+ hardwareDecompression = true ;
+
+ // If hardware can't handle by-reference, punt to by-copy.
+ if (isByReference() && !decompressByRef(cv.ctx)) {
+ createByCopy(compressedGeometry) ;
+ }
+
+ return this;
+ }
+
+ // Decompress the data into a GeometryArrayRetained representation
+ // for the mirror geometry reference.
+ GeometryDecompressorRetained gdr =
+ new GeometryDecompressorRetained() ;
+
+ mirrorGeometry = gdr.decompress(this) ;
+ gdr.getBoundingBox(geoBounds) ;
+
+ // The mirror geometry contains a superset of the pick geometry
+ // data. Since hardware decompression isn't available, there's no
+ // need to retain separate pick geometry.
+ pickGeometry = mirrorGeometry ;
+ }
+
+ return mirrorGeometry ;
+ }
+
+ /**
+ * This method always decompresses the geometry and retains the result in
+ * order to support geometry-based picking and collision detection. The
+ * returned GeometryRetained object will contain only positions and
+ * connections.
+ */
+ GeometryRetained getPickGeometry() {
+ // Return the pick geometry if available.
+ if (pickGeometry != null)
+ return pickGeometry ;
+
+ // Decompress the data into a GeometryArrayRetained representation for
+ // the pick geometry reference. Retain it and its bounding box.
+ GeometryDecompressorRetained gdr = new GeometryDecompressorRetained() ;
+ gdr.setDecompressPositionsOnly(true) ;
+
+ pickGeometry = gdr.decompress(this) ;
+ gdr.getBoundingBox(geoBounds) ;
+ return pickGeometry ;
+ }
+
+ //
+ // The following intersect() methods are used to implement geometry-based
+ // picking and collision.
+ //
+ @Override
+ boolean intersect(PickShape pickShape, PickInfo pickInfo, int flags, Point3d iPnt,
+ GeometryRetained geom, int geomIndex) {
+ GeometryRetained geomR = getPickGeometry() ;
+ return (geomR != null ?
+ geomR.intersect(pickShape, pickInfo, flags, iPnt, geom, geomIndex) : false);
+ }
+
+ @Override
+ boolean intersect(Bounds targetBound) {
+ GeometryRetained geom = getPickGeometry() ;
+ return (geom != null ? geom.intersect(targetBound) : false);
+ }
+
+ @Override
+ boolean intersect(Transform3D thisToOtherVworld, GeometryRetained g) {
+ GeometryRetained geom = getPickGeometry() ;
+ return (geom != null ?
+ geom.intersect(thisToOtherVworld, g) : false);
+ }
+
+ @Override
+ boolean intersect(Point3d[] pnts) {
+ GeometryRetained geom = getPickGeometry() ;
+ return (geom != null ? geom.intersect(pnts) : false);
+ }
+
+ /**
+ * Return a vertex format mask that's compatible with GeometryArray
+ * objects.
+ */
+ @Override
+ int getVertexFormat() {
+ int vertexFormat = GeometryArray.COORDINATES ;
+
+ if ((this.bufferContents &
+ CompressedGeometryHeader.NORMAL_IN_BUFFER) != 0)
+ vertexFormat |= GeometryArray.NORMALS ;
+
+ if ((this.bufferContents &
+ CompressedGeometryHeader.COLOR_IN_BUFFER) != 0)
+ vertexFormat |= GeometryArray.COLOR ;
+
+ if ((this.bufferContents &
+ CompressedGeometryHeader.ALPHA_IN_BUFFER) != 0)
+ vertexFormat |= GeometryArray.WITH_ALPHA ;
+
+ return vertexFormat ;
+ }
+
+ /**
+ * Return a buffer type that's compatible with CompressedGeometryHeader.
+ */
+ int getBufferType() {
+ switch(this.bufferType) {
+ case TYPE_POINT:
+ return CompressedGeometryHeader.POINT_BUFFER ;
+ case TYPE_LINE:
+ return CompressedGeometryHeader.LINE_BUFFER ;
+ default:
+ case TYPE_TRIANGLE:
+ return CompressedGeometryHeader.TRIANGLE_BUFFER ;
+ }
+ }
+
+ /**
+ * Copies compressed geometry data into the given array of bytes.
+ * The internal header information is not copied.
+ *
+ * @param buff array of bytes into which to copy compressed geometry
+ */
+ void copy(byte[] buff) {
+ System.arraycopy(compressedGeometry, offset, buff, 0, size) ;
+ }
+
+ /**
+ * Returns a reference to the original compressed geometry byte array,
+ * which may have been copied even if by-reference semantics have been
+ * requested. It will be null if byCopy is in effect.
+ *
+ * @return reference to array of bytes containing the compressed geometry.
+ */
+ byte[] getReference() {
+ return originalCompressedGeometry ;
+ }
+
+ /**
+ * Copies all retained data for cloneNodeComponent() on the non-retained
+ * side. This is unlike GeometryArray subclasses which just call the
+ * public API constructors and then duplicateNodeComponent() to invoke the
+ * GeometryArray implementation of duplicateAttributes(), since the
+ * CompressedGeometry class directly subclasses Geometry and calling the
+ * public constructors would cause a lot of redundant data copying.
+ */
+ void duplicate(CompressedGeometryRetained cgr) {
+ cgr.majorVersionNumber = this.majorVersionNumber ;
+ cgr.minorVersionNumber = this.minorVersionNumber ;
+ cgr.minorMinorVersionNumber = this.minorMinorVersionNumber ;
+
+ cgr.packedVersion = this.packedVersion ;
+ cgr.bufferType = this.bufferType ;
+ cgr.bufferContents = this.bufferContents ;
+ cgr.renderFlags = this.renderFlags ;
+
+ cgr.offset = this.offset ;
+ cgr.size= this.size ;
+
+ cgr.geoBounds.setLower(this.geoBounds.lower) ;
+ cgr.geoBounds.setUpper(this.geoBounds.upper) ;
+ cgr.pickGeometry = this.pickGeometry ;
+ cgr.byReference = this.byReference ;
+
+ if (this.byReference) {
+ // Copy references only.
+ cgr.compressedGeometry = this.compressedGeometry ;
+ cgr.originalCompressedGeometry = this.originalCompressedGeometry ;
+ } else {
+ // Copy entire byte array including 48-byte native OpenGL header.
+ cgr.compressedGeometry = new byte[this.compressedGeometry.length] ;
+ System.arraycopy(this.compressedGeometry, 0,
+ cgr.compressedGeometry, 0,
+ this.compressedGeometry.length) ;
+ cgr.originalCompressedGeometry = null ;
+ }
+ }
+
+ @Override
+ int getClassType() {
+ return COMPRESS_TYPE;
+ }
+}