ege/src/org/atriasoft/gameengine/engines/EnginePhysics.java

194 lines
6.5 KiB
Java

package org.atriasoft.gameengine.engines;
import java.util.Vector;
import org.atriasoft.etk.math.Vector3f;
import org.atriasoft.gale.resource.ResourceColored3DObject;
import org.atriasoft.gameengine.Component;
import org.atriasoft.gameengine.Engine;
import org.atriasoft.gameengine.Environement;
import org.atriasoft.gameengine.camera.Camera;
import org.atriasoft.gameengine.components.ComponentPhysics;
import org.atriasoft.gameengine.internal.Log;
import net.jreactphysics3d.constraint.ContactPointInfo;
import net.jreactphysics3d.engine.DynamicsWorld;
import net.jreactphysics3d.engine.EventListener;
public class EnginePhysics extends Engine implements EventListener {
public static final String ENGINE_NAME = "physics";
// Constant physics time step
private static final float TIME_STEP = 1.0f / 60.0f;
boolean propertyDebugAABB = false;
boolean propertyDebugShape = false;
// Start engine with no gravity
private final Vector3f gravity = new Vector3f(0.0f, 0.0f, 0.0f);
private float accumulator = 0;
//private final EngineGravity gravity;
private final DynamicsWorld dynamicsWorld;
private final Vector<ComponentPhysics> components = new Vector<ComponentPhysics>();
private final ResourceColored3DObject debugDrawProperty = ResourceColored3DObject.create();
public EnginePhysics(final Environement env) {
super(env);
/*
this.gravity = (EngineGravity) env.getEngine("gravity");
if (this.gravity == null) {
Log.critical("Must initialyse Gravity before physics...");
}
*/
final Vector3f gravity = new Vector3f(0.0f, 0.0f, 0.0f);
this.dynamicsWorld = new DynamicsWorld(gravity);
// Set the number of iterations of the constraint solver
this.dynamicsWorld.setNbIterationsVelocitySolver(15);
this.dynamicsWorld.setEventListener(this);
}
private void applyForces(final float timeStep) {
for (final ComponentPhysics it : this.components) {
//it.applyForces(TIME_STEP, gravity);
}
}
@Override
public void beginContact(final ContactPointInfo contact) {
ComponentPhysics component1 = null;
ComponentPhysics component2 = null;
// Called when a new contact point is found between two bodies that were separated before.
Log.warning("collision detection [BEGIN] " + contact.localPoint1 + " depth=" + contact.penetrationDepth);
if (contact.shape1 != null && contact.shape1.getUserData() != null) {
component1 = (ComponentPhysics) contact.shape1.getUserData();
}
if (contact.shape2 != null && contact.shape2.getUserData() != null) {
component2 = (ComponentPhysics) contact.shape2.getUserData();
}
if (component1 != null) {
component1.beginContact(component2, contact.normal, contact.localPoint1, contact.localPoint2, contact.penetrationDepth);
}
if (component2 != null) {
component2.beginContact(component1, contact.normal.multiplyNew(-1), contact.localPoint2, contact.localPoint1, contact.penetrationDepth);
}
}
@Override
public void beginInternalTick() {
// TODO Auto-generated method stub
}
@Override
public void componentAdd(final Component ref) {
if (ref instanceof ComponentPhysics == false) {
return;
}
final ComponentPhysics elem = (ComponentPhysics) ref;
this.components.add(elem);
elem.generate();
}
@Override
public void componentRemove(final Component ref) {
this.components.remove(ref);
}
@Override
public void endInternalTick() {
// TODO Auto-generated method stub
}
public DynamicsWorld getDynamicsWorld() {
return this.dynamicsWorld;
}
@Override
public String getType() {
// TODO Auto-generated method stub
return ENGINE_NAME;
}
@Override
public void newContact(final ContactPointInfo contact) {
ComponentPhysics component1 = null;
ComponentPhysics component2 = null;
//Called when a new contact point is found between two bodies.
Log.warning("collision detection [ NEW ] " + contact.localPoint1 + " depth=" + contact.penetrationDepth);
if (contact.shape1 != null && contact.shape1.getUserData() != null) {
component1 = (ComponentPhysics) contact.shape1.getUserData();
}
if (contact.shape2 != null && contact.shape2.getUserData() != null) {
component2 = (ComponentPhysics) contact.shape2.getUserData();
}
if (component1 != null) {
component1.newContact(component2, contact.normal, contact.localPoint1, contact.localPoint2, contact.penetrationDepth);
}
if (component2 != null) {
component2.newContact(component1, contact.normal.multiplyNew(-1), contact.localPoint2, contact.localPoint1, contact.penetrationDepth);
}
}
@Override
public void render(final long deltaMili, final Camera camera) {
// TODO Auto-generated method stub
for (final ComponentPhysics it : this.components) {
//Log.info("Render " + it);
it.renderDebug(this.debugDrawProperty, camera);
}
//debugDrawProperty.drawCone(2, 5, 9, 12, Matrix4f.identity(), new Color(1,1,0,1));
//debugDrawProperty.drawSquare(new Vector3f(1,1,1), Matrix4f.identity(), new Color(1,1,0,1));
//debugDrawProperty.drawCubeLine(new Vector3f(1,1,1), new Vector3f(5,5,5), new Color(1,0,1,1), Matrix4f.identity(), true, true);
//debugDrawProperty.drawCubeLine(new Vector3f(0,0,0), new Vector3f(32,32,32), new Color(1,0,1,1), Matrix4f.identity(), true, true);
}
@Override
public void renderDebug(final long deltaMili, final Camera camera) {
if (this.propertyDebugShape == true) {
for (final ComponentPhysics it : this.components) {
it.drawShape(this.debugDrawProperty, camera);
}
}
if (this.propertyDebugAABB == true) {
for (final ComponentPhysics it : this.components) {
it.renderDebug(this.debugDrawProperty, camera);
}
}
}
void setGravity(final Vector3f _axePower) {
if (this.dynamicsWorld != null) {
final Vector3f gravity = _axePower.clone();
this.dynamicsWorld.setGravity(gravity);
}
}
@Override
public void update(final long deltaMili) {
final float deltaTime = deltaMili * 0.0001f;
// Add the time difference in the accumulator
this.accumulator += deltaTime;
// While there is enough accumulated time to take one or several physics steps
while (this.accumulator >= TIME_STEP) {
if (this.dynamicsWorld != null) {
// call every object to usdate their constant forces applyed
for (final ComponentPhysics it : this.components) {
if (it != null) {
it.update(TIME_STEP);
}
}
// Update the Dynamics world with a constant time step
Log.debug("Update the Physic engine ... " + TIME_STEP);
this.dynamicsWorld.update(TIME_STEP);
}
// Decrease the accumulated time
this.accumulator -= TIME_STEP;
}
for (final ComponentPhysics elem : this.components) {
elem.emitAll();
}
}
}