/** * 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.utility.geometry; import java.util.ArrayList; import java.util.Vector; import org.openmali.vecmath2.Colorf; import org.openmali.vecmath2.Point3f; import org.openmali.vecmath2.TexCoord2f; import org.openmali.vecmath2.Vector3f; /** * This class supports converting per-component index data to common-index data. Some file formats * allow to specify separate indices for coordinates, normals and tex coords. With this class, it is possible * to convert this data for use with GeometryInfo for further processing.<BR> * In case you would like to use it for non-indexed geometry, just assign indexes incrementally, with every * vertex component having it's own index.<BR> * Vertex component data can be specified at any moment - only requirement is that it needs to be specified * before fillGeometryInfo method is called.<BR> * Index data needs to be specified with per-face granularity. You can specify 3 coordinates and 3 normals, * or 1 coord, 1 normal, 1 coord, 1 normal, 1 coord, 1 normal, as long as 3 used components are specified * for a face before nextFace is called. setFaceSmoothingGroup can be called only once per face, and it * can to be called at any moment before nextFace call. Example (single triangle with same normal for each vertex) * <pre> * GeometryCreator gc = new GeometryCreator(); * gc.addNormal(0,1,0); * gc.addCoordinate(0,0,0); * gc.addCoordinate(1,0,1); * gc.addCoordinate(0,0,1); * gc.addCoordIndex(0); gc.addNormalIndex(0); * gc.addCoordIndex(1); gc.addNormalIndex(0); * gc.addCoordIndex(2); gc.addNormalIndex(0); * gc.nextFace(); * XithGeometryInfo xgi = new XithGeometryInfo(); * gc.fillGeometryInfo(xgi); * //gc is not longer important * </pre> * * Important - all methods in this class copy vecmath objects by reference, so please do NOT reuse them * for filling data. * * @author YVG */ public class GeometryCreator { private ArrayList< Point3f > coordinates = new ArrayList< Point3f >(); private ArrayList< Vector3f > normals = new ArrayList< Vector3f >(); private ArrayList< Colorf > colors = new ArrayList< Colorf >(); private ArrayList< TexCoord2f[] > texCoords = new ArrayList< TexCoord2f[] >(); private Vector< Integer > coordIndices = new Vector< Integer >(); private Vector< Integer > normalIndices = new Vector< Integer >(); private Vector< Integer > colorIndices = new Vector< Integer >(); private Vector< Integer > texIndices = new Vector< Integer >(); private Vector< Integer > faceSizes = new Vector< Integer >(); private Vector< Integer > smoothGroups = new Vector< Integer >(); private int lastFaceEnd = 0; private int texSets = 1; /** * Default constructor allows for no or one texture coordinate set. For more sets, please use * GeometryCreator(int textureCoordinateSets); * */ public GeometryCreator() { } public GeometryCreator( int textureCoordinateSets ) { texSets = textureCoordinateSets; } public void addCoordinate( float x, float y, float z ) { addCoordinate( new Point3f( x, y, z ) ); } public void addCoordinate( Point3f p ) { coordinates.add( p ); } public void addNormal( float x, float y, float z ) { normals.add( new Vector3f( x, y, z ) ); } public void addNormal( Vector3f v ) { normals.add( v ); } public void addColor( float r, float g, float b ) { addColor( new Colorf( r, g, b ) ); } public void addColor( float r, float g, float b, float a ) { addColor( new Colorf( r, g, b, a ) ); } public void addTexCoord( float s, float t ) { if ( texSets > 1 ) throw new IllegalArgumentException( "For more than 1 texture coord set, use addTexCoord(TexCoord2f[])" ); addTexCoord( new TexCoord2f( s, t ) ); } public void addTexCoord( TexCoord2f t ) { if ( texSets > 1 ) throw new IllegalArgumentException( "For more than 1 texture coord set, use addTexCoord(TexCoord2f[])" ); addTexCoords( new TexCoord2f[] { t } ); } public void addTexCoords( TexCoord2f[] t ) { if ( t.length != texSets ) { throw new IllegalArgumentException( "Number of texture coordinates (" + t.length + ") differs from number of textureSets defined(" + texSets + ")" ); } texCoords.add( t ); } public void addColor( Colorf c ) { colors.add( c ); } public void addCoordIndex( int i ) { coordIndices.add( i ); } public void addNormalIndex( int i ) { normalIndices.add( i ); } public void addColorIndex( int i ) { colorIndices.add( i ); } public void addTexIndex( int i ) { texIndices.add( i ); } public void setFaceSmoothingGroup( int group ) { smoothGroups.add( group ); } public void nextFace() { int count = coordIndices.size(); if ( lastFaceEnd == count ) return; if ( lastFaceEnd + 3 != count ) throw new IllegalStateException( "Currently only triangles are supported (face with 3 indices)" ); if ( normalIndices.size() != 0 && normalIndices.size() != count ) throw new IllegalStateException( "Different number of coordinate and normal indices" ); if ( colorIndices.size() != 0 && colorIndices.size() != count ) throw new IllegalStateException( "Different number of coordinate and color indices" ); if ( texIndices.size() != 0 && texIndices.size() != count ) throw new IllegalStateException( "Different number of coordinate and texture indices" ); faceSizes.add( count - lastFaceEnd ); if ( smoothGroups.size() != 0 && smoothGroups.size() != faceSizes.size() ) throw new IllegalStateException( "Different number of faces and smoothing group info" ); lastFaceEnd = count; } public void fillGeometryInfo( GeometryInfo gi ) { // only 3-face sizes int[] faceData = new int[ coordIndices.size() ]; VertexData[] vertices = new VertexData[ coordIndices.size() ]; for ( int i = 0; i < coordIndices.size(); i++ ) { VertexData vd = new VertexData(); vd.coord = new Point3f( coordinates.get( coordIndices.get( i ) ) ); if ( normalIndices.size() != 0 ) vd.normal = new Vector3f( normals.get( normalIndices.get( i ) ) ); if ( colorIndices.size() != 0 ) { vd.color = colors.get( colorIndices.get( i ) ); } if ( texIndices.size() != 0 ) { vd.texCoords = texCoords.get( texIndices.get( i ) ); } faceData[ i ] = i; vertices[ i ] = vd; } int[] smooth = new int[ faceSizes.size() ]; for ( int i = 0; i < smooth.length; i++ ) { if ( smoothGroups.size() > 0 ) smooth[ i ] = smoothGroups.get( i ); else smooth[ i ] = -1; } gi.vertices = vertices; gi.triangles = faceData; gi.smoothGroups = smooth; gi.state = GeometryInfo.STATE_SPLIT; } }