Wednesday, April 27, 2011

PhysX Basics Tutorial: A Simple Bouncing Box


In this tutorial, I will show you how to create a simple box at a specific position and let it bounce under influence of gravity. We will be adding to the code base from the previous tutorials. We first create the PhysX sdk object and store it into a global pointer like this,
#include <iostream>

#include <GL/freeglut.h>

#include <NxPhysics.h>



#pragma comment(lib, "PhysXLoader.lib")



NxPhysicsSDK* gPhysicsSDK = NULL;

NxScene* gScene = NULL;

NxActor* groundPlane; 

NxActor* box; 



NxReal myTimestep = 1.0f/60.0f;



void InitializePhysX() {

   gPhysicsSDK = NxCreatePhysicsSDK(NX_PHYSICS_SDK_VERSION);

   if(gPhysicsSDK == NULL) {

      cerr<<"Error creating PhysX device."<<endl;

      cerr<<"Exiting..."<<endl;

      exit(1);

   }

In the above lines, we just store pointers to the PhysX sdk object, the scene object and two actors (our ground plane and the box) and the timeStep value for stepping the PhysX simulation.

   //Create the scene

   NxSceneDesc sceneDesc;

   sceneDesc.gravity.set(0.0f, -9.8f, 0.0f); 

   gScene = gPhysicsSDK->createScene(sceneDesc);



In PhysX any physics object you want to make, you need to fill a relevant descriptor and then pass that descriptor to the sdk function (through the PhysX sdk pointer) responsible for creating the object for you. In this case, we ask PhysX to set up the global scene gravity to 9.8 m/s^2 The -ve sign is to make it point downwards.

   NxMaterial* defaultMaterial = gScene->getMaterialFromIndex(0);

   defaultMaterial->setRestitution(0.5);

   defaultMaterial->setStaticFriction(0.5);

   defaultMaterial->setDynamicFriction(0.5);



   gScene->setTiming(myTimestep / 4.0f, 4, NX_TIMESTEP_FIXED);

In the above lines, we set the default material's physical properties like static and dynamic friction and the coefficient of restitution. Next, we set the update timing for the PhysX sdk. We ask the sdk to use a fix time stepping. For the simple demo like this, fixed time steps should suffice.
Creating actors
   //Create actors 

   //1) Create ground plane

   NxPlaneShapeDesc planeDesc;

   NxActorDesc actorDesc, actorDesc2;

   actorDesc.shapes.pushBack(&planeDesc);

   gScene->createActor(actorDesc);



   //2) Create cube  

   NxBodyDesc bodyDesc;

   bodyDesc.angularDamping = 0.75f;

   bodyDesc.linearVelocity = NxVec3(0,0,0);

   NxBoxShapeDesc boxDesc;

   boxDesc.dimensions = NxVec3(0.5, 0.5, 0.5);

   actorDesc2.shapes.pushBack(&boxDesc);

   actorDesc2.body   = &bodyDesc;

   actorDesc2.density  = 1.0f;

   actorDesc2.globalPose.t  = NxVec3(0,10,0);

   gScene->createActor(actorDesc2);

}

In the above lines, we create two actors for the ground plane and the box. For each of these actors, their descriptors are filled first to allow us to adjust the parameters. For the ground plane, the default parameters create a ground plane at origin and a positive Y normal direction. Once created, the actor descriptor is given to the scene's createActor function. Next, the same steps are taken for the box. In case of box however the body descriptot is first filled to store the box's linear velocity and angular damping. Then the box's shape descriptor is filled to fill its dimensions. This shape is then adde to the actors shapes list. Next, the actor descriptor sets the body, density and the initial position (globalPose.t). Finally, the createActor function is invoked again. Thats it, we have successfully added the two actors to the PhysX engine.

Handling PhysX stepping loop
Once the actor stuff is done, the next thing we need to handle is the PhysX loop. This will allow the simulation to step ahead in time. We will implement an asynchronous loop which can be done using the following lines of code.
void StepPhysX() 

{ 

   gScene->simulate(myTimestep);        

   gScene->flushStream();        

   //...perform useful work here using previous frame's state data        

   while(!gScene->fetchResults(NX_RIGID_BODY_FINISHED, false) )     

   {

      // do something useful        

   }

} 

These lines were copied directly from the documentation so rather than commenting anything on these, I would ask you to go and read the asynchronous loop section in the PhysX documentation. We will call this function once from our display function.

Rendering of Actors
The next step is to render the actors. To make easier for use to work with PhysX, I have modularized the code into functions. First, the RenderActors() function is implemented as follows,
void RenderActors() 

{ 

    // Render all the actors in the scene 

    int nbActors = gScene->getNbActors(); 

    NxActor** actors = gScene->getActors(); 

    while (nbActors--) 

    { 

        NxActor* actor = *actors++; 

        DrawActor(actor); 

    } 

} 

Nothing fancy here, we first query the scene for the total number of actors it contains. Then, we loop through each actor and draw it by calling the DrawActor function. The DrawActor function is implemented as follows,

 

void DrawActor(NxActor* actor) 

{ 

    NxShape* const* shapes = actor->getShapes(); 

    NxU32 nShapes = actor->getNbShapes(); 

     

    while (nShapes--) 

    { 

        DrawShape(shapes[nShapes]); 

    } 

} 

It looks a lot like the previous function doesn't it. It basically ask the actor for the number of shapes it has and then calls the DrawShapes function with the shape parameter. The DrawShape function is implemented as follows,

void DrawShape(NxShape* shape) 

{ 

   int type = shape->getType();

   switch(type) 

   {          

      case NX_SHAPE_BOX:

         DrawBox(shape);

      break;

   } 

} 

This function first identifies the type of the shape and then uses a switch case to call the appropriate Draw function. For our case, we check for the Box object and then call the DrawBox function passing it the shape parameter. THe DrawBox function is implemented as follows,

void DrawBox(NxShape* pShape) {

   NxMat34 pose = pShape->getGlobalPose(); 

   float mat[16];

   pose.getColumnMajor44(mat);

   glPushMatrix(); 

      glMultMatrixf(mat);

      glutSolidCube(1);

   glPopMatrix(); 

}

The DrawBox function gets the current Global pose (basically the shapes tranform matrix) and then converts it into a column major form (so that we can pass this matrix to OpenGL). Next, the currnet transformation matrix is stored (glPushMatrix) and then the box's matrix is multiplied to the current matrix. Then, we draw the box's geometry (using the glutSolitCube function) and finally revert the old transformation back by calling glPopMatrix.

The Display Function
Now after these function definitions, the display function becomes this,
void Display() {

   glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

   glLoadIdentity();

   //setup the view transformation using 

   //gluLookAt(...);



   //Update PhysX 

   if (gScene) 

   { 

       StepPhysX(); 

   }   



   RenderActors();



   glutSwapBuffers();

}


That's it. Attached is the complete source code for this tutorial. Here is the snapshot of the application.
PhysX Simple Box

Source code for this tutorial

38 comments:

Ovidiu said...

Hi there !
I was trying to run your sample code and I get this error:

Unhandled exception at 0x00c44b6c in SimpleBox.exe: 0xC0000005: Access violation reading location 0x00000000.
at the line gPhysicsSDK->releaseScene(*gScene);

And it also fails to create the PhysX device:

Error creating PhysX device.
Exiting...

Ovidiu said...

I found out what the problem was... I forgot to put PhysXLoader.dll and PhysXCore.dll in the exe folder !

Mobeen said...

Hi Ovidiu,
I am glad that you found it out yourself.

antonio said...

Hi!!
I was trying to run your sample code but with Physx 3.0

so I have many problems with your code...

Do you think you can use your code with the new version?

I should create a cube and a sphere with the new version ...
But I do not understand very much ..
thanks

Mobeen said...

Hi,
IN PhysX 3 the API has been changed considerably so i would need to look into the details. I will convert the tutorials to PhysX 3 and revert asap.

antonio said...

well,
I'm trying to do this conversion
but, as you say, is very different ...
I'm trying to change the examples of 3.0
but it is not easy for me, becuase, I'm still to the first experiences

Mobeen said...

Hi,
I have already added the PhysX3 conversions. I hope they are easy to follow. The new PhysX3 samples are not as good as what the aerlier versions were and so I think my tutorials would help in filling the gap.

antonio said...

Hi!!
thank you very much
I tried the new version ...
after arranging the various files, I managed to get it to work ...
congratulations you have been really good, in so a short time ...
thanks again!!!

antonio said...

but I found a little error...

here:

void ShutdownPhysX() {
gScene->removeActor(box);
gScene->release();
box->release();
gPhysicsSDK->release();

when you call the function "removeActor(box)" it isn't correct

the correct is
"removeActor(*box)"
and now the files RUN
thanks again

Mobeen said...

thanks for the correction antonio. I would make the changes in the zip file. One more thing, do u think i should do cloth also? I am not sure if PhysX3 has a decent cloth support but I can do cloth in PhysX 2.8.x?

Mobeen said...

What other topic should I cover? Currently I will be adding basic joint as I did for PhysX2.8.

antonio said...

Hi!
Look at the examples that are on site,
I believe there is no example where we take the objects and can move, maybe even deform ...
regarding the clothes, I think it possible, in video games do ...
but I think it is not easy ... especially with the new version, 3.0, I'm trying to understand.
I think to create objects, move them or place them on the floor with the opportunity to cover with a blanket, so you can see the behavior of an object clothes.

Mobeen said...

Hi Antonio,
Regarding moving an object i think u can modify the picking tutorial to do that. Currently, the picked object is attached to a distance joint, u may remove this and instead move the object directly.
As for cloth, I dont think PhysX3 has any support for cloth. I only sae PxDeformable for doing Deformable objects which I will try to see if I could do a short demo on deformable object. Other than that the new version is severly lacking in what was previouly the edge of PhysX i.ie the cloth.

antonio said...

I just finished making the case of multiple objects, different that move ... nice.
now I wish I could get the values ​​of force applied to objects ...
or at least be able to apply forces to objects ....
for the clothes ... I do not know how to do
it is very difficult!

Mobeen said...

I have done cloth in the previous v of PhysX 2.8.x.

Pozarnik said...

I've also run into a problem having the Access Violation at createActor. However, the debugger indicates that the dll's are loading (Loader, Core, and cudart). Is there any other reason that I might get his error?

Mobeen said...

Hi Pozarnik,
You should recheck the version of PhysX dlls are they the same?
Another thing you can do is just try the getting started tutorial which is just creating PhysX device.
See if this helps.

Rahat said...

check this physxloader dll post ..and get your solution

milton said...

In the DrawActor() function there are the lines:

NxU32 nShapes = actor->getNbShapes();

nShapes = actor->getNbShapes();

It would appear there is a duplicate assignment of getNbShapes() to nShapes, not that this should matter performance-wise in any perceivable way, just thought I'd point it out as an innocuous mistake.

I was surprised to see that nobody else had yet pointed it out, which worries me about all the layers of 'work' done by the endless number of mystery coders, running invisibly behind the scenes on *my* hardware throughout OS/drivers/applications at times when striving for optimum system performance..

As coders we must never trust our own work to be correct and accurate, and must eye it suspiciously at all times in search of our own mistakes, for they will always be there.

Thank you for the article :)

Muhammad Mobeen Movania said...

Thanks for your response milton, highly appreciated. I will correct it right away.

Zohaib Akmal said...

The design look great though! Hope you get
the problem fixed soon. Many thanks
TEAMVIEWER 9 LICENSE CODE

Shahzad Hashmi said...

I need to to thank you for this very good read!! I definitely loved every bit of it.
I’ve got you book-marked to look at new stuff you post…Adobe Premiere Pro Cs6 Serial Number

Muhammad Mobeen Movania said...

Thanks Shahzad,
Glad it was helpful.

WALEED HASHMI said...

thanks for sharing. .

Muhammad Mobeen Movania said...

You are always welcome Waleed

WALEED HASHMI said...

Nice Work Bro Keep it up Your Blogg is Awesome Work Over Heir Really Great Full for Your Coment Back Thanks : winzip-19-pro-full-version-with-crack

Muhammad Mobeen Movania said...

Thanks Waleed and I am glad it has helped you.

atifa bushra said...

Hello Sir,
What a great site you have made...Its totally fabulous and I am really amazed to see your site.You have really worked hard on this site.
Cloude System Booster Pro 3.6

Muhammad Mobeen Movania said...

Thanks Atifa for apperciation.

Shahzad Hashmi said...

thanks for the great site and data thanks Mobeen for this awesome site..Resoftonic

Muhammad Mobeen Movania said...

You are welcome Shahzad

Yousaf Bhatti said...

I’m extremely pleased to discover this great site Mr. M. Mobeen
I want to to thank you for ones time for this particularly wonderful read!!
I definitely enjoyed every little bit of it and i also have you saved
as a favorite to check out new stuff on your web site
Windows 10 Activator Crack 64 Bit

Muhammad Mobeen Movania said...

Thanks Yousaf Bhatti for appeciation. Glad it was helpful.

Weiner jones110 said...

This is nice site with amazing info. I have spent here very much time. have read all discussion. nice work and good performance you have. bookmarked your site for further information. Thanks.
google sketchup pro 2016 patch

Rizwan Amjad said...

nice post we are impressed Hideman vpn,

Shahzad Hashmi said...

thanks for the great post it was really helpful to me.

R-Studio 7.7 Serial

Unknown said...

How would i convert this to PhysX 3.2.4?

Muhammad Mobeen Movania said...

Check this out: http://mmmovania.blogspot.com/2011/05/simple-bouncing-box-physx3.html

Popular Posts

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