/**
* Copyright (c) 2003-2009, Xith3D Project Group all rights reserved.
*
* Portions based on the Java3D interface, Copyright by Sun Microsystems.
* Many thanks to the developers of Java3D and Sun Microsystems for their
* innovation and design.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the 'Xith3D Project Group' nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) A
* RISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE
*/
package org.xith3d.scenegraph.primitives;
import org.openmali.FastMath;
import org.openmali.vecmath2.Colorf;
import org.openmali.vecmath2.Point3f;
import org.openmali.vecmath2.TexCoord2f;
import org.openmali.vecmath2.TexCoord3f;
import org.openmali.vecmath2.Tuple3f;
import org.openmali.vecmath2.Vector3f;
import org.xith3d.scenegraph.Appearance;
import org.xith3d.scenegraph.Geometry;
import org.xith3d.scenegraph.TextureImage3D;
import org.xith3d.scenegraph.IndexedTriangleArray;
import org.xith3d.scenegraph.IndexedTriangleStripArray;
import org.xith3d.scenegraph.TriangleArray;
import org.xith3d.scenegraph.TriangleStripArray;
import org.xith3d.scenegraph.Geometry.Optimization;
/**
* Geometry Util class
*
* @author William Denniss
* @author Amos Wenger (aka BlueSky)
* @author Marvin Froehlich (aka Qudus)
*/
public class GeomFactory
{
/**
* Swaps vertex 0 and 2 of each following 3.
*
* @param ga
*/
public static void reverseWinding( Geometry ga )
{
final float[] coords = ga.getCoordinatesData().getData();
for ( int i = 0; i < coords.length / 9; i++ )
{
final int j = i * 9;
float tempx = coords[ j + 6 ];
float tempy = coords[ j + 7 ];
float tempz = coords[ j + 8 ];
coords[ j + 6 ] = coords[ j + 0 ];
coords[ j + 7 ] = coords[ j + 1 ];
coords[ j + 8 ] = coords[ j + 2 ];
coords[ j + 0 ] = tempx;
coords[ j + 1 ] = tempy;
coords[ j + 2 ] = tempz;
}
ga.setCoordinate( 0, coords );
}
/**
* Retrieves the GeometryArray features from the Appearance, that are at
* least necessary to handle this Appearance.
*
* @param app
*
* @return the collected GoometryArray features
*/
public static int getFeaturesFromAppearance( Appearance app )
{
int features = 0;
if ( app == null )
{
return ( features );
}
if ( app.getTexture() != null )
{
if ( app.getTexture().getImage( 0 ) instanceof TextureImage3D )
features |= Geometry.TEXTURE_COORDINATES;
else //if (app.getTexture().getImage( 0 ) instanceof TextureImage2D)
features |= Geometry.TEXTURE_COORDINATES;
}
return ( features );
}
/**
* Retrieves the GeometryArray features from the Appearance, that are at
* least necessary to handle this Appearance.
*
* @param app
*
* @return the collected GoometryArray features
*/
public static int getTexCoordsSize( Appearance app )
{
if ( app.getTexture() != null )
{
if ( app.getTexture().getImage( 0 ) instanceof TextureImage3D )
return ( 3 );
//else if (app.getTexture().getImage( 0 ) instanceof TextureImage2D)
return ( 2 );
}
return ( 0 );
}
/**
* Auto-generates the normals.
*
* @param vertices
*
* @return the normals-array
*/
public static Vector3f[] generateNaiveNormals( Tuple3f[] vertices )
{
final Vector3f[] normals = new Vector3f[ vertices.length ];
for ( int i = 0; i < vertices.length; i++ )
{
normals[ i ] = new Vector3f( vertices[ i ] );
normals[ i ].normalize();
}
return ( normals );
}
/**
* Auto-generates the normals.
*
* @param vertices
*
* @return the normals-array
*/
private static void generateNaiveNormals( Tuple3f[] vertices, Geometry trg )
{
Vector3f normal = new Vector3f();
for ( int i = 0; i < vertices.length; i++ )
{
normal.set( vertices[ i ] );
normal.normalize();
trg.setNormal( i, normal );
}
}
/**
* Auto-generates the texture coordinates.
*
* @param vertices
*
* @return the tex-coords-array
*/
public static TexCoord2f[] generateTexCoords2( Tuple3f[] vertices )
{
// Find the range of z values
float zmin = Float.MAX_VALUE;
float zmax = Float.MIN_VALUE;
for ( int i = 0; i < vertices.length; i++ )
{
zmin = Math.min( zmin, vertices[ i ].getZ() );
zmax = Math.max( zmax, vertices[ i ].getZ() );
}
final float zscale = 1 / ( zmax - zmin );
// Generate the coordinates
TexCoord2f[] texCoords = new TexCoord2f[ vertices.length ];
for ( int i = 0; i < vertices.length; i++ )
{
texCoords[ i ] = new TexCoord2f();
texCoords[ i ].setS( ( FastMath.atan2( vertices[ i ].getY(), vertices[ i ].getX() ) + FastMath.PI ) / FastMath.TWO_PI );
texCoords[ i ].setT( zscale * ( vertices[ i ].getZ() - zmin ) );
}
return ( texCoords );
}
/**
* Auto-generates the texture coordinates.
*
* @param vertices
*
* @return the tex-coords-array
*/
public static TexCoord3f[] generateTexCoords3( Tuple3f[] vertices )
{
// Find the range of z values
float zmin = Float.MAX_VALUE;
float zmax = Float.MIN_VALUE;
for ( int i = 0; i < vertices.length; i++ )
{
zmin = Math.min( zmin, vertices[ i ].getZ() );
zmax = Math.max( zmax, vertices[ i ].getZ() );
}
final float zscale = 1.0f / ( zmax - zmin );
// Generate the coordinates
TexCoord3f[] texCoords = new TexCoord3f[ vertices.length ];
for ( int i = 0; i < vertices.length; i++ )
{
texCoords[ i ] = new TexCoord3f();
texCoords[ i ].setS( ( FastMath.atan2( vertices[ i ].getY(), vertices[ i ].getX() ) + FastMath.PI ) / FastMath.TWO_PI );
texCoords[ i ].setT( zscale * ( vertices[ i ].getZ() - zmin ) );
texCoords[ i ].setP( 0.0f ); // ?
}
return ( texCoords );
}
/**
* Auto-generates the colors.
*
* @param alpha
* @param coords
* @param scale
*
* @return the colors-array
*/
public static Colorf[] generateColors( boolean alpha, Tuple3f[] coords )
{
Colorf[] colors = new Colorf[ coords.length ];
// Find the range of z values
float xmin = +Float.MAX_VALUE;
float xmax = -Float.MAX_VALUE;
float ymin = +Float.MAX_VALUE;
float ymax = -Float.MAX_VALUE;
float zmin = +Float.MAX_VALUE;
float zmax = -Float.MAX_VALUE;
for ( int i = 0; i < coords.length; i++ )
{
if ( alpha )
colors[ i ] = new Colorf( coords[ i ].getX(), coords[ i ].getY(), coords[ i ].getZ(), 0f );
else
colors[ i ] = new Colorf( coords[ i ].getX(), coords[ i ].getY(), coords[ i ].getZ() );
xmin = Math.min( xmin, coords[ i ].getX() );
xmax = Math.max( xmax, coords[ i ].getX() );
ymin = Math.min( ymin, coords[ i ].getY() );
ymax = Math.max( ymax, coords[ i ].getY() );
zmin = Math.min( zmin, coords[ i ].getZ() );
zmax = Math.max( zmax, coords[ i ].getZ() );
}
final float scaleX = ( xmax == xmin ) ? 1.0f : 1f / ( xmax - xmin );
final float scaleY = ( ymax == ymin ) ? 1.0f : 1f / ( ymax - ymin );
final float scaleZ = ( zmax == zmin ) ? 1.0f : 1f / ( zmax - zmin );
for ( int i = 0; i < colors.length; i++ )
{
colors[ i ].setRed( ( colors[ i ].getRed() + xmin ) * scaleX );
colors[ i ].setGreen( ( colors[ i ].getGreen() + ymin ) * scaleY );
colors[ i ].setBlue( ( colors[ i ].getBlue() + zmin ) * scaleZ );
}
return ( colors );
}
/**
* Creates the full-featured TriangleArray.
*
* @param vertices
* @param normals
* @param colors
* @param texCoords2
* @param features
* @param colorAlpha
* @param texCoordsSize
*
* @return the TriangleArray
*/
public static TriangleArray createFullFeaturedTriangleArray( Tuple3f[] vertices, Vector3f[] normals, Colorf[] colors, TexCoord2f[] texCoords2, int features, boolean colorAlpha, int texCoordsSize )
{
final TriangleArray geom = new TriangleArray( vertices.length );
geom.setCoordinates( 0, vertices );
if ( normals != null )
{
geom.setNormals( 0, normals );
}
else if ( ( features & Geometry.NORMALS ) > 0 )
{
generateNaiveNormals( vertices, geom );
}
if ( colors != null )
{
geom.setColors( 0, colors );
}
else if ( ( ( features & Geometry.COLORS ) != 0 ) && !colorAlpha )
{
colors = new Colorf[ vertices.length ];
for ( int i = 0; i < vertices.length; i++ )
{
colors[ i ] = new Colorf( vertices[ i ].getX(), vertices[ i ].getY(), vertices[ i ].getZ() );
colors[ i ].mul( 2f ); // Why that?
}
geom.setColors( 0, colors );
}
else if ( ( ( features & Geometry.COLORS ) != 0 ) && colorAlpha )
{
colors = new Colorf[ vertices.length ];
for ( int i = 0; i < vertices.length; i++ )
{
colors[ i ] = new Colorf( vertices[ i ].getX(), vertices[ i ].getY(), vertices[ i ].getZ(), 0f );
colors[ i ].mul( 2f ); // Why that?
}
geom.setColors( 0, colors );
}
if ( texCoords2 != null )
{
geom.setTextureCoordinates( 0, 0, texCoords2 );
}
else if ( ( features & Geometry.TEXTURE_COORDINATES ) > 0 )
{
if ( texCoordsSize == 2 )
geom.setTextureCoordinates( 0, 0, generateTexCoords2( vertices ) );
}
return ( geom );
}
/**
* Creates the full-featured TriangleArray.
*
* @param geoms
*
* @return the TriangleArray
*/
protected static TriangleArray createFullFeaturedTriangleArray( GeometryConstruct[] geoms )
{
int numVertices = 0;
for ( int i = 0; i < geoms.length; i++ )
{
numVertices += geoms[ i ].getCoordinates().length;
}
Tuple3f[] vertices = new Tuple3f[ numVertices ];
{
int k = 0;
for ( int i = 0; i < geoms.length; i++ )
{
final Tuple3f[] vs = geoms[ i ].getCoordinates();
for ( int j = 0; j < vs.length; j++ )
{
vertices[ k++ ] = vs[ j ];
}
}
}
int numNormals = 0;
for ( int i = 0; i < geoms.length; i++ )
{
if ( geoms[ i ].getNormals() != null )
numNormals += geoms[ i ].getNormals().length;
}
Vector3f[] normals = null;
if ( numNormals > 0 )
{
normals = new Vector3f[ numVertices ];
int k = 0;
for ( int i = 0; i < geoms.length; i++ )
{
final Vector3f[] ns = geoms[ i ].getNormals();
if ( ns == null )
{
for ( int j = 0; j < geoms[ i ].getCoordinates().length; j++ )
{
normals[ k++ ] = new Vector3f( geoms[ i ].getCoordinates()[ j ] );
normals[ k++ ].normalize();
}
}
else
{
for ( int j = 0; j < geoms[ i ].getCoordinates().length; j++ )
{
normals[ k++ ] = ns[ j ];
}
}
}
}
int numTexCoords2 = 0;
for ( int i = 0; i < geoms.length; i++ )
{
if ( geoms[ i ].getTextureCoordinates2f() != null )
numTexCoords2 += geoms[ i ].getTextureCoordinates2f().length;
}
TexCoord2f[] texCoords2 = null;
if ( numTexCoords2 > 0 )
{
texCoords2 = new TexCoord2f[ numVertices ];
int k = 0;
for ( int i = 0; i < geoms.length; i++ )
{
TexCoord2f[] ts = geoms[ i ].getTextureCoordinates2f();
if ( ts == null )
{
ts = generateTexCoords2( vertices );
}
for ( int j = 0; j < geoms[ i ].getCoordinates().length; j++ )
{
texCoords2[ k++ ] = ts[ j ];
}
}
}
int numTexCoords3 = 0;
for ( int i = 0; i < geoms.length; i++ )
{
if ( geoms[ i ].getTextureCoordinates2f() != null )
numTexCoords3 += geoms[ i ].getTextureCoordinates2f().length;
}
TexCoord3f[] texCoords3 = null;
if ( numTexCoords3 > 0 )
{
texCoords3 = new TexCoord3f[ numVertices ];
int k = 0;
for ( int i = 0; i < geoms.length; i++ )
{
TexCoord3f[] ts = geoms[ i ].getTextureCoordinates3f();
if ( ts == null )
{
ts = generateTexCoords3( vertices );
}
for ( int j = 0; j < geoms[ i ].getCoordinates().length; j++ )
{
texCoords3[ k++ ] = ts[ j ];
}
}
}
int numColors = 0;
boolean alphaColors = false;
for ( int i = 0; i < geoms.length; i++ )
{
if ( geoms[ i ].getColors() != null )
{
numColors += geoms[ i ].getColors().length;
alphaColors = ( ( geoms[ i ].getColors()[ 0 ] != null ) && ( geoms[ i ].getColors()[ 0 ].hasAlpha() ) );
}
}
Colorf[] colors = null;
if ( numColors > 0 )
{
colors = new Colorf[ numVertices ];
int k = 0;
for ( int i = 0; i < geoms.length; i++ )
{
Colorf[] cs = geoms[ i ].getColors();
if ( cs == null )
{
cs = generateColors( alphaColors, vertices );
}
for ( int j = 0; j < geoms[ i ].getCoordinates().length; j++ )
{
colors[ k++ ] = cs[ j ];
}
}
}
return ( createTriangleArray( vertices, normals, colors, texCoords2, texCoords3 ) );
}
/**
* Calculates the GeometryArray features.
*
* @param coords
* @param normals
* @param texCoords2
* @param texCoords3
* @param colors
*
* @return the GeometryArray features
*/
protected static int calculateFeatures( Tuple3f[] coords, Vector3f[] normals, Colorf[] colors, TexCoord2f[] texCoords2, TexCoord3f[] texCoords3 )
{
int features = Geometry.COORDINATES;
if ( normals != null )
features |= Geometry.NORMALS;
if ( ( texCoords2 != null ) || ( texCoords3 != null ) )
features |= Geometry.TEXTURE_COORDINATES;
if ( colors != null )
features |= Geometry.COLORS;
return ( features );
}
/**
* Creates a TriangleArray.
*
* @param vertices
* @param normals
* @param texCoords2
* @param texCoords3
* @param colors
*
* @return the TriangleArray
*/
public static TriangleArray createTriangleArray( Tuple3f[] vertices, Vector3f[] normals, Colorf[] colors, TexCoord2f[] texCoords2, TexCoord3f[] texCoords3 )
{
final int features = calculateFeatures( vertices, normals, colors, texCoords2, texCoords3 );
final boolean colorAlpha = ( colors != null ) ? colors[ 0 ].hasAlpha() : false;
final int[] texCoordsSizes;
if ( texCoords2 != null )
texCoordsSizes = new int[] { 2 };
else if ( texCoords3 != null )
texCoordsSizes = new int[] { 3 };
else
texCoordsSizes = null;
final TriangleArray geom = new TriangleArray( vertices.length );
geom.makeInterleaved( features, colorAlpha, texCoordsSizes, null );
geom.setOptimization( Optimization.USE_DISPLAY_LISTS );
geom.setCoordinates( 0, vertices );
if ( normals != null )
{
geom.setNormals( 0, normals );
}
if ( texCoords2 != null )
{
geom.setTextureCoordinates( 0, 0, texCoords2 );
}
if ( texCoords3 != null )
{
geom.setTextureCoordinates( 0, 0, texCoords3 );
}
if ( colors != null )
{
geom.setColors( 0, colors );
}
return ( geom );
}
/**
* Creates a TriangleArray.
*
* @param geomConstruct
*
* @return the TriangleArray
*/
public static TriangleArray createTriangleArray( GeometryConstruct geomConstruct )
{
if ( geomConstruct.getGeometryTypeHint() != GeometryType.TRIANGLE_ARRAY )
throw new IllegalArgumentException( "The GeometryConstruct is not made " + geomConstruct.getGeometryTypeHint().getCorrespondingClass().getSimpleName() + ", but " + GeometryType.TRIANGLE_ARRAY.getCorrespondingClass().getSimpleName() + " is expected." );
return ( createTriangleArray( geomConstruct.getCoordinates(), geomConstruct.getNormals(), geomConstruct.getColors(), geomConstruct.getTextureCoordinates2f(), geomConstruct.getTextureCoordinates3f() ) );
}
/**
* Creates an IndexedTriangleArray.
*
* @param vertices
* @param indices
* @param normals
* @param colors
* @param texCoords2
* @param texCoords3
*
* @return the IndexedTriangleArray
*/
public static IndexedTriangleArray createIndexedTriangleArray( Tuple3f[] vertices, int[] indices, Vector3f[] normals, Colorf[] colors, TexCoord2f[] texCoords2, TexCoord3f[] texCoords3 )
{
final int features = calculateFeatures( vertices, normals, colors, texCoords2, texCoords3 );
final boolean colorAlpha = ( colors != null ) ? colors[ 0 ].hasAlpha() : false;
final int[] texCoordsSizes;
if ( texCoords2 != null )
texCoordsSizes = new int[] { 2 };
else if ( texCoords3 != null )
texCoordsSizes = new int[] { 3 };
else
texCoordsSizes = null;
final IndexedTriangleArray geom = new IndexedTriangleArray( vertices.length, indices.length );
geom.makeInterleaved( features, colorAlpha, texCoordsSizes, null );
geom.setOptimization( Optimization.USE_DISPLAY_LISTS );
geom.setCoordinates( 0, vertices );
geom.setIndex( indices );
if ( normals != null )
{
geom.setNormals( 0, normals );
}
if ( texCoords2 != null )
{
geom.setTextureCoordinates( 0, 0, texCoords2 );
}
if ( texCoords3 != null )
{
geom.setTextureCoordinates( 0, 0, texCoords3 );
}
if ( colors != null )
{
geom.setColors( 0, colors );
}
return ( geom );
}
/**
* Creates a IndexedTriangleArray.
*
* @param geomConstruct
*
* @return the IndexedTriangleArray
*/
public static IndexedTriangleArray createIndexedTriangleArray( GeometryConstruct geomConstruct )
{
if ( geomConstruct.getGeometryTypeHint() != GeometryType.INDEXED_TRIANGLE_ARRAY )
throw new IllegalArgumentException( "The GeometryConstruct is not made " + geomConstruct.getGeometryTypeHint().getCorrespondingClass().getSimpleName() + ", but " + GeometryType.INDEXED_TRIANGLE_ARRAY.getCorrespondingClass().getSimpleName() + " is expected." );
return ( createIndexedTriangleArray( geomConstruct.getCoordinates(), geomConstruct.getIndices(), geomConstruct.getNormals(), geomConstruct.getColors(), geomConstruct.getTextureCoordinates2f(), geomConstruct.getTextureCoordinates3f() ) );
}
/**
* Creates a TriangleStripArray.
*
* @param vertices
* @param normals
* @param colors
* @param texCoords2
* @param texCoords3
* @param stripLengths
*
* @return the TriangleStripArray
*/
public static TriangleStripArray createTriangleStripArray( Tuple3f[] vertices, Vector3f[] normals, Colorf[] colors, TexCoord2f[] texCoords2, TexCoord3f[] texCoords3, int[] stripLengths )
{
final int features = calculateFeatures( vertices, normals, colors, texCoords2, texCoords3 );
final boolean colorAlpha = ( colors != null ) ? colors[ 0 ].hasAlpha() : false;
final int[] texCoordsSizes;
if ( texCoords2 != null )
texCoordsSizes = new int[] { 2 };
else if ( texCoords3 != null )
texCoordsSizes = new int[] { 3 };
else
texCoordsSizes = null;
final TriangleStripArray geom = new TriangleStripArray( vertices.length, stripLengths );
geom.makeInterleaved( features, colorAlpha, texCoordsSizes, null );
geom.setOptimization( Optimization.USE_DISPLAY_LISTS );
geom.setCoordinates( 0, vertices );
if ( normals != null )
{
geom.setNormals( 0, normals );
}
if ( texCoords2 != null )
{
geom.setTextureCoordinates( 0, 0, texCoords2 );
}
if ( texCoords3 != null )
{
geom.setTextureCoordinates( 0, 0, texCoords3 );
}
if ( colors != null )
{
geom.setColors( 0, colors );
}
return ( geom );
}
/**
* Creates a TriangleStripArray.
*
* @param geomConstruct
*
* @return the TriangleStripArray
*/
public static TriangleStripArray createTriangleStripArray( GeometryConstruct geomConstruct )
{
if ( geomConstruct.getGeometryTypeHint() != GeometryType.TRIANGLE_STRIP_ARRAY )
throw new IllegalArgumentException( "The GeometryConstruct is not made " + geomConstruct.getGeometryTypeHint().getCorrespondingClass().getSimpleName() + ", but " + GeometryType.TRIANGLE_STRIP_ARRAY.getCorrespondingClass().getSimpleName() + " is expected." );
return ( createTriangleStripArray( geomConstruct.getCoordinates(), geomConstruct.getNormals(), geomConstruct.getColors(), geomConstruct.getTextureCoordinates2f(), geomConstruct.getTextureCoordinates3f(), geomConstruct.getStripLengths() ) );
}
/**
* Creates an IndexedTriangleStripArray.
*
* @param vertices
* @param indices
* @param normals
* @param colors
* @param texCoords2
* @param texCoords3
* @param stripLengths
*
* @return the IndexedTriangleStripArray
*/
public static IndexedTriangleStripArray createIndexedTriangleStripArray( Tuple3f[] vertices, int[] indices, Vector3f[] normals, Colorf[] colors, TexCoord2f[] texCoords2, TexCoord3f[] texCoords3, int[] stripLengths )
{
final int features = calculateFeatures( vertices, normals, colors, texCoords2, texCoords3 );
final boolean colorAlpha = ( colors != null ) ? colors[ 0 ].hasAlpha() : false;
final int[] texCoordsSizes;
if ( texCoords2 != null )
texCoordsSizes = new int[] { 2 };
else if ( texCoords3 != null )
texCoordsSizes = new int[] { 3 };
else
texCoordsSizes = null;
final IndexedTriangleStripArray geom = new IndexedTriangleStripArray( vertices.length, indices.length, stripLengths );
geom.makeInterleaved( features, colorAlpha, texCoordsSizes, null );
geom.setOptimization( Optimization.USE_DISPLAY_LISTS );
geom.setCoordinates( 0, vertices );
geom.setIndex( indices );
if ( normals != null )
{
geom.setNormals( 0, normals );
}
if ( texCoords2 != null )
{
geom.setTextureCoordinates( 0, 0, texCoords2 );
}
if ( texCoords3 != null )
{
geom.setTextureCoordinates( 0, 0, texCoords3 );
}
if ( colors != null )
{
geom.setColors( 0, colors );
}
return ( geom );
}
/**
* Creates a IndexedTriangleStripArray.
*
* @param geomConstruct
*
* @return the IndexedTriangleStripArray
*/
public static IndexedTriangleStripArray createIndexedTriangleStripArray( GeometryConstruct geomConstruct )
{
if ( geomConstruct.getGeometryTypeHint() != GeometryType.INDEXED_TRIANGLE_STRIP_ARRAY )
throw new IllegalArgumentException( "The GeometryConstruct is made for " + geomConstruct.getGeometryTypeHint().getCorrespondingClass().getSimpleName() + ", but " + GeometryType.INDEXED_TRIANGLE_STRIP_ARRAY.getCorrespondingClass().getSimpleName() + " is expected." );
return ( createIndexedTriangleStripArray( geomConstruct.getCoordinates(), geomConstruct.getIndices(), geomConstruct.getNormals(), geomConstruct.getColors(), geomConstruct.getTextureCoordinates2f(), geomConstruct.getTextureCoordinates3f(), geomConstruct.getStripLengths() ) );
}
public static Geometry createGeometryArray( GeometryConstruct gc )
{
if ( gc.getGeometryTypeHint() == GeometryType.INDEXED_TRIANGLE_STRIP_ARRAY )
{
return ( createIndexedTriangleStripArray( gc ) );
}
else if ( gc.getGeometryTypeHint() == GeometryType.INDEXED_TRIANGLE_ARRAY )
{
return ( createIndexedTriangleArray( gc ) );
}
else if ( gc.getGeometryTypeHint() == GeometryType.TRIANGLE_STRIP_ARRAY )
{
return ( createTriangleStripArray( gc ) );
}
else if ( gc.getGeometryTypeHint() == GeometryType.TRIANGLE_ARRAY )
{
return ( createTriangleArray( gc ) );
}
else
{
throw new UnsupportedOperationException( "The type " + gc.getGeometryTypeHint() + " cannot currently be created. (Must be implemented)" );
}
}
/**
* Converts a GeometryConstruct made for IndexedTriangleStripArray to one made for IndexedTriangleArrays.<br>
* <b>The data instances will be the same for both GeometryConstructs!</b>
*
* @param gcITSA the source GeometryConstruct made for IndexedTriangleStripArrays
*
* @return the new GeometryConstruct made for IndexedTriangleArrays
*/
public static GeometryConstruct convertGeometryConstructITSA2ITA( GeometryConstruct gcITSA )
{
final int numStrips = gcITSA.getStripLengths().length;
int[] indices = new int[ ( gcITSA.numIndices() - 2 * numStrips ) * 3 ];
int o = 0;
int k = 0;
for ( int s = 0; s < numStrips; s++ )
{
for ( int i = o; i < o + gcITSA.getStripLengths()[ s ] - 2; i++ )
{
for ( int j = 0; j < 3; j++ )
{
indices[ k++ ] = gcITSA.getIndices()[ i + j ];
}
}
o += gcITSA.getStripLengths()[ s ];
}
GeometryConstruct gcITA = new GeometryConstruct( GeometryType.INDEXED_TRIANGLE_ARRAY, gcITSA.getCoordinates(), gcITSA.getNormals(), gcITSA.getTextureCoordinates2f(), indices, null );
return ( gcITA );
}
/**
* Converts a GeometryConstruct made for IndexedTriangleStripArray to one made for TriangleStripArrays.<br>
* <b>The data instances will be the same for both GeometryConstructs!</b>
*
* @param gcITSA the source GeometryConstruct made for IndexedTriangleStripArrays
*
* @return the new GeometryConstruct made for TriangleStripArrays
*/
public static GeometryConstruct convertGeometryConstructITSA2TSA( GeometryConstruct gcITSA )
{
final int numStrips = gcITSA.getStripLengths().length;
int[] stripLengths = new int[ numStrips ];
for ( int i = 0; i < numStrips; i++ )
{
stripLengths[ i ] = gcITSA.getIndices().length / numStrips;
}
Point3f[] vertices = new Point3f[ gcITSA.numIndices() ];
Vector3f[] normals = null;
TexCoord2f[] texCoords = null;
if ( gcITSA.numNormals() > 0 )
normals = new Vector3f[ vertices.length ];
if ( gcITSA.numTextureCoordinates2f() > 0 )
texCoords = new TexCoord2f[ vertices.length ];
for ( int i = 0; i < gcITSA.getIndices().length; i++ )
{
final int idx = gcITSA.getIndices()[ i ];
vertices[ i ] = new Point3f( gcITSA.getCoordinates()[ idx ] );
if ( gcITSA.numNormals() > 0 )
normals[ i ] = new Vector3f( gcITSA.getNormals()[ idx ] );
if ( gcITSA.numTextureCoordinates2f() > 0 )
texCoords[ i ] = new TexCoord2f( gcITSA.getTextureCoordinates2f()[ idx ] );
}
GeometryConstruct gcTSA = new GeometryConstruct( GeometryType.TRIANGLE_STRIP_ARRAY, vertices, normals, texCoords, null, stripLengths );
return ( gcTSA );
}
/**
* Converts a GeometryConstruct made for IndexedTriangleStripArray to one made for TriangleArrays.<br>
* <b>The data instances will be the same for both GeometryConstructs!</b>
*
* @param gcITSA the source GeometryConstruct made for IndexedTriangleStripArrays
*
* @return the new GeometryConstruct made for TriangleArrays
*/
public static GeometryConstruct convertGeometryConstructITSA2TA( GeometryConstruct gcITSA )
{
final int numStrips = gcITSA.getStripLengths().length;
Point3f[] coords = new Point3f[ ( gcITSA.numIndices() - 2 * numStrips ) * 3 ];
Vector3f[] normals = null;
TexCoord2f[] texCoords2 = null;
TexCoord3f[] texCoords3 = null;
Colorf[] colors = null;
if ( gcITSA.numNormals() > 0 )
normals = new Vector3f[ coords.length ];
if ( gcITSA.numTextureCoordinates2f() > 0 )
texCoords2 = new TexCoord2f[ coords.length ];
if ( gcITSA.numTextureCoordinates3f() > 0 )
texCoords3 = new TexCoord3f[ coords.length ];
if ( gcITSA.numColors() > 0 )
colors = new Colorf[ coords.length ];
int o = 0;
int k = 0;
for ( int s = 0; s < gcITSA.getStripLengths().length; s++ )
{
for ( int i = o; i < o + gcITSA.getStripLengths()[ s ] - 2; i++ )
{
for ( int j = 0; j < 3; j++ )
{
final int idx = gcITSA.getIndices()[ i + j ];
coords[ k ] = new Point3f( gcITSA.getCoordinates()[ idx ] );
if ( gcITSA.numNormals() > 0 )
normals[ k ] = new Vector3f( gcITSA.getNormals()[ idx ] );
if ( gcITSA.numTextureCoordinates2f() > 0 )
texCoords2[ k ] = new TexCoord2f( gcITSA.getTextureCoordinates2f()[ idx ] );
if ( gcITSA.numTextureCoordinates3f() > 0 )
texCoords3[ k ] = new TexCoord3f( gcITSA.getTextureCoordinates3f()[ idx ] );
if ( gcITSA.numColors() > 0 )
colors[ k ] = gcITSA.getColors()[ idx ];
k++;
}
}
o += gcITSA.getStripLengths()[ s ];
}
GeometryConstruct gcTA;
if ( ( texCoords3 != null ) && ( colors != null ) )
gcTA = new GeometryConstruct( GeometryType.TRIANGLE_ARRAY, coords, normals, texCoords3, colors );
else
gcTA = new GeometryConstruct( GeometryType.TRIANGLE_ARRAY, coords, normals, texCoords2, colors );
return ( gcTA );
}
/**
* Creates an IndexedTriangleArray for a Shape3D.
*
* @param gcITSA the GeometryConstruct to build it from
*/
public static IndexedTriangleArray createITAfromITSA( GeometryConstruct gcITSA )
{
if ( gcITSA.getGeometryTypeHint() != GeometryType.INDEXED_TRIANGLE_STRIP_ARRAY )
throw new IllegalArgumentException( "The given GeometryConstruct must be of type " + GeometryType.INDEXED_TRIANGLE_STRIP_ARRAY + ", but is of type " + gcITSA.getGeometryTypeHint() );
final int numStrips = gcITSA.getStripLengths().length;
final int features = gcITSA.calculateFeatures();
final boolean colorAlpha = ( gcITSA.getColors() != null ) ? gcITSA.getColors()[ 0 ].hasAlpha() : false;
final int[] texCoordsSizes;
if ( gcITSA.getTextureCoordinates2f() != null )
texCoordsSizes = new int[] { 2 };
else if ( gcITSA.getTextureCoordinates3f() != null )
texCoordsSizes = new int[] { 3 };
else
texCoordsSizes = null;
IndexedTriangleArray geom = new IndexedTriangleArray( gcITSA.numVertices(), ( gcITSA.numIndices() - 2 * numStrips ) * 3 );
geom.makeInterleaved( features, colorAlpha, texCoordsSizes, null );
geom.setOptimization( Optimization.USE_DISPLAY_LISTS );
geom.setCoordinates( 0, gcITSA.getCoordinates() );
if ( gcITSA.numNormals() > 0 )
geom.setNormals( 0, gcITSA.getNormals() );
if ( gcITSA.numTextureCoordinates2f() > 0 )
geom.setTextureCoordinates( 0, 0, gcITSA.getTextureCoordinates2f() );
if ( gcITSA.numTextureCoordinates3f() > 0 )
geom.setTextureCoordinates( 0, 0, gcITSA.getTextureCoordinates3f() );
if ( gcITSA.numColors() > 0 )
geom.setColors( 0, gcITSA.getColors() );
int o = 0;
int k = 0;
for ( int s = 0; s < numStrips; s++ )
{
for ( int i = o; i < o + gcITSA.getStripLengths()[ s ] - 2; i++ )
{
for ( int j = 0; j < 3; j++ )
{
geom.setIndex( k++, gcITSA.getIndices()[ i + j ] );
}
}
o += gcITSA.getStripLengths()[ s ];
}
return ( geom );
}
/**
* Creates a TriangleStripArray for a Shape3D.
*
* @param gcITSA the GeometryConstruct to build it from
*/
public static TriangleStripArray createTSAfromITSA( GeometryConstruct gcITSA )
{
if ( gcITSA.getGeometryTypeHint() != GeometryType.INDEXED_TRIANGLE_STRIP_ARRAY )
throw new IllegalArgumentException( "The given GeometryConstruct must be of type " + GeometryType.INDEXED_TRIANGLE_STRIP_ARRAY + ", but is of type " + gcITSA.getGeometryTypeHint() );
final int numStrips = gcITSA.getStripLengths().length;
int[] stripLengths = new int[ numStrips ];
for ( int i = 0; i < numStrips; i++ )
{
stripLengths[ i ] = gcITSA.getIndices().length / numStrips;
}
final int features = gcITSA.calculateFeatures();
final boolean colorAlpha = ( gcITSA.getColors() != null ) ? gcITSA.getColors()[ 0 ].hasAlpha() : false;
final int[] texCoordsSizes;
if ( gcITSA.getTextureCoordinates2f() != null )
texCoordsSizes = new int[] { 2 };
else if ( gcITSA.getTextureCoordinates3f() != null )
texCoordsSizes = new int[] { 3 };
else
texCoordsSizes = null;
TriangleStripArray geom = new TriangleStripArray( gcITSA.numIndices(), stripLengths );
geom.makeInterleaved( features, colorAlpha, texCoordsSizes, null );
geom.setOptimization( Optimization.USE_DISPLAY_LISTS );
for ( int i = 0; i < gcITSA.getIndices().length; i++ )
{
final int idx = gcITSA.getIndices()[ i ];
geom.setCoordinate( i, gcITSA.getCoordinates()[ idx ] );
if ( gcITSA.numNormals() > 0 )
geom.setNormal( i, gcITSA.getNormals()[ idx ] );
if ( gcITSA.numTextureCoordinates2f() > 0 )
geom.setTextureCoordinate( 0, i, gcITSA.getTextureCoordinates2f()[ idx ] );
}
return ( geom );
}
/**
* Creates a TriangleArray for a Shape3D.
*
* @param gcITSA the GeometryConstruct to build it from
*/
public static TriangleArray createTAfromITSA( GeometryConstruct gcITSA )
{
if ( gcITSA.getGeometryTypeHint() != GeometryType.INDEXED_TRIANGLE_STRIP_ARRAY )
throw new IllegalArgumentException( "The given GeometryConstruct must be of type " + GeometryType.INDEXED_TRIANGLE_STRIP_ARRAY + ", but is of type " + gcITSA.getGeometryTypeHint() );
final int numStrips = gcITSA.getStripLengths().length;
final int features = gcITSA.calculateFeatures();
final boolean colorAlpha = ( gcITSA.getColors() != null ) ? gcITSA.getColors()[ 0 ].hasAlpha() : false;
final int[] texCoordsSizes;
if ( gcITSA.getTextureCoordinates2f() != null )
texCoordsSizes = new int[] { 2 };
else if ( gcITSA.getTextureCoordinates3f() != null )
texCoordsSizes = new int[] { 3 };
else
texCoordsSizes = null;
TriangleArray geom = new TriangleArray( ( gcITSA.numIndices() - 2 * numStrips ) * 3 );
geom.makeInterleaved( features, colorAlpha, texCoordsSizes, null );
geom.setOptimization( Optimization.USE_DISPLAY_LISTS );
int o = 0;
int k = 0;
for ( int s = 0; s < gcITSA.getStripLengths().length; s++ )
{
for ( int i = o; i < o + gcITSA.getStripLengths()[ s ] - 2; i++ )
{
for ( int j = 0; j < 3; j++ )
{
final int idx = gcITSA.getIndices()[ i + j ];
geom.setCoordinate( k, gcITSA.getCoordinates()[ idx ] );
if ( gcITSA.numNormals() > 0 )
geom.setNormal( k, gcITSA.getNormals()[ idx ] );
if ( gcITSA.numTextureCoordinates2f() > 0 )
geom.setTextureCoordinate( 0, k, gcITSA.getTextureCoordinates2f()[ idx ] );
if ( gcITSA.numTextureCoordinates3f() > 0 )
geom.setTextureCoordinate( 0, k, gcITSA.getTextureCoordinates3f()[ idx ] );
if ( gcITSA.numColors() > 0 )
geom.setColor( k, gcITSA.getColors()[ idx ] );
k++;
}
}
o += gcITSA.getStripLengths()[ s ];
}
return ( geom );
}
}