Friday, March 28, 2014

Havok Physics Engine Tutorial Series: A Simple Bouncing Box

OK Now that we know how to setup Havok SDK on VisualStudio 2012. If not, you may want to go through my first tutorial which tells you how to get started with the new Havok SDK. In this tutorial, similar to my PhysX Tutorials, I start with a very simple box falling on the floor due to gravity.

In this tutorial, the InitializeHavok function is changed to the following.

I have highlighted the new additions in bold. Similar to the first tutorial, we initialize the memory, physics world settings and the visual debugger. After that, we lock the Havok physics world, then add our rigid bodies to the world and then we unlock the world. This is done to ensure that no two threads may access the world at the same time. All functions that may effect the physics world should be called by sandwiching them inside the world lock/unlock call.

Adding rigid bodies:
Similar to other physics engines like PhysX and Bullet, Havok also adds rigid bodies to the physics world by first specifying shape and its properties like moment of inertia tensor. In the tutorial, I add these in using the AddRigidBodies function which is defined as follows.

Lets take a closer look at this function piece by piece. In this tutorial, we will allow a box to fall under gravity on a flat floor. We have purposely created two scopes to highlight the two added rigid bodies. In the first scope, we create a dynamic rigid body, a simple box that falls under gravity.

In the above lines, we first specify the box's shape(hkpBoxShape) by passing it the half extents of the box.

In the above lines, after we specify the box's shape, we have to fill in the rigid body info structure which stores the shape as well as other rigid body dynamics properties like mass, moment of inertia, position, motion type etc. We then set its motion state to be dynamic (MOTION_DYNAMIC). If we want to make the rigid body static, we set the motion state to MOTION_FIXED. For all physics object, a collision margin is specified which controls the offset at which the collision is detected. We set the value to 0.001 which creates a very thin offset. If we left this line out, the box will collide at a much higher position than what is visible.

In the above lines, we first calculate the box's moment of inertia and then specify the mass properties.
Once the rigidbody cinfo structure is filled, we can create a rigid body from it using the following code.

Note that once the rigid body has been created, we can delete the box shape. We do so by making a call to removeReference function. This is the recommended approach to delete objects in Havok rather than calling the delete function.  After this call, we add the rigid body to the physics world by calling g_pWorld->addEntity function passing it the rigid body. On success, the returned reference contains the created rigid body entity. After this call, we can safely remove the reference to the rigid body to ensure that we always have a single reference to the rigid body.

In case of the static box (our floor), the only difference is in the motion state which is set at MOTION_FIXED. The rest of the code is same.

Obtaining the box's transform:
If all goes well, once we add the rigid body into the world, it starts to simulate. The step function calculates the next transform for all rigid bodies in the world taking into account their collisions and collision responses. For rendering or any other purposes, we need to know the local transform of the dynamic box. In order to prevent two threads from accessing the same object, Havok mandates that all world objects and their properties should be read inside a hkpWorld->lockForRead/unlockForRead fuction pair as follows.

Now to access the matrix of the given box, we first call the box rigid body's approxCurrentTransform function that calculates the box's transformation matrix. Next, we store the matrix into a local variable. Using the local matrix varible, we fill our float array which we then pass to the rendering API. 

Drawing the box:
If we are successful, the mat array contains our 4x4 matrix. In OpenGL, we can then multiply this matrix to the current modelview matrix and then the object is placed and oriented in the 3D graphics world using the transform calculated by the Havok physics engine.

For all those modern OpenGL lovers, I know this is legacy OpenGL code but my point is to preset the concept. You can convert this to modern OpenGL if required without a problem by using math libraries like glm.

That's all, the accompanying tutorial code should give you a simple box falling under gravity on the grid plane as shown in the following figure.  

You can get the full source code from my github repo

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 add multiple boxes.



Popular Posts

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