diff options
Diffstat (limited to 'src/javax/media/j3d/GeneralizedStrip.java')
-rw-r--r-- | src/javax/media/j3d/GeneralizedStrip.java | 889 |
1 files changed, 889 insertions, 0 deletions
diff --git a/src/javax/media/j3d/GeneralizedStrip.java b/src/javax/media/j3d/GeneralizedStrip.java new file mode 100644 index 0000000..baddedf --- /dev/null +++ b/src/javax/media/j3d/GeneralizedStrip.java @@ -0,0 +1,889 @@ +/* + * 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; + + +/** + * This class provides static methods to support topological + * transformations on generalized strips. This is used by the + * GeometryDecompressor. These methods only need to look at the + * vertex replacement flags to determine how the vertices in the strip + * are connected. The connections are rearranged in different ways to + * transform generalized strips to GeometryArray representations. + * + * @see GeneralizedStripFlags + * @see GeneralizedVertexList + * @see GeometryDecompressor + */ +class GeneralizedStrip { + private static final boolean debug = false ; + + // Private convenience copies of various constants. + private static final int CW = + GeneralizedStripFlags.FRONTFACE_CW ; + private static final int CCW = + GeneralizedStripFlags.FRONTFACE_CCW ; + private static final int RESTART_CW = + GeneralizedStripFlags.RESTART_CW ; + private static final int RESTART_CCW = + GeneralizedStripFlags.RESTART_CCW ; + private static final int REPLACE_MIDDLE = + GeneralizedStripFlags.REPLACE_MIDDLE ; + private static final int REPLACE_OLDEST = + GeneralizedStripFlags.REPLACE_OLDEST ; + + /** + * The IntList is like an ArrayList, but avoids the Integer + * object wrapper and accessor overhead for simple lists of ints. + */ + static class IntList { + /** + * The array of ints. + */ + int ints[] ; + + /** + * The number of ints in this instance. + */ + int count ; + + /** + * Construct a new empty IntList of the given initial size. + * @param initialSize initial size of the backing array + */ + IntList(int initialSize) { + ints = new int[initialSize] ; + count = 0 ; + } + + /** + * Constructs an IntList with the given contents. + * @param ints the array of ints to use as the contents + */ + IntList(int ints[]) { + this.ints = ints ; + this.count = ints.length ; + } + + /** + * Add a new int to the end of this list. + * @param i the int to be appended to this list + */ + void add(int i) { + if (count == ints.length) { + int newints[] = new int[2*count] ; + System.arraycopy(ints, 0, newints, 0, count) ; + ints = newints ; + if (debug) + System.err.println + ("GeneralizedStrip.IntList: reallocated " + + (2*count) + " ints") ; + } + ints[count++] = i ; + } + + /** + * Trim the backing array to the current count and return the + * resulting backing array. + */ + int[] trim() { + if (count != ints.length) { + int newints[] = new int[count] ; + System.arraycopy(ints, 0, newints, 0, count) ; + ints = newints ; + } + return ints ; + } + + /** + * Fill the list with consecutive integers starting from 0. + */ + void fillAscending() { + for (int i = 0 ; i < ints.length ; i++) + ints[i] = i ; + + count = ints.length ; + } + + @Override + public String toString() { + String s = new String("[") ; + for (int i = 0 ; i < count-1 ; i++) + s = s + Integer.toString(ints[i]) + ", " ; + return s + Integer.toString(ints[count-1]) + "]" ; + } + } + + /** + * The StripArray class is used as the output of some conversion methods + * in the GeneralizedStrip class. + */ + static class StripArray { + /** + * A list of indices into the vertices of the original generalized + * strip. It specifies the order in which vertices in the original + * strip should be followed to build GeometryArray objects. + */ + IntList vertices ; + + /** + * A list of strip counts. + */ + IntList stripCounts ; + + /** + * Creates a StripArray with the specified vertices and stripCounts. + * @param vertices IntList containing vertex indicies. + * @param stripCounts IntList containing strip lengths. + */ + StripArray(IntList vertices, IntList stripCounts) { + this.vertices = vertices ; + this.stripCounts = stripCounts ; + } + } + + /** + * Interprets the vertex flags associated with a class implementing + * GeneralizedStripFlags, constructing and returning a 2-element array of + * StripArray objects. The first StripArray will contain triangle strips + * and the second will contain triangle fans. + * + * @param vertices an object implementing GeneralizedStripFlags + * @param frontFace a flag, either GeneralizedStripFlags.FRONTFACE_CW or + * GeneralizedStripFlags.FRONTFACE_CCW, indicating front face winding + * @return a 2-element array containing strips in 0 and fans in 1 + */ + static StripArray[] toStripsAndFans(GeneralizedStripFlags vertices, + int frontFace) { + + int size = vertices.getFlagCount() ; + + // Initialize IntLists to worst-case sizes. + IntList stripVerts = new IntList(size*3) ; + IntList fanVerts = new IntList(size*3) ; + IntList stripCounts = new IntList(size) ; + IntList fanCounts = new IntList(size) ; + + toStripsAndFans(vertices, frontFace, + stripVerts, stripCounts, fanVerts, fanCounts) ; + + // Construct the StripArray output. + StripArray sa[] = new StripArray[2] ; + + if (stripCounts.count > 0) + sa[0] = new StripArray(stripVerts, stripCounts) ; + + if (fanCounts.count > 0) + sa[1] = new StripArray(fanVerts, fanCounts) ; + + return sa ; + } + + private static void toStripsAndFans(GeneralizedStripFlags vertices, + int frontFace, + IntList stripVerts, + IntList stripCounts, + IntList fanVerts, + IntList fanCounts) { + int newFlag, curFlag, winding ; + int v, size, stripStart, stripLength ; + boolean transition = false ; + + stripStart = 0 ; + stripLength = 3 ; + curFlag = vertices.getFlag(0) ; + winding = (curFlag == RESTART_CW ? CW : CCW) ; + size = vertices.getFlagCount() ; + + // Vertex replace flags for the first 3 vertices are irrelevant since + // they can only define a single triangle. The first meaningful + // replace flag starts at the 4th vertex. + v = 3 ; + if (v < size) + curFlag = vertices.getFlag(v) ; + + while (v < size) { + newFlag = vertices.getFlag(v) ; + + if ((newFlag == curFlag) && + (newFlag != RESTART_CW) && (newFlag != RESTART_CCW)) { + // The last flag was the same as this one, and it wasn't a + // restart: proceed to the next vertex. + stripLength++ ; + v++ ; + + } else { + // Either this vertex flag changed from the last one, or + // the flag explicitly specifies a restart: process the + // last strip and start up a new one. + if (curFlag == REPLACE_MIDDLE) + addFan(fanVerts, fanCounts, stripStart, stripLength, + frontFace, winding, transition) ; + else + addStrip(stripVerts, stripCounts, stripStart, stripLength, + frontFace, winding) ; + + // Restart: skip to the 4th vertex of the new strip. + if ((newFlag == RESTART_CW) || (newFlag == RESTART_CCW)) { + winding = (newFlag == RESTART_CW ? CW : CCW) ; + stripStart = v ; + stripLength = 3 ; + v += 3 ; + transition = false ; + if (v < size) + curFlag = vertices.getFlag(v) ; + } + // Strip/fan transition: decrement start of strip. + else { + if (newFlag == REPLACE_OLDEST) { + // Flip winding order when transitioning from fans + // to strips. + winding = (winding == CW ? CCW : CW) ; + stripStart = v-2 ; + stripLength = 3 ; + } else { + // Flip winding order when transitioning from + // strips to fans only if the preceding strip has + // an even number of vertices. + if ((stripLength & 0x01) == 0) + winding = (winding == CW ? CCW : CW) ; + stripStart = v-3 ; + stripLength = 4 ; + } + v++ ; + transition = true ; + curFlag = newFlag ; + } + } + } + + // Finish off the last strip or fan. + // If v > size then the strip is degenerate. + if (v == size) + if (curFlag == REPLACE_MIDDLE) + addFan(fanVerts, fanCounts, stripStart, stripLength, + frontFace, winding, transition) ; + else + addStrip(stripVerts, stripCounts, stripStart, stripLength, + frontFace, winding) ; + else + throw new IllegalArgumentException + (J3dI18N.getString("GeneralizedStrip0")) ; + + if (debug) { + System.err.println("GeneralizedStrip.toStripsAndFans") ; + if (v > size) + System.err.println(" ended with a degenerate triangle:" + + " number of vertices: " + (v-size)) ; + + System.err.println("\n number of strips: " + stripCounts.count) ; + if (stripCounts.count > 0) { + System.err.println(" number of vertices: " + stripVerts.count) ; + System.err.println(" vertices/strip: " + + (float)stripVerts.count/stripCounts.count) ; + System.err.println(" strip counts: " + stripCounts.toString()) ; + // System.err.println(" indices: " + stripVerts.toString()) ; + } + + System.err.println("\n number of fans: " + fanCounts.count) ; + if (fanCounts.count > 0) { + System.err.println(" number of vertices: " + fanVerts.count) ; + System.err.println(" vertices/strip: " + + (float)fanVerts.count/fanCounts.count) ; + System.err.println(" fan counts: " + fanCounts.toString()) ; + // System.err.println(" indices: " + fanVerts.toString()) ; + } + System.err.println("\n total vertices: " + + (stripVerts.count + fanVerts.count) + + "\n original number of vertices: " + size + + "\n") ; + } + } + + // + // Java 3D specifies that the vertices of front-facing polygons + // have counter-clockwise (CCW) winding order when projected to + // the view surface. Polygons with clockwise (CW) vertex winding + // will be culled as back-facing by default. + // + // Generalized triangle strips can flip the orientation of their + // triangles with the RESTART_CW and RESTART_CCW vertex flags. + // Strips flagged with an orientation opposite to what has been + // specified as front-facing must have their windings reversed in + // order to have the correct face orientation when represented as + // GeometryArray objects. + // + private static void addStrip(IntList stripVerts, + IntList stripCounts, + int start, int length, + int frontFace, int winding) { + int vindex = start ; + + if (winding == frontFace) { + // Maintain original order. + stripCounts.add(length) ; + while (vindex < start + length) { + stripVerts.add(vindex++) ; + } + } else if ((length & 0x1) == 1) { + // Reverse winding order if number of vertices is odd. + stripCounts.add(length) ; + vindex += length-1 ; + while (vindex >= start) { + stripVerts.add(vindex--) ; + } + } else if (length == 4) { + // Swap middle vertices. + stripCounts.add(4) ; + stripVerts.add(vindex) ; + stripVerts.add(vindex+2) ; + stripVerts.add(vindex+1) ; + stripVerts.add(vindex+3) ; + } else { + // Make the 1st triangle a singleton with reverse winding. + stripCounts.add(3) ; + stripVerts.add(vindex) ; + stripVerts.add(vindex+2) ; + stripVerts.add(vindex+1) ; + if (length > 3) { + // Copy the rest of the vertices in original order. + vindex++ ; + stripCounts.add(length-1) ; + while (vindex < start + length) { + stripVerts.add(vindex++) ; + } + } + } + } + + private static void addFan(IntList fanVerts, + IntList fanCounts, + int start, int length, + int frontFace, int winding, + boolean transition) { + int vindex = start ; + fanVerts.add(vindex++) ; + + if (winding == frontFace) { + if (transition) { + // Skip 1st triangle if this is the result of a transition. + fanCounts.add(length-1) ; + vindex++ ; + } else { + fanCounts.add(length) ; + fanVerts.add(vindex++) ; + } + while (vindex < start + length) { + fanVerts.add(vindex++) ; + } + } else { + // Reverse winding order. + vindex += length-2 ; + while (vindex > start+1) { + fanVerts.add(vindex--) ; + } + if (transition) { + // Skip 1st triangle if this is the result of a transition. + fanCounts.add(length-1) ; + } else { + fanCounts.add(length) ; + fanVerts.add(vindex) ; + } + } + } + + /** + * Interprets the vertex flags associated with a class implementing + * GeneralizedStripFlags, constructing and returning a StripArray containing + * exclusively strips. + * + * @param vertices an object implementing GeneralizedStripFlags + * @param frontFace a flag, either GeneralizedStripFlags.FRONTFACE_CW or + * GeneralizedStripFlags.FRONTFACE_CCW, indicating front face winding + * @return a StripArray containing the converted strips + */ + static StripArray toTriangleStrips(GeneralizedStripFlags vertices, + int frontFace) { + + int size = vertices.getFlagCount() ; + + // initialize lists to worst-case sizes. + IntList stripVerts = new IntList(size*3) ; + IntList fanVerts = new IntList(size*3) ; + IntList stripCounts = new IntList(size) ; + IntList fanCounts = new IntList(size) ; + + toStripsAndFans(vertices, frontFace, + stripVerts, stripCounts, fanVerts, fanCounts) ; + + if (fanCounts.count == 0) + if (stripCounts.count > 0) + return new StripArray(stripVerts, stripCounts) ; + else + return null ; + + // convert each fan to one or more strips + int i, v = 0 ; + for (i = 0 ; i < fanCounts.count ; i++) { + fanToStrips(v, fanCounts.ints[i], fanVerts.ints, + stripVerts, stripCounts, false) ; + v += fanCounts.ints[i] ; + } + + // create the StripArray output + StripArray sa = new StripArray(stripVerts, stripCounts) ; + + if (debug) { + System.err.println("GeneralizedStrip.toTriangleStrips" + + "\n number of strips: " + + sa.stripCounts.count) ; + if (sa.stripCounts.count > 0) { + System.err.println(" number of vertices: " + + sa.vertices.count + + "\n vertices/strip: " + + ((float)sa.vertices.count / + (float)sa.stripCounts.count)) ; + System.err.print(" strip counts: [") ; + for (i = 0 ; i < sa.stripCounts.count-1 ; i++) + System.err.print(sa.stripCounts.ints[i] + ", ") ; + System.err.println(sa.stripCounts.ints[i] + "]") ; + } + System.err.println() ; + } + return sa ; + } + + private static void fanToStrips(int v, int length, int fans[], + IntList stripVerts, + IntList stripCounts, + boolean convexPlanar) { + if (convexPlanar) { + // Construct a strip by criss-crossing across the interior. + stripCounts.add(length) ; + stripVerts.add(fans[v]) ; + + int j = v + 1 ; + int k = v + (length - 1) ; + while (j <= k) { + stripVerts.add(fans[j++]) ; + if (j > k) break ; + stripVerts.add(fans[k--]) ; + } + } else { + // Traverse non-convex or non-planar fan, biting off 3-triangle + // strips or less. First 5 vertices produce 1 strip of 3 + // triangles, and every 4 vertices after that produce another + // strip of 3 triangles. Each remaining strip adds 2 vertices. + int fanStart = v ; + v++ ; + while (v+4 <= fanStart + length) { + stripVerts.add(fans[v]) ; + stripVerts.add(fans[v+1]) ; + stripVerts.add(fans[fanStart]) ; + stripVerts.add(fans[v+2]) ; + stripVerts.add(fans[v+3]) ; + stripCounts.add(5) ; + v += 3 ; + } + + // Finish off the fan. + if (v+1 < fanStart + length) { + stripVerts.add(fans[v]) ; + stripVerts.add(fans[v+1]) ; + stripVerts.add(fans[fanStart]) ; + v++ ; + + if (v+1 < fanStart + length) { + stripVerts.add(fans[v+1]) ; + stripCounts.add(4) ; + } + else + stripCounts.add(3) ; + } + } + } + + /** + * Interprets the vertex flags associated with a class implementing + * GeneralizedStripFlags, constructing and returning an array of vertex + * references representing the original generalized strip as individual + * triangles. Each sequence of three consecutive vertex references in the + * output defines a single triangle. + * + * @param vertices an object implementing GeneralizedStripFlags + * @param frontFace a flag, either GeneralizedStripFlags.FRONTFACE_CW or + * GeneralizedStripFlags.FRONTFACE_CCW, indicating front face winding + * @return an array of indices into the original vertex array + */ + static int[] toTriangles(GeneralizedStripFlags vertices, int frontFace) { + + int vertexCount = 0 ; + StripArray sa[] = toStripsAndFans(vertices, frontFace) ; + + if (sa[0] != null) + vertexCount = 3 * getTriangleCount(sa[0].stripCounts) ; + if (sa[1] != null) + vertexCount += 3 * getTriangleCount(sa[1].stripCounts) ; + + if (debug) + System.err.println("GeneralizedStrip.toTriangles\n" + + " number of triangles: " + vertexCount/3 + "\n" + + " number of vertices: " + vertexCount + "\n") ; + int t = 0 ; + int triangles[] = new int[vertexCount] ; + + if (sa[0] != null) + t = stripsToTriangles(t, triangles, + 0, sa[0].vertices.ints, + 0, sa[0].stripCounts.ints, + sa[0].stripCounts.count) ; + if (sa[1] != null) + t = fansToTriangles(t, triangles, + 0, sa[1].vertices.ints, + 0, sa[1].stripCounts.ints, + sa[1].stripCounts.count) ; + return triangles ; + } + + private static int stripsToTriangles(int tstart, int tbuff[], + int vstart, int vertices[], + int stripStart, int stripCounts[], + int stripCount) { + int t = tstart ; + int v = vstart ; + for (int i = 0 ; i < stripCount ; i++) { + for (int j = 0 ; j < stripCounts[i+stripStart] - 2 ; j++) { + if ((j & 0x01) == 0) { + // even-numbered triangles + tbuff[t*3 +0] = vertices[v+0] ; + tbuff[t*3 +1] = vertices[v+1] ; + tbuff[t*3 +2] = vertices[v+2] ; + } else { + // odd-numbered triangles + tbuff[t*3 +0] = vertices[v+1] ; + tbuff[t*3 +1] = vertices[v+0] ; + tbuff[t*3 +2] = vertices[v+2] ; + } + t++ ; v++ ; + } + v += 2 ; + } + return t ; + } + + private static int fansToTriangles(int tstart, int tbuff[], + int vstart, int vertices[], + int stripStart, int stripCounts[], + int stripCount) { + int t = tstart ; + int v = vstart ; + for (int i = 0 ; i < stripCount ; i++) { + for (int j = 0 ; j < stripCounts[i+stripStart] - 2 ; j++) { + tbuff[t*3 +0] = vertices[v] ; + tbuff[t*3 +1] = vertices[v+j+1] ; + tbuff[t*3 +2] = vertices[v+j+2] ; + t++ ; + } + v += stripCounts[i+stripStart] ; + } + return t ; + } + + /** + * Interprets the vertex flags associated with a class implementing + * GeneralizedStripFlags, constructing and returning a 2-element array of + * StripArray objects. The first StripArray will contain triangle strips + * and the second will contain individual triangles in the vertices + * field. Short strips will be converted to individual triangles. + * + * @param vertices an object implementing GeneralizedStripFlags + * @param frontFace a flag, either GeneralizedStripFlags.FRONTFACE_CW or + * GeneralizedStripFlags.FRONTFACE_CCW, indicating front face winding + * @param shortStripSize strips this size or less will be converted to + * individual triangles if there are more than maxShortStrips of them + * @param maxShortStrips maximum number of short strips allowed before + * creating individual triangles + * @return a 2-element array containing strips in 0 and triangles in 1 + */ + static StripArray[] toStripsAndTriangles(GeneralizedStripFlags vertices, + int frontFace, int shortStripSize, + int maxShortStrips) { + int longStripCount = 0 ; + int longStripVertexCount = 0 ; + int shortStripCount = 0 ; + int triangleCount = 0 ; + + StripArray sa[] = new StripArray[2] ; + StripArray ts = toTriangleStrips(vertices, frontFace) ; + + for (int i = 0 ; i < ts.stripCounts.count ; i++) + if (ts.stripCounts.ints[i] <= shortStripSize) { + shortStripCount++ ; + triangleCount += ts.stripCounts.ints[i] - 2 ; + } else { + longStripCount++ ; + longStripVertexCount += ts.stripCounts.ints[i] ; + } + + if (debug) + System.err.print("GeneralizedStrip.toStripsAndTriangles\n" + + " short strip size: " + shortStripSize + + " short strips tolerated: " + maxShortStrips + + " number of short strips: " + shortStripCount + + "\n\n") ; + + if (shortStripCount <= maxShortStrips) { + sa[0] = ts ; + sa[1] = null ; + } else { + int si = 0 ; int newStripVerts[] = new int[longStripVertexCount] ; + int ci = 0 ; int newStripCounts[] = new int[longStripCount] ; + int ti = 0 ; int triangles[] = new int[3*triangleCount] ; + int vi = 0 ; + + for (int i = 0 ; i < ts.stripCounts.count ; i++) { + if (ts.stripCounts.ints[i] <= shortStripSize) { + ti = stripsToTriangles(ti, triangles, + vi, ts.vertices.ints, + i, ts.stripCounts.ints, 1) ; + vi += ts.stripCounts.ints[i] ; + } else { + newStripCounts[ci++] = ts.stripCounts.ints[i] ; + for (int j = 0 ; j < ts.stripCounts.ints[i] ; j++) + newStripVerts[si++] = ts.vertices.ints[vi++] ; + } + } + + if (longStripCount > 0) + sa[0] = new StripArray(new IntList(newStripVerts), + new IntList(newStripCounts)) ; + else + sa[0] = null ; + + sa[1] = new StripArray(new IntList(triangles), null) ; + + if (debug) { + System.err.println(" triangles separated: " + triangleCount) ; + if (longStripCount > 0) { + System.err.println + (" new vertices/strip: " + + ((float)longStripVertexCount/(float)longStripCount)) ; + + System.err.print(" long strip counts: [") ; + for (int i = 0 ; i < longStripCount-1 ; i++) + System.err.print(newStripCounts[i++] + ", ") ; + + System.err.println + (newStripCounts[longStripCount-1] + "]\n") ; + } + } + } + return sa ; + } + + /** + * Interprets the vertex flags associated with a class implementing + * GeneralizedStripFlags, constructing and returning a StripArray. + * + * RESTART_CW and RESTART_CCW are treated as equivalent, as are + * REPLACE_MIDDLE and REPLACE_OLDEST. + * + * @param vertices an object implementing GeneralizedStripFlags + * @return a StripArray representing an array of line strips + */ + static StripArray toLineStrips(GeneralizedStripFlags vertices) { + int v, size, stripStart, stripLength, flag ; + + stripStart = 0 ; + stripLength = 2 ; + size = vertices.getFlagCount() ; + + // Initialize IntLists to worst-case sizes. + IntList stripVerts = new IntList(size*2) ; + IntList stripCounts = new IntList(size) ; + + // Vertex replace flags for the first two vertices are irrelevant. + v = 2 ; + while (v < size) { + flag = vertices.getFlag(v) ; + + if ((flag != RESTART_CW) && (flag != RESTART_CCW)) { + // proceed to the next vertex. + stripLength++ ; + v++ ; + + } else { + // Record the last strip. + stripCounts.add(stripLength) ; + for (int i = stripStart ; i < stripStart+stripLength ; i++) + stripVerts.add(i) ; + + // Start a new strip and skip to its 3rd vertex. + stripStart = v ; + stripLength = 2 ; + v += 2 ; + } + } + + // Finish off the last strip. + // If v > size then the strip is degenerate. + if (v == size) { + stripCounts.add(stripLength) ; + for (int i = stripStart ; i < stripStart+stripLength ; i++) + stripVerts.add(i) ; + } else + throw new IllegalArgumentException + (J3dI18N.getString("GeneralizedStrip0")) ; + + if (debug) { + System.err.println("GeneralizedStrip.toLineStrips\n") ; + if (v > size) + System.err.println(" ended with a degenerate line") ; + + System.err.println(" number of strips: " + stripCounts.count) ; + if (stripCounts.count > 0) { + System.err.println(" number of vertices: " + stripVerts.count) ; + System.err.println(" vertices/strip: " + + (float)stripVerts.count/stripCounts.count) ; + System.err.println(" strip counts: " + stripCounts.toString()) ; + // System.err.println(" indices: " + stripVerts.toString()) ; + } + System.err.println() ; + } + + if (stripCounts.count > 0) + return new StripArray(stripVerts, stripCounts) ; + else + return null ; + } + + /** + * Counts the number of lines defined by arrays of line strips. + * + * @param stripCounts array of strip counts, as used by the + * GeometryStripArray object + * @return number of lines in the strips + */ + static int getLineCount(int stripCounts[]) { + int count = 0 ; + for (int i = 0 ; i < stripCounts.length ; i++) + count += (stripCounts[i] - 1) ; + return count ; + } + + /** + * Counts the number of triangles defined by arrays of + * triangle strips or fans. + * + * @param stripCounts array of strip counts, as used by the + * GeometryStripArray object + * @return number of triangles in the strips or fans + */ + static int getTriangleCount(int stripCounts[]) { + int count = 0 ; + for (int i = 0 ; i < stripCounts.length ; i++) + count += (stripCounts[i] - 2) ; + return count ; + } + + /** + * Counts the number of triangles defined by arrays of + * triangle strips or fans. + * + * @param stripCounts IntList of strip counts + * @return number of triangles in the strips or fans + */ + static int getTriangleCount(IntList stripCounts) { + int count = 0 ; + for (int i = 0 ; i < stripCounts.count ; i++) + count += (stripCounts.ints[i] - 2) ; + return count ; + } + + /** + * Breaks up triangle strips into separate triangles. + * + * @param stripCounts array of strip counts, as used by the + * GeometryStripArray object + * @return array of ints which index into the original vertex array; each + * set of three consecutive vertex indices defines a single triangle + */ + static int[] stripsToTriangles(int stripCounts[]) { + int triangleCount = getTriangleCount(stripCounts) ; + int tbuff[] = new int[3*triangleCount] ; + IntList vertices = new IntList(triangleCount + 2*stripCounts.length) ; + + vertices.fillAscending() ; + stripsToTriangles(0, tbuff, + 0, vertices.ints, + 0, stripCounts, + stripCounts.length) ; + return tbuff ; + } + + /** + * Breaks up triangle fans into separate triangles. + * + * @param stripCounts array of strip counts, as used by the + * GeometryStripArray object + * @return array of ints which index into the original vertex array; each + * set of three consecutive vertex indices defines a single triangle + */ + static int[] fansToTriangles(int stripCounts[]) { + int triangleCount = getTriangleCount(stripCounts) ; + int tbuff[] = new int[3*triangleCount] ; + IntList vertices = new IntList(triangleCount + 2*stripCounts.length) ; + + vertices.fillAscending() ; + fansToTriangles(0, tbuff, + 0, vertices.ints, + 0, stripCounts, + stripCounts.length) ; + return tbuff ; + } + + /** + * Takes a fan and converts it to one or more strips. + * + * @param v index into the fans array of the first vertex in the fan + * @param length number of vertices in the fan + * @param fans array of vertex indices representing one or more fans + * @param convexPlanar if true indicates that the fan is convex and + * planar; such fans will always be converted into a single strip + * @return a StripArray containing the converted strips + */ + static StripArray fanToStrips(int v, int length, int fans[], + boolean convexPlanar) { + + // Initialize IntLists to worst-case sizes. + IntList stripVerts = new IntList(length*3) ; + IntList stripCounts = new IntList(length) ; + + fanToStrips(v, length, fans, stripVerts, stripCounts, convexPlanar) ; + return new StripArray(stripVerts, stripCounts) ; + } +} |