/**
* 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 java.util.ArrayList;
import java.util.List;
import java.util.Vector;
import org.jagatoo.datatypes.Enableable;
import org.openmali.spatial.IndexContainer;
import org.openmali.spatial.TriangleContainer;
import org.openmali.spatial.VertexContainer;
import org.openmali.spatial.polygons.Triangle;
import org.openmali.vecmath2.Point3f;
import org.openmali.vecmath2.Tuple3f;
import org.openmali.vecmath2.Vector3f;
import org.xith3d.loop.Updatable;
import org.xith3d.loop.UpdatingThread.TimingMode;
import org.xith3d.physics.collision.collideable.BoxCollideable;
import org.xith3d.physics.collision.collideable.CapsuleCollideable;
import org.xith3d.physics.collision.collideable.CylinderCollideable;
import org.xith3d.physics.collision.collideable.PlaneCollideable;
import org.xith3d.physics.collision.collideable.RayCollideable;
import org.xith3d.physics.collision.collideable.SphereCollideable;
import org.xith3d.physics.collision.collideable.TriMeshCollideable;
import org.xith3d.scenegraph.Geometry;
import org.xith3d.scenegraph.GroupNode;
import org.xith3d.scenegraph.Node;
import org.xith3d.scenegraph.Shape3D;
/**
* A Collision Engine. The base implementation is the JOODE one, but any engine
* can be implemented... even your own one ! Put your imagination at work !<br>
* <br>
* A Collision Engine is in charge of : creating every CollideableGroup or
* Collideable,<br>
* <br>
* Many thanks to the ODE Team for design ideas..
*
* @author Amos Wenger (aka BlueSky)
* @author Marvin Froehlich (aka Qudus)
*/
public abstract class CollisionEngine implements Updatable, Enableable
{
private final Vector<CollisionCheck> collisionCheckList = new Vector<CollisionCheck>();
private CollisionListener defaultCollisionListener = null;
private boolean enabled = true;
/**
* Error thrown when the user tries to create a Collideable which
* type hasn't been implemented in the engine he uses.
*
* @author Amos Wenger (aka BlueSky)
*/
public class NotImplementedYetError extends Error
{
private static final long serialVersionUID = -5061974919339663639L;
/**
* Creates a new {@link NotImplementedYetError} error.
*
* @param message
*/
public NotImplementedYetError( String message )
{
super( message );
}
}
/*
* CREATION METHODS : GROUPS
*/
/**
* @return a list of all group types
*/
public abstract List<CollideableGroupType> getGroupTypes();
/**
* Creates a new group of the "best" available type (by best we mean the best
* compromise between speed and memory, the one which would be fine for most
* situations).
*
* To create a group of a specific type :
*
* @see #newGroup(String) To know all implemented group types
* @see #getGroupTypes()
*
* @return The newly created Group
*/
public abstract CollideableGroup newGroup();
/**
* Creates a new group of a specified type.
*
* @param type
*
* @see #getGroupTypes()
*
* @return The newly created Group
*/
public abstract CollideableGroup newGroup( String type );
/*
* CREATION METHODS : COLLIDEABLES
* Notes on the implementation :
* all the method aren't abstract, which means the Collision engine
* has no obligation to implement anything at all. If the user call
* a creation method and the engine hasn't implemented it, an Exception
* will be thrown, which is the "implementation" of the creation methods
* by default in the CollisionEngine class.
* Here, and implementation is equal to an override.
* If an engine implements a primitive which isn't supported by XPAL
* yet, a new method + an abstract class in org.xith3d.physics.collision.collideable
* should be added.
*/
/**
* Creates a new ray collideable
*
* @param originX
* @param originY
* @param originZ
* @param directionX
* @param directionY
* @param directionZ
*
* @return a ray collideable
*/
public RayCollideable newRay( float originX, float originY, float originZ, float directionX, float directionY, float directionZ )
{
throw new NotImplementedYetError( "The engine " + getVendorInformation().getName() +
" hasn't implemented Ray collision detection yet !" );
}
/**
* Creates a new ray collideable
*
* @param origin
* @param direction
*
* @return a ray collideable
*/
public final RayCollideable newRay( Tuple3f origin, Tuple3f direction )
{
return ( newRay( origin.getX(), origin.getY(), origin.getZ(), direction.getX(), direction.getY(), direction.getZ() ) );
}
/**
* Creates a new ray collideable
*
* @param ray the template ray to create the RayCollideable from
*
* @return a ray collideable
*/
public final RayCollideable newRay( org.openmali.vecmath2.Ray3f ray )
{
final RayCollideable c = newRay( ray.getOrigin(), ray.getDirection() );
return ( c );
}
/**
* Creates a new ray collideable
*
* @param vertexContainer the VertexContainer to take the vertex coordinates from
*
* @return a ray collideable
*/
public final RayCollideable newRay( VertexContainer vertexContainer )
{
org.openmali.vecmath2.Point3f coord = org.openmali.vecmath2.Point3f.fromPool();
vertexContainer.getVertex( 0, coord );
float x0 = coord.getX();
float y0 = coord.getY();
float z0 = coord.getZ();
vertexContainer.getVertex( 1, coord );
float x1 = coord.getX();
float y1 = coord.getY();
float z1 = coord.getZ();
return ( newRay( x0, y0, z0, x1, y1, z1 ) );
}
/**
* Creates a new ray collideable
*
* @param shape the tempalte shape
*
* @return a ray collideable
*/
public final RayCollideable newRay( Shape3D shape )
{
return ( newRay( shape.getGeometry() ) );
}
/**
* Creates a new sphere collideable
*
* @param radius The radius of the sphere
*
* @return a sphere collideable
*/
public SphereCollideable newSphere( float radius )
{
throw new NotImplementedYetError( "The engine " + getVendorInformation().getName() +
" hasn't implemented Sphere collision detection yet !" );
}
/**
* Creates a new sphere collideable
*
* @param sphere the template sphere to create the SphereCollideable from
*
* @return a sphere collideable
*/
public final SphereCollideable newSphere( org.openmali.spatial.bodies.Sphere sphere )
{
final SphereCollideable c = newSphere( sphere.getRadius() );
c.setPosition( sphere.getCenterX(), sphere.getCenterY(), sphere.getCenterZ() );
return ( c );
}
/**
* Creates a new sphere collideable
*
* @param vertexContainer the VertexContainer to take the vertex coordinates from
*
* @return a sphere collideable
*/
public final SphereCollideable newSphere( VertexContainer vertexContainer )
{
org.openmali.spatial.bounds.BoundingSphere bs = org.openmali.spatial.bounds.BoundingSphere.newBoundingSphere( vertexContainer );
return ( newSphere( bs ) );
}
/**
* Creates a new sphere collideable
*
* @param shape the tempalte shape
*
* @return a sphere collideable
*/
public final SphereCollideable newSphere( Shape3D shape )
{
return ( newSphere( shape.getGeometry() ) );
}
/**
* Creates a new box collideable
*
* @param size The size of the box
*
* @return a box collideable
*/
public final BoxCollideable newBox( Tuple3f size )
{
return ( newBox( size.getX(), size.getY(), size.getZ() ) );
}
/**
* Creates a new box collideable
*
* @param xSize The size of the box along the X axis
* @param ySize The size of the box along the Y axis
* @param zSize The size of the box along the Z axis
*
* @return a box collideable
*/
public BoxCollideable newBox( float xSize, float ySize, float zSize )
{
throw new NotImplementedYetError( "The engine " + getVendorInformation().getName() +
" hasn't implemented Box collision detection yet !" );
}
/**
* Creates a new box collideable
*
* @param box the template box to create the BoxCollideable from
*
* @return a box collideable
*/
public final BoxCollideable newBox( org.openmali.spatial.bodies.Box box )
{
final BoxCollideable c = newBox( box.getXSpan(), box.getYSpan(), box.getZSpan() );
c.setPosition( box.getCenterX(), box.getCenterY(), box.getCenterZ() );
return ( c );
}
/**
* Creates a new box collideable
*
* @param vertexContainer the VertexContainer to take the vertex coordinates from
*
* @return a box collideable
*/
public final BoxCollideable newBox( VertexContainer vertexContainer )
{
org.openmali.spatial.bounds.BoundingBox bb = org.openmali.spatial.bounds.BoundingBox.newAABB( vertexContainer );
return ( newBox( bb ) );
}
/**
* Creates a new box collideable
*
* @param shape the template shape
*
* @return a box collideable
*/
public final BoxCollideable newBox( Shape3D shape )
{
return ( newBox( shape.getGeometry() ) );
}
/**
* Creates a new box collideable
*
* @param box the template box to create the BoxCollideable from
*
* @return a box collideable
*/
public final CollideableGroup newBoxOutline( org.openmali.spatial.bodies.Box box )
{
CollideableGroup boxOutline = newGroup( "Simple" );
final float inverted = -1f;
PlaneCollideable top = newPlane( new Vector3f( 0f, 1f * inverted, 0f ), box.getUpper() );
boxOutline.addCollideable( top );
PlaneCollideable bottom = newPlane( new Vector3f( 0f, -1f * inverted, 0f ), box.getLower() );
boxOutline.addCollideable( bottom );
PlaneCollideable front = newPlane( new Vector3f( 0f, 0f, -1f * inverted ), box.getLower() );
boxOutline.addCollideable( front );
PlaneCollideable back = newPlane( new Vector3f( 0f, 0f, +1f * inverted ), box.getUpper() );
boxOutline.addCollideable( back );
PlaneCollideable left = newPlane( new Vector3f( -1f * inverted, 0f, 0f ), box.getLower() );
boxOutline.addCollideable( left );
PlaneCollideable right = newPlane( new Vector3f( 1f * inverted, 0f, 0f ), box.getUpper() );
boxOutline.addCollideable( right );
return ( boxOutline );
}
/**
* Creates a new "box outline" collideable
* @param vertexContainer the VertexContainer to take the vertex coordinates from
* @return the created CollideableGroup
*/
public final CollideableGroup newBoxOutline( VertexContainer vertexContainer )
{
org.openmali.spatial.bounds.BoundingBox bb = org.openmali.spatial.bounds.BoundingBox.newAABB( vertexContainer );
return ( newBoxOutline( bb ) );
}
/**
* Creates a new "box outline" collideable
* @param shape the template shape
* @return the created CollideableGroup
*/
public final CollideableGroup newBoxOutline( Shape3D shape )
{
return ( newBoxOutline( shape.getGeometry() ) );
}
/**
* Creates a new capsule collideable
*
* @param radius The radius of the capsule
* @param length The length of the capsule
*
* @return a capsule collideable
*/
public CapsuleCollideable newCapsule( float radius, float length )
{
throw new NotImplementedYetError( "The engine " + getVendorInformation().getName() +
" hasn't implemented Capsule collision detection yet !" );
}
/**
* Creates a new cylinder collideable
*
* @param radius The radius of the capsule
* @param length The length of the capsule
*
* @return a cylinder collideable
*/
public CylinderCollideable newCylinder( float radius, float length )
{
throw new NotImplementedYetError( "The engine " + getVendorInformation().getName() +
" hasn't implemented Cylinder collision detection yet !");
}
/**
* Creates a new plane collideable
*
* @param normal The normal of the plane to be created
* @param point A point by which this plane is defined
*
* @return a plane collideable
*/
public PlaneCollideable newPlane( Vector3f normal, Point3f point )
{
throw new NotImplementedYetError( "The engine " + getVendorInformation().getName() +
" hasn't implemented Plane collision detection yet !" );
}
/**
* Creates a new plane collideable
*
* @param normal The normal of the plane to be created
* @param d The d-parameter by which this plane is defined
*
* @return a plane collideable
*/
public PlaneCollideable newPlane( Vector3f normal, float d )
{
throw new NotImplementedYetError( "The engine " + getVendorInformation().getName() +
" hasn't implemented Plane collision detection yet !" );
}
/**
* Creates a new plane collideable
*
* @param a the x-component of the plane's normal
* @param b the y-component of the plane's normal
* @param c the z-component of the plane's normal
* @param d The d-parameter by which this plane is defined
*
* @return a plane collideable
*/
public PlaneCollideable newPlane( float a, float b, float c, float d )
{
throw new NotImplementedYetError( "The engine " + getVendorInformation().getName() +
" hasn't implemented Plane collision detection yet !" );
}
/**
* Creates a new plane collideable
*
* @param plane the Plane, the new PlaneCollideable is defained off.
*
* @return a plane collideable
*/
public final PlaneCollideable newPlane( org.openmali.spatial.bodies.Plane plane )
{
return ( newPlane( plane.getA(), plane.getB(), plane.getC(), plane.getD() ) );
}
/**
* Creates a new triangle mesh collideable
*
* @param vertexContainer A vertex container of a Triangle-based mesh (All Geometry types implements that interface)
* @param indexContainer An index container of a Triangle-based mesh (Indexed Geometry types implements that interface)
*
* If your geometry is not indexed, see the newTriMesh(VertexContainer) method.
*
* @return a triangle mesh collideable
*/
public TriMeshCollideable newTriMesh( VertexContainer vertexContainer, IndexContainer indexContainer )
{
final Point3f[] vertices = new Point3f[ vertexContainer.getVertexCount() ];
final Point3f coord = new Point3f();
for ( int i = 0; i < vertices.length; i++ )
{
vertexContainer.getVertex( i, coord );
vertices[i] = new Point3f( coord );
}
final int[] indices;
if ( indexContainer == null )
{
indices = new int[ vertexContainer.getVertexCount() ];
for ( int i = 0; i < indices.length; i++ )
{
indices[i] = i;
}
}
else
{
indices = new int[ indexContainer.getIndexCount() ];
for ( int i = 0; i < indices.length; i++ )
{
indices[i] = indexContainer.getIndex( i );
}
}
return ( newTriMesh( vertices, indices ) );
}
/**
* Creates a new triangle mesh collideable
*
* @param vertexContainer A vertex container of a Triangle-based mesh (All Geometry types implements that interface)
*
* @return a triangle mesh collideable
*/
public final TriMeshCollideable newTriMesh( VertexContainer vertexContainer )
{
return ( newTriMesh( vertexContainer, null ) );
}
/**
* Creates a new triangle mesh collideable
*
* @param triangleContainer A vertex container of a Triangle-based mesh (All Geometry types implements that interface)
*
* @return a triangle mesh collideable
*/
public TriMeshCollideable newTriMesh( TriangleContainer triangleContainer )
{
final VertexContainer vertexContainer = (VertexContainer)triangleContainer;
final int nt = triangleContainer.getTriangleCount();
final int nv = vertexContainer.getVertexCount();
final Point3f[] coords = new Point3f[ nv ];
final Point3f coord = new Point3f();
for ( int i = 0; i < coords.length; i++ )
{
vertexContainer.getVertex( i, coord );
coords[i] = new Point3f( coord );
}
final Triangle trian = new Triangle();
final Vector3f edgeAC = new Vector3f();
final Vector3f edgeAB = new Vector3f();
final Vector3f faceNormal = new Vector3f();
final Vector3f crossNormal = new Vector3f();
final int[] indices = new int[ nt * 3 ];
int i = 0;
for ( int t = 0; t < nt; t++ )
{
triangleContainer.getTriangle( t, trian );
// TODO: Check this!
if ( false && trian.hasFeature( Geometry.NORMALS ) )
{
edgeAC.sub( trian.getVertexCoordA(), trian.getVertexCoordB() );
edgeAB.sub( trian.getVertexCoordA(), trian.getVertexCoordC() );
crossNormal.cross( edgeAC, edgeAB );
crossNormal.normalize();
trian.getFaceNormal( faceNormal );
indices[i++] = trian.getVertexIndexA();
if ( crossNormal.epsilonEquals( faceNormal, 0.001f ) )
{
indices[i++] = trian.getVertexIndexB();
indices[i++] = trian.getVertexIndexC();
}
else
{
indices[i++] = trian.getVertexIndexC();
indices[i++] = trian.getVertexIndexB();
}
}
else
{
indices[i++] = trian.getVertexIndexC();
indices[i++] = trian.getVertexIndexB();
indices[i++] = trian.getVertexIndexA();
}
}
return ( newTriMesh( coords, indices ) );
}
/**
* Creates a new triangle mesh collideable
*
* @param geometry A Xith3D geometry
*
* @return a triangle mesh collideable
*/
public final TriMeshCollideable newTriMesh( Geometry geometry )
{
if ( geometry instanceof TriangleContainer )
return ( newTriMesh( (TriangleContainer)geometry ) );
return ( newTriMesh( (VertexContainer)geometry ) );
}
/**
* Creates a new triangle mesh collideable
*
* @param shape A Xith3D Shape3D
*
* @return a triangle mesh collideable
*/
public final TriMeshCollideable newTriMesh( Shape3D shape )
{
return ( newTriMesh( shape.getGeometry() ) );
}
/**
* Creates a new triangle mesh collideable
*
* @param vertices The vertex data which is indexed
* @param indices The vertices to chose from the vertex data
*
* @return a triangle mesh collideable
*/
public TriMeshCollideable newTriMesh( Tuple3f[] vertices, int[] indices )
{
throw new NotImplementedYetError( "The engine " + getVendorInformation().getName() +
" hasn't implemented TriMesh collision detection yet !" );
}
/**
* Creates a new triangle mesh collideable
*
* @param vertices The vertices of the triangle mesh (three vertices = one triangle)
*
* @return a triangle mesh collideable
*/
public final TriMeshCollideable newTriMesh( Tuple3f[] vertices )
{
return ( newTriMesh( vertices, null ) );
}
/**
* Creates a new CollideableGroup filled with TriMeshes derived from the
* contained Shape3Ds.
*
* @param group A Xith3D GroupNode
*
* @return a collideable group
*/
public final CollideableGroup newTriMeshGroup( GroupNode group )
{
CollideableGroup collGroup = newGroup( "Simple" );
for ( int i = 0; i < group.numChildren(); i++ )
{
final Node child = group.getChild( i );
if ( child instanceof GroupNode )
{
collGroup.addCollideable( newTriMeshGroup( (GroupNode)child ) );
}
else if ( child instanceof Shape3D )
{
collGroup.addCollideable( newTriMesh( (Shape3D)child ) );
}
}
return ( collGroup );
}
/**
* Creates a new CollideableGroup filled with Spheres derived from the
* contained Shape3Ds.
*
* @param group A Xith3D GroupNode
*
* @return a collideable group
*/
public final CollideableGroup newSphereGroup( GroupNode group )
{
CollideableGroup collGroup = newGroup( "Simple" );
for ( int i = 0; i < group.numChildren(); i++ )
{
final Node child = group.getChild( i );
if ( child instanceof GroupNode )
{
collGroup.addCollideable( newSphereGroup( (GroupNode)child ) );
}
else if ( child instanceof Shape3D )
{
collGroup.addCollideable( newSphere( (Shape3D)child ) );
}
}
return ( collGroup );
}
/**
* Creates a new CollideableGroup filled with Boxes derived from the
* contained Shape3Ds.
*
* @param group A Xith3D GroupNode
*
* @return a collideable group
*/
public final CollideableGroup newBoxGroup( GroupNode group )
{
CollideableGroup collGroup = newGroup( "Simple" );
for ( int i = 0; i < group.numChildren(); i++ )
{
final Node child = group.getChild( i );
if ( child instanceof GroupNode )
{
collGroup.addCollideable( newBoxGroup( (GroupNode)child ) );
}
else if ( child instanceof Shape3D )
{
collGroup.addCollideable( newSphere( (Shape3D)child ) );
}
}
return ( collGroup );
}
/*
* COLLISION DETECTION METHODS
*/
/*
* n x m, Collideable(Group) vs Collideable(Group)
*/
/**
* Checks two Collideables (or collideable groups) for collision (n x m collision check)
*
* @param c1 A Collideable or CollideableGroup
* @param c2 A Collideable or CollideableGroup
* @param ignoreStatic
* @param collisions the list to write collisions to
*
* @return the number of detected collisions
*/
public abstract int checkCollisions( Collideable c1, Collideable c2, boolean ignoreStatic, ArrayList<Collision> collisions );
/**
* Checks two Collideables (or collideable groups) for collision (n x m collision check)
*
* @param c1 A Collideable or CollideableGroup
* @param c2 A Collideable or CollideableGroup
* @param ignoreStatic
*
* @return An ArrayList containing all the collision, or an empty list if there's none.
*/
public final ArrayList<Collision> checkCollisions( Collideable c1, Collideable c2, boolean ignoreStatic )
{
ArrayList<Collision> collisions = new ArrayList<Collision>();
checkCollisions( c1, c2, ignoreStatic, collisions );
return ( collisions );
}
/**
* Checks two Collideables (or collideable groups) for collision (n x m collision check)
* The listener is notified of any collision.
*
* @param c1 A Collideable or CollideableGroup
* @param c2 A Collideable or CollideableGroup
* @param ignoreStatic
* @param listener The CollisionListener to be notified, when a collision is detected.
*
* @return the number of detected collisions
*/
public abstract int checkCollisions( Collideable c1, Collideable c2, boolean ignoreStatic,
CollisionListener listener );
/*
* n x n, ColllideableGroup vs itself
*/
/**
* Does an n x n collision check for all Collideables in the Group.
* If there's any collision it's put in the returned array list
*
* @param group
* @param ignoreStatic
* @param collisions the list to write collisions to
*
* @return the number of detected collisions
*/
public abstract int checkCollisions( CollideableGroup group, boolean ignoreStatic, ArrayList<Collision> collisions );
/**
* Does an n x n collision check for all Collideables in the Group.
* If there's any collision it's put in the returned array list
*
* @param group
* @param ignoreStatic
* @return a list of collisions
*/
public final ArrayList<Collision> checkCollisions( CollideableGroup group, boolean ignoreStatic )
{
ArrayList<Collision> collisions = new ArrayList<Collision>();
checkCollisions( group, ignoreStatic, collisions );
return ( collisions );
}
/**
* Does an n x n collision check for all Collideables in the Group. The
* listener is notified of any collision.
*
* @param group
* @param ignoreStatic
* @param listener
*
* @return the number of detected collisions
*/
public abstract int checkCollisions( CollideableGroup group, boolean ignoreStatic,
CollisionListener listener );
/*
* INFOS METHODS
*/
/**
* @return the CollisionEngine's vendor information
*/
public abstract CollisionEngineVendorInformation getVendorInformation();
/*
* Updatable implementation
*/
/**
* Adds a {@link CollisionCheck} to the list, that is handled each frame.
*
* @param cc
*/
public final void addCollisionCheck( CollisionCheck cc )
{
collisionCheckList.add( cc );
}
/**
* Removes a {@link CollisionCheck} from the list, that is handled each frame.
*
* @param cc
*/
public final void removeCollisionCheck( CollisionCheck cc )
{
collisionCheckList.remove( cc );
}
/**
* Sets the {@link CollisionListener}, that is being used, if a CollisionCheck
* doesn't define an own {@link CollisionListener}.
*
* @param cl
*/
public final void setDefaultCollisionListener( CollisionListener cl )
{
this.defaultCollisionListener = cl;
}
/**
* @return the {@link CollisionListener}, that is being used, if a CollisionCheck
* doesn't define an own {@link CollisionListener}.
*/
public final CollisionListener getDefaultCollisionListener()
{
return ( defaultCollisionListener );
}
/**
* Sets this CollisionEngine enabled/disabled.<br>
* If not enabled, the update() method will do nothing.
*
* @param enabled
*/
public final void setEnabled( boolean enabled )
{
this.enabled = enabled;
}
/**
* @return if this CollisionEngine is enabled.<br>
* If not enabled, the update() method will do nothing.
*/
public final boolean isEnabled()
{
return ( enabled );
}
/**
* {@inheritDoc}
*/
public void update( long gameTime, long frameTime, TimingMode timingMode )
{
if ( isEnabled() )
{
for ( int i = 0; i < collisionCheckList.size(); i++ )
{
final CollisionCheck cc = collisionCheckList.get( i );
final CollisionListener cl = ( cc.getCollisionListener() != null ) ? cc.getCollisionListener() : defaultCollisionListener;
if ( cl != null )
{
this.checkCollisions( cc.getCollideable1(), cc.getCollideable2(), cc.getIgnoreStatic(), cl );
}
else
{
System.err.println( "Warning: Neither the CollisionCheck defines a CollisionListener, nor the CollisionEngine has a default one." );
}
}
}
}
}