Monday, March 31, 2014

Havok Physics Engine Tutorial Series: Simple Distance Joint

In this tutorial, I will show you how to render a simple distance joint (a basic stiff spring). We will add to the picking code we covered in the last tutorial so that we can displace a given box using the mouse.

The scene in this tutorial contains two boxes: a static box and a dynamic box. The dynamic box and the static box are linked with a distance constraint. We can move the dynamic box using mouse and due to the spring constraint, it maintains a certain distance from the static box. So lets get started. For this demo, the AddRigidBodies function is as follow.
void AddRigidBodies() {
//add the falling movingBox
{
hkVector4 halfExtents(0.5f, 0.5f, 0.5f);
hkpBoxShape* boxShape = new hkpBoxShape(halfExtents);
hkpRigidBodyCinfo ci;
ci.m_shape = boxShape;
ci.m_position = pos2;
ci.m_motionType = hkpMotion::MOTION_DYNAMIC;
boxShape->setRadius(0.001f);
const hkReal boxMass(10.0f);
hkMassProperties massProps;
hkpInertiaTensorComputer::computeShapeVolumeMassProperties(boxShape, boxMass, massProps);
ci.setMassProperties(massProps);
hkpRigidBody* rigidBody = new hkpRigidBody(ci);
movingBox = static_cast<hkpRigidBody*>(g_pWorld->addEntity(rigidBody));
rigidBody->removeReference();
//create the fixed box
ci.m_position = pos1;
ci.m_motionType = hkpMotion::MOTION_FIXED;
rigidBody = new hkpRigidBody(ci);
fixedBox = static_cast<hkpRigidBody*>(g_pWorld->addEntity(rigidBody));
rigidBody->removeReference();
boxShape->removeReference();
}
//create the static box where the smaller movingBox 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();
}
//
// CREATE STIFF SPRING CONSTRAINT
//
{
hkpStiffSpringConstraintData* spring = new hkpStiffSpringConstraintData();
// Create constraint
spring->setInWorldSpace(movingBox->getTransform(), fixedBox->getTransform(), pos2, pos1);
//
// Create and add the constraint
//
{
hkpConstraintInstance* constraint = new hkpConstraintInstance(movingBox, fixedBox, spring );
g_pWorld->addConstraint(constraint);
constraint->removeReference();
}
spring->removeReference();
}
}
view raw Distance_01 hosted with ❤ by GitHub


Adding a spring constraint
The only difference here is the addition of the stiff spring constraint. To create it, we first create the hkpStiffSpringConstraintData object. We then pass it the world space position of where the spring is located along with the two rigid bodies between which this constraint is created. Next,
the hkpStiffSpringConstraintData object and the two rigid bodies are passed to the hkpConstraintInstance object and then hkpWorld::addConstraint function is called passing it the hkpConstraintInstance object as shown in the following code snippet.

hkpStiffSpringConstraintData* spring = new hkpStiffSpringConstraintData();
// Create constraint
spring->setInWorldSpace(movingBox->getTransform(), fixedBox->getTransform(), pos2, pos1);
// Create and add the constraint
{
hkpConstraintInstance* constraint = new hkpConstraintInstance(movingBox, fixedBox, spring );
g_pWorld->addConstraint(constraint);
constraint->removeReference();
}
spring->removeReference();
view raw Distance_02 hosted with ❤ by GitHub


Rendering of the spring constraint
Another change we did is in the render function. It is now changed to render the spring constraint as well along with the two rigid bodies. The picked dynamic rigid body is rendered green when picked.
//draw spring
glBegin(GL_LINES);
glColor3f(0,1,0);
glVertex3f(pos1.getComponent(0), pos1.getComponent(1), pos1.getComponent(2));
glVertex3f(pos2.getComponent(0), pos2.getComponent(1), pos2.getComponent(2));
glEnd();
//draw boxes
glEnable(GL_LIGHTING);
glColor3f(1,1,1);
DrawBox(fixedBox);
if(wasHit)
glColor3f(0,1,0);
DrawBox(movingBox, true);
glDisable(GL_LIGHTING);
view raw Distance_03 hosted with ❤ by GitHub


Output
That's all, after compiling and running, you will see two boxes linked with a spring constraint. You can pick the lower (dynamic) box by left clicking and dragging the mouse to reposition it as shown in the following figure.


After displacement, the spring constraint acts on the dynamic rigid body to ensure that it remains at the fixed distance that was given at the time of instantiation of the constraint.

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 show you how to create a simple chain.

2 comments:

Unknown said...

How do you control the stiffness of spring

MMMovania said...

You can use the restlength parameter of stiff spring. Check the members of hkpStiffSpringConstraintData class

Popular Posts

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