Saturday, April 30, 2011

PhysX Basics Tutorial: Joint Basics



In this tutorial, we will see how to create a simple distance joint. We will reuse the picking code in this tutorial to make things a bit more interesting. So without any further ado, lets get started. We will create two boxes one of which will be a static object. The other box will be manipulated by the mouse hence it will be dynamic.
Creating the boxes
The dynamic box
We simply call the box descriptor as discussed in the past tutorials. Nothing new here.

NxBodyDesc bodyDesc;
bodyDesc.angularDamping = 0.75f;
bodyDesc.linearVelocity = NxVec3(0,0,0);

NxBoxShapeDesc boxDesc;
size_t box_size = 1;
boxDesc.dimensions = NxVec3(box_size/2.0f, box_size/2.0f, box_size/2.0f);

actorDesc2.shapes.pushBack(&boxDesc);
actorDesc2.body = &bodyDesc;
actorDesc2.density = 1.0f;
actorDesc2.globalPose.t = NxVec3(0.0f,3.0f,0.0f);

NxActor* dynamicBox = gScene->createActor(actorDesc2);
dynamicBox->userData= (void*)box_size;


The static box
For static box, we simply create the actor as before and then raise the body flag to be NX_BF_FROZEN.

//create another box which is static
actorDesc2.globalPose.t = NxVec3(0.0f,5.0f,0.0f);

NxActor* staticBox = gScene->createActor(actorDesc2);
staticBox->userData= (void*)box_size;
staticBox->raiseBodyFlag(NX_BF_FROZEN);


Creating joint
For creating a very basic distance joint, we need to fill in the descriptor called
NxDistanceJointDesc. The first things we will give it are the actors that the joint links.

//create a joint
NxDistanceJointDesc desc;
desc.actor[0] = dynamicBox;
desc.actor[1] = staticBox;

For this, we store the references returned from createActor function as shown in the previous section. Next, we specify the different properties of the joint descriptor.
The max/minDistance denote the limits of stretch/compression for this joint respectively.

desc.maxDistance = 2.0f;
desc.minDistance = 1.0f;

The damper determines how damped the springiness of the spring is. A high value dampens the spring and vice verse for spring value.

desc.spring.damper = 1.0f;
desc.spring.spring = 200.0f;

The next two lines are very important. The first setsup the desc's flags. This controls whether the min, max limit of the distance joint, and the spring in the distance joint is enabled. If you dont add these flags, there will be no limit and no springiness to the joint. Likewise the jointFlags are also important. If u want that the actors connected to the distance joint collide, you must pass the NX_JF_COLLISION_ENABLED flag to the jointFlags descriptor. Finally, the spring is created as any other object that we have covered in the past tutorials.

desc.flags |= NX_DJF_MIN_DISTANCE_ENABLED | NX_DJF_MAX_DISTANCE_ENABLED | NX_DJF_SPRING_ENABLED;
desc.jointFlags |= NX_JF_COLLISION_ENABLED;
gScene->createJoint(desc);


Rendering of the distance joint
For rendering of the distance joint, we do a fairly simple thing by creating a global array for 2 NxVec3 types. When we are about to draw the box actors, we store their current positions in the global array so the new DrawCube function is this,

//Stored globally
NxVec3 pos[2]; //for storing the two end points of spring

void DrawBox(NxShape* pShape, size_t size) {
static int count=0;
pos[(count++)%2] = pShape->getGlobalPosition();
NxMat34 pose = pShape->getGlobalPose();
float mat[16];
pose.getColumnMajor44(mat);
glPushMatrix();
glMultMatrixf(mat);
glutSolidCube(size);
glPopMatrix();
}

Next, in the render function, we draw the line between the two positions just stored.

glColor3f(gMouseJoint!=NULL,gMouseJoint==NULL,gMouseJoint==NULL);
//Draw the spring
glBegin(GL_LINES);
glVertex3f(pos[0].x, pos[0].y, pos[0].z);
glVertex3f(pos[1].x, pos[1].y, pos[1].z);
glEnd();


That's it we have a simple distance joint between two boxes. Here is the snapshot from this application.

PhysX Basics

Source code of this tutorial

0 comments:

Popular Posts

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