/** * 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.xith3d.loaders.texture.TextureLoader; import org.xith3d.scenegraph.Appearance; import org.xith3d.scenegraph.Geometry; import org.xith3d.scenegraph.Shape3D; import org.xith3d.scenegraph.Texture; import org.xith3d.scenegraph.TriangleArray; import org.xith3d.scenegraph.Geometry.Optimization; /** * An ellipsoid using the stacks/slices specification. * * @author Daniel Herring */ public class Ellipsoid extends Shape3D { /** * Create an ellipsoid using the stacks/slices specification * * Creates 2*slices*(stacks-1) triangles * * @param rx Radius along x axis * @param ry Radius along y axis * @param rz Radius along z axis * @param slices Number of vertical stripes down the ellipsoid * @param stacks Number of stacked rings around the ellipsoid * @param features the GeometryArray features * @param colorAlpha * @param texCoordsSize */ public Ellipsoid( float rx, float ry, float rz, int slices, int stacks, int features, boolean colorAlpha, int texCoordsSize ) { if ( ( stacks < 2 ) || ( slices < 3 ) ) { throw new IllegalArgumentException( "insufficient stacks or slices" ); } features |= Geometry.COORDINATES; Point3f[] coords = new Point3f[ 3 * slices * 2 * ( stacks - 1 ) ]; Point3f[][] buffer = new Point3f[ 2 ][ stacks + 1 ]; // Store the vertices in buffers // Init the left buffer for ( int j = 0; j <= stacks; j++ ) { buffer[ 0 ][ j ] = new Point3f(); buffer[ 0 ][ j ].setX( FastMath.sin( j * FastMath.PI / stacks ) ); buffer[ 0 ][ j ].setY( 0f ); buffer[ 0 ][ j ].setZ( FastMath.cos( j * FastMath.PI / stacks ) ); } int left, right; // select the appropriate buffer int index = 0; for ( int i = 0; i < slices; i++ ) { // auto-swap buffers left = i % 2; right = ( i + 1 ) % 2; // Start the right column buffer[ right ][ 0 ] = new Point3f( 0f, 0f, 1f ); for ( int j = 0; j < stacks; j++ ) { // next right point buffer[ right ][ j + 1 ] = new Point3f(); buffer[ right ][ j + 1 ].setX( FastMath.cos( 2f * ( i + 1 ) * FastMath.PI / slices ) * FastMath.sin( ( j + 1 ) * FastMath.PI / stacks ) ); buffer[ right ][ j + 1 ].setY( FastMath.sin( 2f * ( i + 1 ) * FastMath.PI / slices ) * FastMath.sin( ( j + 1 ) * FastMath.PI / stacks ) ); buffer[ right ][ j + 1 ].setZ( buffer[ left ][ j + 1 ].getZ() ); if ( j > 0 ) { coords[ index++ ] = buffer[ left ][ j ]; coords[ index++ ] = buffer[ left ][ j + 1 ]; coords[ index++ ] = buffer[ right ][ j ]; } if ( j < ( stacks - 1 ) ) { coords[ index++ ] = buffer[ right ][ j ]; coords[ index++ ] = buffer[ left ][ j + 1 ]; coords[ index++ ] = buffer[ right ][ j + 1 ]; } } } Point3f[] vertices = new Point3f[ coords.length ]; for ( int i = 0; i < coords.length; i++ ) { vertices[ i ] = new Point3f( coords[ i ] ); vertices[ i ].mul( rx, ry, rz ); } Colorf[] colors = null; if ( ( features & Geometry.COLORS ) != 0 ) { colors = new Colorf[ vertices.length ]; for ( int i = 0; i < colors.length; i++ ) { if ( colorAlpha ) 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() ); } } TriangleArray geom = new TriangleArray( vertices.length ); geom.makeInterleaved( features, colorAlpha, new int[] { texCoordsSize }, null ); geom.setOptimization( Optimization.USE_DISPLAY_LISTS ); geom.setCoordinates( 0, vertices ); if ( colors != null ) geom.setColors( 0, colors ); super.setGeometry( geom ); } /** * Create an ellipsoid using the stacks/slices specification * * Creates 2*slices*(stacks-1) triangles * * @param rx Radius along x axis * @param ry Radius along y axis * @param rz Radius along z axis * @param slices Number of vertical stripes down the ellipsoid * @param stacks Number of stacked rings around the ellipsoid * @param texture the Texture to be applied to this Shape's Appearance */ public Ellipsoid( float rx, float ry, float rz, int slices, int stacks, Texture texture ) { this( rx, ry, rz, slices, stacks, Geometry.COORDINATES | Geometry.NORMALS | Geometry.TEXTURE_COORDINATES, false, 2 ); getAppearance( true ).setTexture( texture ); } /** * Create an ellipsoid using the stacks/slices specification * * Creates 2*slices*(stacks-1) triangles * * @param rx Radius along x axis * @param ry Radius along y axis * @param rz Radius along z axis * @param slices Number of vertical stripes down the ellipsoid * @param stacks Number of stacked rings around the ellipsoid * @param texture the Texture to be applied to this Shape's Appearance */ public Ellipsoid( float rx, float ry, float rz, int slices, int stacks, String texture ) { this( rx, ry, rz, slices, stacks, TextureLoader.getInstance().getTexture( texture ) ); } /** * Create an ellipsoid using the stacks/slices specification * * Creates 2*slices*(stacks-1) triangles * * @param rx Radius along x axis * @param ry Radius along y axis * @param rz Radius along z axis * @param slices Number of vertical stripes down the ellipsoid * @param stacks Number of stacked rings around the ellipsoid * @param color the color to be applied to this Shape's Appearance's ColoringAttributes */ public Ellipsoid( float rx, float ry, float rz, int slices, int stacks, Colorf color ) { this( rx, ry, rz, slices, stacks, Geometry.COORDINATES | Geometry.NORMALS, false, 2 ); getAppearance( true ).getColoringAttributes( true ).setColor( color ); if ( color.hasAlpha() ) this.getAppearance( true ).getTransparencyAttributes( true ).setTransparency( color.getAlpha() ); } /** * Create an ellipsoid using the stacks/slices specification * * Creates 2*slices*(stacks-1) triangles * * @param rx Radius along x axis * @param ry Radius along y axis * @param rz Radius along z axis * @param slices Number of vertical stripes down the ellipsoid * @param stacks Number of stacked rings around the ellipsoid * @param app the Appearance to be applide to this Shape */ public Ellipsoid( float rx, float ry, float rz, int slices, int stacks, Appearance app ) { this( rx, ry, rz, slices, stacks, Geometry.COORDINATES | Geometry.NORMALS | GeomFactory.getFeaturesFromAppearance( app ), false, GeomFactory.getTexCoordsSize( app ) ); setAppearance( app ); } }