/**
* 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.physics.collision;
import org.openmali.vecmath2.Matrix3f;
import org.openmali.vecmath2.Point3f;
import org.openmali.vecmath2.Tuple3f;
import org.openmali.vecmath2.util.MatrixUtils;
import org.xith3d.physics.simulation.Body;
/**
* Common parent (abstract class) for all Collideable Objects.
*
* @author Amos Wenger (aka BlueSky)
* @author Marvin Froehlich (aka Qudus)
*/
public abstract class CollideableBase implements Collideable
{
private final CollisionEngine engine;
private String name = null;
private Object userObject = null;
private Body body = null;
/** The parent node to this one */
private CollideableGroup parent;
/** The position (in local coordinates) */
private final Point3f position;
/** The position (in world coordinates) */
private final Point3f worldPos;
/** The rotation (in local coordinates) */
private final Matrix3f rotation;
/** The rotation (in world coordinates) */
private final Matrix3f worldRot;
/** Here is a lazily-allocated Point3f to avoid garbage creation */
private Point3f posPoint3f = null;
/** Here is a lazily-allocated Tuple3f to avoid garbage creation */
private Tuple3f rotTuple3f = null;
/** Here is a lazily-allocated Matrix3f to avoid garbage creation */
private Matrix3f rotMatrix3f = null;
/**
* {@inheritDoc}
*/
public CollisionEngine getEngine()
{
return ( engine );
}
/**
* {@inheritDoc}
*/
public final void setName( String name )
{
this.name = name;
}
/**
* {@inheritDoc}
*/
public final String getName()
{
return ( name );
}
/**
* {@inheritDoc}
*/
public final void setUserObject( Object userObject )
{
this.userObject = userObject;
}
/**
* {@inheritDoc}
*/
public final Object getUserObject()
{
return ( userObject );
}
/**
* Sets this Collideable's parent group.
*
* @param parent
*/
protected void setParent( CollideableGroup parent )
{
this.parent = parent;
}
/**
* {@inheritDoc}
*/
public final CollideableGroup getParent()
{
return ( parent );
}
/**
* {@inheritDoc}
*/
public void setBody( Body body )
{
this.body = body;
}
/**
* {@inheritDoc}
*/
public final Body getBody()
{
if ( body != null )
return ( body );
if ( getParent() != null )
return ( getParent().getBody() );
return ( null );
}
public void setRotation( float x, float y, float z, boolean recomputeWorldCoords )
{
MatrixUtils.eulerToMatrix3f( x, y, z, rotation );
if ( recomputeWorldCoords )
recomputeWorldCoords( true, true );
}
/**
* {@inheritDoc}
*/
public final void setRotation( float x, float y, float z )
{
setRotation( x, y, z, true );
}
/**
* {@inheritDoc}
*/
public final void setRotation( Tuple3f rot )
{
setRotation( rot.getX(), rot.getY(), rot.getZ() );
}
/**
* {@inheritDoc}
*/
public final void setRotationX( float x )
{
Tuple3f rotation = getRotation();
rotation.setX( x );
setRotation(rotation);
}
/**
* {@inheritDoc}
*/
public final void setRotationY( float y )
{
Tuple3f rotation = getRotation();
rotation.setY( y );
setRotation( rotation );
}
/**
* {@inheritDoc}
*/
public final void setRotationZ( float z )
{
Tuple3f rotation = getRotation();
rotation.setZ( z );
setRotation( rotation );
}
/**
* {@inheritDoc}
*/
public final Tuple3f getRotation()
{
if ( rotTuple3f == null )
rotTuple3f = new Tuple3f();
MatrixUtils.matrixToEuler( rotation, rotTuple3f );
return ( rotTuple3f );
}
/**
* {@inheritDoc}
*/
public final void getRotation( Tuple3f rot )
{
MatrixUtils.matrixToEuler( rotation, rot );
}
/**
* {@inheritDoc}
*/
public void setRotationMatrix( Matrix3f rot, boolean recomputeWorldCoords )
{
rotation.set( rot );
if ( recomputeWorldCoords )
recomputeWorldCoords( true, true );
}
public final void setRotationMatrix( Matrix3f rot )
{
setRotationMatrix( rot, true );
}
/**
* {@inheritDoc}
*/
public final Matrix3f getRotationMatrix()
{
return ( rotation.getReadOnly() );
}
/**
* {@inheritDoc}
*/
public final void getRotationMatrix( Matrix3f mat )
{
mat.set( rotation );
}
public void setPosition( float x, float y, float z, boolean recomputeWorldCoords )
{
position.set( x, y, z );
if ( recomputeWorldCoords )
recomputeWorldCoords( true, true );
}
/**
* {@inheritDoc}
*/
public final void setPosition( float x, float y, float z )
{
setPosition( x, y, z, true );
}
/**
* {@inheritDoc}
*/
public final void setPosition( Tuple3f pos )
{
setPosition( pos.getX(), pos.getY(), pos.getZ() );
}
/**
* {@inheritDoc}
*/
public final void setPositionX( float x )
{
Tuple3f position = getPosition();
setPosition( x, position.getY(), position.getZ() );
}
/**
* {@inheritDoc}
*/
public final void setPositionY( float y )
{
Tuple3f position = getPosition();
setPosition( position.getX(), y, position.getZ() );
}
/**
* {@inheritDoc}
*/
public final void setPositionZ( float z )
{
Tuple3f position = getPosition();
setPosition( position.getX(), position.getY(), z );
}
/**
* {@inheritDoc}
*/
public final Point3f getPosition()
{
return ( position.getReadOnly() );
}
/**
* {@inheritDoc}
*/
public final void getPosition( Tuple3f pos )
{
pos.set( this.position );
}
/**
* {@inheritDoc}
*/
public final Point3f getWorldPos()
{
if ( posPoint3f == null )
posPoint3f = new Point3f();
getWorldPos( posPoint3f );
return ( posPoint3f );
}
/**
* {@inheritDoc}
*/
public final void getWorldPos( Tuple3f pos )
{
pos.set( worldPos );
}
/**
* {@inheritDoc}
*/
public final Tuple3f getWorldRot()
{
if ( rotTuple3f == null )
rotTuple3f = new Tuple3f();
getWorldRot( rotTuple3f );
return ( rotTuple3f );
}
/**
* {@inheritDoc}
*/
public final void getWorldRot( Tuple3f rot )
{
MatrixUtils.matrixToEuler( getWorldRotMat(), rot );
}
/**
* {@inheritDoc}
*/
public final Matrix3f getWorldRotMat()
{
if ( rotMatrix3f == null )
rotMatrix3f = new Matrix3f();
getWorldRotMat( rotMatrix3f );
return ( rotMatrix3f );
}
/**
* {@inheritDoc}
*/
public final void getWorldRotMat( Matrix3f rot )
{
rot.set( worldRot );
}
/**
* Applies the world-rotation to the implementation.
*
* @param worldRot
*/
protected abstract void applyWorldRotation( Matrix3f worldRot );
/**
* Applies the world-position to the implementation.
*
* @param worldPos
*/
protected abstract void applyWorldPosition( Tuple3f worldPos );
/**
* Recomputes the World coordinates rotation matrix.
*
* @param worldRot
* @param applyToImplementation
*/
protected void recomputeWorldRotMat( Matrix3f worldRot, boolean applyToImplementation )
{
if ( getParent() == null )
{
worldRot.setIdentity();
}
else
{
getParent().getWorldRotMat( worldRot );
}
worldRot.mul( getRotationMatrix() );
if ( applyToImplementation )
{
applyWorldRotation( worldRot );
}
}
/**
* Recomputes the World coordinates position.
*
* @param worldPos
* @param applyToImplementation
*/
protected void recomputeWorldPos( Point3f worldPos, boolean applyToImplementation )
{
if ( getParent() == null )
{
worldPos.set( getPosition() );
}
else
{
if ( posPoint3f == null )
posPoint3f = new Point3f();
if ( rotMatrix3f == null )
rotMatrix3f = new Matrix3f();
getParent().getWorldPos( posPoint3f );
getParent().getWorldRotMat( rotMatrix3f );
worldPos.set( getPosition() );
rotMatrix3f.transform( worldPos );
worldPos.add( posPoint3f, worldPos );
}
if ( applyToImplementation )
{
applyWorldPosition( worldPos );
}
}
/**
* {@inheritDoc}
*/
public void recomputeChildrenWorldCoords( boolean applyToImplementation )
{
if ( this instanceof CollideableGroup )
{
final int n = ( (CollideableGroup)this ).getChildrenCount();
for ( int i = 0; i < n; i++ )
{
( (CollideableGroup)this ).getChild( i ).recomputeWorldCoords( true, applyToImplementation );
}
}
}
/**
* {@inheritDoc}
*/
public void recomputeWorldCoords( boolean childrenToo, boolean applyToImplementation )
{
recomputeWorldPos( worldPos, applyToImplementation );
recomputeWorldRotMat( worldRot, applyToImplementation );
if ( childrenToo )
{
recomputeChildrenWorldCoords( applyToImplementation );
}
}
/**
* {@inheritDoc}
*/
@Override
public String toString()
{
if ( this.getName() == null )
return ( super.toString() );
return ( super.toString() + " \"" + this.getName() + "\"" );
}
/**
* Creates a new {@link CollideableBase}.
*/
public CollideableBase( CollisionEngine engine )
{
this.engine = engine;
this.position = new Point3f();
this.worldPos = new Point3f();
this.rotation = new Matrix3f();
this.rotation.setIdentity();
this.worldRot = new Matrix3f();
this.worldRot.setIdentity();
}
}