diff --git a/Demos/CommonRigidBodySetup.h b/Demos/CommonRigidBodySetup.h new file mode 100644 index 000000000..bf28d5f59 --- /dev/null +++ b/Demos/CommonRigidBodySetup.h @@ -0,0 +1,233 @@ + +#ifndef COMMON_RIGID_BODY_SETUP_H +#define COMMON_RIGID_BODY_SETUP_H + +//todo: replace this 'btBulletDynamicsCommon.h' header with specific used header files +#include "btBulletDynamicsCommon.h" +#include "CommonPhysicsSetup.h" + +struct CommonRigidBodySetup : public CommonPhysicsSetup +{ + //keep the collision shapes, for deletion/cleanup + btAlignedObjectArray m_collisionShapes; + btBroadphaseInterface* m_broadphase; + btCollisionDispatcher* m_dispatcher; + btConstraintSolver* m_solver; + btDefaultCollisionConfiguration* m_collisionConfiguration; + btDiscreteDynamicsWorld* m_dynamicsWorld; + + //data for picking objects + class btRigidBody* m_pickedBody; + class btTypedConstraint* m_pickedConstraint; + btVector3 m_oldPickingPos; + btVector3 m_hitPos; + btScalar m_oldPickingDist; + + CommonRigidBodySetup() + :m_broadphase(0), + m_dispatcher(0), + m_solver(0), + m_collisionConfiguration(0), + m_dynamicsWorld(0), + m_pickedBody(0), + m_pickedConstraint(0) + { + } + + virtual void createEmptyDynamicsWorld() + { + ///collision configuration contains default setup for memory, collision setup + m_collisionConfiguration = new btDefaultCollisionConfiguration(); + //m_collisionConfiguration->setConvexConvexMultipointIterations(); + + ///use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded) + m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration); + + m_broadphase = new btDbvtBroadphase(); + + ///the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded) + btSequentialImpulseConstraintSolver* sol = new btSequentialImpulseConstraintSolver; + m_solver = sol; + + m_dynamicsWorld = new btDiscreteDynamicsWorld(m_dispatcher, m_broadphase, m_solver, m_collisionConfiguration); + + m_dynamicsWorld->setGravity(btVector3(0, -10, 0)); + } + + + virtual void stepSimulation(float deltaTime) + { + if (m_dynamicsWorld) + { + m_dynamicsWorld->stepSimulation(deltaTime); + } + } + + + virtual void exitPhysics() + { + removePickingConstraint(); + //cleanup in the reverse order of creation/initialization + + //remove the rigidbodies from the dynamics world and delete them + int i; + if (m_dynamicsWorld) + { + + for (i = m_dynamicsWorld->getNumCollisionObjects() - 1; i >= 0; i--) + { + btCollisionObject* obj = m_dynamicsWorld->getCollisionObjectArray()[i]; + btRigidBody* body = btRigidBody::upcast(obj); + if (body && body->getMotionState()) + { + delete body->getMotionState(); + } + m_dynamicsWorld->removeCollisionObject(obj); + delete obj; + } + } + //delete collision shapes + for (int j = 0; jrayTest(rayFromWorld, rayToWorld, rayCallback); + if (rayCallback.hasHit()) + { + + btVector3 pickPos = rayCallback.m_hitPointWorld; + btRigidBody* body = (btRigidBody*)btRigidBody::upcast(rayCallback.m_collisionObject); + if (body) + { + //other exclusions? + if (!(body->isStaticObject() || body->isKinematicObject())) + { + m_pickedBody = body; + m_pickedBody->setActivationState(DISABLE_DEACTIVATION); + //printf("pickPos=%f,%f,%f\n",pickPos.getX(),pickPos.getY(),pickPos.getZ()); + btVector3 localPivot = body->getCenterOfMassTransform().inverse() * pickPos; + btPoint2PointConstraint* p2p = new btPoint2PointConstraint(*body, localPivot); + m_dynamicsWorld->addConstraint(p2p, true); + m_pickedConstraint = p2p; + btScalar mousePickClamping = 30.f; + p2p->m_setting.m_impulseClamp = mousePickClamping; + //very weak constraint for picking + p2p->m_setting.m_tau = 0.001f; + } + } + + + // pickObject(pickPos, rayCallback.m_collisionObject); + m_oldPickingPos = rayToWorld; + m_hitPos = pickPos; + m_oldPickingDist = (pickPos - rayFromWorld).length(); + // printf("hit !\n"); + //add p2p + } + return false; + } + virtual bool movePickedBody(const btVector3& rayFromWorld, const btVector3& rayToWorld) + { + if (m_pickedBody && m_pickedConstraint) + { + btPoint2PointConstraint* pickCon = static_cast(m_pickedConstraint); + if (pickCon) + { + //keep it at the same picking distance + + btVector3 newPivotB; + + btVector3 dir = rayToWorld - rayFromWorld; + dir.normalize(); + dir *= m_oldPickingDist; + + newPivotB = rayFromWorld + dir; + pickCon->setPivotB(newPivotB); + return true; + } + } + return false; + } + virtual void removePickingConstraint() + { + if (m_pickedConstraint) + { + m_dynamicsWorld->removeConstraint(m_pickedConstraint); + delete m_pickedConstraint; + m_pickedConstraint = 0; + m_pickedBody = 0; + } + } + + + + btBoxShape* createBoxShape(const btVector3& halfExtents) + { + btBoxShape* box = new btBoxShape(halfExtents); + return box; + } + + btRigidBody* createRigidBody(float mass, const btTransform& startTransform, btCollisionShape* shape, const btVector4& color = btVector4(1, 0, 0, 1)) + { + btAssert((!shape || shape->getShapeType() != INVALID_SHAPE_PROXYTYPE)); + + //rigidbody is dynamic if and only if mass is non zero, otherwise static + bool isDynamic = (mass != 0.f); + + btVector3 localInertia(0, 0, 0); + if (isDynamic) + shape->calculateLocalInertia(mass, localInertia); + + //using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects + +#define USE_MOTIONSTATE 1 +#ifdef USE_MOTIONSTATE + btDefaultMotionState* myMotionState = new btDefaultMotionState(startTransform); + + btRigidBody::btRigidBodyConstructionInfo cInfo(mass, myMotionState, shape, localInertia); + + btRigidBody* body = new btRigidBody(cInfo); + //body->setContactProcessingThreshold(m_defaultContactProcessingThreshold); + +#else + btRigidBody* body = new btRigidBody(mass, 0, shape, localInertia); + body->setWorldTransform(startTransform); +#endif// + + body->setUserIndex(-1); + m_dynamicsWorld->addRigidBody(body); + return body; + } +}; + +#endif //COMMON_RIGID_BODY_SETUP_H +