package org.andork.j3d;
/**
*
*/
import javax.media.j3d.Appearance;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.Group;
import javax.media.j3d.Material;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.vecmath.Color3f;
import javax.vecmath.Point3f;
import javax.vecmath.Vector3f;
import org.andork.j3d.math.TransformComputer3f;
/**
* @author brian.kamery
* @author andy.edwards
*/
public class Cylinder extends Primitive
{
protected com.sun.j3d.utils.geometry.Cylinder m_primative;
protected TransformComputer3f m_tc;
public Cylinder( float radius , float length , TransformComputer3f tc , Color3f color )
{
this( radius , new Point3f( 0 , -length * .5f , 0 ) , new Point3f( 0 , length * .5f , 0 ) , tc , color );
}
/**
* creates a cylinder with center endcap at p1 and center endcap at p2
*
* @param p1
* @param p2
*/
public Cylinder( float radius , Point3f p1 , Point3f p2 , TransformComputer3f tc , Color3f color )
{
length = p1.distance( p2 );
if( length == 0 )
{
throw new IllegalArgumentException( "Points must be different!" );
}
this.radius = radius;
m_tc = tc;
// the extra tacked on is ONLY for the bore model ...needs to go elsewhere
m_primative = new com.sun.j3d.utils.geometry.Cylinder( 1 , 1 );
Appearance appearance = new Appearance( );
Material mat = new Material( );
mat.setAmbientColor( color );
mat.setDiffuseColor( color );
mat.setSpecularColor( color );
// mat.setShininess(1.0f);
appearance.setMaterial( mat );
appearance.setCapability( Appearance.ALLOW_MATERIAL_WRITE );
m_primative.setAppearance( appearance );
m_primative.setCapability( com.sun.j3d.utils.geometry.Cylinder.ENABLE_APPEARANCE_MODIFY );
this.setCapability( BranchGroup.ALLOW_DETACH );
m_transformGroup.addChild( m_primative );
m_transformGroup.setCapability( Group.ALLOW_CHILDREN_EXTEND );
m_transformGroup.setCapability( Group.ALLOW_CHILDREN_READ );
m_transformGroup.setCapability( Group.ALLOW_CHILDREN_WRITE );
m_transformGroup.setCapability( TransformGroup.ALLOW_TRANSFORM_WRITE );
setEndpoints( p1 , p2 );
}
/**
* creates a cylinder with center endcap at p1 and center endcap at p2
*
* @param p1
* @param p2
*/
public Cylinder( float radius , Point3f p1 , Point3f p2 , Vector3f normal , TransformComputer3f tc , Color3f color )
{
length = p1.distance( p2 );
if( length == 0 )
{
throw new IllegalArgumentException( "Points must be different!" );
}
this.radius = radius;
m_tc = tc;
// the extra tacked on is ONLY for the bore model ...needs to go elsewhere
m_primative = new com.sun.j3d.utils.geometry.Cylinder( 1 , 1 );
Appearance appearance = new Appearance( );
Material mat = new Material( );
mat.setAmbientColor( color );
mat.setDiffuseColor( color );
mat.setSpecularColor( color );
// mat.setShininess(1.0f);
appearance.setMaterial( mat );
appearance.setCapability( Appearance.ALLOW_MATERIAL_WRITE );
m_primative.setAppearance( appearance );
m_primative.setCapability( com.sun.j3d.utils.geometry.Cylinder.ENABLE_APPEARANCE_MODIFY );
this.setCapability( BranchGroup.ALLOW_DETACH );
m_transformGroup.addChild( m_primative );
m_transformGroup.setCapability( Group.ALLOW_CHILDREN_EXTEND );
m_transformGroup.setCapability( Group.ALLOW_CHILDREN_READ );
m_transformGroup.setCapability( Group.ALLOW_CHILDREN_WRITE );
m_transformGroup.setCapability( TransformGroup.ALLOW_TRANSFORM_WRITE );
setEndpoints( p1 , p2 , normal );
}
/**
* Sets the radius of the existing cylinder this assumes that the calling entity has detached the BranchGroup somewhere in the heirarchy
*
* @param radius
*/
public void setRadius( float radius )
{
if( radius != this.radius )
{
this.radius = radius;
createTransform( m_transform );
apply( );
}
}
public float getRadius( )
{
return radius;
}
public float getLength( )
{
return length;
}
public void setEndpoints( Point3f p1 , Point3f p2 )
{
length = p1.distance( p2 );
createTransform( p1 , p2 , m_transform );
apply( );
}
public void setEndpoints( Point3f p1 , Point3f p2 , Vector3f normal )
{
length = p1.distance( p2 );
createTransform( p1 , p2 , normal , m_transform );
apply( );
}
/**
* Appearance modifiable
*
* @param color
*/
public void setColor( Color3f color )
{
Material mat = new Material( );
mat.setAmbientColor( color );
mat.setDiffuseColor( color );
mat.setSpecularColor( color );
m_primative.getAppearance( ).setMaterial( mat );
}
public void setAppearance( Appearance app )
{
m_primative.setAppearance( app );
}
public Appearance getAppearance( )
{
return m_primative.getAppearance( );
}
public void getEndpoints( Point3f p1 , Point3f p2 )
{
p1.set( 0 , -.5f , 0 );
p2.set( 0 , .5f , 0 );
m_transform.transform( p1 );
m_transform.transform( p2 );
}
protected void createTransform( Point3f p1 , Point3f p2 , Transform3D result )
{
m_tc.p1.set( 0 , 0 , 0 );
m_tc.v1.set( 1 , 0 , 0 );
m_tc.v2.set( 0 , .5f , 0 );
m_tc.v3.set( 0 , 0 , 1 );
m_tc.p2.interpolate( p1 , p2 , .5f );
m_tc.v5.sub( p2 , m_tc.p2 );
if( m_tc.v5.x == 0 && m_tc.v5.y == 0 && m_tc.v5.z == 0 )
{
throw new IllegalArgumentException( "p1 and p2 must not be the same or infinitesimally close together" );
}
if( m_tc.v5.x == 0 && m_tc.v5.y == 0 )
{
m_tc.v4.set( 0 , radius , 0 );
m_tc.v6.set( radius , 0 , 0 );
}
else
{
m_tc.v6.set( 0 , 0 , 1 );
m_tc.v4.cross( m_tc.v5 , m_tc.v6 );
m_tc.v4.scale( radius / m_tc.v4.length( ) );
m_tc.v6.cross( m_tc.v4 , m_tc.v5 );
m_tc.v6.scale( radius / m_tc.v6.length( ) );
}
m_tc.shear( result );
}
protected void createTransform( Point3f p1 , Point3f p2 , Vector3f normal , Transform3D result )
{
m_tc.p1.set( 0 , 0 , 0 );
m_tc.v1.set( 1 , 0 , 0 );
m_tc.v2.set( 0 , .5f , 0 );
m_tc.v3.set( 0 , 0 , 1 );
m_tc.p2.interpolate( p1 , p2 , .5f );
m_tc.v5.sub( p2 , m_tc.p2 );
if( m_tc.v5.x == 0 && m_tc.v5.y == 0 && m_tc.v5.z == 0 )
{
throw new IllegalArgumentException( "p1 and p2 must not be the same or infinitesimally close together" );
}
m_tc.v4.cross( m_tc.v5 , normal );
if( m_tc.v4.x == 0 && m_tc.v4.y == 0 && m_tc.v4.z == 0 )
{
throw new IllegalArgumentException( "normal must not be parallel to vector from p1 to p2" );
}
m_tc.v4.scale( radius / m_tc.v4.length( ) );
m_tc.v6.cross( m_tc.v4 , m_tc.v5 );
m_tc.v6.scale( radius / m_tc.v6.length( ) );
m_tc.shear( result );
}
protected void createTransform( Transform3D result )
{
m_tc.p1.set( 0 , 0 , 0 );
m_tc.v1.set( 1 , 0 , 0 );
m_tc.v2.set( 0 , .5f , 0 );
m_tc.v3.set( 0 , 0 , 1 );
m_transform.transform( m_tc.p1 , m_tc.p2 );
m_transform.transform( m_tc.v1 , m_tc.v4 );
m_transform.transform( m_tc.v2 , m_tc.v5 );
m_transform.transform( m_tc.v3 , m_tc.v6 );
m_tc.v4.scale( radius / m_tc.v4.length( ) );
m_tc.v6.scale( radius / m_tc.v6.length( ) );
m_tc.shear( result );
}
public void setAppearanceOverrideEnable( boolean flag )
{
for( int i = 0 ; i < 3 ; i++ )
{
m_primative.getShape( i ).setAppearanceOverrideEnable( flag );
}
}
private float radius;
private float length;
}