Sunday, March 30, 2014

Havok Physics Engine Tutorial Series: Multiple Bouncing Boxes

OK Now that we know hot to create one box. We will now add multiple boxes and let them fall under gravity and collide with each other.  The InitializeHavok functions remains the same. The changes here are in the AddRigidBodies function, the ShutdownHavok function and the OnRender function. Lets go through each of these one by one.

We create a global vector to store all of our rigid bodies (boxes).
const int MAX_BOXES = 100;
std::vector<hkpRigidBody*> boxes;



The AddRigidBodies function
The AddRigidBodies function is changed to the following.

void AddRigidBodies() {
//add the falling box
{
hkVector4 halfExtents(0.5f, 0.5f, 0.5f);
hkpBoxShape* boxShape = new hkpBoxShape(halfExtents);
boxShape->setRadius(0.001f);
hkpRigidBodyCinfo ci;
ci.m_shape = boxShape;
ci.m_motionType = hkpMotion::MOTION_DYNAMIC;
const hkReal boxMass(10.0f);
hkMassProperties massProps;
hkpInertiaTensorComputer::computeShapeVolumeMassProperties(boxShape, boxMass, massProps);
ci.setMassProperties(massProps);
for(int i=0;i<MAX_BOXES;++i) {
ci.m_position = hkVector4(0.0f,5.0f+5*i,0.0f);
hkpRigidBody* rigidBody = new hkpRigidBody(ci);
boxes.push_back(static_cast<hkpRigidBody*>(g_pWorld->addEntity(rigidBody)));
}
boxShape->removeReference();
}
//create the static box where the smaller box will fall
{
hkVector4 halfExtents(20.0f, 2.0f, 20.f);
hkpBoxShape* boxShape = new hkpBoxShape(halfExtents);
hkpRigidBodyCinfo ci;
ci.m_shape = boxShape;
ci.m_position = hkVector4(0, -2, 0);
ci.m_motionType = hkpMotion::MOTION_FIXED;
boxShape->setRadius(0.001f);
hkpRigidBody* rigidBody = new hkpRigidBody(ci);
boxShape->removeReference();
g_pWorld->addEntity(rigidBody)->removeReference();
}
}


The only difference here from the previous SimpleBox demo is that now we reuse the box shape to create several rigid bodies. We alter their positions by using the loop variable. We add the rigid body to the global vector as shown in the code snippet below.
for(int i=0;i<MAX_BOXES;++i) {
ci.m_position = hkVector4(0.0f,5.0f+5*i,0.0f);
hkpRigidBody* rigidBody = new hkpRigidBody(ci);
boxes.push_back(static_cast<hkpRigidBody*>(g_pWorld->addEntity(rigidBody)));
}


The ShutdownHavok function
This function is changed to the following.

void ShutdownHavok() {
g_pWorld->markForWrite();
for(int i=0;i<MAX_BOXES;++i) {
boxes[i]->removeReference();
}
g_pWorld->unmarkForWrite();
if(g_pWorld)
{
g_pWorld->markForWrite();
g_pWorld->removeReference();
g_pWorld = HK_NULL;
}
delete g_pJobQueue;
// Clean up the thread pool
g_pThreadPool->removeReference();
if (g_bVdbEnabled)
ShutdownVDB();
boxes.clear();
hkBaseSystem::quit();
hkMemoryInitUtil::quit();
}

We simply run a loop to remove reference of each rigidbody one by one.

The OnRender function
The only difference in this function is that instead of one box we run a loop to access the ith box rigid body and pass it to DrawBox function as follows.
glEnable(GL_LIGHTING);
for(int i=0;i<MAX_BOXES;++i) {
DrawBox(boxes[i]);
}
glDisable(GL_LIGHTING);


Output
That's all, the accompanying tutorial code should give you a number of boxes falling under gravity on the grid plane colliding with each other as shown in the following figure.  

You can get the full source code from my github repo https://github.com/mmmovania/HavokPhysicsTutorials

Controls:
Left click to rotate
Middle click to zoom
Right click to pan

What's next:
In the next tutorial, I will show you how to pick a rigid body.


Enjoy!!!



0 comments:

Popular Posts

Copyright (C) 2011 - Movania Muhammad Mobeen. Awesome Inc. theme. Powered by Blogger.