Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'extern/bullet2/BulletDynamics/Dynamics')
-rw-r--r--extern/bullet2/BulletDynamics/Dynamics/Bullet-C-API.cpp405
-rw-r--r--extern/bullet2/BulletDynamics/Dynamics/btActionInterface.h50
-rw-r--r--extern/bullet2/BulletDynamics/Dynamics/btContinuousDynamicsWorld.cpp196
-rw-r--r--extern/bullet2/BulletDynamics/Dynamics/btContinuousDynamicsWorld.h46
-rw-r--r--extern/bullet2/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp1161
-rw-r--r--extern/bullet2/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h198
-rw-r--r--extern/bullet2/BulletDynamics/Dynamics/btDynamicsWorld.h148
-rw-r--r--extern/bullet2/BulletDynamics/Dynamics/btRigidBody.cpp400
-rw-r--r--extern/bullet2/BulletDynamics/Dynamics/btRigidBody.h670
-rw-r--r--extern/bullet2/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp253
-rw-r--r--extern/bullet2/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h81
11 files changed, 3608 insertions, 0 deletions
diff --git a/extern/bullet2/BulletDynamics/Dynamics/Bullet-C-API.cpp b/extern/bullet2/BulletDynamics/Dynamics/Bullet-C-API.cpp
new file mode 100644
index 00000000000..bd8e2748383
--- /dev/null
+++ b/extern/bullet2/BulletDynamics/Dynamics/Bullet-C-API.cpp
@@ -0,0 +1,405 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+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.
+*/
+
+/*
+ Draft high-level generic physics C-API. For low-level access, use the physics SDK native API's.
+ Work in progress, functionality will be added on demand.
+
+ If possible, use the richer Bullet C++ API, by including <src/btBulletDynamicsCommon.h>
+*/
+
+#include "Bullet-C-Api.h"
+#include "btBulletDynamicsCommon.h"
+#include "LinearMath/btAlignedAllocator.h"
+
+
+
+#include "LinearMath/btVector3.h"
+#include "LinearMath/btScalar.h"
+#include "LinearMath/btMatrix3x3.h"
+#include "LinearMath/btTransform.h"
+#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
+#include "BulletCollision/CollisionShapes/btTriangleShape.h"
+
+#include "BulletCollision/NarrowPhaseCollision/btGjkPairDetector.h"
+#include "BulletCollision/NarrowPhaseCollision/btPointCollector.h"
+#include "BulletCollision/NarrowPhaseCollision/btVoronoiSimplexSolver.h"
+#include "BulletCollision/NarrowPhaseCollision/btSubSimplexConvexCast.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h"
+#include "BulletCollision/NarrowPhaseCollision/btGjkEpa2.h"
+#include "BulletCollision/CollisionShapes/btMinkowskiSumShape.h"
+#include "BulletCollision/NarrowPhaseCollision/btDiscreteCollisionDetectorInterface.h"
+#include "BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h"
+#include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h"
+
+
+/*
+ Create and Delete a Physics SDK
+*/
+
+struct btPhysicsSdk
+{
+
+// btDispatcher* m_dispatcher;
+// btOverlappingPairCache* m_pairCache;
+// btConstraintSolver* m_constraintSolver
+
+ btVector3 m_worldAabbMin;
+ btVector3 m_worldAabbMax;
+
+
+ //todo: version, hardware/optimization settings etc?
+ btPhysicsSdk()
+ :m_worldAabbMin(-1000,-1000,-1000),
+ m_worldAabbMax(1000,1000,1000)
+ {
+
+ }
+
+
+};
+
+plPhysicsSdkHandle plNewBulletSdk()
+{
+ void* mem = btAlignedAlloc(sizeof(btPhysicsSdk),16);
+ return (plPhysicsSdkHandle)new (mem)btPhysicsSdk;
+}
+
+void plDeletePhysicsSdk(plPhysicsSdkHandle physicsSdk)
+{
+ btPhysicsSdk* phys = reinterpret_cast<btPhysicsSdk*>(physicsSdk);
+ btAlignedFree(phys);
+}
+
+
+/* Dynamics World */
+plDynamicsWorldHandle plCreateDynamicsWorld(plPhysicsSdkHandle physicsSdkHandle)
+{
+ btPhysicsSdk* physicsSdk = reinterpret_cast<btPhysicsSdk*>(physicsSdkHandle);
+ void* mem = btAlignedAlloc(sizeof(btDefaultCollisionConfiguration),16);
+ btDefaultCollisionConfiguration* collisionConfiguration = new (mem)btDefaultCollisionConfiguration();
+ mem = btAlignedAlloc(sizeof(btCollisionDispatcher),16);
+ btDispatcher* dispatcher = new (mem)btCollisionDispatcher(collisionConfiguration);
+ mem = btAlignedAlloc(sizeof(btAxisSweep3),16);
+ btBroadphaseInterface* pairCache = new (mem)btAxisSweep3(physicsSdk->m_worldAabbMin,physicsSdk->m_worldAabbMax);
+ mem = btAlignedAlloc(sizeof(btSequentialImpulseConstraintSolver),16);
+ btConstraintSolver* constraintSolver = new(mem) btSequentialImpulseConstraintSolver();
+
+ mem = btAlignedAlloc(sizeof(btDiscreteDynamicsWorld),16);
+ return (plDynamicsWorldHandle) new (mem)btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver,collisionConfiguration);
+}
+void plDeleteDynamicsWorld(plDynamicsWorldHandle world)
+{
+ //todo: also clean up the other allocations, axisSweep, pairCache,dispatcher,constraintSolver,collisionConfiguration
+ btDynamicsWorld* dynamicsWorld = reinterpret_cast< btDynamicsWorld* >(world);
+ btAlignedFree(dynamicsWorld);
+}
+
+void plStepSimulation(plDynamicsWorldHandle world, plReal timeStep)
+{
+ btDynamicsWorld* dynamicsWorld = reinterpret_cast< btDynamicsWorld* >(world);
+ btAssert(dynamicsWorld);
+ dynamicsWorld->stepSimulation(timeStep);
+}
+
+void plAddRigidBody(plDynamicsWorldHandle world, plRigidBodyHandle object)
+{
+ btDynamicsWorld* dynamicsWorld = reinterpret_cast< btDynamicsWorld* >(world);
+ btAssert(dynamicsWorld);
+ btRigidBody* body = reinterpret_cast< btRigidBody* >(object);
+ btAssert(body);
+
+ dynamicsWorld->addRigidBody(body);
+}
+
+void plRemoveRigidBody(plDynamicsWorldHandle world, plRigidBodyHandle object)
+{
+ btDynamicsWorld* dynamicsWorld = reinterpret_cast< btDynamicsWorld* >(world);
+ btAssert(dynamicsWorld);
+ btRigidBody* body = reinterpret_cast< btRigidBody* >(object);
+ btAssert(body);
+
+ dynamicsWorld->removeRigidBody(body);
+}
+
+/* Rigid Body */
+
+plRigidBodyHandle plCreateRigidBody( void* user_data, float mass, plCollisionShapeHandle cshape )
+{
+ btTransform trans;
+ trans.setIdentity();
+ btVector3 localInertia(0,0,0);
+ btCollisionShape* shape = reinterpret_cast<btCollisionShape*>( cshape);
+ btAssert(shape);
+ if (mass)
+ {
+ shape->calculateLocalInertia(mass,localInertia);
+ }
+ void* mem = btAlignedAlloc(sizeof(btRigidBody),16);
+ btRigidBody::btRigidBodyConstructionInfo rbci(mass, 0,shape,localInertia);
+ btRigidBody* body = new (mem)btRigidBody(rbci);
+ body->setWorldTransform(trans);
+ body->setUserPointer(user_data);
+ return (plRigidBodyHandle) body;
+}
+
+void plDeleteRigidBody(plRigidBodyHandle cbody)
+{
+ btRigidBody* body = reinterpret_cast< btRigidBody* >(cbody);
+ btAssert(body);
+ btAlignedFree( body);
+}
+
+
+/* Collision Shape definition */
+
+plCollisionShapeHandle plNewSphereShape(plReal radius)
+{
+ void* mem = btAlignedAlloc(sizeof(btSphereShape),16);
+ return (plCollisionShapeHandle) new (mem)btSphereShape(radius);
+
+}
+
+plCollisionShapeHandle plNewBoxShape(plReal x, plReal y, plReal z)
+{
+ void* mem = btAlignedAlloc(sizeof(btBoxShape),16);
+ return (plCollisionShapeHandle) new (mem)btBoxShape(btVector3(x,y,z));
+}
+
+plCollisionShapeHandle plNewCapsuleShape(plReal radius, plReal height)
+{
+ //capsule is convex hull of 2 spheres, so use btMultiSphereShape
+
+ const int numSpheres = 2;
+ btVector3 positions[numSpheres] = {btVector3(0,height,0),btVector3(0,-height,0)};
+ btScalar radi[numSpheres] = {radius,radius};
+ void* mem = btAlignedAlloc(sizeof(btMultiSphereShape),16);
+ return (plCollisionShapeHandle) new (mem)btMultiSphereShape(positions,radi,numSpheres);
+}
+plCollisionShapeHandle plNewConeShape(plReal radius, plReal height)
+{
+ void* mem = btAlignedAlloc(sizeof(btConeShape),16);
+ return (plCollisionShapeHandle) new (mem)btConeShape(radius,height);
+}
+
+plCollisionShapeHandle plNewCylinderShape(plReal radius, plReal height)
+{
+ void* mem = btAlignedAlloc(sizeof(btCylinderShape),16);
+ return (plCollisionShapeHandle) new (mem)btCylinderShape(btVector3(radius,height,radius));
+}
+
+/* Convex Meshes */
+plCollisionShapeHandle plNewConvexHullShape()
+{
+ void* mem = btAlignedAlloc(sizeof(btConvexHullShape),16);
+ return (plCollisionShapeHandle) new (mem)btConvexHullShape();
+}
+
+
+/* Concave static triangle meshes */
+plMeshInterfaceHandle plNewMeshInterface()
+{
+ return 0;
+}
+
+plCollisionShapeHandle plNewCompoundShape()
+{
+ void* mem = btAlignedAlloc(sizeof(btCompoundShape),16);
+ return (plCollisionShapeHandle) new (mem)btCompoundShape();
+}
+
+void plAddChildShape(plCollisionShapeHandle compoundShapeHandle,plCollisionShapeHandle childShapeHandle, plVector3 childPos,plQuaternion childOrn)
+{
+ btCollisionShape* colShape = reinterpret_cast<btCollisionShape*>(compoundShapeHandle);
+ btAssert(colShape->getShapeType() == COMPOUND_SHAPE_PROXYTYPE);
+ btCompoundShape* compoundShape = reinterpret_cast<btCompoundShape*>(colShape);
+ btCollisionShape* childShape = reinterpret_cast<btCollisionShape*>(childShapeHandle);
+ btTransform localTrans;
+ localTrans.setIdentity();
+ localTrans.setOrigin(btVector3(childPos[0],childPos[1],childPos[2]));
+ localTrans.setRotation(btQuaternion(childOrn[0],childOrn[1],childOrn[2],childOrn[3]));
+ compoundShape->addChildShape(localTrans,childShape);
+}
+
+void plSetEuler(plReal yaw,plReal pitch,plReal roll, plQuaternion orient)
+{
+ btQuaternion orn;
+ orn.setEuler(yaw,pitch,roll);
+ orient[0] = orn.getX();
+ orient[1] = orn.getY();
+ orient[2] = orn.getZ();
+ orient[3] = orn.getW();
+
+}
+
+
+// extern void plAddTriangle(plMeshInterfaceHandle meshHandle, plVector3 v0,plVector3 v1,plVector3 v2);
+// extern plCollisionShapeHandle plNewStaticTriangleMeshShape(plMeshInterfaceHandle);
+
+
+void plAddVertex(plCollisionShapeHandle cshape, plReal x,plReal y,plReal z)
+{
+ btCollisionShape* colShape = reinterpret_cast<btCollisionShape*>( cshape);
+ (void)colShape;
+ btAssert(colShape->getShapeType()==CONVEX_HULL_SHAPE_PROXYTYPE);
+ btConvexHullShape* convexHullShape = reinterpret_cast<btConvexHullShape*>( cshape);
+ convexHullShape->addPoint(btVector3(x,y,z));
+
+}
+
+void plDeleteShape(plCollisionShapeHandle cshape)
+{
+ btCollisionShape* shape = reinterpret_cast<btCollisionShape*>( cshape);
+ btAssert(shape);
+ btAlignedFree(shape);
+}
+void plSetScaling(plCollisionShapeHandle cshape, plVector3 cscaling)
+{
+ btCollisionShape* shape = reinterpret_cast<btCollisionShape*>( cshape);
+ btAssert(shape);
+ btVector3 scaling(cscaling[0],cscaling[1],cscaling[2]);
+ shape->setLocalScaling(scaling);
+}
+
+
+
+void plSetPosition(plRigidBodyHandle object, const plVector3 position)
+{
+ btRigidBody* body = reinterpret_cast< btRigidBody* >(object);
+ btAssert(body);
+ btVector3 pos(position[0],position[1],position[2]);
+ btTransform worldTrans = body->getWorldTransform();
+ worldTrans.setOrigin(pos);
+ body->setWorldTransform(worldTrans);
+}
+
+void plSetOrientation(plRigidBodyHandle object, const plQuaternion orientation)
+{
+ btRigidBody* body = reinterpret_cast< btRigidBody* >(object);
+ btAssert(body);
+ btQuaternion orn(orientation[0],orientation[1],orientation[2],orientation[3]);
+ btTransform worldTrans = body->getWorldTransform();
+ worldTrans.setRotation(orn);
+ body->setWorldTransform(worldTrans);
+}
+
+void plSetOpenGLMatrix(plRigidBodyHandle object, plReal* matrix)
+{
+ btRigidBody* body = reinterpret_cast< btRigidBody* >(object);
+ btAssert(body);
+ btTransform& worldTrans = body->getWorldTransform();
+ worldTrans.setFromOpenGLMatrix(matrix);
+}
+
+void plGetOpenGLMatrix(plRigidBodyHandle object, plReal* matrix)
+{
+ btRigidBody* body = reinterpret_cast< btRigidBody* >(object);
+ btAssert(body);
+ body->getWorldTransform().getOpenGLMatrix(matrix);
+
+}
+
+void plGetPosition(plRigidBodyHandle object,plVector3 position)
+{
+ btRigidBody* body = reinterpret_cast< btRigidBody* >(object);
+ btAssert(body);
+ const btVector3& pos = body->getWorldTransform().getOrigin();
+ position[0] = pos.getX();
+ position[1] = pos.getY();
+ position[2] = pos.getZ();
+}
+
+void plGetOrientation(plRigidBodyHandle object,plQuaternion orientation)
+{
+ btRigidBody* body = reinterpret_cast< btRigidBody* >(object);
+ btAssert(body);
+ const btQuaternion& orn = body->getWorldTransform().getRotation();
+ orientation[0] = orn.getX();
+ orientation[1] = orn.getY();
+ orientation[2] = orn.getZ();
+ orientation[3] = orn.getW();
+}
+
+
+
+//plRigidBodyHandle plRayCast(plDynamicsWorldHandle world, const plVector3 rayStart, const plVector3 rayEnd, plVector3 hitpoint, plVector3 normal);
+
+// extern plRigidBodyHandle plObjectCast(plDynamicsWorldHandle world, const plVector3 rayStart, const plVector3 rayEnd, plVector3 hitpoint, plVector3 normal);
+
+double plNearestPoints(float p1[3], float p2[3], float p3[3], float q1[3], float q2[3], float q3[3], float *pa, float *pb, float normal[3])
+{
+ btVector3 vp(p1[0], p1[1], p1[2]);
+ btTriangleShape trishapeA(vp,
+ btVector3(p2[0], p2[1], p2[2]),
+ btVector3(p3[0], p3[1], p3[2]));
+ trishapeA.setMargin(0.000001f);
+ btVector3 vq(q1[0], q1[1], q1[2]);
+ btTriangleShape trishapeB(vq,
+ btVector3(q2[0], q2[1], q2[2]),
+ btVector3(q3[0], q3[1], q3[2]));
+ trishapeB.setMargin(0.000001f);
+
+ // btVoronoiSimplexSolver sGjkSimplexSolver;
+ // btGjkEpaPenetrationDepthSolver penSolverPtr;
+
+ static btSimplexSolverInterface sGjkSimplexSolver;
+ sGjkSimplexSolver.reset();
+
+ static btGjkEpaPenetrationDepthSolver Solver0;
+ static btMinkowskiPenetrationDepthSolver Solver1;
+
+ btConvexPenetrationDepthSolver* Solver = NULL;
+
+ Solver = &Solver1;
+
+ btGjkPairDetector convexConvex(&trishapeA ,&trishapeB,&sGjkSimplexSolver,Solver);
+
+ convexConvex.m_catchDegeneracies = 1;
+
+ // btGjkPairDetector convexConvex(&trishapeA ,&trishapeB,&sGjkSimplexSolver,0);
+
+ btPointCollector gjkOutput;
+ btGjkPairDetector::ClosestPointInput input;
+
+
+ btTransform tr;
+ tr.setIdentity();
+
+ input.m_transformA = tr;
+ input.m_transformB = tr;
+
+ convexConvex.getClosestPoints(input, gjkOutput, 0);
+
+
+ if (gjkOutput.m_hasResult)
+ {
+
+ pb[0] = pa[0] = gjkOutput.m_pointInWorld[0];
+ pb[1] = pa[1] = gjkOutput.m_pointInWorld[1];
+ pb[2] = pa[2] = gjkOutput.m_pointInWorld[2];
+
+ pb[0]+= gjkOutput.m_normalOnBInWorld[0] * gjkOutput.m_distance;
+ pb[1]+= gjkOutput.m_normalOnBInWorld[1] * gjkOutput.m_distance;
+ pb[2]+= gjkOutput.m_normalOnBInWorld[2] * gjkOutput.m_distance;
+
+ normal[0] = gjkOutput.m_normalOnBInWorld[0];
+ normal[1] = gjkOutput.m_normalOnBInWorld[1];
+ normal[2] = gjkOutput.m_normalOnBInWorld[2];
+
+ return gjkOutput.m_distance;
+ }
+ return -1.0f;
+}
+
diff --git a/extern/bullet2/BulletDynamics/Dynamics/btActionInterface.h b/extern/bullet2/BulletDynamics/Dynamics/btActionInterface.h
new file mode 100644
index 00000000000..40a07c6eae3
--- /dev/null
+++ b/extern/bullet2/BulletDynamics/Dynamics/btActionInterface.h
@@ -0,0 +1,50 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+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.
+*/
+
+#ifndef _BT_ACTION_INTERFACE_H
+#define _BT_ACTION_INTERFACE_H
+
+class btIDebugDraw;
+class btCollisionWorld;
+
+#include "LinearMath/btScalar.h"
+#include "btRigidBody.h"
+
+///Basic interface to allow actions such as vehicles and characters to be updated inside a btDynamicsWorld
+class btActionInterface
+{
+protected:
+
+ static btRigidBody& getFixedBody()
+ {
+ static btRigidBody s_fixed(0, 0,0);
+ s_fixed.setMassProps(btScalar(0.),btVector3(btScalar(0.),btScalar(0.),btScalar(0.)));
+ return s_fixed;
+ }
+
+public:
+
+ virtual ~btActionInterface()
+ {
+ }
+
+ virtual void updateAction( btCollisionWorld* collisionWorld, btScalar deltaTimeStep)=0;
+
+ virtual void debugDraw(btIDebugDraw* debugDrawer) = 0;
+
+};
+
+#endif //_BT_ACTION_INTERFACE_H
+
diff --git a/extern/bullet2/BulletDynamics/Dynamics/btContinuousDynamicsWorld.cpp b/extern/bullet2/BulletDynamics/Dynamics/btContinuousDynamicsWorld.cpp
new file mode 100644
index 00000000000..23501c4435e
--- /dev/null
+++ b/extern/bullet2/BulletDynamics/Dynamics/btContinuousDynamicsWorld.cpp
@@ -0,0 +1,196 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2007 Erwin Coumans http://continuousphysics.com/Bullet/
+
+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.
+*/
+
+
+#include "btContinuousDynamicsWorld.h"
+#include "LinearMath/btQuickprof.h"
+
+//collision detection
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h"
+#include "BulletCollision/CollisionShapes/btCollisionShape.h"
+#include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h"
+
+//rigidbody & constraints
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h"
+#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h"
+#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
+
+
+
+#include <stdio.h>
+
+btContinuousDynamicsWorld::btContinuousDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration)
+:btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver,collisionConfiguration)
+{
+}
+
+btContinuousDynamicsWorld::~btContinuousDynamicsWorld()
+{
+}
+
+
+void btContinuousDynamicsWorld::internalSingleStepSimulation( btScalar timeStep)
+{
+
+ startProfiling(timeStep);
+
+ if(0 != m_internalPreTickCallback) {
+ (*m_internalPreTickCallback)(this, timeStep);
+ }
+
+
+ ///update aabbs information
+ updateAabbs();
+ //static int frame=0;
+// printf("frame %d\n",frame++);
+
+ ///apply gravity, predict motion
+ predictUnconstraintMotion(timeStep);
+
+ btDispatcherInfo& dispatchInfo = getDispatchInfo();
+
+ dispatchInfo.m_timeStep = timeStep;
+ dispatchInfo.m_stepCount = 0;
+ dispatchInfo.m_debugDraw = getDebugDrawer();
+
+ ///perform collision detection
+ performDiscreteCollisionDetection();
+
+ calculateSimulationIslands();
+
+
+ getSolverInfo().m_timeStep = timeStep;
+
+
+
+ ///solve contact and other joint constraints
+ solveConstraints(getSolverInfo());
+
+ ///CallbackTriggers();
+ calculateTimeOfImpacts(timeStep);
+
+ btScalar toi = dispatchInfo.m_timeOfImpact;
+// if (toi < 1.f)
+// printf("toi = %f\n",toi);
+ if (toi < 0.f)
+ printf("toi = %f\n",toi);
+
+
+ ///integrate transforms
+ integrateTransforms(timeStep * toi);
+
+ ///update vehicle simulation
+ updateActions(timeStep);
+
+ updateActivationState( timeStep );
+
+ if(0 != m_internalTickCallback) {
+ (*m_internalTickCallback)(this, timeStep);
+ }
+}
+
+void btContinuousDynamicsWorld::calculateTimeOfImpacts(btScalar timeStep)
+{
+ ///these should be 'temporal' aabbs!
+ updateTemporalAabbs(timeStep);
+
+ ///'toi' is the global smallest time of impact. However, we just calculate the time of impact for each object individually.
+ ///so we handle the case moving versus static properly, and we cheat for moving versus moving
+ btScalar toi = 1.f;
+
+
+ btDispatcherInfo& dispatchInfo = getDispatchInfo();
+ dispatchInfo.m_timeStep = timeStep;
+ dispatchInfo.m_timeOfImpact = 1.f;
+ dispatchInfo.m_stepCount = 0;
+ dispatchInfo.m_dispatchFunc = btDispatcherInfo::DISPATCH_CONTINUOUS;
+
+ ///calculate time of impact for overlapping pairs
+
+
+ btDispatcher* dispatcher = getDispatcher();
+ if (dispatcher)
+ dispatcher->dispatchAllCollisionPairs(m_broadphasePairCache->getOverlappingPairCache(),dispatchInfo,m_dispatcher1);
+
+ toi = dispatchInfo.m_timeOfImpact;
+
+ dispatchInfo.m_dispatchFunc = btDispatcherInfo::DISPATCH_DISCRETE;
+
+}
+
+void btContinuousDynamicsWorld::updateTemporalAabbs(btScalar timeStep)
+{
+
+ btVector3 temporalAabbMin,temporalAabbMax;
+
+ for ( int i=0;i<m_collisionObjects.size();i++)
+ {
+ btCollisionObject* colObj = m_collisionObjects[i];
+
+ btRigidBody* body = btRigidBody::upcast(colObj);
+ if (body)
+ {
+ body->getCollisionShape()->getAabb(m_collisionObjects[i]->getWorldTransform(),temporalAabbMin,temporalAabbMax);
+ const btVector3& linvel = body->getLinearVelocity();
+
+ //make the AABB temporal
+ btScalar temporalAabbMaxx = temporalAabbMax.getX();
+ btScalar temporalAabbMaxy = temporalAabbMax.getY();
+ btScalar temporalAabbMaxz = temporalAabbMax.getZ();
+ btScalar temporalAabbMinx = temporalAabbMin.getX();
+ btScalar temporalAabbMiny = temporalAabbMin.getY();
+ btScalar temporalAabbMinz = temporalAabbMin.getZ();
+
+ // add linear motion
+ btVector3 linMotion = linvel*timeStep;
+
+ if (linMotion.x() > 0.f)
+ temporalAabbMaxx += linMotion.x();
+ else
+ temporalAabbMinx += linMotion.x();
+ if (linMotion.y() > 0.f)
+ temporalAabbMaxy += linMotion.y();
+ else
+ temporalAabbMiny += linMotion.y();
+ if (linMotion.z() > 0.f)
+ temporalAabbMaxz += linMotion.z();
+ else
+ temporalAabbMinz += linMotion.z();
+
+ //add conservative angular motion
+ btScalar angularMotion(0);// = angvel.length() * GetAngularMotionDisc() * timeStep;
+ btVector3 angularMotion3d(angularMotion,angularMotion,angularMotion);
+ temporalAabbMin = btVector3(temporalAabbMinx,temporalAabbMiny,temporalAabbMinz);
+ temporalAabbMax = btVector3(temporalAabbMaxx,temporalAabbMaxy,temporalAabbMaxz);
+
+ temporalAabbMin -= angularMotion3d;
+ temporalAabbMax += angularMotion3d;
+
+ m_broadphasePairCache->setAabb(body->getBroadphaseHandle(),temporalAabbMin,temporalAabbMax,m_dispatcher1);
+ }
+ }
+
+ //update aabb (of all moved objects)
+
+ m_broadphasePairCache->calculateOverlappingPairs(m_dispatcher1);
+
+
+
+}
+
+
+
diff --git a/extern/bullet2/BulletDynamics/Dynamics/btContinuousDynamicsWorld.h b/extern/bullet2/BulletDynamics/Dynamics/btContinuousDynamicsWorld.h
new file mode 100644
index 00000000000..61c8dea03eb
--- /dev/null
+++ b/extern/bullet2/BulletDynamics/Dynamics/btContinuousDynamicsWorld.h
@@ -0,0 +1,46 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2007 Erwin Coumans http://continuousphysics.com/Bullet/
+
+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.
+*/
+
+#ifndef BT_CONTINUOUS_DYNAMICS_WORLD_H
+#define BT_CONTINUOUS_DYNAMICS_WORLD_H
+
+#include "btDiscreteDynamicsWorld.h"
+
+///btContinuousDynamicsWorld adds optional (per object) continuous collision detection for fast moving objects to the btDiscreteDynamicsWorld.
+///This copes with fast moving objects that otherwise would tunnel/miss collisions.
+///Under construction, don't use yet! Please use btDiscreteDynamicsWorld instead.
+class btContinuousDynamicsWorld : public btDiscreteDynamicsWorld
+{
+
+ void updateTemporalAabbs(btScalar timeStep);
+
+ public:
+
+ btContinuousDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration);
+ virtual ~btContinuousDynamicsWorld();
+
+ ///time stepping with calculation of time of impact for selected fast moving objects
+ virtual void internalSingleStepSimulation( btScalar timeStep);
+
+ virtual void calculateTimeOfImpacts(btScalar timeStep);
+
+ virtual btDynamicsWorldType getWorldType() const
+ {
+ return BT_CONTINUOUS_DYNAMICS_WORLD;
+ }
+
+};
+
+#endif //BT_CONTINUOUS_DYNAMICS_WORLD_H
diff --git a/extern/bullet2/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp b/extern/bullet2/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp
new file mode 100644
index 00000000000..a88ed1cafa8
--- /dev/null
+++ b/extern/bullet2/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp
@@ -0,0 +1,1161 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
+
+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.
+*/
+
+
+#include "btDiscreteDynamicsWorld.h"
+
+//collision detection
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h"
+#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h"
+#include "BulletCollision/CollisionShapes/btCollisionShape.h"
+#include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h"
+#include "LinearMath/btTransformUtil.h"
+#include "LinearMath/btQuickprof.h"
+
+//rigidbody & constraints
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h"
+#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h"
+#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btHingeConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btConeTwistConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h"
+#include "BulletDynamics/ConstraintSolver/btSliderConstraint.h"
+
+#include "LinearMath/btIDebugDraw.h"
+#include "BulletCollision/CollisionShapes/btSphereShape.h"
+
+
+#include "BulletDynamics/Dynamics/btActionInterface.h"
+#include "LinearMath/btQuickprof.h"
+#include "LinearMath/btMotionState.h"
+
+#include "LinearMath/btSerializer.h"
+
+
+
+btDiscreteDynamicsWorld::btDiscreteDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver, btCollisionConfiguration* collisionConfiguration)
+:btDynamicsWorld(dispatcher,pairCache,collisionConfiguration),
+m_constraintSolver(constraintSolver),
+m_gravity(0,-10,0),
+m_localTime(btScalar(1.)/btScalar(60.)),
+m_synchronizeAllMotionStates(false),
+m_profileTimings(0)
+{
+ if (!m_constraintSolver)
+ {
+ void* mem = btAlignedAlloc(sizeof(btSequentialImpulseConstraintSolver),16);
+ m_constraintSolver = new (mem) btSequentialImpulseConstraintSolver;
+ m_ownsConstraintSolver = true;
+ } else
+ {
+ m_ownsConstraintSolver = false;
+ }
+
+ {
+ void* mem = btAlignedAlloc(sizeof(btSimulationIslandManager),16);
+ m_islandManager = new (mem) btSimulationIslandManager();
+ }
+
+ m_ownsIslandManager = true;
+}
+
+
+btDiscreteDynamicsWorld::~btDiscreteDynamicsWorld()
+{
+ //only delete it when we created it
+ if (m_ownsIslandManager)
+ {
+ m_islandManager->~btSimulationIslandManager();
+ btAlignedFree( m_islandManager);
+ }
+ if (m_ownsConstraintSolver)
+ {
+
+ m_constraintSolver->~btConstraintSolver();
+ btAlignedFree(m_constraintSolver);
+ }
+}
+
+void btDiscreteDynamicsWorld::saveKinematicState(btScalar timeStep)
+{
+///would like to iterate over m_nonStaticRigidBodies, but unfortunately old API allows
+///to switch status _after_ adding kinematic objects to the world
+///fix it for Bullet 3.x release
+ for (int i=0;i<m_collisionObjects.size();i++)
+ {
+ btCollisionObject* colObj = m_collisionObjects[i];
+ btRigidBody* body = btRigidBody::upcast(colObj);
+ if (body && body->getActivationState() != ISLAND_SLEEPING)
+ {
+ if (body->isKinematicObject())
+ {
+ //to calculate velocities next frame
+ body->saveKinematicState(timeStep);
+ }
+ }
+ }
+
+}
+
+void btDiscreteDynamicsWorld::debugDrawWorld()
+{
+ BT_PROFILE("debugDrawWorld");
+
+ btCollisionWorld::debugDrawWorld();
+
+ bool drawConstraints = false;
+ if (getDebugDrawer())
+ {
+ int mode = getDebugDrawer()->getDebugMode();
+ if(mode & (btIDebugDraw::DBG_DrawConstraints | btIDebugDraw::DBG_DrawConstraintLimits))
+ {
+ drawConstraints = true;
+ }
+ }
+ if(drawConstraints)
+ {
+ for(int i = getNumConstraints()-1; i>=0 ;i--)
+ {
+ btTypedConstraint* constraint = getConstraint(i);
+ debugDrawConstraint(constraint);
+ }
+ }
+
+
+
+ if (getDebugDrawer() && getDebugDrawer()->getDebugMode() & (btIDebugDraw::DBG_DrawWireframe | btIDebugDraw::DBG_DrawAabb))
+ {
+ int i;
+
+ if (getDebugDrawer() && getDebugDrawer()->getDebugMode())
+ {
+ for (i=0;i<m_actions.size();i++)
+ {
+ m_actions[i]->debugDraw(m_debugDrawer);
+ }
+ }
+ }
+}
+
+void btDiscreteDynamicsWorld::clearForces()
+{
+ ///@todo: iterate over awake simulation islands!
+ for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
+ {
+ btRigidBody* body = m_nonStaticRigidBodies[i];
+ //need to check if next line is ok
+ //it might break backward compatibility (people applying forces on sleeping objects get never cleared and accumulate on wake-up
+ body->clearForces();
+ }
+}
+
+///apply gravity, call this once per timestep
+void btDiscreteDynamicsWorld::applyGravity()
+{
+ ///@todo: iterate over awake simulation islands!
+ for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
+ {
+ btRigidBody* body = m_nonStaticRigidBodies[i];
+ if (body->isActive())
+ {
+ body->applyGravity();
+ }
+ }
+}
+
+
+void btDiscreteDynamicsWorld::synchronizeSingleMotionState(btRigidBody* body)
+{
+ btAssert(body);
+
+ if (body->getMotionState() && !body->isStaticOrKinematicObject())
+ {
+ //we need to call the update at least once, even for sleeping objects
+ //otherwise the 'graphics' transform never updates properly
+ ///@todo: add 'dirty' flag
+ //if (body->getActivationState() != ISLAND_SLEEPING)
+ {
+ btTransform interpolatedTransform;
+ btTransformUtil::integrateTransform(body->getInterpolationWorldTransform(),
+ body->getInterpolationLinearVelocity(),body->getInterpolationAngularVelocity(),m_localTime*body->getHitFraction(),interpolatedTransform);
+ body->getMotionState()->setWorldTransform(interpolatedTransform);
+ }
+ }
+}
+
+
+void btDiscreteDynamicsWorld::synchronizeMotionStates()
+{
+ BT_PROFILE("synchronizeMotionStates");
+ if (m_synchronizeAllMotionStates)
+ {
+ //iterate over all collision objects
+ for ( int i=0;i<m_collisionObjects.size();i++)
+ {
+ btCollisionObject* colObj = m_collisionObjects[i];
+ btRigidBody* body = btRigidBody::upcast(colObj);
+ if (body)
+ synchronizeSingleMotionState(body);
+ }
+ } else
+ {
+ //iterate over all active rigid bodies
+ for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
+ {
+ btRigidBody* body = m_nonStaticRigidBodies[i];
+ if (body->isActive())
+ synchronizeSingleMotionState(body);
+ }
+ }
+}
+
+
+int btDiscreteDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, btScalar fixedTimeStep)
+{
+ startProfiling(timeStep);
+
+ BT_PROFILE("stepSimulation");
+
+ int numSimulationSubSteps = 0;
+
+ if (maxSubSteps)
+ {
+ //fixed timestep with interpolation
+ m_localTime += timeStep;
+ if (m_localTime >= fixedTimeStep)
+ {
+ numSimulationSubSteps = int( m_localTime / fixedTimeStep);
+ m_localTime -= numSimulationSubSteps * fixedTimeStep;
+ }
+ } else
+ {
+ //variable timestep
+ fixedTimeStep = timeStep;
+ m_localTime = timeStep;
+ if (btFuzzyZero(timeStep))
+ {
+ numSimulationSubSteps = 0;
+ maxSubSteps = 0;
+ } else
+ {
+ numSimulationSubSteps = 1;
+ maxSubSteps = 1;
+ }
+ }
+
+ //process some debugging flags
+ if (getDebugDrawer())
+ {
+ btIDebugDraw* debugDrawer = getDebugDrawer ();
+ gDisableDeactivation = (debugDrawer->getDebugMode() & btIDebugDraw::DBG_NoDeactivation) != 0;
+ }
+ if (numSimulationSubSteps)
+ {
+
+ //clamp the number of substeps, to prevent simulation grinding spiralling down to a halt
+ int clampedSimulationSteps = (numSimulationSubSteps > maxSubSteps)? maxSubSteps : numSimulationSubSteps;
+
+ saveKinematicState(fixedTimeStep*clampedSimulationSteps);
+
+ applyGravity();
+
+
+
+ for (int i=0;i<clampedSimulationSteps;i++)
+ {
+ internalSingleStepSimulation(fixedTimeStep);
+ synchronizeMotionStates();
+ }
+
+ } else
+ {
+ synchronizeMotionStates();
+ }
+
+ clearForces();
+
+#ifndef BT_NO_PROFILE
+ CProfileManager::Increment_Frame_Counter();
+#endif //BT_NO_PROFILE
+
+ return numSimulationSubSteps;
+}
+
+void btDiscreteDynamicsWorld::internalSingleStepSimulation(btScalar timeStep)
+{
+
+ BT_PROFILE("internalSingleStepSimulation");
+
+ if(0 != m_internalPreTickCallback) {
+ (*m_internalPreTickCallback)(this, timeStep);
+ }
+
+ ///apply gravity, predict motion
+ predictUnconstraintMotion(timeStep);
+
+ btDispatcherInfo& dispatchInfo = getDispatchInfo();
+
+ dispatchInfo.m_timeStep = timeStep;
+ dispatchInfo.m_stepCount = 0;
+ dispatchInfo.m_debugDraw = getDebugDrawer();
+
+ ///perform collision detection
+ performDiscreteCollisionDetection();
+
+ calculateSimulationIslands();
+
+
+ getSolverInfo().m_timeStep = timeStep;
+
+
+
+ ///solve contact and other joint constraints
+ solveConstraints(getSolverInfo());
+
+ ///CallbackTriggers();
+
+ ///integrate transforms
+ integrateTransforms(timeStep);
+
+ ///update vehicle simulation
+ updateActions(timeStep);
+
+ updateActivationState( timeStep );
+
+ if(0 != m_internalTickCallback) {
+ (*m_internalTickCallback)(this, timeStep);
+ }
+}
+
+void btDiscreteDynamicsWorld::setGravity(const btVector3& gravity)
+{
+ m_gravity = gravity;
+ for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
+ {
+ btRigidBody* body = m_nonStaticRigidBodies[i];
+ if (body->isActive() && !(body->getFlags() &BT_DISABLE_WORLD_GRAVITY))
+ {
+ body->setGravity(gravity);
+ }
+ }
+}
+
+btVector3 btDiscreteDynamicsWorld::getGravity () const
+{
+ return m_gravity;
+}
+
+void btDiscreteDynamicsWorld::addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup,short int collisionFilterMask)
+{
+ btCollisionWorld::addCollisionObject(collisionObject,collisionFilterGroup,collisionFilterMask);
+}
+
+void btDiscreteDynamicsWorld::removeCollisionObject(btCollisionObject* collisionObject)
+{
+ btRigidBody* body = btRigidBody::upcast(collisionObject);
+ if (body)
+ removeRigidBody(body);
+ else
+ btCollisionWorld::removeCollisionObject(collisionObject);
+}
+
+void btDiscreteDynamicsWorld::removeRigidBody(btRigidBody* body)
+{
+ m_nonStaticRigidBodies.remove(body);
+ btCollisionWorld::removeCollisionObject(body);
+}
+
+
+void btDiscreteDynamicsWorld::addRigidBody(btRigidBody* body)
+{
+ if (!body->isStaticOrKinematicObject() && !(body->getFlags() &BT_DISABLE_WORLD_GRAVITY))
+ {
+ body->setGravity(m_gravity);
+ }
+
+ if (body->getCollisionShape())
+ {
+ if (!body->isStaticObject())
+ {
+ m_nonStaticRigidBodies.push_back(body);
+ } else
+ {
+ body->setActivationState(ISLAND_SLEEPING);
+ }
+
+ bool isDynamic = !(body->isStaticObject() || body->isKinematicObject());
+ short collisionFilterGroup = isDynamic? short(btBroadphaseProxy::DefaultFilter) : short(btBroadphaseProxy::StaticFilter);
+ short collisionFilterMask = isDynamic? short(btBroadphaseProxy::AllFilter) : short(btBroadphaseProxy::AllFilter ^ btBroadphaseProxy::StaticFilter);
+
+ addCollisionObject(body,collisionFilterGroup,collisionFilterMask);
+ }
+}
+
+void btDiscreteDynamicsWorld::addRigidBody(btRigidBody* body, short group, short mask)
+{
+ if (!body->isStaticOrKinematicObject() && !(body->getFlags() &BT_DISABLE_WORLD_GRAVITY))
+ {
+ body->setGravity(m_gravity);
+ }
+
+ if (body->getCollisionShape())
+ {
+ if (!body->isStaticObject())
+ {
+ m_nonStaticRigidBodies.push_back(body);
+ }
+ else
+ {
+ body->setActivationState(ISLAND_SLEEPING);
+ }
+ addCollisionObject(body,group,mask);
+ }
+}
+
+
+void btDiscreteDynamicsWorld::updateActions(btScalar timeStep)
+{
+ BT_PROFILE("updateActions");
+
+ for ( int i=0;i<m_actions.size();i++)
+ {
+ m_actions[i]->updateAction( this, timeStep);
+ }
+}
+
+
+void btDiscreteDynamicsWorld::updateActivationState(btScalar timeStep)
+{
+ BT_PROFILE("updateActivationState");
+
+ for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
+ {
+ btRigidBody* body = m_nonStaticRigidBodies[i];
+ if (body)
+ {
+ body->updateDeactivation(timeStep);
+
+ if (body->wantsSleeping())
+ {
+ if (body->isStaticOrKinematicObject())
+ {
+ body->setActivationState(ISLAND_SLEEPING);
+ } else
+ {
+ if (body->getActivationState() == ACTIVE_TAG)
+ body->setActivationState( WANTS_DEACTIVATION );
+ if (body->getActivationState() == ISLAND_SLEEPING)
+ {
+ body->setAngularVelocity(btVector3(0,0,0));
+ body->setLinearVelocity(btVector3(0,0,0));
+ }
+
+ }
+ } else
+ {
+ if (body->getActivationState() != DISABLE_DEACTIVATION)
+ body->setActivationState( ACTIVE_TAG );
+ }
+ }
+ }
+}
+
+void btDiscreteDynamicsWorld::addConstraint(btTypedConstraint* constraint,bool disableCollisionsBetweenLinkedBodies)
+{
+ m_constraints.push_back(constraint);
+ if (disableCollisionsBetweenLinkedBodies)
+ {
+ constraint->getRigidBodyA().addConstraintRef(constraint);
+ constraint->getRigidBodyB().addConstraintRef(constraint);
+ }
+}
+
+void btDiscreteDynamicsWorld::removeConstraint(btTypedConstraint* constraint)
+{
+ m_constraints.remove(constraint);
+ constraint->getRigidBodyA().removeConstraintRef(constraint);
+ constraint->getRigidBodyB().removeConstraintRef(constraint);
+}
+
+void btDiscreteDynamicsWorld::addAction(btActionInterface* action)
+{
+ m_actions.push_back(action);
+}
+
+void btDiscreteDynamicsWorld::removeAction(btActionInterface* action)
+{
+ m_actions.remove(action);
+}
+
+
+void btDiscreteDynamicsWorld::addVehicle(btActionInterface* vehicle)
+{
+ addAction(vehicle);
+}
+
+void btDiscreteDynamicsWorld::removeVehicle(btActionInterface* vehicle)
+{
+ removeAction(vehicle);
+}
+
+void btDiscreteDynamicsWorld::addCharacter(btActionInterface* character)
+{
+ addAction(character);
+}
+
+void btDiscreteDynamicsWorld::removeCharacter(btActionInterface* character)
+{
+ removeAction(character);
+}
+
+
+SIMD_FORCE_INLINE int btGetConstraintIslandId(const btTypedConstraint* lhs)
+{
+ int islandId;
+
+ const btCollisionObject& rcolObj0 = lhs->getRigidBodyA();
+ const btCollisionObject& rcolObj1 = lhs->getRigidBodyB();
+ islandId= rcolObj0.getIslandTag()>=0?rcolObj0.getIslandTag():rcolObj1.getIslandTag();
+ return islandId;
+
+}
+
+
+class btSortConstraintOnIslandPredicate
+{
+ public:
+
+ bool operator() ( const btTypedConstraint* lhs, const btTypedConstraint* rhs )
+ {
+ int rIslandId0,lIslandId0;
+ rIslandId0 = btGetConstraintIslandId(rhs);
+ lIslandId0 = btGetConstraintIslandId(lhs);
+ return lIslandId0 < rIslandId0;
+ }
+};
+
+
+
+void btDiscreteDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo)
+{
+ BT_PROFILE("solveConstraints");
+
+ struct InplaceSolverIslandCallback : public btSimulationIslandManager::IslandCallback
+ {
+
+ btContactSolverInfo& m_solverInfo;
+ btConstraintSolver* m_solver;
+ btTypedConstraint** m_sortedConstraints;
+ int m_numConstraints;
+ btIDebugDraw* m_debugDrawer;
+ btStackAlloc* m_stackAlloc;
+ btDispatcher* m_dispatcher;
+
+ btAlignedObjectArray<btCollisionObject*> m_bodies;
+ btAlignedObjectArray<btPersistentManifold*> m_manifolds;
+ btAlignedObjectArray<btTypedConstraint*> m_constraints;
+
+
+ InplaceSolverIslandCallback(
+ btContactSolverInfo& solverInfo,
+ btConstraintSolver* solver,
+ btTypedConstraint** sortedConstraints,
+ int numConstraints,
+ btIDebugDraw* debugDrawer,
+ btStackAlloc* stackAlloc,
+ btDispatcher* dispatcher)
+ :m_solverInfo(solverInfo),
+ m_solver(solver),
+ m_sortedConstraints(sortedConstraints),
+ m_numConstraints(numConstraints),
+ m_debugDrawer(debugDrawer),
+ m_stackAlloc(stackAlloc),
+ m_dispatcher(dispatcher)
+ {
+
+ }
+
+
+ InplaceSolverIslandCallback& operator=(InplaceSolverIslandCallback& other)
+ {
+ btAssert(0);
+ (void)other;
+ return *this;
+ }
+ virtual void ProcessIsland(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifolds,int numManifolds, int islandId)
+ {
+ if (islandId<0)
+ {
+ if (numManifolds + m_numConstraints)
+ {
+ ///we don't split islands, so all constraints/contact manifolds/bodies are passed into the solver regardless the island id
+ m_solver->solveGroup( bodies,numBodies,manifolds, numManifolds,&m_sortedConstraints[0],m_numConstraints,m_solverInfo,m_debugDrawer,m_stackAlloc,m_dispatcher);
+ }
+ } else
+ {
+ //also add all non-contact constraints/joints for this island
+ btTypedConstraint** startConstraint = 0;
+ int numCurConstraints = 0;
+ int i;
+
+ //find the first constraint for this island
+ for (i=0;i<m_numConstraints;i++)
+ {
+ if (btGetConstraintIslandId(m_sortedConstraints[i]) == islandId)
+ {
+ startConstraint = &m_sortedConstraints[i];
+ break;
+ }
+ }
+ //count the number of constraints in this island
+ for (;i<m_numConstraints;i++)
+ {
+ if (btGetConstraintIslandId(m_sortedConstraints[i]) == islandId)
+ {
+ numCurConstraints++;
+ }
+ }
+
+ if (m_solverInfo.m_minimumSolverBatchSize<=1)
+ {
+ ///only call solveGroup if there is some work: avoid virtual function call, its overhead can be excessive
+ if (numManifolds + numCurConstraints)
+ {
+ m_solver->solveGroup( bodies,numBodies,manifolds, numManifolds,startConstraint,numCurConstraints,m_solverInfo,m_debugDrawer,m_stackAlloc,m_dispatcher);
+ }
+ } else
+ {
+
+ for (i=0;i<numBodies;i++)
+ m_bodies.push_back(bodies[i]);
+ for (i=0;i<numManifolds;i++)
+ m_manifolds.push_back(manifolds[i]);
+ for (i=0;i<numCurConstraints;i++)
+ m_constraints.push_back(startConstraint[i]);
+ if ((m_constraints.size()+m_manifolds.size())>m_solverInfo.m_minimumSolverBatchSize)
+ {
+ processConstraints();
+ } else
+ {
+ //printf("deferred\n");
+ }
+ }
+ }
+ }
+ void processConstraints()
+ {
+ if (m_manifolds.size() + m_constraints.size()>0)
+ {
+ m_solver->solveGroup( &m_bodies[0],m_bodies.size(), &m_manifolds[0], m_manifolds.size(), &m_constraints[0], m_constraints.size() ,m_solverInfo,m_debugDrawer,m_stackAlloc,m_dispatcher);
+ }
+ m_bodies.resize(0);
+ m_manifolds.resize(0);
+ m_constraints.resize(0);
+
+ }
+
+ };
+
+
+
+ //sorted version of all btTypedConstraint, based on islandId
+ btAlignedObjectArray<btTypedConstraint*> sortedConstraints;
+ sortedConstraints.resize( m_constraints.size());
+ int i;
+ for (i=0;i<getNumConstraints();i++)
+ {
+ sortedConstraints[i] = m_constraints[i];
+ }
+
+// btAssert(0);
+
+
+
+ sortedConstraints.quickSort(btSortConstraintOnIslandPredicate());
+
+ btTypedConstraint** constraintsPtr = getNumConstraints() ? &sortedConstraints[0] : 0;
+
+ InplaceSolverIslandCallback solverCallback( solverInfo, m_constraintSolver, constraintsPtr,sortedConstraints.size(), m_debugDrawer,m_stackAlloc,m_dispatcher1);
+
+ m_constraintSolver->prepareSolve(getCollisionWorld()->getNumCollisionObjects(), getCollisionWorld()->getDispatcher()->getNumManifolds());
+
+ /// solve all the constraints for this island
+ m_islandManager->buildAndProcessIslands(getCollisionWorld()->getDispatcher(),getCollisionWorld(),&solverCallback);
+
+ solverCallback.processConstraints();
+
+ m_constraintSolver->allSolved(solverInfo, m_debugDrawer, m_stackAlloc);
+}
+
+
+
+
+void btDiscreteDynamicsWorld::calculateSimulationIslands()
+{
+ BT_PROFILE("calculateSimulationIslands");
+
+ getSimulationIslandManager()->updateActivationState(getCollisionWorld(),getCollisionWorld()->getDispatcher());
+
+ {
+ int i;
+ int numConstraints = int(m_constraints.size());
+ for (i=0;i< numConstraints ; i++ )
+ {
+ btTypedConstraint* constraint = m_constraints[i];
+
+ const btRigidBody* colObj0 = &constraint->getRigidBodyA();
+ const btRigidBody* colObj1 = &constraint->getRigidBodyB();
+
+ if (((colObj0) && (!(colObj0)->isStaticOrKinematicObject())) &&
+ ((colObj1) && (!(colObj1)->isStaticOrKinematicObject())))
+ {
+ if (colObj0->isActive() || colObj1->isActive())
+ {
+
+ getSimulationIslandManager()->getUnionFind().unite((colObj0)->getIslandTag(),
+ (colObj1)->getIslandTag());
+ }
+ }
+ }
+ }
+
+ //Store the island id in each body
+ getSimulationIslandManager()->storeIslandActivationState(getCollisionWorld());
+
+
+}
+
+
+
+
+class btClosestNotMeConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback
+{
+ btCollisionObject* m_me;
+ btScalar m_allowedPenetration;
+ btOverlappingPairCache* m_pairCache;
+ btDispatcher* m_dispatcher;
+
+
+public:
+ btClosestNotMeConvexResultCallback (btCollisionObject* me,const btVector3& fromA,const btVector3& toA,btOverlappingPairCache* pairCache,btDispatcher* dispatcher) :
+ btCollisionWorld::ClosestConvexResultCallback(fromA,toA),
+ m_me(me),
+ m_allowedPenetration(0.0f),
+ m_pairCache(pairCache),
+ m_dispatcher(dispatcher)
+ {
+ }
+
+ virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& convexResult,bool normalInWorldSpace)
+ {
+ if (convexResult.m_hitCollisionObject == m_me)
+ return 1.0f;
+
+ //ignore result if there is no contact response
+ if(!convexResult.m_hitCollisionObject->hasContactResponse())
+ return 1.0f;
+
+ btVector3 linVelA,linVelB;
+ linVelA = m_convexToWorld-m_convexFromWorld;
+ linVelB = btVector3(0,0,0);//toB.getOrigin()-fromB.getOrigin();
+
+ btVector3 relativeVelocity = (linVelA-linVelB);
+ //don't report time of impact for motion away from the contact normal (or causes minor penetration)
+ if (convexResult.m_hitNormalLocal.dot(relativeVelocity)>=-m_allowedPenetration)
+ return 1.f;
+
+ return ClosestConvexResultCallback::addSingleResult (convexResult, normalInWorldSpace);
+ }
+
+ virtual bool needsCollision(btBroadphaseProxy* proxy0) const
+ {
+ //don't collide with itself
+ if (proxy0->m_clientObject == m_me)
+ return false;
+
+ ///don't do CCD when the collision filters are not matching
+ if (!ClosestConvexResultCallback::needsCollision(proxy0))
+ return false;
+
+ btCollisionObject* otherObj = (btCollisionObject*) proxy0->m_clientObject;
+
+ //call needsResponse, see http://code.google.com/p/bullet/issues/detail?id=179
+ if (m_dispatcher->needsResponse(m_me,otherObj))
+ {
+ ///don't do CCD when there are already contact points (touching contact/penetration)
+ btAlignedObjectArray<btPersistentManifold*> manifoldArray;
+ btBroadphasePair* collisionPair = m_pairCache->findPair(m_me->getBroadphaseHandle(),proxy0);
+ if (collisionPair)
+ {
+ if (collisionPair->m_algorithm)
+ {
+ manifoldArray.resize(0);
+ collisionPair->m_algorithm->getAllContactManifolds(manifoldArray);
+ for (int j=0;j<manifoldArray.size();j++)
+ {
+ btPersistentManifold* manifold = manifoldArray[j];
+ if (manifold->getNumContacts()>0)
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+ }
+
+
+};
+
+///internal debugging variable. this value shouldn't be too high
+int gNumClampedCcdMotions=0;
+
+//#include "stdio.h"
+void btDiscreteDynamicsWorld::integrateTransforms(btScalar timeStep)
+{
+ BT_PROFILE("integrateTransforms");
+ btTransform predictedTrans;
+ for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
+ {
+ btRigidBody* body = m_nonStaticRigidBodies[i];
+ body->setHitFraction(1.f);
+
+ if (body->isActive() && (!body->isStaticOrKinematicObject()))
+ {
+ body->predictIntegratedTransform(timeStep, predictedTrans);
+ btScalar squareMotion = (predictedTrans.getOrigin()-body->getWorldTransform().getOrigin()).length2();
+
+ if (body->getCcdSquareMotionThreshold() && body->getCcdSquareMotionThreshold() < squareMotion)
+ {
+ BT_PROFILE("CCD motion clamping");
+ if (body->getCollisionShape()->isConvex())
+ {
+ gNumClampedCcdMotions++;
+
+ btClosestNotMeConvexResultCallback sweepResults(body,body->getWorldTransform().getOrigin(),predictedTrans.getOrigin(),getBroadphase()->getOverlappingPairCache(),getDispatcher());
+ //btConvexShape* convexShape = static_cast<btConvexShape*>(body->getCollisionShape());
+ btSphereShape tmpSphere(body->getCcdSweptSphereRadius());//btConvexShape* convexShape = static_cast<btConvexShape*>(body->getCollisionShape());
+
+ sweepResults.m_collisionFilterGroup = body->getBroadphaseProxy()->m_collisionFilterGroup;
+ sweepResults.m_collisionFilterMask = body->getBroadphaseProxy()->m_collisionFilterMask;
+
+ convexSweepTest(&tmpSphere,body->getWorldTransform(),predictedTrans,sweepResults);
+ if (sweepResults.hasHit() && (sweepResults.m_closestHitFraction < 1.f))
+ {
+ body->setHitFraction(sweepResults.m_closestHitFraction);
+ body->predictIntegratedTransform(timeStep*body->getHitFraction(), predictedTrans);
+ body->setHitFraction(0.f);
+// printf("clamped integration to hit fraction = %f\n",fraction);
+ }
+ }
+ }
+
+ body->proceedToTransform( predictedTrans);
+ }
+ }
+}
+
+
+
+
+
+void btDiscreteDynamicsWorld::predictUnconstraintMotion(btScalar timeStep)
+{
+ BT_PROFILE("predictUnconstraintMotion");
+ for ( int i=0;i<m_nonStaticRigidBodies.size();i++)
+ {
+ btRigidBody* body = m_nonStaticRigidBodies[i];
+ if (!body->isStaticOrKinematicObject())
+ {
+ body->integrateVelocities( timeStep);
+ //damping
+ body->applyDamping(timeStep);
+
+ body->predictIntegratedTransform(timeStep,body->getInterpolationWorldTransform());
+ }
+ }
+}
+
+
+void btDiscreteDynamicsWorld::startProfiling(btScalar timeStep)
+{
+ (void)timeStep;
+
+#ifndef BT_NO_PROFILE
+ CProfileManager::Reset();
+#endif //BT_NO_PROFILE
+
+}
+
+
+
+
+
+
+void btDiscreteDynamicsWorld::debugDrawConstraint(btTypedConstraint* constraint)
+{
+ bool drawFrames = (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawConstraints) != 0;
+ bool drawLimits = (getDebugDrawer()->getDebugMode() & btIDebugDraw::DBG_DrawConstraintLimits) != 0;
+ btScalar dbgDrawSize = constraint->getDbgDrawSize();
+ if(dbgDrawSize <= btScalar(0.f))
+ {
+ return;
+ }
+
+ switch(constraint->getConstraintType())
+ {
+ case POINT2POINT_CONSTRAINT_TYPE:
+ {
+ btPoint2PointConstraint* p2pC = (btPoint2PointConstraint*)constraint;
+ btTransform tr;
+ tr.setIdentity();
+ btVector3 pivot = p2pC->getPivotInA();
+ pivot = p2pC->getRigidBodyA().getCenterOfMassTransform() * pivot;
+ tr.setOrigin(pivot);
+ getDebugDrawer()->drawTransform(tr, dbgDrawSize);
+ // that ideally should draw the same frame
+ pivot = p2pC->getPivotInB();
+ pivot = p2pC->getRigidBodyB().getCenterOfMassTransform() * pivot;
+ tr.setOrigin(pivot);
+ if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
+ }
+ break;
+ case HINGE_CONSTRAINT_TYPE:
+ {
+ btHingeConstraint* pHinge = (btHingeConstraint*)constraint;
+ btTransform tr = pHinge->getRigidBodyA().getCenterOfMassTransform() * pHinge->getAFrame();
+ if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
+ tr = pHinge->getRigidBodyB().getCenterOfMassTransform() * pHinge->getBFrame();
+ if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
+ btScalar minAng = pHinge->getLowerLimit();
+ btScalar maxAng = pHinge->getUpperLimit();
+ if(minAng == maxAng)
+ {
+ break;
+ }
+ bool drawSect = true;
+ if(minAng > maxAng)
+ {
+ minAng = btScalar(0.f);
+ maxAng = SIMD_2_PI;
+ drawSect = false;
+ }
+ if(drawLimits)
+ {
+ btVector3& center = tr.getOrigin();
+ btVector3 normal = tr.getBasis().getColumn(2);
+ btVector3 axis = tr.getBasis().getColumn(0);
+ getDebugDrawer()->drawArc(center, normal, axis, dbgDrawSize, dbgDrawSize, minAng, maxAng, btVector3(0,0,0), drawSect);
+ }
+ }
+ break;
+ case CONETWIST_CONSTRAINT_TYPE:
+ {
+ btConeTwistConstraint* pCT = (btConeTwistConstraint*)constraint;
+ btTransform tr = pCT->getRigidBodyA().getCenterOfMassTransform() * pCT->getAFrame();
+ if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
+ tr = pCT->getRigidBodyB().getCenterOfMassTransform() * pCT->getBFrame();
+ if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
+ if(drawLimits)
+ {
+ //const btScalar length = btScalar(5);
+ const btScalar length = dbgDrawSize;
+ static int nSegments = 8*4;
+ btScalar fAngleInRadians = btScalar(2.*3.1415926) * (btScalar)(nSegments-1)/btScalar(nSegments);
+ btVector3 pPrev = pCT->GetPointForAngle(fAngleInRadians, length);
+ pPrev = tr * pPrev;
+ for (int i=0; i<nSegments; i++)
+ {
+ fAngleInRadians = btScalar(2.*3.1415926) * (btScalar)i/btScalar(nSegments);
+ btVector3 pCur = pCT->GetPointForAngle(fAngleInRadians, length);
+ pCur = tr * pCur;
+ getDebugDrawer()->drawLine(pPrev, pCur, btVector3(0,0,0));
+
+ if (i%(nSegments/8) == 0)
+ getDebugDrawer()->drawLine(tr.getOrigin(), pCur, btVector3(0,0,0));
+
+ pPrev = pCur;
+ }
+ btScalar tws = pCT->getTwistSpan();
+ btScalar twa = pCT->getTwistAngle();
+ bool useFrameB = (pCT->getRigidBodyB().getInvMass() > btScalar(0.f));
+ if(useFrameB)
+ {
+ tr = pCT->getRigidBodyB().getCenterOfMassTransform() * pCT->getBFrame();
+ }
+ else
+ {
+ tr = pCT->getRigidBodyA().getCenterOfMassTransform() * pCT->getAFrame();
+ }
+ btVector3 pivot = tr.getOrigin();
+ btVector3 normal = tr.getBasis().getColumn(0);
+ btVector3 axis1 = tr.getBasis().getColumn(1);
+ getDebugDrawer()->drawArc(pivot, normal, axis1, dbgDrawSize, dbgDrawSize, -twa-tws, -twa+tws, btVector3(0,0,0), true);
+
+ }
+ }
+ break;
+ case D6_CONSTRAINT_TYPE:
+ {
+ btGeneric6DofConstraint* p6DOF = (btGeneric6DofConstraint*)constraint;
+ btTransform tr = p6DOF->getCalculatedTransformA();
+ if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
+ tr = p6DOF->getCalculatedTransformB();
+ if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
+ if(drawLimits)
+ {
+ tr = p6DOF->getCalculatedTransformA();
+ const btVector3& center = p6DOF->getCalculatedTransformB().getOrigin();
+ btVector3 up = tr.getBasis().getColumn(2);
+ btVector3 axis = tr.getBasis().getColumn(0);
+ btScalar minTh = p6DOF->getRotationalLimitMotor(1)->m_loLimit;
+ btScalar maxTh = p6DOF->getRotationalLimitMotor(1)->m_hiLimit;
+ btScalar minPs = p6DOF->getRotationalLimitMotor(2)->m_loLimit;
+ btScalar maxPs = p6DOF->getRotationalLimitMotor(2)->m_hiLimit;
+ getDebugDrawer()->drawSpherePatch(center, up, axis, dbgDrawSize * btScalar(.9f), minTh, maxTh, minPs, maxPs, btVector3(0,0,0));
+ axis = tr.getBasis().getColumn(1);
+ btScalar ay = p6DOF->getAngle(1);
+ btScalar az = p6DOF->getAngle(2);
+ btScalar cy = btCos(ay);
+ btScalar sy = btSin(ay);
+ btScalar cz = btCos(az);
+ btScalar sz = btSin(az);
+ btVector3 ref;
+ ref[0] = cy*cz*axis[0] + cy*sz*axis[1] - sy*axis[2];
+ ref[1] = -sz*axis[0] + cz*axis[1];
+ ref[2] = cz*sy*axis[0] + sz*sy*axis[1] + cy*axis[2];
+ tr = p6DOF->getCalculatedTransformB();
+ btVector3 normal = -tr.getBasis().getColumn(0);
+ btScalar minFi = p6DOF->getRotationalLimitMotor(0)->m_loLimit;
+ btScalar maxFi = p6DOF->getRotationalLimitMotor(0)->m_hiLimit;
+ if(minFi > maxFi)
+ {
+ getDebugDrawer()->drawArc(center, normal, ref, dbgDrawSize, dbgDrawSize, -SIMD_PI, SIMD_PI, btVector3(0,0,0), false);
+ }
+ else if(minFi < maxFi)
+ {
+ getDebugDrawer()->drawArc(center, normal, ref, dbgDrawSize, dbgDrawSize, minFi, maxFi, btVector3(0,0,0), true);
+ }
+ tr = p6DOF->getCalculatedTransformA();
+ btVector3 bbMin = p6DOF->getTranslationalLimitMotor()->m_lowerLimit;
+ btVector3 bbMax = p6DOF->getTranslationalLimitMotor()->m_upperLimit;
+ getDebugDrawer()->drawBox(bbMin, bbMax, tr, btVector3(0,0,0));
+ }
+ }
+ break;
+ case SLIDER_CONSTRAINT_TYPE:
+ {
+ btSliderConstraint* pSlider = (btSliderConstraint*)constraint;
+ btTransform tr = pSlider->getCalculatedTransformA();
+ if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
+ tr = pSlider->getCalculatedTransformB();
+ if(drawFrames) getDebugDrawer()->drawTransform(tr, dbgDrawSize);
+ if(drawLimits)
+ {
+ btTransform tr = pSlider->getUseLinearReferenceFrameA() ? pSlider->getCalculatedTransformA() : pSlider->getCalculatedTransformB();
+ btVector3 li_min = tr * btVector3(pSlider->getLowerLinLimit(), 0.f, 0.f);
+ btVector3 li_max = tr * btVector3(pSlider->getUpperLinLimit(), 0.f, 0.f);
+ getDebugDrawer()->drawLine(li_min, li_max, btVector3(0, 0, 0));
+ btVector3 normal = tr.getBasis().getColumn(0);
+ btVector3 axis = tr.getBasis().getColumn(1);
+ btScalar a_min = pSlider->getLowerAngLimit();
+ btScalar a_max = pSlider->getUpperAngLimit();
+ const btVector3& center = pSlider->getCalculatedTransformB().getOrigin();
+ getDebugDrawer()->drawArc(center, normal, axis, dbgDrawSize, dbgDrawSize, a_min, a_max, btVector3(0,0,0), true);
+ }
+ }
+ break;
+ default :
+ break;
+ }
+ return;
+}
+
+
+
+
+
+void btDiscreteDynamicsWorld::setConstraintSolver(btConstraintSolver* solver)
+{
+ if (m_ownsConstraintSolver)
+ {
+ btAlignedFree( m_constraintSolver);
+ }
+ m_ownsConstraintSolver = false;
+ m_constraintSolver = solver;
+}
+
+btConstraintSolver* btDiscreteDynamicsWorld::getConstraintSolver()
+{
+ return m_constraintSolver;
+}
+
+
+int btDiscreteDynamicsWorld::getNumConstraints() const
+{
+ return int(m_constraints.size());
+}
+btTypedConstraint* btDiscreteDynamicsWorld::getConstraint(int index)
+{
+ return m_constraints[index];
+}
+const btTypedConstraint* btDiscreteDynamicsWorld::getConstraint(int index) const
+{
+ return m_constraints[index];
+}
+
+
+
+void btDiscreteDynamicsWorld::serializeRigidBodies(btSerializer* serializer)
+{
+ int i;
+ //serialize all collision objects
+ for (i=0;i<m_collisionObjects.size();i++)
+ {
+ btCollisionObject* colObj = m_collisionObjects[i];
+ if (colObj->getInternalType() == btCollisionObject::CO_RIGID_BODY)
+ {
+ int len = colObj->calculateSerializeBufferSize();
+ btChunk* chunk = serializer->allocate(len,1);
+ const char* structType = colObj->serialize(chunk->m_oldPtr, serializer);
+ serializer->finalizeChunk(chunk,structType,BT_RIGIDBODY_CODE,colObj);
+ }
+ }
+
+ for (i=0;i<m_constraints.size();i++)
+ {
+ btTypedConstraint* constraint = m_constraints[i];
+ int size = constraint->calculateSerializeBufferSize();
+ btChunk* chunk = serializer->allocate(size,1);
+ const char* structType = constraint->serialize(chunk->m_oldPtr,serializer);
+ serializer->finalizeChunk(chunk,structType,BT_CONSTRAINT_CODE,constraint);
+ }
+}
+
+
+void btDiscreteDynamicsWorld::serialize(btSerializer* serializer)
+{
+
+ serializer->startSerialization();
+
+ serializeRigidBodies(serializer);
+
+ serializeCollisionObjects(serializer);
+
+ serializer->finishSerialization();
+}
+
diff --git a/extern/bullet2/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h b/extern/bullet2/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h
new file mode 100644
index 00000000000..df47c29044f
--- /dev/null
+++ b/extern/bullet2/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h
@@ -0,0 +1,198 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2009 Erwin Coumans http://bulletphysics.org
+
+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.
+*/
+
+
+#ifndef BT_DISCRETE_DYNAMICS_WORLD_H
+#define BT_DISCRETE_DYNAMICS_WORLD_H
+
+#include "btDynamicsWorld.h"
+
+class btDispatcher;
+class btOverlappingPairCache;
+class btConstraintSolver;
+class btSimulationIslandManager;
+class btTypedConstraint;
+class btActionInterface;
+
+class btIDebugDraw;
+#include "LinearMath/btAlignedObjectArray.h"
+
+
+///btDiscreteDynamicsWorld provides discrete rigid body simulation
+///those classes replace the obsolete CcdPhysicsEnvironment/CcdPhysicsController
+class btDiscreteDynamicsWorld : public btDynamicsWorld
+{
+protected:
+
+ btConstraintSolver* m_constraintSolver;
+
+ btSimulationIslandManager* m_islandManager;
+
+ btAlignedObjectArray<btTypedConstraint*> m_constraints;
+
+ btAlignedObjectArray<btRigidBody*> m_nonStaticRigidBodies;
+
+ btVector3 m_gravity;
+
+ //for variable timesteps
+ btScalar m_localTime;
+ //for variable timesteps
+
+ bool m_ownsIslandManager;
+ bool m_ownsConstraintSolver;
+ bool m_synchronizeAllMotionStates;
+
+ btAlignedObjectArray<btActionInterface*> m_actions;
+
+ int m_profileTimings;
+
+ virtual void predictUnconstraintMotion(btScalar timeStep);
+
+ virtual void integrateTransforms(btScalar timeStep);
+
+ virtual void calculateSimulationIslands();
+
+ virtual void solveConstraints(btContactSolverInfo& solverInfo);
+
+ void updateActivationState(btScalar timeStep);
+
+ void updateActions(btScalar timeStep);
+
+ void startProfiling(btScalar timeStep);
+
+ virtual void internalSingleStepSimulation( btScalar timeStep);
+
+
+ virtual void saveKinematicState(btScalar timeStep);
+
+ void serializeRigidBodies(btSerializer* serializer);
+
+public:
+
+
+ ///this btDiscreteDynamicsWorld constructor gets created objects from the user, and will not delete those
+ btDiscreteDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration);
+
+ virtual ~btDiscreteDynamicsWorld();
+
+ ///if maxSubSteps > 0, it will interpolate motion between fixedTimeStep's
+ virtual int stepSimulation( btScalar timeStep,int maxSubSteps=1, btScalar fixedTimeStep=btScalar(1.)/btScalar(60.));
+
+
+ virtual void synchronizeMotionStates();
+
+ ///this can be useful to synchronize a single rigid body -> graphics object
+ void synchronizeSingleMotionState(btRigidBody* body);
+
+ virtual void addConstraint(btTypedConstraint* constraint, bool disableCollisionsBetweenLinkedBodies=false);
+
+ virtual void removeConstraint(btTypedConstraint* constraint);
+
+ virtual void addAction(btActionInterface*);
+
+ virtual void removeAction(btActionInterface*);
+
+ btSimulationIslandManager* getSimulationIslandManager()
+ {
+ return m_islandManager;
+ }
+
+ const btSimulationIslandManager* getSimulationIslandManager() const
+ {
+ return m_islandManager;
+ }
+
+ btCollisionWorld* getCollisionWorld()
+ {
+ return this;
+ }
+
+ virtual void setGravity(const btVector3& gravity);
+
+ virtual btVector3 getGravity () const;
+
+ virtual void addCollisionObject(btCollisionObject* collisionObject,short int collisionFilterGroup=btBroadphaseProxy::StaticFilter,short int collisionFilterMask=btBroadphaseProxy::AllFilter ^ btBroadphaseProxy::StaticFilter);
+
+ virtual void addRigidBody(btRigidBody* body);
+
+ virtual void addRigidBody(btRigidBody* body, short group, short mask);
+
+ virtual void removeRigidBody(btRigidBody* body);
+
+ ///removeCollisionObject will first check if it is a rigid body, if so call removeRigidBody otherwise call btCollisionWorld::removeCollisionObject
+ virtual void removeCollisionObject(btCollisionObject* collisionObject);
+
+
+ void debugDrawConstraint(btTypedConstraint* constraint);
+
+ virtual void debugDrawWorld();
+
+ virtual void setConstraintSolver(btConstraintSolver* solver);
+
+ virtual btConstraintSolver* getConstraintSolver();
+
+ virtual int getNumConstraints() const;
+
+ virtual btTypedConstraint* getConstraint(int index) ;
+
+ virtual const btTypedConstraint* getConstraint(int index) const;
+
+
+ virtual btDynamicsWorldType getWorldType() const
+ {
+ return BT_DISCRETE_DYNAMICS_WORLD;
+ }
+
+ ///the forces on each rigidbody is accumulating together with gravity. clear this after each timestep.
+ virtual void clearForces();
+
+ ///apply gravity, call this once per timestep
+ virtual void applyGravity();
+
+ virtual void setNumTasks(int numTasks)
+ {
+ (void) numTasks;
+ }
+
+ ///obsolete, use updateActions instead
+ virtual void updateVehicles(btScalar timeStep)
+ {
+ updateActions(timeStep);
+ }
+
+ ///obsolete, use addAction instead
+ virtual void addVehicle(btActionInterface* vehicle);
+ ///obsolete, use removeAction instead
+ virtual void removeVehicle(btActionInterface* vehicle);
+ ///obsolete, use addAction instead
+ virtual void addCharacter(btActionInterface* character);
+ ///obsolete, use removeAction instead
+ virtual void removeCharacter(btActionInterface* character);
+
+ void setSynchronizeAllMotionStates(bool synchronizeAll)
+ {
+ m_synchronizeAllMotionStates = synchronizeAll;
+ }
+ bool getSynchronizeAllMotionStates() const
+ {
+ return m_synchronizeAllMotionStates;
+ }
+
+ ///Preliminary serialization test for Bullet 2.76. Loading those files requires a separate parser (see Bullet/Demos/SerializeDemo)
+ virtual void serialize(btSerializer* serializer);
+
+};
+
+#endif //BT_DISCRETE_DYNAMICS_WORLD_H
diff --git a/extern/bullet2/BulletDynamics/Dynamics/btDynamicsWorld.h b/extern/bullet2/BulletDynamics/Dynamics/btDynamicsWorld.h
new file mode 100644
index 00000000000..a7b85afbec9
--- /dev/null
+++ b/extern/bullet2/BulletDynamics/Dynamics/btDynamicsWorld.h
@@ -0,0 +1,148 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+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.
+*/
+
+#ifndef BT_DYNAMICS_WORLD_H
+#define BT_DYNAMICS_WORLD_H
+
+#include "BulletCollision/CollisionDispatch/btCollisionWorld.h"
+#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h"
+
+class btTypedConstraint;
+class btActionInterface;
+class btConstraintSolver;
+class btDynamicsWorld;
+
+
+/// Type for the callback for each tick
+typedef void (*btInternalTickCallback)(btDynamicsWorld *world, btScalar timeStep);
+
+enum btDynamicsWorldType
+{
+ BT_SIMPLE_DYNAMICS_WORLD=1,
+ BT_DISCRETE_DYNAMICS_WORLD=2,
+ BT_CONTINUOUS_DYNAMICS_WORLD=3
+};
+
+///The btDynamicsWorld is the interface class for several dynamics implementation, basic, discrete, parallel, and continuous etc.
+class btDynamicsWorld : public btCollisionWorld
+{
+
+protected:
+ btInternalTickCallback m_internalTickCallback;
+ btInternalTickCallback m_internalPreTickCallback;
+ void* m_worldUserInfo;
+
+ btContactSolverInfo m_solverInfo;
+
+public:
+
+
+ btDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* broadphase,btCollisionConfiguration* collisionConfiguration)
+ :btCollisionWorld(dispatcher,broadphase,collisionConfiguration), m_internalTickCallback(0),m_internalPreTickCallback(0), m_worldUserInfo(0)
+ {
+ }
+
+ virtual ~btDynamicsWorld()
+ {
+ }
+
+ ///stepSimulation proceeds the simulation over 'timeStep', units in preferably in seconds.
+ ///By default, Bullet will subdivide the timestep in constant substeps of each 'fixedTimeStep'.
+ ///in order to keep the simulation real-time, the maximum number of substeps can be clamped to 'maxSubSteps'.
+ ///You can disable subdividing the timestep/substepping by passing maxSubSteps=0 as second argument to stepSimulation, but in that case you have to keep the timeStep constant.
+ virtual int stepSimulation( btScalar timeStep,int maxSubSteps=1, btScalar fixedTimeStep=btScalar(1.)/btScalar(60.))=0;
+
+ virtual void debugDrawWorld() = 0;
+
+ virtual void addConstraint(btTypedConstraint* constraint, bool disableCollisionsBetweenLinkedBodies=false)
+ {
+ (void)constraint; (void)disableCollisionsBetweenLinkedBodies;
+ }
+
+ virtual void removeConstraint(btTypedConstraint* constraint) {(void)constraint;}
+
+ virtual void addAction(btActionInterface* action) = 0;
+
+ virtual void removeAction(btActionInterface* action) = 0;
+
+ //once a rigidbody is added to the dynamics world, it will get this gravity assigned
+ //existing rigidbodies in the world get gravity assigned too, during this method
+ virtual void setGravity(const btVector3& gravity) = 0;
+ virtual btVector3 getGravity () const = 0;
+
+ virtual void synchronizeMotionStates() = 0;
+
+ virtual void addRigidBody(btRigidBody* body) = 0;
+
+ virtual void removeRigidBody(btRigidBody* body) = 0;
+
+ virtual void setConstraintSolver(btConstraintSolver* solver) = 0;
+
+ virtual btConstraintSolver* getConstraintSolver() = 0;
+
+ virtual int getNumConstraints() const { return 0; }
+
+ virtual btTypedConstraint* getConstraint(int index) { (void)index; return 0; }
+
+ virtual const btTypedConstraint* getConstraint(int index) const { (void)index; return 0; }
+
+ virtual btDynamicsWorldType getWorldType() const=0;
+
+ virtual void clearForces() = 0;
+
+ /// Set the callback for when an internal tick (simulation substep) happens, optional user info
+ void setInternalTickCallback(btInternalTickCallback cb, void* worldUserInfo=0,bool isPreTick=false)
+ {
+ if (isPreTick)
+ {
+ m_internalPreTickCallback = cb;
+ } else
+ {
+ m_internalTickCallback = cb;
+ }
+ m_worldUserInfo = worldUserInfo;
+ }
+
+ void setWorldUserInfo(void* worldUserInfo)
+ {
+ m_worldUserInfo = worldUserInfo;
+ }
+
+ void* getWorldUserInfo() const
+ {
+ return m_worldUserInfo;
+ }
+
+ btContactSolverInfo& getSolverInfo()
+ {
+ return m_solverInfo;
+ }
+
+
+ ///obsolete, use addAction instead.
+ virtual void addVehicle(btActionInterface* vehicle) {(void)vehicle;}
+ ///obsolete, use removeAction instead
+ virtual void removeVehicle(btActionInterface* vehicle) {(void)vehicle;}
+ ///obsolete, use addAction instead.
+ virtual void addCharacter(btActionInterface* character) {(void)character;}
+ ///obsolete, use removeAction instead
+ virtual void removeCharacter(btActionInterface* character) {(void)character;}
+
+
+};
+
+#endif //BT_DYNAMICS_WORLD_H
+
+
diff --git a/extern/bullet2/BulletDynamics/Dynamics/btRigidBody.cpp b/extern/bullet2/BulletDynamics/Dynamics/btRigidBody.cpp
new file mode 100644
index 00000000000..35de8e47570
--- /dev/null
+++ b/extern/bullet2/BulletDynamics/Dynamics/btRigidBody.cpp
@@ -0,0 +1,400 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+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.
+*/
+
+#include "btRigidBody.h"
+#include "BulletCollision/CollisionShapes/btConvexShape.h"
+#include "LinearMath/btMinMax.h"
+#include "LinearMath/btTransformUtil.h"
+#include "LinearMath/btMotionState.h"
+#include "BulletDynamics/ConstraintSolver/btTypedConstraint.h"
+#include "LinearMath/btSerializer.h"
+
+//'temporarily' global variables
+btScalar gDeactivationTime = btScalar(2.);
+bool gDisableDeactivation = false;
+static int uniqueId = 0;
+
+
+btRigidBody::btRigidBody(const btRigidBody::btRigidBodyConstructionInfo& constructionInfo)
+{
+ setupRigidBody(constructionInfo);
+}
+
+btRigidBody::btRigidBody(btScalar mass, btMotionState *motionState, btCollisionShape *collisionShape, const btVector3 &localInertia)
+{
+ btRigidBodyConstructionInfo cinfo(mass,motionState,collisionShape,localInertia);
+ setupRigidBody(cinfo);
+}
+
+void btRigidBody::setupRigidBody(const btRigidBody::btRigidBodyConstructionInfo& constructionInfo)
+{
+
+ m_internalType=CO_RIGID_BODY;
+
+ m_linearVelocity.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
+ m_angularVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
+ m_angularFactor.setValue(1,1,1);
+ m_linearFactor.setValue(1,1,1);
+ m_gravity.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
+ m_gravity_acceleration.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
+ m_totalForce.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
+ m_totalTorque.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0)),
+ m_linearDamping = btScalar(0.);
+ m_angularDamping = btScalar(0.5);
+ m_linearSleepingThreshold = constructionInfo.m_linearSleepingThreshold;
+ m_angularSleepingThreshold = constructionInfo.m_angularSleepingThreshold;
+ m_optionalMotionState = constructionInfo.m_motionState;
+ m_contactSolverType = 0;
+ m_frictionSolverType = 0;
+ m_additionalDamping = constructionInfo.m_additionalDamping;
+ m_additionalDampingFactor = constructionInfo.m_additionalDampingFactor;
+ m_additionalLinearDampingThresholdSqr = constructionInfo.m_additionalLinearDampingThresholdSqr;
+ m_additionalAngularDampingThresholdSqr = constructionInfo.m_additionalAngularDampingThresholdSqr;
+ m_additionalAngularDampingFactor = constructionInfo.m_additionalAngularDampingFactor;
+
+ if (m_optionalMotionState)
+ {
+ m_optionalMotionState->getWorldTransform(m_worldTransform);
+ } else
+ {
+ m_worldTransform = constructionInfo.m_startWorldTransform;
+ }
+
+ m_interpolationWorldTransform = m_worldTransform;
+ m_interpolationLinearVelocity.setValue(0,0,0);
+ m_interpolationAngularVelocity.setValue(0,0,0);
+
+ //moved to btCollisionObject
+ m_friction = constructionInfo.m_friction;
+ m_restitution = constructionInfo.m_restitution;
+
+ setCollisionShape( constructionInfo.m_collisionShape );
+ m_debugBodyId = uniqueId++;
+
+ setMassProps(constructionInfo.m_mass, constructionInfo.m_localInertia);
+ setDamping(constructionInfo.m_linearDamping, constructionInfo.m_angularDamping);
+ updateInertiaTensor();
+
+ m_rigidbodyFlags = 0;
+
+
+ m_deltaLinearVelocity.setZero();
+ m_deltaAngularVelocity.setZero();
+ m_invMass = m_inverseMass*m_linearFactor;
+ m_pushVelocity.setZero();
+ m_turnVelocity.setZero();
+
+
+
+}
+
+
+void btRigidBody::predictIntegratedTransform(btScalar timeStep,btTransform& predictedTransform)
+{
+ btTransformUtil::integrateTransform(m_worldTransform,m_linearVelocity,m_angularVelocity,timeStep,predictedTransform);
+}
+
+void btRigidBody::saveKinematicState(btScalar timeStep)
+{
+ //todo: clamp to some (user definable) safe minimum timestep, to limit maximum angular/linear velocities
+ if (timeStep != btScalar(0.))
+ {
+ //if we use motionstate to synchronize world transforms, get the new kinematic/animated world transform
+ if (getMotionState())
+ getMotionState()->getWorldTransform(m_worldTransform);
+ btVector3 linVel,angVel;
+
+ btTransformUtil::calculateVelocity(m_interpolationWorldTransform,m_worldTransform,timeStep,m_linearVelocity,m_angularVelocity);
+ m_interpolationLinearVelocity = m_linearVelocity;
+ m_interpolationAngularVelocity = m_angularVelocity;
+ m_interpolationWorldTransform = m_worldTransform;
+ //printf("angular = %f %f %f\n",m_angularVelocity.getX(),m_angularVelocity.getY(),m_angularVelocity.getZ());
+ }
+}
+
+void btRigidBody::getAabb(btVector3& aabbMin,btVector3& aabbMax) const
+{
+ getCollisionShape()->getAabb(m_worldTransform,aabbMin,aabbMax);
+}
+
+
+
+
+void btRigidBody::setGravity(const btVector3& acceleration)
+{
+ if (m_inverseMass != btScalar(0.0))
+ {
+ m_gravity = acceleration * (btScalar(1.0) / m_inverseMass);
+ }
+ m_gravity_acceleration = acceleration;
+}
+
+
+
+
+
+
+void btRigidBody::setDamping(btScalar lin_damping, btScalar ang_damping)
+{
+ m_linearDamping = GEN_clamped(lin_damping, (btScalar)btScalar(0.0), (btScalar)btScalar(1.0));
+ m_angularDamping = GEN_clamped(ang_damping, (btScalar)btScalar(0.0), (btScalar)btScalar(1.0));
+}
+
+
+
+
+///applyDamping damps the velocity, using the given m_linearDamping and m_angularDamping
+void btRigidBody::applyDamping(btScalar timeStep)
+{
+ //On new damping: see discussion/issue report here: http://code.google.com/p/bullet/issues/detail?id=74
+ //todo: do some performance comparisons (but other parts of the engine are probably bottleneck anyway
+
+//#define USE_OLD_DAMPING_METHOD 1
+#ifdef USE_OLD_DAMPING_METHOD
+ m_linearVelocity *= GEN_clamped((btScalar(1.) - timeStep * m_linearDamping), (btScalar)btScalar(0.0), (btScalar)btScalar(1.0));
+ m_angularVelocity *= GEN_clamped((btScalar(1.) - timeStep * m_angularDamping), (btScalar)btScalar(0.0), (btScalar)btScalar(1.0));
+#else
+ m_linearVelocity *= btPow(btScalar(1)-m_linearDamping, timeStep);
+ m_angularVelocity *= btPow(btScalar(1)-m_angularDamping, timeStep);
+#endif
+
+ if (m_additionalDamping)
+ {
+ //Additional damping can help avoiding lowpass jitter motion, help stability for ragdolls etc.
+ //Such damping is undesirable, so once the overall simulation quality of the rigid body dynamics system has improved, this should become obsolete
+ if ((m_angularVelocity.length2() < m_additionalAngularDampingThresholdSqr) &&
+ (m_linearVelocity.length2() < m_additionalLinearDampingThresholdSqr))
+ {
+ m_angularVelocity *= m_additionalDampingFactor;
+ m_linearVelocity *= m_additionalDampingFactor;
+ }
+
+
+ btScalar speed = m_linearVelocity.length();
+ if (speed < m_linearDamping)
+ {
+ btScalar dampVel = btScalar(0.005);
+ if (speed > dampVel)
+ {
+ btVector3 dir = m_linearVelocity.normalized();
+ m_linearVelocity -= dir * dampVel;
+ } else
+ {
+ m_linearVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
+ }
+ }
+
+ btScalar angSpeed = m_angularVelocity.length();
+ if (angSpeed < m_angularDamping)
+ {
+ btScalar angDampVel = btScalar(0.005);
+ if (angSpeed > angDampVel)
+ {
+ btVector3 dir = m_angularVelocity.normalized();
+ m_angularVelocity -= dir * angDampVel;
+ } else
+ {
+ m_angularVelocity.setValue(btScalar(0.),btScalar(0.),btScalar(0.));
+ }
+ }
+ }
+}
+
+
+void btRigidBody::applyGravity()
+{
+ if (isStaticOrKinematicObject())
+ return;
+
+ applyCentralForce(m_gravity);
+
+}
+
+void btRigidBody::proceedToTransform(const btTransform& newTrans)
+{
+ setCenterOfMassTransform( newTrans );
+}
+
+
+void btRigidBody::setMassProps(btScalar mass, const btVector3& inertia)
+{
+ if (mass == btScalar(0.))
+ {
+ m_collisionFlags |= btCollisionObject::CF_STATIC_OBJECT;
+ m_inverseMass = btScalar(0.);
+ } else
+ {
+ m_collisionFlags &= (~btCollisionObject::CF_STATIC_OBJECT);
+ m_inverseMass = btScalar(1.0) / mass;
+ }
+
+ m_invInertiaLocal.setValue(inertia.x() != btScalar(0.0) ? btScalar(1.0) / inertia.x(): btScalar(0.0),
+ inertia.y() != btScalar(0.0) ? btScalar(1.0) / inertia.y(): btScalar(0.0),
+ inertia.z() != btScalar(0.0) ? btScalar(1.0) / inertia.z(): btScalar(0.0));
+
+ m_invMass = m_linearFactor*m_inverseMass;
+}
+
+
+
+void btRigidBody::updateInertiaTensor()
+{
+ m_invInertiaTensorWorld = m_worldTransform.getBasis().scaled(m_invInertiaLocal) * m_worldTransform.getBasis().transpose();
+}
+
+
+void btRigidBody::integrateVelocities(btScalar step)
+{
+ if (isStaticOrKinematicObject())
+ return;
+
+ m_linearVelocity += m_totalForce * (m_inverseMass * step);
+ m_angularVelocity += m_invInertiaTensorWorld * m_totalTorque * step;
+
+#define MAX_ANGVEL SIMD_HALF_PI
+ /// clamp angular velocity. collision calculations will fail on higher angular velocities
+ btScalar angvel = m_angularVelocity.length();
+ if (angvel*step > MAX_ANGVEL)
+ {
+ m_angularVelocity *= (MAX_ANGVEL/step) /angvel;
+ }
+
+}
+
+btQuaternion btRigidBody::getOrientation() const
+{
+ btQuaternion orn;
+ m_worldTransform.getBasis().getRotation(orn);
+ return orn;
+}
+
+
+void btRigidBody::setCenterOfMassTransform(const btTransform& xform)
+{
+
+ if (isStaticOrKinematicObject())
+ {
+ m_interpolationWorldTransform = m_worldTransform;
+ } else
+ {
+ m_interpolationWorldTransform = xform;
+ }
+ m_interpolationLinearVelocity = getLinearVelocity();
+ m_interpolationAngularVelocity = getAngularVelocity();
+ m_worldTransform = xform;
+ updateInertiaTensor();
+}
+
+
+bool btRigidBody::checkCollideWithOverride(btCollisionObject* co)
+{
+ btRigidBody* otherRb = btRigidBody::upcast(co);
+ if (!otherRb)
+ return true;
+
+ for (int i = 0; i < m_constraintRefs.size(); ++i)
+ {
+ btTypedConstraint* c = m_constraintRefs[i];
+ if (&c->getRigidBodyA() == otherRb || &c->getRigidBodyB() == otherRb)
+ return false;
+ }
+
+ return true;
+}
+
+void btRigidBody::internalWritebackVelocity(btScalar timeStep)
+{
+ (void) timeStep;
+ if (m_inverseMass)
+ {
+ setLinearVelocity(getLinearVelocity()+ m_deltaLinearVelocity);
+ setAngularVelocity(getAngularVelocity()+m_deltaAngularVelocity);
+
+ //correct the position/orientation based on push/turn recovery
+ btTransform newTransform;
+ btTransformUtil::integrateTransform(getWorldTransform(),m_pushVelocity,m_turnVelocity,timeStep,newTransform);
+ setWorldTransform(newTransform);
+ //m_originalBody->setCompanionId(-1);
+ }
+ m_deltaLinearVelocity.setZero();
+ m_deltaAngularVelocity .setZero();
+ m_pushVelocity.setZero();
+ m_turnVelocity.setZero();
+}
+
+
+
+void btRigidBody::addConstraintRef(btTypedConstraint* c)
+{
+ int index = m_constraintRefs.findLinearSearch(c);
+ if (index == m_constraintRefs.size())
+ m_constraintRefs.push_back(c);
+
+ m_checkCollideWith = true;
+}
+
+void btRigidBody::removeConstraintRef(btTypedConstraint* c)
+{
+ m_constraintRefs.remove(c);
+ m_checkCollideWith = m_constraintRefs.size() > 0;
+}
+
+int btRigidBody::calculateSerializeBufferSize() const
+{
+ int sz = sizeof(btRigidBodyData);
+ return sz;
+}
+
+ ///fills the dataBuffer and returns the struct name (and 0 on failure)
+const char* btRigidBody::serialize(void* dataBuffer, class btSerializer* serializer) const
+{
+ btRigidBodyData* rbd = (btRigidBodyData*) dataBuffer;
+
+ btCollisionObject::serialize(&rbd->m_collisionObjectData, serializer);
+
+ m_invInertiaTensorWorld.serialize(rbd->m_invInertiaTensorWorld);
+ m_linearVelocity.serialize(rbd->m_linearVelocity);
+ m_angularVelocity.serialize(rbd->m_angularVelocity);
+ rbd->m_inverseMass = m_inverseMass;
+ m_angularFactor.serialize(rbd->m_angularFactor);
+ m_linearFactor.serialize(rbd->m_linearFactor);
+ m_gravity.serialize(rbd->m_gravity);
+ m_gravity_acceleration.serialize(rbd->m_gravity_acceleration);
+ m_invInertiaLocal.serialize(rbd->m_invInertiaLocal);
+ m_totalForce.serialize(rbd->m_totalForce);
+ m_totalTorque.serialize(rbd->m_totalTorque);
+ rbd->m_linearDamping = m_linearDamping;
+ rbd->m_angularDamping = m_angularDamping;
+ rbd->m_additionalDamping = m_additionalDamping;
+ rbd->m_additionalDampingFactor = m_additionalDampingFactor;
+ rbd->m_additionalLinearDampingThresholdSqr = m_additionalLinearDampingThresholdSqr;
+ rbd->m_additionalAngularDampingThresholdSqr = m_additionalAngularDampingThresholdSqr;
+ rbd->m_additionalAngularDampingFactor = m_additionalAngularDampingFactor;
+ rbd->m_linearSleepingThreshold=m_linearSleepingThreshold;
+ rbd->m_angularSleepingThreshold = m_angularSleepingThreshold;
+
+ return btRigidBodyDataName;
+}
+
+
+
+void btRigidBody::serializeSingleObject(class btSerializer* serializer) const
+{
+ btChunk* chunk = serializer->allocate(calculateSerializeBufferSize(),1);
+ const char* structType = serialize(chunk->m_oldPtr, serializer);
+ serializer->finalizeChunk(chunk,structType,BT_RIGIDBODY_CODE,(void*)this);
+}
+
+
diff --git a/extern/bullet2/BulletDynamics/Dynamics/btRigidBody.h b/extern/bullet2/BulletDynamics/Dynamics/btRigidBody.h
new file mode 100644
index 00000000000..571a30ce6b8
--- /dev/null
+++ b/extern/bullet2/BulletDynamics/Dynamics/btRigidBody.h
@@ -0,0 +1,670 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+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.
+*/
+
+#ifndef RIGIDBODY_H
+#define RIGIDBODY_H
+
+#include "LinearMath/btAlignedObjectArray.h"
+#include "LinearMath/btTransform.h"
+#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h"
+#include "BulletCollision/CollisionDispatch/btCollisionObject.h"
+
+class btCollisionShape;
+class btMotionState;
+class btTypedConstraint;
+
+
+extern btScalar gDeactivationTime;
+extern bool gDisableDeactivation;
+
+#ifdef BT_USE_DOUBLE_PRECISION
+#define btRigidBodyData btRigidBodyDoubleData
+#define btRigidBodyDataName "btRigidBodyDoubleData"
+#else
+#define btRigidBodyData btRigidBodyFloatData
+#define btRigidBodyDataName "btRigidBodyFloatData"
+#endif //BT_USE_DOUBLE_PRECISION
+
+
+enum btRigidBodyFlags
+{
+ BT_DISABLE_WORLD_GRAVITY = 1
+};
+
+
+///The btRigidBody is the main class for rigid body objects. It is derived from btCollisionObject, so it keeps a pointer to a btCollisionShape.
+///It is recommended for performance and memory use to share btCollisionShape objects whenever possible.
+///There are 3 types of rigid bodies:
+///- A) Dynamic rigid bodies, with positive mass. Motion is controlled by rigid body dynamics.
+///- B) Fixed objects with zero mass. They are not moving (basically collision objects)
+///- C) Kinematic objects, which are objects without mass, but the user can move them. There is on-way interaction, and Bullet calculates a velocity based on the timestep and previous and current world transform.
+///Bullet automatically deactivates dynamic rigid bodies, when the velocity is below a threshold for a given time.
+///Deactivated (sleeping) rigid bodies don't take any processing time, except a minor broadphase collision detection impact (to allow active objects to activate/wake up sleeping objects)
+class btRigidBody : public btCollisionObject
+{
+
+ btMatrix3x3 m_invInertiaTensorWorld;
+ btVector3 m_linearVelocity;
+ btVector3 m_angularVelocity;
+ btScalar m_inverseMass;
+ btVector3 m_linearFactor;
+
+ btVector3 m_gravity;
+ btVector3 m_gravity_acceleration;
+ btVector3 m_invInertiaLocal;
+ btVector3 m_totalForce;
+ btVector3 m_totalTorque;
+
+ btScalar m_linearDamping;
+ btScalar m_angularDamping;
+
+ bool m_additionalDamping;
+ btScalar m_additionalDampingFactor;
+ btScalar m_additionalLinearDampingThresholdSqr;
+ btScalar m_additionalAngularDampingThresholdSqr;
+ btScalar m_additionalAngularDampingFactor;
+
+
+ btScalar m_linearSleepingThreshold;
+ btScalar m_angularSleepingThreshold;
+
+ //m_optionalMotionState allows to automatic synchronize the world transform for active objects
+ btMotionState* m_optionalMotionState;
+
+ //keep track of typed constraints referencing this rigid body
+ btAlignedObjectArray<btTypedConstraint*> m_constraintRefs;
+
+ int m_rigidbodyFlags;
+
+ int m_debugBodyId;
+
+
+protected:
+
+ ATTRIBUTE_ALIGNED64(btVector3 m_deltaLinearVelocity);
+ btVector3 m_deltaAngularVelocity;
+ btVector3 m_angularFactor;
+ btVector3 m_invMass;
+ btVector3 m_pushVelocity;
+ btVector3 m_turnVelocity;
+
+
+public:
+
+
+ ///The btRigidBodyConstructionInfo structure provides information to create a rigid body. Setting mass to zero creates a fixed (non-dynamic) rigid body.
+ ///For dynamic objects, you can use the collision shape to approximate the local inertia tensor, otherwise use the zero vector (default argument)
+ ///You can use the motion state to synchronize the world transform between physics and graphics objects.
+ ///And if the motion state is provided, the rigid body will initialize its initial world transform from the motion state,
+ ///m_startWorldTransform is only used when you don't provide a motion state.
+ struct btRigidBodyConstructionInfo
+ {
+ btScalar m_mass;
+
+ ///When a motionState is provided, the rigid body will initialize its world transform from the motion state
+ ///In this case, m_startWorldTransform is ignored.
+ btMotionState* m_motionState;
+ btTransform m_startWorldTransform;
+
+ btCollisionShape* m_collisionShape;
+ btVector3 m_localInertia;
+ btScalar m_linearDamping;
+ btScalar m_angularDamping;
+
+ ///best simulation results when friction is non-zero
+ btScalar m_friction;
+ ///best simulation results using zero restitution.
+ btScalar m_restitution;
+
+ btScalar m_linearSleepingThreshold;
+ btScalar m_angularSleepingThreshold;
+
+ //Additional damping can help avoiding lowpass jitter motion, help stability for ragdolls etc.
+ //Such damping is undesirable, so once the overall simulation quality of the rigid body dynamics system has improved, this should become obsolete
+ bool m_additionalDamping;
+ btScalar m_additionalDampingFactor;
+ btScalar m_additionalLinearDampingThresholdSqr;
+ btScalar m_additionalAngularDampingThresholdSqr;
+ btScalar m_additionalAngularDampingFactor;
+
+ btRigidBodyConstructionInfo( btScalar mass, btMotionState* motionState, btCollisionShape* collisionShape, const btVector3& localInertia=btVector3(0,0,0)):
+ m_mass(mass),
+ m_motionState(motionState),
+ m_collisionShape(collisionShape),
+ m_localInertia(localInertia),
+ m_linearDamping(btScalar(0.)),
+ m_angularDamping(btScalar(0.)),
+ m_friction(btScalar(0.5)),
+ m_restitution(btScalar(0.)),
+ m_linearSleepingThreshold(btScalar(0.8)),
+ m_angularSleepingThreshold(btScalar(1.f)),
+ m_additionalDamping(false),
+ m_additionalDampingFactor(btScalar(0.005)),
+ m_additionalLinearDampingThresholdSqr(btScalar(0.01)),
+ m_additionalAngularDampingThresholdSqr(btScalar(0.01)),
+ m_additionalAngularDampingFactor(btScalar(0.01))
+ {
+ m_startWorldTransform.setIdentity();
+ }
+ };
+
+ ///btRigidBody constructor using construction info
+ btRigidBody( const btRigidBodyConstructionInfo& constructionInfo);
+
+ ///btRigidBody constructor for backwards compatibility.
+ ///To specify friction (etc) during rigid body construction, please use the other constructor (using btRigidBodyConstructionInfo)
+ btRigidBody( btScalar mass, btMotionState* motionState, btCollisionShape* collisionShape, const btVector3& localInertia=btVector3(0,0,0));
+
+
+ virtual ~btRigidBody()
+ {
+ //No constraints should point to this rigidbody
+ //Remove constraints from the dynamics world before you delete the related rigidbodies.
+ btAssert(m_constraintRefs.size()==0);
+ }
+
+protected:
+
+ ///setupRigidBody is only used internally by the constructor
+ void setupRigidBody(const btRigidBodyConstructionInfo& constructionInfo);
+
+public:
+
+ void proceedToTransform(const btTransform& newTrans);
+
+ ///to keep collision detection and dynamics separate we don't store a rigidbody pointer
+ ///but a rigidbody is derived from btCollisionObject, so we can safely perform an upcast
+ static const btRigidBody* upcast(const btCollisionObject* colObj)
+ {
+ if (colObj->getInternalType()==btCollisionObject::CO_RIGID_BODY)
+ return (const btRigidBody*)colObj;
+ return 0;
+ }
+ static btRigidBody* upcast(btCollisionObject* colObj)
+ {
+ if (colObj->getInternalType()==btCollisionObject::CO_RIGID_BODY)
+ return (btRigidBody*)colObj;
+ return 0;
+ }
+
+ /// continuous collision detection needs prediction
+ void predictIntegratedTransform(btScalar step, btTransform& predictedTransform) ;
+
+ void saveKinematicState(btScalar step);
+
+ void applyGravity();
+
+ void setGravity(const btVector3& acceleration);
+
+ const btVector3& getGravity() const
+ {
+ return m_gravity_acceleration;
+ }
+
+ void setDamping(btScalar lin_damping, btScalar ang_damping);
+
+ btScalar getLinearDamping() const
+ {
+ return m_linearDamping;
+ }
+
+ btScalar getAngularDamping() const
+ {
+ return m_angularDamping;
+ }
+
+ btScalar getLinearSleepingThreshold() const
+ {
+ return m_linearSleepingThreshold;
+ }
+
+ btScalar getAngularSleepingThreshold() const
+ {
+ return m_angularSleepingThreshold;
+ }
+
+ void applyDamping(btScalar timeStep);
+
+ SIMD_FORCE_INLINE const btCollisionShape* getCollisionShape() const {
+ return m_collisionShape;
+ }
+
+ SIMD_FORCE_INLINE btCollisionShape* getCollisionShape() {
+ return m_collisionShape;
+ }
+
+ void setMassProps(btScalar mass, const btVector3& inertia);
+
+ const btVector3& getLinearFactor() const
+ {
+ return m_linearFactor;
+ }
+ void setLinearFactor(const btVector3& linearFactor)
+ {
+ m_linearFactor = linearFactor;
+ m_invMass = m_linearFactor*m_inverseMass;
+ }
+ btScalar getInvMass() const { return m_inverseMass; }
+ const btMatrix3x3& getInvInertiaTensorWorld() const {
+ return m_invInertiaTensorWorld;
+ }
+
+ void integrateVelocities(btScalar step);
+
+ void setCenterOfMassTransform(const btTransform& xform);
+
+ void applyCentralForce(const btVector3& force)
+ {
+ m_totalForce += force*m_linearFactor;
+ }
+
+ const btVector3& getTotalForce()
+ {
+ return m_totalForce;
+ };
+
+ const btVector3& getTotalTorque()
+ {
+ return m_totalTorque;
+ };
+
+ const btVector3& getInvInertiaDiagLocal() const
+ {
+ return m_invInertiaLocal;
+ };
+
+ void setInvInertiaDiagLocal(const btVector3& diagInvInertia)
+ {
+ m_invInertiaLocal = diagInvInertia;
+ }
+
+ void setSleepingThresholds(btScalar linear,btScalar angular)
+ {
+ m_linearSleepingThreshold = linear;
+ m_angularSleepingThreshold = angular;
+ }
+
+ void applyTorque(const btVector3& torque)
+ {
+ m_totalTorque += torque*m_angularFactor;
+ }
+
+ void applyForce(const btVector3& force, const btVector3& rel_pos)
+ {
+ applyCentralForce(force);
+ applyTorque(rel_pos.cross(force*m_linearFactor));
+ }
+
+ void applyCentralImpulse(const btVector3& impulse)
+ {
+ m_linearVelocity += impulse *m_linearFactor * m_inverseMass;
+ }
+
+ void applyTorqueImpulse(const btVector3& torque)
+ {
+ m_angularVelocity += m_invInertiaTensorWorld * torque * m_angularFactor;
+ }
+
+ void applyImpulse(const btVector3& impulse, const btVector3& rel_pos)
+ {
+ if (m_inverseMass != btScalar(0.))
+ {
+ applyCentralImpulse(impulse);
+ if (m_angularFactor)
+ {
+ applyTorqueImpulse(rel_pos.cross(impulse*m_linearFactor));
+ }
+ }
+ }
+
+ void clearForces()
+ {
+ m_totalForce.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
+ m_totalTorque.setValue(btScalar(0.0), btScalar(0.0), btScalar(0.0));
+ }
+
+ void updateInertiaTensor();
+
+ const btVector3& getCenterOfMassPosition() const {
+ return m_worldTransform.getOrigin();
+ }
+ btQuaternion getOrientation() const;
+
+ const btTransform& getCenterOfMassTransform() const {
+ return m_worldTransform;
+ }
+ const btVector3& getLinearVelocity() const {
+ return m_linearVelocity;
+ }
+ const btVector3& getAngularVelocity() const {
+ return m_angularVelocity;
+ }
+
+
+ inline void setLinearVelocity(const btVector3& lin_vel)
+ {
+ m_linearVelocity = lin_vel;
+ }
+
+ inline void setAngularVelocity(const btVector3& ang_vel)
+ {
+ m_angularVelocity = ang_vel;
+ }
+
+ btVector3 getVelocityInLocalPoint(const btVector3& rel_pos) const
+ {
+ //we also calculate lin/ang velocity for kinematic objects
+ return m_linearVelocity + m_angularVelocity.cross(rel_pos);
+
+ //for kinematic objects, we could also use use:
+ // return (m_worldTransform(rel_pos) - m_interpolationWorldTransform(rel_pos)) / m_kinematicTimeStep;
+ }
+
+ void translate(const btVector3& v)
+ {
+ m_worldTransform.getOrigin() += v;
+ }
+
+
+ void getAabb(btVector3& aabbMin,btVector3& aabbMax) const;
+
+
+
+
+
+ SIMD_FORCE_INLINE btScalar computeImpulseDenominator(const btVector3& pos, const btVector3& normal) const
+ {
+ btVector3 r0 = pos - getCenterOfMassPosition();
+
+ btVector3 c0 = (r0).cross(normal);
+
+ btVector3 vec = (c0 * getInvInertiaTensorWorld()).cross(r0);
+
+ return m_inverseMass + normal.dot(vec);
+
+ }
+
+ SIMD_FORCE_INLINE btScalar computeAngularImpulseDenominator(const btVector3& axis) const
+ {
+ btVector3 vec = axis * getInvInertiaTensorWorld();
+ return axis.dot(vec);
+ }
+
+ SIMD_FORCE_INLINE void updateDeactivation(btScalar timeStep)
+ {
+ if ( (getActivationState() == ISLAND_SLEEPING) || (getActivationState() == DISABLE_DEACTIVATION))
+ return;
+
+ if ((getLinearVelocity().length2() < m_linearSleepingThreshold*m_linearSleepingThreshold) &&
+ (getAngularVelocity().length2() < m_angularSleepingThreshold*m_angularSleepingThreshold))
+ {
+ m_deactivationTime += timeStep;
+ } else
+ {
+ m_deactivationTime=btScalar(0.);
+ setActivationState(0);
+ }
+
+ }
+
+ SIMD_FORCE_INLINE bool wantsSleeping()
+ {
+
+ if (getActivationState() == DISABLE_DEACTIVATION)
+ return false;
+
+ //disable deactivation
+ if (gDisableDeactivation || (gDeactivationTime == btScalar(0.)))
+ return false;
+
+ if ( (getActivationState() == ISLAND_SLEEPING) || (getActivationState() == WANTS_DEACTIVATION))
+ return true;
+
+ if (m_deactivationTime> gDeactivationTime)
+ {
+ return true;
+ }
+ return false;
+ }
+
+
+
+ const btBroadphaseProxy* getBroadphaseProxy() const
+ {
+ return m_broadphaseHandle;
+ }
+ btBroadphaseProxy* getBroadphaseProxy()
+ {
+ return m_broadphaseHandle;
+ }
+ void setNewBroadphaseProxy(btBroadphaseProxy* broadphaseProxy)
+ {
+ m_broadphaseHandle = broadphaseProxy;
+ }
+
+ //btMotionState allows to automatic synchronize the world transform for active objects
+ btMotionState* getMotionState()
+ {
+ return m_optionalMotionState;
+ }
+ const btMotionState* getMotionState() const
+ {
+ return m_optionalMotionState;
+ }
+ void setMotionState(btMotionState* motionState)
+ {
+ m_optionalMotionState = motionState;
+ if (m_optionalMotionState)
+ motionState->getWorldTransform(m_worldTransform);
+ }
+
+ //for experimental overriding of friction/contact solver func
+ int m_contactSolverType;
+ int m_frictionSolverType;
+
+ void setAngularFactor(const btVector3& angFac)
+ {
+ m_angularFactor = angFac;
+ }
+
+ void setAngularFactor(btScalar angFac)
+ {
+ m_angularFactor.setValue(angFac,angFac,angFac);
+ }
+ const btVector3& getAngularFactor() const
+ {
+ return m_angularFactor;
+ }
+
+ //is this rigidbody added to a btCollisionWorld/btDynamicsWorld/btBroadphase?
+ bool isInWorld() const
+ {
+ return (getBroadphaseProxy() != 0);
+ }
+
+ virtual bool checkCollideWithOverride(btCollisionObject* co);
+
+ void addConstraintRef(btTypedConstraint* c);
+ void removeConstraintRef(btTypedConstraint* c);
+
+ btTypedConstraint* getConstraintRef(int index)
+ {
+ return m_constraintRefs[index];
+ }
+
+ int getNumConstraintRefs()
+ {
+ return m_constraintRefs.size();
+ }
+
+ void setFlags(int flags)
+ {
+ m_rigidbodyFlags = flags;
+ }
+
+ int getFlags() const
+ {
+ return m_rigidbodyFlags;
+ }
+
+
+ ////////////////////////////////////////////////
+ ///some internal methods, don't use them
+
+ btVector3& internalGetDeltaLinearVelocity()
+ {
+ return m_deltaLinearVelocity;
+ }
+
+ btVector3& internalGetDeltaAngularVelocity()
+ {
+ return m_deltaAngularVelocity;
+ }
+
+ const btVector3& internalGetAngularFactor() const
+ {
+ return m_angularFactor;
+ }
+
+ const btVector3& internalGetInvMass() const
+ {
+ return m_invMass;
+ }
+
+ btVector3& internalGetPushVelocity()
+ {
+ return m_pushVelocity;
+ }
+
+ btVector3& internalGetTurnVelocity()
+ {
+ return m_turnVelocity;
+ }
+
+ SIMD_FORCE_INLINE void internalGetVelocityInLocalPointObsolete(const btVector3& rel_pos, btVector3& velocity ) const
+ {
+ velocity = getLinearVelocity()+m_deltaLinearVelocity + (getAngularVelocity()+m_deltaAngularVelocity).cross(rel_pos);
+ }
+
+ SIMD_FORCE_INLINE void internalGetAngularVelocity(btVector3& angVel) const
+ {
+ angVel = getAngularVelocity()+m_deltaAngularVelocity;
+ }
+
+
+ //Optimization for the iterative solver: avoid calculating constant terms involving inertia, normal, relative position
+ SIMD_FORCE_INLINE void internalApplyImpulse(const btVector3& linearComponent, const btVector3& angularComponent,const btScalar impulseMagnitude)
+ {
+ if (m_inverseMass)
+ {
+ m_deltaLinearVelocity += linearComponent*impulseMagnitude;
+ m_deltaAngularVelocity += angularComponent*(impulseMagnitude*m_angularFactor);
+ }
+ }
+
+ SIMD_FORCE_INLINE void internalApplyPushImpulse(const btVector3& linearComponent, const btVector3& angularComponent,btScalar impulseMagnitude)
+ {
+ if (m_inverseMass)
+ {
+ m_pushVelocity += linearComponent*impulseMagnitude;
+ m_turnVelocity += angularComponent*(impulseMagnitude*m_angularFactor);
+ }
+ }
+
+ void internalWritebackVelocity()
+ {
+ if (m_inverseMass)
+ {
+ setLinearVelocity(getLinearVelocity()+ m_deltaLinearVelocity);
+ setAngularVelocity(getAngularVelocity()+m_deltaAngularVelocity);
+ m_deltaLinearVelocity.setZero();
+ m_deltaAngularVelocity .setZero();
+ //m_originalBody->setCompanionId(-1);
+ }
+ }
+
+
+ void internalWritebackVelocity(btScalar timeStep);
+
+
+ ///////////////////////////////////////////////
+
+ virtual int calculateSerializeBufferSize() const;
+
+ ///fills the dataBuffer and returns the struct name (and 0 on failure)
+ virtual const char* serialize(void* dataBuffer, class btSerializer* serializer) const;
+
+ virtual void serializeSingleObject(class btSerializer* serializer) const;
+
+};
+
+//@todo add m_optionalMotionState and m_constraintRefs to btRigidBodyData
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btRigidBodyFloatData
+{
+ btCollisionObjectFloatData m_collisionObjectData;
+ btMatrix3x3FloatData m_invInertiaTensorWorld;
+ btVector3FloatData m_linearVelocity;
+ btVector3FloatData m_angularVelocity;
+ btVector3FloatData m_angularFactor;
+ btVector3FloatData m_linearFactor;
+ btVector3FloatData m_gravity;
+ btVector3FloatData m_gravity_acceleration;
+ btVector3FloatData m_invInertiaLocal;
+ btVector3FloatData m_totalForce;
+ btVector3FloatData m_totalTorque;
+ float m_inverseMass;
+ float m_linearDamping;
+ float m_angularDamping;
+ float m_additionalDampingFactor;
+ float m_additionalLinearDampingThresholdSqr;
+ float m_additionalAngularDampingThresholdSqr;
+ float m_additionalAngularDampingFactor;
+ float m_linearSleepingThreshold;
+ float m_angularSleepingThreshold;
+ int m_additionalDamping;
+};
+
+///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
+struct btRigidBodyDoubleData
+{
+ btCollisionObjectDoubleData m_collisionObjectData;
+ btMatrix3x3DoubleData m_invInertiaTensorWorld;
+ btVector3DoubleData m_linearVelocity;
+ btVector3DoubleData m_angularVelocity;
+ btVector3DoubleData m_angularFactor;
+ btVector3DoubleData m_linearFactor;
+ btVector3DoubleData m_gravity;
+ btVector3DoubleData m_gravity_acceleration;
+ btVector3DoubleData m_invInertiaLocal;
+ btVector3DoubleData m_totalForce;
+ btVector3DoubleData m_totalTorque;
+ double m_inverseMass;
+ double m_linearDamping;
+ double m_angularDamping;
+ double m_additionalDampingFactor;
+ double m_additionalLinearDampingThresholdSqr;
+ double m_additionalAngularDampingThresholdSqr;
+ double m_additionalAngularDampingFactor;
+ double m_linearSleepingThreshold;
+ double m_angularSleepingThreshold;
+ int m_additionalDamping;
+ char m_padding[4];
+};
+
+
+
+#endif
+
diff --git a/extern/bullet2/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp b/extern/bullet2/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp
new file mode 100644
index 00000000000..ae449f292f6
--- /dev/null
+++ b/extern/bullet2/BulletDynamics/Dynamics/btSimpleDynamicsWorld.cpp
@@ -0,0 +1,253 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+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.
+*/
+
+#include "btSimpleDynamicsWorld.h"
+#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h"
+#include "BulletCollision/BroadphaseCollision/btSimpleBroadphase.h"
+#include "BulletCollision/CollisionShapes/btCollisionShape.h"
+#include "BulletDynamics/Dynamics/btRigidBody.h"
+#include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h"
+#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h"
+
+
+/*
+ Make sure this dummy function never changes so that it
+ can be used by probes that are checking whether the
+ library is actually installed.
+*/
+extern "C"
+{
+ void btBulletDynamicsProbe ();
+ void btBulletDynamicsProbe () {}
+}
+
+
+
+
+btSimpleDynamicsWorld::btSimpleDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration)
+:btDynamicsWorld(dispatcher,pairCache,collisionConfiguration),
+m_constraintSolver(constraintSolver),
+m_ownsConstraintSolver(false),
+m_gravity(0,0,-10)
+{
+
+}
+
+
+btSimpleDynamicsWorld::~btSimpleDynamicsWorld()
+{
+ if (m_ownsConstraintSolver)
+ btAlignedFree( m_constraintSolver);
+}
+
+int btSimpleDynamicsWorld::stepSimulation( btScalar timeStep,int maxSubSteps, btScalar fixedTimeStep)
+{
+ (void)fixedTimeStep;
+ (void)maxSubSteps;
+
+
+ ///apply gravity, predict motion
+ predictUnconstraintMotion(timeStep);
+
+ btDispatcherInfo& dispatchInfo = getDispatchInfo();
+ dispatchInfo.m_timeStep = timeStep;
+ dispatchInfo.m_stepCount = 0;
+ dispatchInfo.m_debugDraw = getDebugDrawer();
+
+ ///perform collision detection
+ performDiscreteCollisionDetection();
+
+ ///solve contact constraints
+ int numManifolds = m_dispatcher1->getNumManifolds();
+ if (numManifolds)
+ {
+ btPersistentManifold** manifoldPtr = ((btCollisionDispatcher*)m_dispatcher1)->getInternalManifoldPointer();
+
+ btContactSolverInfo infoGlobal;
+ infoGlobal.m_timeStep = timeStep;
+ m_constraintSolver->prepareSolve(0,numManifolds);
+ m_constraintSolver->solveGroup(0,0,manifoldPtr, numManifolds,0,0,infoGlobal,m_debugDrawer, m_stackAlloc,m_dispatcher1);
+ m_constraintSolver->allSolved(infoGlobal,m_debugDrawer, m_stackAlloc);
+ }
+
+ ///integrate transforms
+ integrateTransforms(timeStep);
+
+ updateAabbs();
+
+ synchronizeMotionStates();
+
+ clearForces();
+
+ return 1;
+
+}
+
+void btSimpleDynamicsWorld::clearForces()
+{
+ ///@todo: iterate over awake simulation islands!
+ for ( int i=0;i<m_collisionObjects.size();i++)
+ {
+ btCollisionObject* colObj = m_collisionObjects[i];
+
+ btRigidBody* body = btRigidBody::upcast(colObj);
+ if (body)
+ {
+ body->clearForces();
+ }
+ }
+}
+
+
+void btSimpleDynamicsWorld::setGravity(const btVector3& gravity)
+{
+ m_gravity = gravity;
+ for ( int i=0;i<m_collisionObjects.size();i++)
+ {
+ btCollisionObject* colObj = m_collisionObjects[i];
+ btRigidBody* body = btRigidBody::upcast(colObj);
+ if (body)
+ {
+ body->setGravity(gravity);
+ }
+ }
+}
+
+btVector3 btSimpleDynamicsWorld::getGravity () const
+{
+ return m_gravity;
+}
+
+void btSimpleDynamicsWorld::removeRigidBody(btRigidBody* body)
+{
+ btCollisionWorld::removeCollisionObject(body);
+}
+
+void btSimpleDynamicsWorld::removeCollisionObject(btCollisionObject* collisionObject)
+{
+ btRigidBody* body = btRigidBody::upcast(collisionObject);
+ if (body)
+ removeRigidBody(body);
+ else
+ btCollisionWorld::removeCollisionObject(collisionObject);
+}
+
+
+void btSimpleDynamicsWorld::addRigidBody(btRigidBody* body)
+{
+ body->setGravity(m_gravity);
+
+ if (body->getCollisionShape())
+ {
+ addCollisionObject(body);
+ }
+}
+
+void btSimpleDynamicsWorld::updateAabbs()
+{
+ btTransform predictedTrans;
+ for ( int i=0;i<m_collisionObjects.size();i++)
+ {
+ btCollisionObject* colObj = m_collisionObjects[i];
+ btRigidBody* body = btRigidBody::upcast(colObj);
+ if (body)
+ {
+ if (body->isActive() && (!body->isStaticObject()))
+ {
+ btVector3 minAabb,maxAabb;
+ colObj->getCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb,maxAabb);
+ btBroadphaseInterface* bp = getBroadphase();
+ bp->setAabb(body->getBroadphaseHandle(),minAabb,maxAabb, m_dispatcher1);
+ }
+ }
+ }
+}
+
+void btSimpleDynamicsWorld::integrateTransforms(btScalar timeStep)
+{
+ btTransform predictedTrans;
+ for ( int i=0;i<m_collisionObjects.size();i++)
+ {
+ btCollisionObject* colObj = m_collisionObjects[i];
+ btRigidBody* body = btRigidBody::upcast(colObj);
+ if (body)
+ {
+ if (body->isActive() && (!body->isStaticObject()))
+ {
+ body->predictIntegratedTransform(timeStep, predictedTrans);
+ body->proceedToTransform( predictedTrans);
+ }
+ }
+ }
+}
+
+
+
+void btSimpleDynamicsWorld::predictUnconstraintMotion(btScalar timeStep)
+{
+ for ( int i=0;i<m_collisionObjects.size();i++)
+ {
+ btCollisionObject* colObj = m_collisionObjects[i];
+ btRigidBody* body = btRigidBody::upcast(colObj);
+ if (body)
+ {
+ if (!body->isStaticObject())
+ {
+ if (body->isActive())
+ {
+ body->applyGravity();
+ body->integrateVelocities( timeStep);
+ body->applyDamping(timeStep);
+ body->predictIntegratedTransform(timeStep,body->getInterpolationWorldTransform());
+ }
+ }
+ }
+ }
+}
+
+
+void btSimpleDynamicsWorld::synchronizeMotionStates()
+{
+ ///@todo: iterate over awake simulation islands!
+ for ( int i=0;i<m_collisionObjects.size();i++)
+ {
+ btCollisionObject* colObj = m_collisionObjects[i];
+ btRigidBody* body = btRigidBody::upcast(colObj);
+ if (body && body->getMotionState())
+ {
+ if (body->getActivationState() != ISLAND_SLEEPING)
+ {
+ body->getMotionState()->setWorldTransform(body->getWorldTransform());
+ }
+ }
+ }
+
+}
+
+
+void btSimpleDynamicsWorld::setConstraintSolver(btConstraintSolver* solver)
+{
+ if (m_ownsConstraintSolver)
+ {
+ btAlignedFree(m_constraintSolver);
+ }
+ m_ownsConstraintSolver = false;
+ m_constraintSolver = solver;
+}
+
+btConstraintSolver* btSimpleDynamicsWorld::getConstraintSolver()
+{
+ return m_constraintSolver;
+}
diff --git a/extern/bullet2/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h b/extern/bullet2/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h
new file mode 100644
index 00000000000..ad1f541340f
--- /dev/null
+++ b/extern/bullet2/BulletDynamics/Dynamics/btSimpleDynamicsWorld.h
@@ -0,0 +1,81 @@
+/*
+Bullet Continuous Collision Detection and Physics Library
+Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
+
+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.
+*/
+
+#ifndef BT_SIMPLE_DYNAMICS_WORLD_H
+#define BT_SIMPLE_DYNAMICS_WORLD_H
+
+#include "btDynamicsWorld.h"
+
+class btDispatcher;
+class btOverlappingPairCache;
+class btConstraintSolver;
+
+///The btSimpleDynamicsWorld serves as unit-test and to verify more complicated and optimized dynamics worlds.
+///Please use btDiscreteDynamicsWorld instead (or btContinuousDynamicsWorld once it is finished).
+class btSimpleDynamicsWorld : public btDynamicsWorld
+{
+protected:
+
+ btConstraintSolver* m_constraintSolver;
+
+ bool m_ownsConstraintSolver;
+
+ void predictUnconstraintMotion(btScalar timeStep);
+
+ void integrateTransforms(btScalar timeStep);
+
+ btVector3 m_gravity;
+
+public:
+
+
+
+ ///this btSimpleDynamicsWorld constructor creates dispatcher, broadphase pairCache and constraintSolver
+ btSimpleDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration);
+
+ virtual ~btSimpleDynamicsWorld();
+
+ ///maxSubSteps/fixedTimeStep for interpolation is currently ignored for btSimpleDynamicsWorld, use btDiscreteDynamicsWorld instead
+ virtual int stepSimulation( btScalar timeStep,int maxSubSteps=1, btScalar fixedTimeStep=btScalar(1.)/btScalar(60.));
+
+ virtual void setGravity(const btVector3& gravity);
+
+ virtual btVector3 getGravity () const;
+
+ virtual void addRigidBody(btRigidBody* body);
+
+ virtual void removeRigidBody(btRigidBody* body);
+
+ ///removeCollisionObject will first check if it is a rigid body, if so call removeRigidBody otherwise call btCollisionWorld::removeCollisionObject
+ virtual void removeCollisionObject(btCollisionObject* collisionObject);
+
+ virtual void updateAabbs();
+
+ virtual void synchronizeMotionStates();
+
+ virtual void setConstraintSolver(btConstraintSolver* solver);
+
+ virtual btConstraintSolver* getConstraintSolver();
+
+ virtual btDynamicsWorldType getWorldType() const
+ {
+ return BT_SIMPLE_DYNAMICS_WORLD;
+ }
+
+ virtual void clearForces();
+
+};
+
+#endif //BT_SIMPLE_DYNAMICS_WORLD_H