001: /*
002: * $RCSfile: MeshBuffer.java,v $
003: *
004: * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: *
010: * - Redistribution of source code must retain the above copyright
011: * notice, this list of conditions and the following disclaimer.
012: *
013: * - Redistribution in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in
015: * the documentation and/or other materials provided with the
016: * distribution.
017: *
018: * Neither the name of Sun Microsystems, Inc. or the names of
019: * contributors may be used to endorse or promote products derived
020: * from this software without specific prior written permission.
021: *
022: * This software is provided "AS IS," without a warranty of any
023: * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
024: * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
025: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
026: * EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL
027: * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF
028: * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
029: * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR
030: * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
031: * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
032: * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
033: * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
034: * POSSIBILITY OF SUCH DAMAGES.
035: *
036: * You acknowledge that this software is not designed, licensed or
037: * intended for use in the design, construction, operation or
038: * maintenance of any nuclear facility.
039: *
040: * $Revision: 1.5 $
041: * $Date: 2007/02/09 17:20:17 $
042: * $State: Exp $
043: */
044:
045: package com.sun.j3d.utils.compression;
046:
047: import javax.vecmath.Color3f;
048: import javax.vecmath.Color4f;
049: import javax.vecmath.Point3f;
050: import javax.vecmath.Vector3f;
051:
052: /**
053: * This class mirrors the vertex mesh buffer stack supported by the geometry
054: * compression semantics.
055: */
056: class MeshBuffer {
057: //
058: // The fixed-length mesh buffer stack is represented by circular buffers.
059: // Three stack representations are provided: vertices, positions, and
060: // indices.
061: //
062: // The vertex representation stores references to CompressionStreamVertex
063: // objects. The position representation stores references to Point3f,
064: // Vector3f, Color3f, and Color4f objects, while the index representation
065: // stores indices into externally maintained arrays of those objects. All
066: // these representations may be used independently and all provide access
067: // to the stored references via a mesh buffer index.
068: //
069: // In addition, the position and index representations provide lookup
070: // mechanisms to check if positions or indices exist in the mesh buffer
071: // and return their mesh buffer indices if they do. This is used to
072: // implement a limited meshing algorithm which reduces the number of
073: // vertices when non-stripped abutting facets are added to a compression
074: // stream.
075: //
076: static final int NOT_FOUND = -1;
077:
078: private static final int SIZE = 16;
079: private static final int NAN_HASH = new Point3f(Float.NaN,
080: Float.NaN, Float.NaN).hashCode();
081:
082: private int topIndex = SIZE - 1;
083: private int positionIndices[] = new int[SIZE];
084: private int normalIndices[] = new int[SIZE];
085: private int colorIndices[] = new int[SIZE];
086:
087: private int topPosition = SIZE - 1;
088: private int positionHashCodes[] = new int[SIZE];
089: private Point3f positions[] = new Point3f[SIZE];
090: private Vector3f normals[] = new Vector3f[SIZE];
091: private Color3f colors3[] = new Color3f[SIZE];
092: private Color4f colors4[] = new Color4f[SIZE];
093:
094: private int topVertex = SIZE - 1;
095: private CompressionStreamVertex vertices[] = new CompressionStreamVertex[SIZE];
096:
097: MeshBuffer() {
098: for (int i = 0; i < SIZE; i++) {
099: positionHashCodes[i] = NAN_HASH;
100:
101: positionIndices[i] = NOT_FOUND;
102: normalIndices[i] = NOT_FOUND;
103: colorIndices[i] = NOT_FOUND;
104: }
105: }
106:
107: private static int nextTop(int top) {
108: // The stack top references an element in the fixed-length backing
109: // array in which the stack is stored. Stack elements below it have
110: // decreasing indices into the backing array until element 0, at which
111: // point the indices wrap to the end of the backing array and back to
112: // the top.
113: //
114: // A push is accomplished by incrementing the stack top in a circular
115: // buffer and storing the data into the new stack element it
116: // references. The bottom of the stack is the element with the next
117: // higher index from the top in the backing array, and is overwritten
118: // with each new push.
119: return (top + 1) % SIZE;
120: }
121:
122: private static int flipOffset(int top, int offset) {
123: // Flips an offset relative to the beginning of the backing array to
124: // an offset from the top of the stack. Also works in reverse, from
125: // an offset from the top of the stack to an offset from the beginning
126: // of the backing array.
127: if (offset > top)
128: offset -= SIZE;
129: return top - offset;
130: }
131:
132: //
133: // Mesh buffer vertex stack. This is currently only used for vertex
134: // lookup during the quantization pass in order to compute delta values;
135: // no mesh reference lookup is necessary.
136: //
137: void push(CompressionStreamVertex v) {
138: topVertex = nextTop(topVertex);
139: vertices[topVertex] = v;
140: }
141:
142: CompressionStreamVertex getVertex(int meshReference) {
143: return vertices[flipOffset(topVertex, meshReference)];
144: }
145:
146: //
147: // Mesh buffer index stack and index reference lookup support.
148: //
149: void push(int positionIndex, int normalIndex) {
150: topIndex = nextTop(topIndex);
151:
152: positionIndices[topIndex] = positionIndex;
153: normalIndices[topIndex] = normalIndex;
154: }
155:
156: void push(int positionIndex, int colorIndex, int normalIndex) {
157: push(positionIndex, normalIndex);
158: colorIndices[topIndex] = colorIndex;
159: }
160:
161: int getMeshReference(int positionIndex) {
162: int index;
163: for (index = 0; index < SIZE; index++)
164: if (positionIndices[index] == positionIndex)
165: break;
166:
167: if (index == SIZE)
168: return NOT_FOUND;
169: return flipOffset(topIndex, index);
170: }
171:
172: int getPositionIndex(int meshReference) {
173: return positionIndices[flipOffset(topIndex, meshReference)];
174: }
175:
176: int getColorIndex(int meshReference) {
177: return colorIndices[flipOffset(topIndex, meshReference)];
178: }
179:
180: int getNormalIndex(int meshReference) {
181: return normalIndices[flipOffset(topIndex, meshReference)];
182: }
183:
184: //
185: // Mesh buffer position stack and position reference lookup support.
186: //
187: void push(Point3f position, Vector3f normal) {
188: topPosition = nextTop(topPosition);
189:
190: positionHashCodes[topPosition] = position.hashCode();
191: positions[topPosition] = position;
192: normals[topPosition] = normal;
193: }
194:
195: void push(Point3f position, Color3f color, Vector3f normal) {
196: push(position, normal);
197: colors3[topPosition] = color;
198: }
199:
200: void push(Point3f position, Color4f color, Vector3f normal) {
201: push(position, normal);
202: colors4[topPosition] = color;
203: }
204:
205: void push(Point3f position, Object color, Vector3f normal) {
206: push(position, normal);
207: if (color instanceof Color3f)
208: colors3[topPosition] = (Color3f) color;
209: else
210: colors4[topPosition] = (Color4f) color;
211: }
212:
213: int getMeshReference(Point3f position) {
214: int index;
215: int hashCode = position.hashCode();
216:
217: for (index = 0; index < SIZE; index++)
218: if (positionHashCodes[index] == hashCode)
219: if (positions[index].equals(position))
220: break;
221:
222: if (index == SIZE)
223: return NOT_FOUND;
224: return flipOffset(topPosition, index);
225: }
226:
227: Point3f getPosition(int meshReference) {
228: return positions[flipOffset(topPosition, meshReference)];
229: }
230:
231: Color3f getColor3(int meshReference) {
232: return colors3[flipOffset(topPosition, meshReference)];
233: }
234:
235: Color4f getColor4(int meshReference) {
236: return colors4[flipOffset(topPosition, meshReference)];
237: }
238:
239: Vector3f getNormal(int meshReference) {
240: return normals[flipOffset(topPosition, meshReference)];
241: }
242: }
|