/*
* Java port of Bullet (c) 2008 Martin Dvorak <jezek2@advel.cz>
*
* Bullet Continuous Collision Detection and Physics Library
* Copyright (c) 2003-2008 Erwin Coumans http://www.bulletphysics.com/
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from
* the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
package com.bulletphysics.dynamics;
import com.bulletphysics.collision.broadphase.BroadphaseInterface;
import com.bulletphysics.collision.broadphase.Dispatcher;
import com.bulletphysics.collision.broadphase.DispatcherInfo;
import com.bulletphysics.collision.dispatch.CollisionConfiguration;
import com.bulletphysics.collision.dispatch.CollisionDispatcher;
import com.bulletphysics.collision.dispatch.CollisionObject;
import com.bulletphysics.collision.narrowphase.PersistentManifold;
import com.bulletphysics.dynamics.constraintsolver.ConstraintSolver;
import com.bulletphysics.dynamics.constraintsolver.ContactSolverInfo;
import com.bulletphysics.linearmath.Transform;
import com.bulletphysics.util.ObjectArrayList;
import cz.advel.stack.Stack;
import javax.vecmath.Vector3f;
/**
* SimpleDynamicsWorld serves as unit-test and to verify more complicated and
* optimized dynamics worlds. Please use {@link DiscreteDynamicsWorld} instead
* (or ContinuousDynamicsWorld once it is finished).
*
* @author jezek2
*/
public class SimpleDynamicsWorld extends DynamicsWorld {
protected ConstraintSolver constraintSolver;
protected boolean ownsConstraintSolver;
protected final Vector3f gravity = new Vector3f(0f, 0f, -10f);
public SimpleDynamicsWorld(Dispatcher dispatcher, BroadphaseInterface pairCache, ConstraintSolver constraintSolver, CollisionConfiguration collisionConfiguration) {
super(dispatcher, pairCache, collisionConfiguration);
this.constraintSolver = constraintSolver;
this.ownsConstraintSolver = false;
}
protected void predictUnconstraintMotion(float timeStep) {
Transform tmpTrans = Stack.alloc(Transform.class);
for (int i = 0; i < collisionObjects.size(); i++) {
CollisionObject colObj = collisionObjects.getQuick(i);
RigidBody body = RigidBody.upcast(colObj);
if (body != null) {
if (!body.isStaticObject()) {
if (body.isActive()) {
body.applyGravity();
body.integrateVelocities(timeStep);
body.applyDamping(timeStep);
body.predictIntegratedTransform(timeStep, body.getInterpolationWorldTransform(tmpTrans));
}
}
}
}
}
protected void integrateTransforms(float timeStep) {
Transform predictedTrans = Stack.alloc(Transform.class);
for (int i = 0; i < collisionObjects.size(); i++) {
CollisionObject colObj = collisionObjects.getQuick(i);
RigidBody body = RigidBody.upcast(colObj);
if (body != null) {
if (body.isActive() && (!body.isStaticObject())) {
body.predictIntegratedTransform(timeStep, predictedTrans);
body.proceedToTransform(predictedTrans);
}
}
}
}
/**
* maxSubSteps/fixedTimeStep for interpolation is currently ignored for SimpleDynamicsWorld, use DiscreteDynamicsWorld instead.
*/
@Override
public int stepSimulation(float timeStep, int maxSubSteps, float fixedTimeStep) {
// apply gravity, predict motion
predictUnconstraintMotion(timeStep);
DispatcherInfo dispatchInfo = getDispatchInfo();
dispatchInfo.timeStep = timeStep;
dispatchInfo.stepCount = 0;
dispatchInfo.debugDraw = getDebugDrawer();
// perform collision detection
performDiscreteCollisionDetection();
// solve contact constraints
int numManifolds = dispatcher1.getNumManifolds();
if (numManifolds != 0)
{
ObjectArrayList<PersistentManifold> manifoldPtr = ((CollisionDispatcher)dispatcher1).getInternalManifoldPointer();
ContactSolverInfo infoGlobal = new ContactSolverInfo();
infoGlobal.timeStep = timeStep;
constraintSolver.prepareSolve(0,numManifolds);
constraintSolver.solveGroup(null,0,manifoldPtr, 0, numManifolds, null,0,0,infoGlobal,debugDrawer/*, m_stackAlloc*/,dispatcher1);
constraintSolver.allSolved(infoGlobal,debugDrawer/*, m_stackAlloc*/);
}
// integrate transforms
integrateTransforms(timeStep);
updateAabbs();
synchronizeMotionStates();
clearForces();
return 1;
}
@Override
public void clearForces() {
// todo: iterate over awake simulation islands!
for (int i = 0; i < collisionObjects.size(); i++) {
CollisionObject colObj = collisionObjects.getQuick(i);
RigidBody body = RigidBody.upcast(colObj);
if (body != null) {
body.clearForces();
}
}
}
@Override
public void setGravity(Vector3f gravity) {
this.gravity.set(gravity);
for (int i = 0; i < collisionObjects.size(); i++) {
CollisionObject colObj = collisionObjects.getQuick(i);
RigidBody body = RigidBody.upcast(colObj);
if (body != null) {
body.setGravity(gravity);
}
}
}
@Override
public Vector3f getGravity(Vector3f out) {
out.set(gravity);
return out;
}
@Override
public void addRigidBody(RigidBody body) {
body.setGravity(gravity);
if (body.getCollisionShape() != null) {
addCollisionObject(body);
}
}
@Override
public void removeRigidBody(RigidBody body) {
removeCollisionObject(body);
}
@Override
public void updateAabbs() {
Transform tmpTrans = Stack.alloc(Transform.class);
Transform predictedTrans = Stack.alloc(Transform.class);
Vector3f minAabb = Stack.alloc(Vector3f.class), maxAabb = Stack.alloc(Vector3f.class);
for (int i = 0; i < collisionObjects.size(); i++) {
CollisionObject colObj = collisionObjects.getQuick(i);
RigidBody body = RigidBody.upcast(colObj);
if (body != null) {
if (body.isActive() && (!body.isStaticObject())) {
colObj.getCollisionShape().getAabb(colObj.getWorldTransform(tmpTrans), minAabb, maxAabb);
BroadphaseInterface bp = getBroadphase();
bp.setAabb(body.getBroadphaseHandle(), minAabb, maxAabb, dispatcher1);
}
}
}
}
public void synchronizeMotionStates() {
Transform tmpTrans = Stack.alloc(Transform.class);
// todo: iterate over awake simulation islands!
for (int i = 0; i < collisionObjects.size(); i++) {
CollisionObject colObj = collisionObjects.getQuick(i);
RigidBody body = RigidBody.upcast(colObj);
if (body != null && body.getMotionState() != null) {
if (body.getActivationState() != CollisionObject.ISLAND_SLEEPING) {
body.getMotionState().setWorldTransform(body.getWorldTransform(tmpTrans));
}
}
}
}
@Override
public void setConstraintSolver(ConstraintSolver solver) {
if (ownsConstraintSolver) {
//btAlignedFree(m_constraintSolver);
}
ownsConstraintSolver = false;
constraintSolver = solver;
}
@Override
public ConstraintSolver getConstraintSolver() {
return constraintSolver;
}
@Override
public void debugDrawWorld() {
// TODO: throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public DynamicsWorldType getWorldType() {
throw new UnsupportedOperationException("Not supported yet.");
}
}