Tags

, , , , , , , , , , , , ,

Time to add some physics to my virtual world.

I installed Bullet Real-Time Physics Simulation, using CMake to target Visual Studio 2015 Win64 and then building the BULLET_PHYSICS.sln to spit out 64-bit libs for my app.

My app is a Microsoft Visual Studio C++ solution (with OpenGL graphics library and the Oculus SDK for Windows). I configure it to point to the Bullet src and libs. And then I drop the Bullet Hello World code into a handy class:

#include <btBulletDynamicsCommon.h>

class PhysicsClient
{

private:
	btRigidBody* fallRigidBody;
	btRigidBody* groundRigidBody;
	btCollisionShape* fallShape;
	btCollisionShape* groundShape;
	btDiscreteDynamicsWorld* dynamicsWorld;
	btSequentialImpulseConstraintSolver* solver;
	btDefaultCollisionConfiguration* collisionConfiguration;
	btCollisionDispatcher* dispatcher;
	btBroadphaseInterface* broadphase;

public:

	PhysicsClient()
	{
		broadphase = new btDbvtBroadphase();

		collisionConfiguration = new btDefaultCollisionConfiguration();
		dispatcher = new btCollisionDispatcher(collisionConfiguration);

		solver = new btSequentialImpulseConstraintSolver;

		dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher, broadphase, solver, collisionConfiguration);

		dynamicsWorld->setGravity(btVector3(0, -10, 0));

		groundShape = new btStaticPlaneShape(btVector3(0, 1, 0), 1);

		fallShape = new btSphereShape(1);

		btDefaultMotionState* groundMotionState = new btDefaultMotionState(btTransform(btQuaternion(0, 0, 0, 1), btVector3(0, -1, 0)));
		btRigidBody::btRigidBodyConstructionInfo
			groundRigidBodyCI(0, groundMotionState, groundShape, btVector3(0, 0, 0));
		groundRigidBody = new btRigidBody(groundRigidBodyCI);
		dynamicsWorld->addRigidBody(groundRigidBody);

		btDefaultMotionState* fallMotionState =
			new btDefaultMotionState(btTransform(btQuaternion(0, 0, 0, 1), btVector3(0, 50, 0)));
		btScalar mass = 1;
		btVector3 fallInertia(0, 0, 0);
		fallShape->calculateLocalInertia(mass, fallInertia);
		btRigidBody::btRigidBodyConstructionInfo fallRigidBodyCI(mass, fallMotionState, fallShape, fallInertia);
		fallRigidBody = new btRigidBody(fallRigidBodyCI);
		dynamicsWorld->addRigidBody(fallRigidBody);
	}

	~PhysicsClient()
	{
		dynamicsWorld->removeRigidBody(fallRigidBody);
		delete fallRigidBody->getMotionState();
		delete fallRigidBody;

		dynamicsWorld->removeRigidBody(groundRigidBody);
		delete groundRigidBody->getMotionState();
		delete groundRigidBody;

		delete fallShape;

		delete groundShape;

		delete dynamicsWorld;
		delete solver;
		delete collisionConfiguration;
		delete dispatcher;
		delete broadphase;
	}

	float StepSimulation() {
		dynamicsWorld->stepSimulation(1 / 60.f, 10);

		btTransform trans;
		fallRigidBody->getMotionState()->getWorldTransform(trans);

		return trans.getOrigin().getY();
	}
};

Great.

Next, I create a simple sphere mesh in Blender (the free and open source 3D creation suite) and import it into my virtual world.

And then on each frame render of the virtual world, I update my sphere’s height to match the physics:

// physics only on one side of the room
if (pos.x < 5.0f) return;

// get ycoord from Bullet physics
float ycoord = physicsClient->StepSimulation();

// update ball ycoord to match physics
for (int i = 0; i < numMyModels; ++i) {
	if (MyModels[i]->MyModelName == Zoodo_Floor1_Ball) {

		for (int j = 0; j < MyModels[i]->numMyMeshes; ++j) {
			MyModels[i]->MyMeshes[j]->Pos.y = ycoord;
		}

		break;
	}
}

I put on my Oculus Rift virtual reality headset, stroll across the virtual room, and watch the sphere fall from the night sky, crash through a table and come to rest on the floor.

Here’s a video of Bullet Real-Time Physics Simulation in my virtual world:

Time to get more physical.

Ciao!

Advertisements