In this tutorial, I will show you how to create a rigid body chain using the simple distance constraint which is wrapped into the hkpStiffSpringConstraint object in the Havok Physics SDK. This tutorial will be building on top of to the Simple Distance Constraint Tutorial and Picking Tutorial that we did earlier.
Creating a Chain using a Simple Distance Constraint
In the previous tutorial, we saw how we could use a distance constraint to limit a pair of rigid bodies. In this tutorial, I will show you how to use a pair of distance constraints to create a chain of rigid bodies.You can pick any rigid body and move it around using the mouse. So lets get started.
The AddRigidBodies function
This function is defined as follows
Lets have a look at this function piece by piece. The AddRigidBodies function first creates a number of blocks. This is similar to how we created the boxes in the Multiple Bouncing Box Tutorial.
Next, we create another loop but this time we create a pair of stiff spring constraints. The constraints are placed in parallel between each pair of boxes. The offsets are calculated based on the size of the box.
Finally, we create the ground rigid body as was seen in earlier tutorials.
The picking and rigid body manipulation functions are virtually unchanged. I simply copied the code from the picking tutorial and it worked without a problem.
Output
That's all, after compiling and building the given code, you will see a chain of boxes. The top most box is fixed to ensure that the chain does not fall down. The rest of the boxes can be picked. You can pick the box by left clicking and dragging the mouse to reposition it 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, left click on box to pick and reposition
Middle click to zoom
Right click to pan
What's next:
In the next tutorial, I will see if I can do a simple cloth using the simple distance constraint object.
Creating a Chain using a Simple Distance Constraint
In the previous tutorial, we saw how we could use a distance constraint to limit a pair of rigid bodies. In this tutorial, I will show you how to use a pair of distance constraints to create a chain of rigid bodies.You can pick any rigid body and move it around using the mouse. So lets get started.
The AddRigidBodies function
This function is defined as follows
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
void AddRigidBodies() { | |
//add the falling box | |
{ | |
hkVector4 halfExtents(0.5f, 0.5f, 0.125f); | |
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) { | |
if(i==(MAX_BOXES-1)) | |
ci.m_motionType = hkpMotion::MOTION_FIXED; | |
ci.m_position = hkVector4(0.0f,1.0f+i*1.125f,0.0f); | |
hkpRigidBody* rigidBody = new hkpRigidBody(ci); | |
boxes.push_back(static_cast<hkpRigidBody*>(g_pWorld->addEntity(rigidBody))); | |
} | |
boxShape->removeReference(); | |
//now add springs between adjacent boxes | |
hkpStiffSpringConstraintData* spring = new hkpStiffSpringConstraintData(); | |
hkpStiffSpringConstraintData* spring2 = new hkpStiffSpringConstraintData(); | |
for(size_t i=0;i<boxes.size()-1;i++) { | |
hkTransform b1 = boxes[i]->getTransform(); | |
hkTransform b2 = boxes[i+1]->getTransform(); | |
hkVector4f t1 = b1.getTranslation(); | |
hkVector4f t2 = b2.getTranslation(); | |
t1.add(hkVector4f(-0.5,0.5,0)); | |
t2.add(hkVector4f(-0.5,-0.5,0)); | |
spring->setInWorldSpace(b1,b2, t1, t2); | |
{ | |
hkpConstraintInstance* constraint = new hkpConstraintInstance(boxes[i], boxes[i+1], spring ); | |
g_pWorld->addConstraint(constraint); | |
constraint->removeReference(); | |
} | |
t1.add(hkVector4f(1,0,0)); | |
t2.add(hkVector4f(1,0,0)); | |
spring2->setInWorldSpace(b1,b2, t1, t2); | |
{ | |
hkpConstraintInstance* constraint = new hkpConstraintInstance(boxes[i], boxes[i+1], spring2 ); | |
g_pWorld->addConstraint(constraint); | |
constraint->removeReference(); | |
} | |
} | |
spring->removeReference(); | |
spring2->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(); | |
} | |
} |
Lets have a look at this function piece by piece. The AddRigidBodies function first creates a number of blocks. This is similar to how we created the boxes in the Multiple Bouncing Box Tutorial.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
hkVector4 halfExtents(0.5f, 0.5f, 0.125f); | |
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) { | |
if(i==(MAX_BOXES-1)) | |
ci.m_motionType = hkpMotion::MOTION_FIXED; | |
ci.m_position = hkVector4(0.0f,1.0f+i*1.125f,0.0f); | |
hkpRigidBody* rigidBody = new hkpRigidBody(ci); | |
boxes.push_back(static_cast<hkpRigidBody*>(g_pWorld->addEntity(rigidBody))); | |
} | |
boxShape->removeReference(); |
Next, we create another loop but this time we create a pair of stiff spring constraints. The constraints are placed in parallel between each pair of boxes. The offsets are calculated based on the size of the box.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//now add springs between adjacent boxes | |
hkpStiffSpringConstraintData* spring = new hkpStiffSpringConstraintData(); | |
hkpStiffSpringConstraintData* spring2 = new hkpStiffSpringConstraintData(); | |
for(size_t i=0;i<boxes.size()-1;i++) { | |
hkTransform b1 = boxes[i]->getTransform(); | |
hkTransform b2 = boxes[i+1]->getTransform(); | |
hkVector4f t1 = b1.getTranslation(); | |
hkVector4f t2 = b2.getTranslation(); | |
t1.add(hkVector4f(-0.5,0.5,0)); | |
t2.add(hkVector4f(-0.5,-0.5,0)); | |
spring->setInWorldSpace(b1,b2, t1, t2); | |
{ | |
hkpConstraintInstance* constraint = new hkpConstraintInstance(boxes[i], boxes[i+1], spring ); | |
g_pWorld->addConstraint(constraint); | |
constraint->removeReference(); | |
} | |
t1.add(hkVector4f(1,0,0)); | |
t2.add(hkVector4f(1,0,0)); | |
spring2->setInWorldSpace(b1,b2, t1, t2); | |
{ | |
hkpConstraintInstance* constraint = new hkpConstraintInstance(boxes[i], boxes[i+1], spring2 ); | |
g_pWorld->addConstraint(constraint); | |
constraint->removeReference(); | |
} | |
} | |
spring->removeReference(); | |
spring2->removeReference(); | |
} |
Finally, we create the ground rigid body as was seen in earlier tutorials.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//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 picking and rigid body manipulation functions are virtually unchanged. I simply copied the code from the picking tutorial and it worked without a problem.
Output
That's all, after compiling and building the given code, you will see a chain of boxes. The top most box is fixed to ensure that the chain does not fall down. The rest of the boxes can be picked. You can pick the box by left clicking and dragging the mouse to reposition it 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, left click on box to pick and reposition
Middle click to zoom
Right click to pan
What's next:
In the next tutorial, I will see if I can do a simple cloth using the simple distance constraint object.