/**
* 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.simulation;
import java.util.ArrayList;
import org.jagatoo.datatypes.Enableable;
import org.jagatoo.datatypes.NamableObject;
import org.openmali.vecmath2.Tuple3f;
import org.openmali.vecmath2.Vector3f;
import org.xith3d.physics.collision.Collideable;
import org.xith3d.physics.collision.CollideableBase;
import org.xith3d.physics.collision.CollideableGroup;
import org.xith3d.physics.util.PlaceableImpl;
import org.xith3d.utility.classes.beans.BeanUtil;
/**
* A body has a position, an orientation, a linear and
* angular velocity, and some forces applied to it.
* It's part of a SimulationWorld and can be stepped.
*
* @author Amos Wenger (aka BlueSky)
* @author Marvin Froehlich (aka Qudus)
*/
public abstract class Body extends PlaceableImpl implements NamableObject, Enableable
{
private String name = null;
private Object userObject = null;
/** The simulation engine we belong to */
protected final SimulationWorld world;
/** Our collideables : used for collision detection */
protected final ArrayList<Collideable> collideables = new ArrayList<Collideable>();
/**
* @return the {@link SimulationWorld}, this {@link Body} belongs to.
*/
public final SimulationWorld getWorld()
{
return ( world );
}
/**
* Sets this Bodie's name.
*
* @param name
*/
public final void setName( String name )
{
this.name = name;
}
/**
* @return this Body's name.
*/
public final String getName()
{
return ( name );
}
/**
* Sets this Bodie's user-object.
*
* @param userObject
*/
public final void setUserObject( Object userObject )
{
this.userObject = userObject;
}
/**
* @return this Bodie's user-object.
*/
public final Object getUserObject()
{
return ( userObject );
}
/**
* Enables or disables this {@link Body}.
*
* @param enabled
*/
public abstract void setEnabled( boolean enabled );
/**
* @return true, if this {@link Body} is enabled.
*/
public abstract boolean isEnabled();
/**
* Enables/Disables gravity specifically for this {@link Body}.
*
* @param enabled
*/
public abstract void setGravityEnabled( boolean enabled );
/**
* @return if gravity is enabled specifically for this {@link Body}.
*/
public abstract boolean isGravityEnabled();
/**
* @return the linear velocity of this body
*/
public abstract Vector3f getLinearVelocity();
/**
* Sets the linear velocity of this object
*
* @param velX
* @param velY
* @param velZ
*/
public abstract void setLinearVelocity( float velX, float velY, float velZ );
/**
* Sets the linear velocity of this object
*
* @param linearVel
*/
public final void setLinearVelocity( Vector3f linearVel )
{
setLinearVelocity( linearVel.getX(), linearVel.getY(), linearVel.getZ() );
}
/**
* Sets the linear velocity of this object to zero.
*/
public final void resetLinearVelocity()
{
setLinearVelocity( 0f, 0f, 0f );
}
/**
* @return the angular velocity, as "euler angles"
* (but for speed), about the X, Y, and Z axis
*/
public abstract Vector3f getAngularVelocity();
/**
* Sets the angular velocity, as "euler angles"
* (but for speed), about the X, Y, and Z axis
*
* @param velX
* @param velY
* @param velZ
*/
public abstract void setAngularVelocity( float velX, float velY, float velZ );
/**
* Sets the angular velocity, as "euler angles"
* (but for speed), about the X, Y, and Z axis
*
* @param angularVel
*/
public final void setAngularVelocity( Tuple3f angularVel )
{
setAngularVelocity( angularVel.getX(), angularVel.getY(), angularVel.getZ() );
}
/**
* Sets the angular velocity, as "euler angles"
* (but for speed), about the X, Y, and Z axis to zero.
*/
public final void resetAngularVelocity()
{
setAngularVelocity( 0f, 0f, 0f );
}
/**
* Adds a torque to this body.
*
* @param tx X component
* @param ty Y component
* @param tz Z component
*/
public abstract void addTorque( float tx, float ty, float tz );
/**
* Adds a torque to this body.
*
* @param torque
*/
public final void addTorque( Tuple3f torque )
{
addTorque( torque.getX(), torque.getY(), torque.getZ() );
}
/**
* Adds a force to this body.
*
* @param fx X component
* @param fy Y component
* @param fz Z component
*/
public abstract void addForce( float fx, float fy, float fz );
/**
* Adds a force to this body.
*
* @param force
*/
public final void addForce( Vector3f force )
{
addForce( force.getX(), force.getY(), force.getZ() );
}
/**
* Gets a member, by name.
*
* @param member the member to get
* @return the parameter, by name
*/
public Object getParameter( String member )
{
return ( BeanUtil.get( this, member ) );
}
/**
* Sets a parameter, by name.
*
* @param member
* The name of the parameter
* @param value
* The "data" : could be Float, Vector3f, whatever..
*/
public void setParameter( String member, Object value )
{
BeanUtil.set( this, member, value );
}
/**
* Sets this Body's mass.
*
* @param mass
*/
public abstract void setMass( float mass );
/**
* @return this Body's mass.
*/
public abstract float getMass();
/**
* Adds a collideable to this Body.
* Collideables which are added to a Body are used for
* collision detection. A Body without any Collideable
* will just fall (if there's gravity) through anything.
* Note that the collideables are moved with the Body.
*
* @param collideable
*/
public void addCollideable( Collideable collideable )
{
this.collideables.add( collideable );
collideable.setBody( this );
collideable.setPosition( this.position );
collideable.setRotationMatrix( this.rotation );
}
/**
* Removes a collideable for this Body.
*
* @param collideable
*/
public void removeCollideable( Collideable collideable )
{
this.collideables.remove( collideable );
collideable.setBody( null );
}
/*
* @return the collideables.
*/
/*
public ArrayList<Collideable> getCollideables()
{
return ( collideables );
}
*/
/**
* @return the number of {@link Collideable}s in this {@link Body}.
*/
public final int getCollideablesCount()
{
return ( collideables.size() );
}
/**
* @param i
*
* @return the i-th {@link Collideable} in this {@link Body}.
*/
public final Collideable getCollideable( int i )
{
return ( collideables.get( i ) );
}
/**
* Refreshes this {@link Body}'s position and rotation from the
* implementation as well as all the child-{@link Collideable}'s ones.
*/
protected void refresh()
{
for ( int i = 0; i < collideables.size(); i++ )
{
final Collideable collideable = collideables.get( i );
//collideable.getPosition().set( this.position );
((CollideableBase)collideable).setPosition( this.position.getX(), this.position.getY(), this.position.getZ(), false );
//collideable.getRotationMatrix().set( this.rotation );
((CollideableBase)collideable).setRotationMatrix( this.rotation, false );
collideable.recomputeWorldCoords( false, false );
if ( collideable instanceof CollideableGroup )
{
( (CollideableGroup)collideable ).recomputeChildrenWorldCoords( true );
}
}
}
/**
* {@inheritDoc}
*/
@Override
public String toString()
{
if ( this.getName() == null )
return ( super.toString() );
return ( super.toString() + " \"" + this.getName() + "\"" );
}
/**
* Creates a new Body.
* At creation time, the Body has no collideable, which means
* it isn't "solid". It's just a "simulated position and rotation".
* If you want it to react to collisions (which you probably want),
* you have to add some collideables to it.
*
* @param world the simulation world we belong to
*
* @see #addCollideable(Collideable)
*/
public Body( SimulationWorld world )
{
super();
this.world = world;
}
}