Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* 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 org.scijava.java3d;
/**
* 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) ;
}
}