1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-15 21:19:57 +00:00
openmw-tes3mp/bullet/cpp_bullet.cpp

230 lines
7.6 KiB
C++
Raw Normal View History

#include "btBulletDynamicsCommon.h"
#include <iostream>
using namespace std;
class CustomOverlappingPairCallback;
// System variables
btDefaultCollisionConfiguration* g_collisionConfiguration;
btCollisionDispatcher *g_dispatcher;
//btBroadphaseInterface *g_broadphase;
btAxisSweep3 *g_broadphase;
btSequentialImpulseConstraintSolver* g_solver;
btDynamicsWorld *g_dynamicsWorld;
// Player variables
btCollisionObject* g_playerObject;
btConvexShape *g_playerShape;
// Player position. This is updated automatically by the physics
// system based on g_walkDirection and collisions. It is read by D
// code through cpp_getPlayerPos().
btVector3 g_playerPosition;
// Walking vector - defines direction and speed that the player
// intends to move right now. This is updated from D code each frame
// through cpp_setPlayerDir(), based on player input (and later, AI
// decisions.) The units of the vector are points per second.
btVector3 g_walkDirection;
// These variables and the class below are used in player collision
// detection. The callback is injected into the broadphase and keeps a
// continuously updated list of what objects are colliding with the
// player (in g_pairCache). This list is used in the function called
// recoverFromPenetration() below.
btHashedOverlappingPairCache* g_pairCache;
CustomOverlappingPairCallback *g_customPairCallback;
// Include the player physics
#include "cpp_player.cpp"
class CustomOverlappingPairCallback : public btOverlappingPairCallback
{
public:
virtual btBroadphasePair* addOverlappingPair(btBroadphaseProxy* proxy0,
btBroadphaseProxy* proxy1)
{
if (proxy0->m_clientObject==g_playerObject ||
proxy1->m_clientObject==g_playerObject)
return g_pairCache->addOverlappingPair(proxy0,proxy1);
return 0;
}
virtual void* removeOverlappingPair(btBroadphaseProxy* proxy0,
btBroadphaseProxy* proxy1,
btDispatcher* dispatcher)
{
if (proxy0->m_clientObject==g_playerObject ||
proxy1->m_clientObject==g_playerObject)
return g_pairCache->removeOverlappingPair(proxy0,proxy1,dispatcher);
return 0;
}
void removeOverlappingPairsContainingProxy(btBroadphaseProxy* proxy0,
btDispatcher* dispatcher)
{ if (proxy0->m_clientObject==g_playerObject)
g_pairCache->removeOverlappingPairsContainingProxy(proxy0,dispatcher);
}
/* KILLME
btBroadphasePairArray& getOverlappingPairArray()
{ return g_pairCache->getOverlappingPairArray(); }
btOverlappingPairCache* getOverlappingPairCache()
{ return g_pairCache; }
*/
};
extern "C" int32_t cpp_initBullet()
{
// ------- SET UP THE WORLD -------
// Set up basic objects
g_collisionConfiguration = new btDefaultCollisionConfiguration();
g_dispatcher = new btCollisionDispatcher(g_collisionConfiguration);
//g_broadphase = new btDbvtBroadphase();
g_solver = new btSequentialImpulseConstraintSolver;
// TODO: Figure out what to do with this. We need the user callback
// function used below (I think), but this is only offered by this
// broadphase implementation (as far as I can see.)
btVector3 worldMin(-100000,-100000,-100000);
btVector3 worldMax(100000,100000,100000);
g_broadphase = new btAxisSweep3(worldMin,worldMax);
g_dynamicsWorld =
new btDiscreteDynamicsWorld(g_dispatcher,
g_broadphase,
g_solver,
g_collisionConfiguration);
//g_dynamicsWorld->setGravity(btVector3(0,-10,0));
// ------- SET UP THE PLAYER -------
// Create the player collision shape.
float width = 50;
//float height = 50;
/*
// One possible shape is the convex hull around two spheres
btVector3 spherePositions[2];
btScalar sphereRadii[2];
sphereRadii[0] = width;
sphereRadii[1] = width;
spherePositions[0] = btVector3 (0.0, height/2.0, 0.0);
spherePositions[1] = btVector3 (0.0, -height/2.0, 0.0);
m_shape = new btMultiSphereShape(btVector3(width/2.0, height/2.0, width/2.0),
&spherePositions[0], &sphereRadii[0], 2);
*/
//g_playerShape = new btCylinderShape(btVector3(50, 50, 50));
g_playerShape = new btSphereShape(width);
// Create the collision object
g_playerObject = new btCollisionObject ();
g_playerObject->setCollisionShape (g_playerShape);
g_playerObject->setCollisionFlags (btCollisionObject::CF_NO_CONTACT_RESPONSE);
// ------- OTHER STUFF -------
// Create a custom callback to pick out all the objects colliding
// with the player. We use this in the collision recovery phase.
g_pairCache = new btHashedOverlappingPairCache();
g_customPairCallback = new CustomOverlappingPairCallback();
g_broadphase->setOverlappingPairUserCallback(g_customPairCallback);
// Set up the callback that moves the player at the end of each
// simulation step.
g_dynamicsWorld->setInternalTickCallback(playerStepCallback);
// Add the character collision object to the world.
g_dynamicsWorld->addCollisionObject(g_playerObject
,btBroadphaseProxy::DebrisFilter
//,btBroadphaseProxy::StaticFilter
);
// Success!
return 0;
}
// Warp the player to a specific location. We do not bother setting
// rotation, since it's completely irrelevant for collision detection.
extern "C" void cpp_movePlayer(float x, float y, float z)
{
btTransform tr;
tr.setIdentity();
tr.setOrigin(btVector3(x,y,z));
g_playerObject->setWorldTransform(tr);
}
// Request that the player moves in this direction
extern "C" void cpp_setPlayerDir(float x, float y, float z)
{ g_walkDirection.setValue(x,y,z); }
// Get the current player position, after physics and collision have
// been applied.
extern "C" void cpp_getPlayerPos(float *x, float *y, float *z)
{
*x = g_playerPosition.getX();
*y = g_playerPosition.getY();
*z = g_playerPosition.getZ();
}
// Insert a debug collision shape
extern "C" void cpp_insertBox(float x, float y, float z)
{
btCollisionShape* groundShape =
new btSphereShape(50);
//new btBoxShape(btVector3(100,100,100));
// Create a motion state to hold the object (not sure why yet.)
btTransform groundTransform;
groundTransform.setIdentity();
groundTransform.setOrigin(btVector3(x,y,z));
btDefaultMotionState* myMotionState =
new btDefaultMotionState(groundTransform);
// Create a rigid body from the motion state. Give it zero mass and
// inertia.
btRigidBody::btRigidBodyConstructionInfo
rbInfo(0, myMotionState, groundShape, btVector3(0,0,0));
btRigidBody* body = new btRigidBody(rbInfo);
// Add the body to the world
g_dynamicsWorld->addRigidBody(body);
}
// Move the physics simulation 'delta' seconds forward in time
extern "C" void cpp_timeStep(float delta)
{
// TODO: We might experiment with the number of time steps. Remember
// that the function also returns the number of steps performed.
g_dynamicsWorld->stepSimulation(delta,2);
}
// Cleanup in the reverse order of creation/initialization
extern "C" void cpp_cleanupBullet()
{
// Remove the rigidbodies from the dynamics world and delete them
for (int i=g_dynamicsWorld->getNumCollisionObjects()-1; i>=0 ;i--)
{
btCollisionObject* obj = g_dynamicsWorld->getCollisionObjectArray()[i];
btRigidBody* body = btRigidBody::upcast(obj);
if (body && body->getMotionState())
delete body->getMotionState();
g_dynamicsWorld->removeCollisionObject( obj );
delete obj;
}
delete g_dynamicsWorld;
delete g_solver;
delete g_broadphase;
delete g_dispatcher;
delete g_collisionConfiguration;
}