/**
* 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;
import org.openmali.vecmath2.AxisAngle3f;
import org.openmali.vecmath2.Matrix3f;
import org.openmali.vecmath2.Matrix4f;
import org.openmali.vecmath2.Point3f;
import org.openmali.vecmath2.Tuple3f;
import org.openmali.vecmath2.Vector3f;
/**
* The Transform class can be used to quickly transform any object, reducing the
* number of lines needed (Transform3D construction, etc..) and improving
* readability of your code.<br>
* <br>
* However, you can live without ^^
*
* @author Amos Wenger (aka BlueSky)
*/
public class Transform extends TransformGroup
{
/** The identity transform (no transformation at all) */
public static final Transform IDENTITY_TRANSFORM = new Transform();
public static final int ROTATION = 0;
public static final int TRANSLATION = 1;
public static final int SCALE = 2;
// GC-friendly hacks
private final Transform3D tempTransform = new Transform3D();
private final AxisAngle3f tempAxisAngle = new AxisAngle3f();
private final Vector3f tempVector = new Vector3f();
/**
* Sets a transformation.
*
* @param mode
* Transform.ROTATION, Transform.TRANSLATION, or Transform.SCALE
* @param x
* X value
* @param y
* Y value
* @param z
* Z value
* @return This transform, for cascade method calls
*/
public Transform setTransform( int mode, float x, float y, float z )
{
Transform3D t3d = getTransform();
switch ( mode )
{
case ROTATION:
t3d.rotXYZ( x, y, z );
break;
case TRANSLATION:
t3d.setTranslation( x, y, z );
break;
case SCALE:
t3d.setScale( x, y, z );
break;
}
setTransform( t3d );
return ( this );
}
/**
* Sets a transformation.
*
* @param mode
* Transform.ROTATION, Transform.TRANSLATION, or Transform.SCALE
* @param transform
* If rotation, euler angles (in radians), if translation or
* scale relevant value
* @return This transform, for cascade method calls
*/
public Transform setTransform( int mode, Tuple3f transform )
{
Transform3D t3d = getTransform();
switch ( mode )
{
case ROTATION:
t3d.rotXYZ( transform.getX(), transform.getY(), transform.getZ() );
break;
case TRANSLATION:
t3d.setTranslation( transform.getX(), transform.getY(), transform.getZ() );
break;
case SCALE:
t3d.setScale( transform.getX(), transform.getY(), transform.getZ() );
break;
}
setTransform( t3d );
return ( this );
}
/**
* Sets a translation.
*
* @param value
* Translation
* @return This transform, for cascade method calls
*/
public Transform setTranslationX( float value )
{
setTranslation( value, 0f, 0f );
return ( this );
}
/**
* Sets a translation.
*
* @param value
* Translation
* @return This transform, for cascade method calls
*/
public Transform setTranslationY( float value )
{
setTranslation( 0f, value, 0f );
return ( this );
}
/**
* Sets a translation.
*
* @param value
*
* @return This transform, for cascade method calls
*/
public Transform setTranslationZ( float value )
{
Transform3D t3d = getTransform();
t3d.setTranslation( 0f, 0f, value );
setTransform( t3d );
return ( this );
}
/**
* Adds a translation to the current transformation.
*
* @param x
* X value
* @param y
* Y value
* @param z
* Z value
* @return This transform, for cascade method calls
*/
public Transform addTranslation( float x, float y, float z )
{
tempTransform.setIdentity();
tempTransform.setTranslation( x, y, z );
getTransform().mul( tempTransform );
setTransform( getTransform() );
return ( this );
}
/**
* Applies a translation.
*
* @param x
* X value
* @param y
* Y value
* @param z
* Z value
* @return This transform, for cascade method calls
*/
public Transform setTranslation( float x, float y, float z )
{
Transform3D t3d = getTransform();
t3d.setTranslation( x, y, z );
setTransform( t3d );
return ( this );
}
/**
* Adds a translation to the current transformation.
*
* @param translate
* Translation
* @return This transform, for cascade method calls
*/
public Transform addTranslation( Tuple3f translate )
{
tempTransform.setIdentity();
tempTransform.setTranslation( translate.getX(), translate.getY(), translate.getZ() );
getTransform().mul( tempTransform );
setTransform( getTransform() );
return ( this );
}
/**
* Applies a translation.
*
* @param translate
* Translation
* @return This transform, for cascade method calls
*/
public Transform setTranslation( Tuple3f translate )
{
Transform3D t3d = getTransform();
t3d.setTranslation( translate.getX(), translate.getY(), translate.getZ() );
setTransform( t3d );
return ( this );
}
/**
* Applies a rotation.
*
* @param rotate
* Euler angles, in radians
* @return This transform, for cascade method calls
*/
public Transform setRotation( Tuple3f rotate )
{
Transform3D t3d = getTransform();
t3d.rotXYZ( rotate.getX(), rotate.getY(), rotate.getZ() );
setTransform( t3d );
return ( this );
}
/**
* Applies a rotation.
*
* @param x
* X angle, in radians
* @param y
* Y angle, in radians
* @param z
* Z angle, in radians
* @return This transform, for cascade method calls
*/
public Transform setRotation( float x, float y, float z )
{
Transform3D t3d = getTransform();
t3d.rotXYZ( x, y, z );
setTransform( t3d );
return ( this );
}
/**
* Adds a rotation to the current transformation.
*
* @param rotate
* Euler angles, in radians
* @return This transform, for cascade method calls
*/
public Transform addRotation( Tuple3f rotate )
{
tempTransform.setIdentity();
tempTransform.rotXYZ( rotate.getX(), rotate.getY(), rotate.getZ() );
getTransform().mul( tempTransform );
setTransform( getTransform() );
return ( this );
}
/**
* Sets a rotation to the current transformation.
*
* @param rotationMatrix
*/
public Transform setRotation( Matrix3f rotationMatrix )
{
getTransform().setRotation( rotationMatrix );
setTransform( getTransform() );
return ( this );
}
/**
* Adds a rotation to the current transformation.
*
* @param rotationMatrix
*/
public Transform addRotation( Matrix3f rotationMatrix )
{
tempTransform.setIdentity();
tempTransform.setRotation( rotationMatrix );
getTransform().mul( tempTransform );
setTransform( getTransform() );
return ( this );
}
/**
* Adds a rotation to the current transformation.
*
* @param x
* X angle, in radians
* @param y
* Y angle, in radians
* @param z
* Z angle, in radians
* @return This transform, for cascade method calls
*/
public Transform addRotation( float x, float y, float z )
{
tempTransform.setIdentity();
tempTransform.rotXYZ( x, y, z );
getTransform().mul( tempTransform );
setTransform( getTransform() );
return ( this );
}
/**
* Applies a rotation.
*
* @param angle
* Euler angle, in radians
* @return This transform, for cascade method calls
*/
public Transform setRotationX( float angle )
{
Transform3D t3d = getTransform();
t3d.rotXYZ( angle, 0f, 0f );
setTransform( t3d );
return ( this );
}
/**
* Adds a rotation to the current transformation.
*
* @param angle
* Euler angle, in radians
* @return This transform, for cascade method calls
*/
public Transform addRotationX( float angle )
{
tempTransform.setIdentity();
tempTransform.rotXYZ( angle, 0f, 0f );
getTransform().mul( tempTransform );
setTransform( getTransform() );
return ( this );
}
/**
* Applies a rotation.
*
* @param angle
* Euler angle, in radians
* @return This transform, for cascade method calls
*/
public Transform setRotationY( float angle )
{
Transform3D t3d = getTransform();
t3d.rotXYZ( 0f, angle, 0f );
setTransform( t3d );
return ( this );
}
/**
* Adds a rotation to the current transformation.
*
* @param angle
* Euler angle, in radians
* @return This transform, for cascade method calls
*/
public Transform addRotationY( float angle )
{
tempTransform.setIdentity();
tempTransform.rotXYZ( 0f, angle, 0f );
getTransform().mul( tempTransform );
setTransform( getTransform() );
return ( this );
}
/**
* Applies a rotation.
*
* @param angle
* Euler angle, in radians
* @return This transform, for cascade method calls
*/
public Transform setRotationZ( float angle )
{
Transform3D t3d = getTransform();
t3d.rotXYZ( 0f, 0f, angle );
setTransform( t3d );
return ( this );
}
/**
* Adds a rotation to the current transformation.
*
* @param angle
* Euler angle, in radians
* @return This transform, for cascade method calls
*/
public Transform addRotationZ( float angle )
{
tempTransform.setIdentity();
tempTransform.rotXYZ( 0f, 0f, angle );
getTransform().mul( tempTransform );
setTransform( getTransform() );
return ( this );
}
/**
* Applies a scale.
*
* @param scale
* X, Y, Z scale
* @return This transform, for cascade method calls
*/
public Transform setScale( Tuple3f scale )
{
Transform3D t3d = getTransform();
t3d.setScale( scale );
setTransform( t3d );
return ( this );
}
/**
* Applies a scale.
*
* @param x
* X scale
* @param y
* Y scale
* @param z
* Z scale
* @return This transform, for cascade method calls
*/
public Transform setScale( float x, float y, float z )
{
Transform3D t3d = getTransform();
t3d.setScale( x, y, z );
setTransform( t3d );
return ( this );
}
/**
* Applies a scale.
*
* @param scale
* X scale
* @return This transform, for cascade method calls
*/
public Transform setScaleX( float scale )
{
Transform3D t3d = getTransform();
t3d.setScale( scale, 0f, 0f );
setTransform( t3d );
return ( this );
}
/**
* Applies a scale.
*
* @param scale
* Y scale
* @return This transform, for cascade method calls
*/
public Transform setScaleY( float scale )
{
Transform3D t3d = getTransform();
t3d.setScale( 0f, scale, 0f );
setTransform( t3d );
return ( this );
}
/**
* Applies a scale.
*
* @param scale
* Z scale
* @return This transform, for cascade method calls
*/
public Transform setScaleZ( float scale )
{
Transform3D t3d = getTransform();
t3d.setScale( 0f, 0f, scale );
setTransform( t3d );
return ( this );
}
/**
* Applies a scale.
*
* @param scale
* X, Y and Z scale
* @return This transform, for cascade method calls
*/
public Transform setScale( float scale )
{
Transform3D t3d = getTransform();
t3d.setScale( scale );
setTransform( t3d );
return ( this );
}
/**
* Adds a scale transformation to the current transform.
*
* @param scale
* Scale factor
*
* @return This transform, for cascade method calls
*/
public Transform addScale( float scale )
{
Transform3D t3d = getTransform();
tempTransform.setIdentity();
tempTransform.setScale( scale );
t3d.mul( tempTransform );
setTransform( t3d );
return ( this );
}
/**
* Adds node n to this transform and returns n.
*
* @param n
* The node to add
* @return This transform, for cascade method calls
*/
public Transform add( Node n )
{
this.addChild( n );
return ( this );
}
/**
* Adds transform t to this transform and returns t.
*
* @param t
* The transform to add
* @return The transform added
*/
public Transform add( Transform t )
{
this.addChild( t );
return ( t );
}
/**
* Clears all transformations (Set the identity matrix).
*
* @return itself
*/
public Transform clear()
{
getTransform().setIdentity();
updateTransform();
return ( this );
}
/**
* Sets rotation about an axis.
*
* @param rotationAxis
* The axis to rotate about
* @param angle
* The angle to rotate of, in radians
* @return itself
*/
public Transform setAxisRotation( Tuple3f rotationAxis, float angle )
{
tempAxisAngle.set( rotationAxis, angle );
getTransform().setRotation( tempAxisAngle );
setTransform( getTransform() );
return ( this );
}
/**
* Adds rotation about an axis.
*
* @param rotationAxis
* The axis to rotate about
* @param angle
* The angle to rotate of, in radians
* @return itself
*/
public Transform addAxisRotation( Tuple3f rotationAxis, float angle )
{
tempTransform.setIdentity();
tempAxisAngle.set( rotationAxis, angle );
tempTransform.setRotation( tempAxisAngle );
getTransform().mul( tempTransform );
setTransform( getTransform() );
return ( this );
}
/**
* Sets translation about an axis with a specified length.
*
* @param translationAxis
* @param length
*
* @return itself
*/
public Transform setAxisTranslation( Tuple3f translationAxis, float length )
{
tempVector.set( translationAxis );
tempVector.normalize();
tempVector.scale( length );
setTranslation( tempVector );
return ( this );
}
/**
* Sets translation about an axis with a specified length.
*
* @param translationAxis
* @param length
*
* @return itself
*/
public Transform addAxisTranslation( Tuple3f translationAxis, float length )
{
tempVector.set( translationAxis );
tempVector.normalize();
tempVector.scale( length );
addTranslation( tempVector );
return ( this );
}
/**
* Sets this transform to a transformation corresponding to the
* matrix argument.
*
* @param matrix The transformation matrix to set this transform to
*
* @return itself
*/
public Transform setMatrix( Matrix4f matrix )
{
getTransform().set( matrix );
setTransform( getTransform() );
return ( this );
}
/**
* @param node
*
* @return The Transform which is parent to the given node (if it's the case)
*/
public static Transform get( Node node )
{
if ( node.getParent() != null )
{
GroupNode parent = node.getParent();
if ( parent instanceof Transform )
{
Transform t = (Transform) parent;
return t;
}
}
return ( null );
}
/**
* Applies this transform to a Point3f.
* Mathematically, the matrix of this transform is multiplied
* with the input Tuple3f and the result is stored in it.
*
* @param input the Tuple3f to be applied the Transform
*/
public void transform( Point3f input )
{
this.getTransform().getMatrix4f().transform( input );
}
/**
* Applies this transform to a Vector3f.
* Mathematically, the matrix of this transform is multiplied
* with the input Tuple3f and the result is stored in it.
*
* @param input the Tuple3f to be applied the Transform
*/
public void transform( Vector3f input )
{
this.getTransform().getMatrix4f().transform( input );
}
/**
* Sets this transform to be equal to another one.
*
* @param trans
*/
public void set( Transform trans )
{
this.getTransform().set( trans.getTransform() );
this.setTransform( this.getTransform() );
}
/**
* @param node
* The node to transform
*/
public Transform( Node node )
{
addChild( node );
}
/**
* @param mode
* Transform.ROTATION, Transform.TRANSLATION, or Transform.SCALE
* @param transform
* If rotation, euler angles (in radians), if translation or
* scale relevant value
* @param node
* The node to transform
*/
public Transform( int mode, Tuple3f transform, Node node )
{
addChild(node);
setTransform(mode, transform);
}
/**
* Creates an empty identity transform.
*/
public Transform()
{
// Nothing to do here
}
}