/*
|
* 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.");
|
}
|
|
}
|