package com.bitwaffle.spaceguts.entities;
import javax.vecmath.Quat4f;
import org.lwjgl.util.vector.Quaternion;
import org.lwjgl.util.vector.Vector3f;
import com.bitwaffle.spaceguts.graphics.model.Model;
import com.bitwaffle.spaceguts.physics.CollisionTypes;
import com.bitwaffle.spaceguts.physics.Physics;
import com.bitwaffle.spaceguts.util.QuaternionHelper;
import com.bitwaffle.spaceout.resources.Models;
import com.bulletphysics.collision.dispatch.CollisionWorld.ClosestRayResultCallback;
import com.bulletphysics.collision.shapes.CollisionShape;
import com.bulletphysics.dynamics.RigidBody;
import com.bulletphysics.dynamics.RigidBodyConstructionInfo;
import com.bulletphysics.linearmath.DefaultMotionState;
import com.bulletphysics.linearmath.Transform;
/**
* And entity that also keeps track of it's own rigid body and model
*
* @author TranquilMarmot
*
*/
public class DynamicEntity extends Entity {
/** the rigid body for this entity */
public RigidBody rigidBody;
/** the model to use for this entity */
public Model model;
/**
* if this is true, the next time the entity is updated it is removed from
* the world
*/
public boolean removeFlag = false;
/**
* Overloaded constructor
*/
public DynamicEntity(Vector3f location, Quaternion rotation, Model model,
float mass, float restitution) {
this(location, rotation, model, mass, restitution,
CollisionTypes.NOTHING, CollisionTypes.NOTHING);
}
public DynamicEntity(Vector3f location, Quaternion rotation, Models model,
float mass, float restitution) {
this(location, rotation, model.getModel(), mass, restitution,
CollisionTypes.NOTHING, CollisionTypes.NOTHING);
}
public DynamicEntity(Vector3f location, Quaternion rotation, Models model,
float mass, float restitution, short collisionGroup,
short collidesWith) {
this(location, rotation, model.getModel(), mass, restitution,
collisionGroup, collidesWith);
}
/**
* Creates the entity and adds it to the dynamics world (but NOT to
* Entities.dynamicEntities)
*
* @param location
* Initial location of the entity
* @param rotation
* Initial rotation of the entity (<i>Be careful!</i> If the
* quaternion isn't right, i.e. not normalized, funny things will
* happen)
* @param model
* The {@link Model} for the entity
* @param mass
* The mass for the entity
* @param restitution
* The restitution (bounciness) of the entity
* @param collisionGroup
* which group from {@link CollisionTypes} this entity belongs to
*/
public DynamicEntity(Vector3f location, Quaternion rotation, Model model,
float mass, float restitution, short collisionGroup,
short collidesWith) {
// see Entity for location and rotation
this.location = location;
this.rotation = rotation;
this.model = model;
// the transform to use for putting the entity into the world
Transform transform = new Transform();
transform.setRotation(new Quat4f(rotation.x, rotation.y, rotation.z,
rotation.w));
transform.origin.set(location.x, location.y, location.z);
DefaultMotionState defaultState = new DefaultMotionState(transform);
// location to use for the entity (need a javax.vecmath Vector3f instead
// of the given org.lwjgl.util.vector Vector3f
javax.vecmath.Vector3f loca = new javax.vecmath.Vector3f(location.x,
location.y, location.z);
// the collision shape is made when the model is made
CollisionShape shape = model.getCollisionShape();
// no initial fall inertia (it isn't vital to set this)
javax.vecmath.Vector3f fallInertia = new javax.vecmath.Vector3f(0.0f,
0.0f, 0.0f);
shape.calculateLocalInertia(mass, fallInertia);
// create the rigid body based on all the stuff we've grabbed
RigidBodyConstructionInfo rigidBodyCI = new RigidBodyConstructionInfo(
mass, defaultState, shape, loca);
rigidBodyCI.restitution = restitution;
rigidBody = new RigidBody(rigidBodyCI);
// set the pointer so the entity can be updated (see
// DynamicEntityCallback)
rigidBody.setUserPointer(this);
// finally, add it to the world
if (collisionGroup != CollisionTypes.NOTHING
&& collidesWith != CollisionTypes.NOTHING)
Physics.dynamicsWorld.addRigidBody(rigidBody, collisionGroup,
collidesWith);
else
Physics.dynamicsWorld.addRigidBody(rigidBody);
}
public DynamicEntity(Vector3f location, Quaternion rotation, CollisionShape shape,
float mass, float restitution, short collisionGroup,
short collidesWith) {
// see Entity for location and rotation
this.location = location;
this.rotation = rotation;
// the transform to use for putting the entity into the world
Transform transform = new Transform();
transform.setRotation(new Quat4f(rotation.x, rotation.y, rotation.z,
rotation.w));
transform.origin.set(location.x, location.y, location.z);
DefaultMotionState defaultState = new DefaultMotionState(transform);
// location to use for the entity (need a javax.vecmath Vector3f instead
// of the given org.lwjgl.util.vector Vector3f
javax.vecmath.Vector3f loca = new javax.vecmath.Vector3f(location.x,
location.y, location.z);
// no initial fall inertia (it isn't vital to set this)
javax.vecmath.Vector3f fallInertia = new javax.vecmath.Vector3f(0.0f,
0.0f, 0.0f);
shape.calculateLocalInertia(mass, fallInertia);
// create the rigid body based on all the stuff we've grabbed
RigidBodyConstructionInfo rigidBodyCI = new RigidBodyConstructionInfo(
mass, defaultState, shape, loca);
rigidBodyCI.restitution = restitution;
rigidBody = new RigidBody(rigidBodyCI);
// set the pointer so the entity can be updated (see
// DynamicEntityCallback)
rigidBody.setUserPointer(this);
// finally, add it to the world
if (collisionGroup != CollisionTypes.NOTHING
&& collidesWith != CollisionTypes.NOTHING)
Physics.dynamicsWorld.addRigidBody(rigidBody, collisionGroup,
collidesWith);
else
Physics.dynamicsWorld.addRigidBody(rigidBody);
}
@Override
/**
* Simple as possible drawing call. This assumes that it's called when the entity's location and rotation have already been applied to the modelview matrix.
*/
public void draw() {
model.getTexture().texture().bind();
model.render();
}
/**
* Draws the physics debug info for this entity. Should be called before
* rotations are applied.
*/
public void drawPhysicsDebug() {
Transform worldTransform = new Transform();
rigidBody.getWorldTransform(worldTransform);
CollisionShape shape = model.getCollisionShape();
Physics.dynamicsWorld.debugDrawObject(worldTransform, shape,
new javax.vecmath.Vector3f(0.0f, 0.0f, 0.0f));
}
public ClosestRayResultCallback rayTest(Vector3f direction){
// rotate the direction we want to test so that it's realtive to the entity's rotation
Vector3f endRotated = QuaternionHelper.rotateVectorByQuaternion(direction, rotation);
Vector3f endAdd = new Vector3f();
// add the rotated direction to the current location to get the end vector
Vector3f.add(location, endRotated, endAdd);
javax.vecmath.Vector3f start = new javax.vecmath.Vector3f(location.x, location.y, location.z);
javax.vecmath.Vector3f end = new javax.vecmath.Vector3f(endAdd.x, endAdd.y, endAdd.z);
ClosestRayResultCallback callback = new ClosestRayResultCallback(start, end);
Physics.dynamicsWorld.rayTest(start, end, callback);
return callback;
}
@Override
/**
* Removes the rigid body from the dynamics world it's in
*/
public void cleanup() {
removeFlag = true;
}
@Override
/**
* Update the dynamic entity
* NOTE: If you're making your own class that extends DynamicEntity,
* you need to override this method!
*/
public void update(float timeStep){};
}