Lesson 101 – Primary Shape
Introduction
This is the first lesson in the Rigid Body chapter of the PhysX SDK. In this lesson, you
will create an instance of the SDK, create a scene, create four actors (a ground plane, a
capsule, a sphere and a box), simulate the other three actors on the plane actor, and apply
global forces to the box by keyboard action during the simulation.
Copyright (c) 2008 NVIDIA Corporation. All rights reserved.
http://www.NVIDIA.com
1
1 Initializing the SDK and Creating a Scene
In each of the lessons, you need to create an instance of the PhysX SDK to build your
simulation. This is done in the function InitNx(). The following block of code is all
you need to initialize the PhysX SDK and create a scene.
#include "Lesson101.h"
// Physics SDK globals
NxPhysicsSDK*
gPhysicsSDK = NULL;
NxScene*
gScene = NULL;
NxVec3
gDefaultGravity(0,-9.8,0);
void InitNx()
{
// Create the physics SDK
gPhysicsSDK = NxCreatePhysicsSDK(NX_PHYSICS_SDK_VERSION);
if (!gPhysicsSDK) return;
// Create the scene
NxSceneDesc sceneDesc;
sceneDesc.gravity
= gDefaultGravity;
gScene = gPhysicsSDK->createScene(sceneDesc);
}
void main(int argc, char** argv)
{
InitNx();
}
From main(), we call InitNx(). InitNx() makes an instance of the physics SDK,
gPhysicsSDK, and creates a scene, gScene. This is probably the simplest PhysX
application possible. This will compile and run.
2 Setting Parameters for the SDK
Now we add parameters to the SDK to flesh out our simulation.
// Set the physics parameters
gPhysicsSDK->setParameter(NX_SKIN_WIDTH, 0.01);
The first parameter is a global physics parameter used by the SDK called skin width. It
is an important parameter, basically a “grace-depth” the SDK allows objects to penetrate
each other by. For now, we are setting it manually to 0.01 (an absolute depth of 0.01m
or 1cm). If we don’t add this line, it will default to 0.025 (0.025m or 2.5cm).
Copyright (c) 2008 NVIDIA Corporation. All rights reserved.
http://www.NVIDIA.com
2
// Set the debug visualization parameters
gPhysicsSDK->setParameter(NX_VISUALIZATION_SCALE, 1);
gPhysicsSDK->setParameter(NX_VISUALIZE_COLLISION_SHAPES, 1);
gPhysicsSDK->setParameter(NX_VISUALIZE_ACTOR_AXES, 1);
These are debug visualization parameters we are setting for the simulation. We are
saying when we switch to Debug Wireframe Mode, we want debug vectors to be 1 meter
in length and we want to see all the collision shapes in the scene and the global poses of
all the actors.
3 Creating the Scene
We have adjusted all the parameters we want to the SDK and added a default material for
objects to be constructed from. Now we create the scene.
// Create the scene
NxSceneDesc sceneDesc;
sceneDesc.gravity
sceneDesc.simType
= gDefaultGravity;
= NX_SIMULATION_SW;
gScene = gPhysicsSDK->createScene(sceneDesc);
We start out with a scene descriptor which we feed to the SDK to create our scene.
Descriptors are widely used throughout the SDK. They are structures that contain all the
information you want your object to be created with. You can adjust the descriptor to
taste or leave it alone and the object will be created with the descriptor’s default settings.
In the above case, we want to create a software scene with the gravity vector provided.
To create a software scene, set the simulation type to NX_SIMULATION_SW .
4 Adding Materials to the Scene
You want to give the scene a default physical material that everything will be made of.
A material defines the collision and surface properties of the object the material is
assigned to, that is, how the object will bounce, slide, and roll off other objects.
// Create the default material
NxMaterial* defaultMaterial = gScene->getMaterialFromIndex(0);
defaultMaterial->setRestitution(0.5);
defaultMaterial->setStaticFriction(0.5);
defaultMaterial->setDynamicFriction(0.5);
This says all objects in the scene are made of a substance with average bounciness
(restitution of 0.5) and average resting and sliding friction (static friction of 0.5 and
dynamic friction of 0.5).
Copyright (c) 2008 NVIDIA Corporation. All rights reserved.
http://www.NVIDIA.com
3
5 Creating the Actors in the Scene
At the end of InitNx(), we add our actors, the box and the plane, to the scene.
// Actor globals
NxActor* groundPlane = NULL;
NxActor* box = NULL;
…
void InitNx()
{
…
// Create the objects in the scene
groundPlane = CreateGroundPlane();
gSelectedActor = CreateBox();
CreateSphere();
CreateCapsule();
…
}
6 Creating the Ground Plane
We will be using a ground plane in most of our simulations and we add it here.
void InitNx()
{
...
groundPlane = CreateGroundPlane();
...
}
Look at the function CreateGroundPlane().
NxActor* CreateGroundPlane()
{
// Create a plane with default descriptor
NxPlaneShapeDesc planeDesc;
NxActorDesc actorDesc;
actorDesc.shapes.pushBack(&planeDesc);
return gScene->createActor(actorDesc);
}
This is probably the simplest actor creation function. The ground plane actor is
initialized with an actor descriptor. The actor descriptor is initialized with the default
plane descriptor, so the ground plane passes through the origin (0,0,0) with normal along
Copyright (c) 2008 NVIDIA Corporation. All rights reserved.
http://www.NVIDIA.com
4
the positive y-axis (0,1,0). The plane has no rigid body assigned to it, so it is a static
actor: it will not move and will push dynamic objects away from it as if it had infinite
mass.
7 Creating the Box
We now create our box. It is a single actor consisting of a single shape.
void InitNx()
{
...
box = CreateBox();
...
}
The CreateBox() function is as follows.
NxActor* CreateBox()
{
// Set the box starting height to 3.5m so box starts off falling onto the ground
NxReal boxStartHeight = 3.5;
// Add a single-shape actor to the scene
NxActorDesc actorDesc;
NxBodyDesc bodyDesc;
// The actor has one shape, a box, 1m on a side
NxBoxShapeDesc boxDesc;
boxDesc.dimensions.set(0.5,0.5,0.5);
actorDesc.shapes.pushBack(&boxDesc);
actorDesc.body
= &bodyDesc;
actorDesc.density
= 10.0f;
actorDesc.globalPose.t = NxVec3(0,boxStartHeight,0);
assert(actorDesc.isValid());
NxActor *pActor = gScene->createActor(actorDesc);
assert(pActor);
// //create actor with no shapes
//NxShape* const *shape = pActor->getShapes();
//NxBoxShape *boxShape = shape[0]->isBox();
//assert(boxShape);
//pActor->releaseShape(*boxShape);
return pActor;
Copyright (c) 2008 NVIDIA Corporation. All rights reserved.
http://www.NVIDIA.com
5
}
We are creating an actor in the scene called “box”. To create the actor we need to pass
an actor descriptor defining the actor to NxScene::createActor(). We give actorDesc a
single shape descriptor, boxDesc. boxDesc describes a box that is one meter on a side.
We set its dimensions using half the length, width, and height of the box with
boxDesc.dimensions.set(0.5, 0.5, 0.5). Then we attach a body to the actor, bodyDesc,
give the actor a density of 10, and set its global position to (0,boxStartHeight,0), meaning
the center of the box will be at boxStartHeight = 3.5 meters above the ground at the
beginning of the simulation.
Our actor consists of a single shape, a box 1m on a side, centered at (0,
boxStartHeight,0), and having a density 10. When we call NxScene::createActor(), the
rigid body we attached to the actor, bodyDesc, will be computed given the box shape and
density we have constructed the actor with.
8 Initializing the HUD
We create a heads-up-display object that displays whether or not the scene is running in
hardware, whether or not the scene is paused, as well as additional information as needed
by the tutorial.
// HUD globals
HUD hud;
…
// Simulation globals
…
bool bHardwareScene = false;
bool bPause = false;
…
void InitNx()
{
…
// Initialize HUD
bHardwareScene = (gScene->getSimType() == NX_SIMULATION_HW);
hud.Update(bHardwareScene, bPause, "");
…
}
The HUD class and its member variables and functions are defined in HUD.cpp and
HUD.h.
9 Updating the Time
Next we call UpdateTime().
Copyright (c) 2008 NVIDIA Corporation. All rights reserved.
http://www.NVIDIA.com
6
UpdateTime.h
NxReal UpdateTime()
{
NxReal deltaTime;
#ifndef LINUX
static __int64 gTime,gLastTime;
__int64 freq;
QueryPerformanceCounter((LARGE_INTEGER *)&gTime); // Get current count
QueryPerformanceFrequency((LARGE_INTEGER *)&freq); // Get processor freq
deltaTime = (double)(gTime - gLastTime)/(double)freq;
gLastTime = gTime;
#else
struct timeval tv;
static struct timeval lasttv = { 0 , 0 };
if (lasttv.tv_usec == 0 && lasttv.tv_sec == 0)
gettimeofday(&lasttv, NULL);
gettimeofday(&tv, NULL);
deltaTime = (tv.tv_usec - lasttv.tv_usec)/1000000.f
+ (tv.tv_sec - lasttv.tv_sec);
lasttv = tv;
#endif
return deltaTime;
}
Lesson101.h
void InitNx()
{
...
// Get the current time
UpdateTime();
...
}
This sets gTime to the current time. Every frame we call UpdateTime() to get
deltaTime, the amount of time that has passed since we last rendered the scene and
therefore the amount of time we need to advance the simulation to render the current
scene.
10 Starting the First Frame of the Simulation
Finally, we call StartPhysics() to start the first frame of the simulation.
Copyright (c) 2008 NVIDIA Corporation. All rights reserved.
http://www.NVIDIA.com
7
void InitNx()
{
...
// Start the first frame of the simulation
if (gScene) StartPhysics();
}
…
void StartPhysics()
{
// Update the time step
gDeltaTime = UpdateTime();
// Start collision and dynamics for delta time since the last frame
gScene->simulate(gDeltaTime);
gScene->flushStream();
}
11 Getting the Results of the Simulation
We have initialized the SDK and created our scene with InitNx(). Now we call
glutMainLoop() from main().
int main(int argc, char** argv)
{
PrintControls();
InitGlut(argc, argv);
InitNx();
glutMainLoop();
ReleaseNx();
return 0;
}
The program will stay in glutMainLoop() until the user ends the simulation. After a
scene is rendered, the RenderCallback() callback function gets called where we set up the
next scene. At the beginning of RenderCallback(), we call NxScene::fetchResults() from
GetPhysicsResults() to get the results of our physics simulation since our last call to
NxScene::simulate() from StartPhysics().
void RenderCallback()
{
...
if (gScene && !bPause)
{
GetPhysicsResults();
Copyright (c) 2008 NVIDIA Corporation. All rights reserved.
http://www.NVIDIA.com
8
ProcessInputs();
StartPhysics();
}
…
}
…
void GetPhysicsResults()
{
// Get results from gScene->simulate(deltaTime)
while (!gScene->fetchResults(NX_RIGID_BODY_FINISHED, false));
}
We call NxScene::fetchResults(NX_RIGID_BODY_FINISHED, false) to close out the
simulation started on the last call to NxScene::simulate(). The
“NX_RIGID_BODY_FINISHED” parameter specifies that we want to close out the
simulation of rigid bodies for this time step. The “false” parameter specifies that the call
is non-blocking. We will not block waiting for the rigid body simulation to finish. If
we put “true” here, instead:
void GetPhysicsResults()
{
// Get results from gScene->simulate(deltaTime)
gScene->fetchResults(NX_RIGID_BODY_FINISHED, true);
}
...the NxScene::fetchResults() call will not return at all until the simulation is finished.
With our call, we continually query to see if the simulation is finished and don't break out
of the loop until the funciton returns true. We could use this space to execute additional
code in case the physics for the frame is not yet finished.
void GetPhysicsResults()
{
// Get results from gScene->simulate(deltaTime)
while (!gScene->fetchResults(NX_RIGID_BODY_FINISHED, false))
{
// Execute additional code here for rendering, AI, etc.,
// while waiting for the rigid body simulation to finish
...
}
}
Copyright (c) 2008 NVIDIA Corporation. All rights reserved.
http://www.NVIDIA.com
9
12 Processing Inputs to the Simulation
We then call ProcessInputs() to collect all physics inputs to the new scene and set up any
callbacks for the new scene. Here we apply forces to the box, set the position of the box,
and set up callbacks, namely the user debug renderer, for the next simulation step.
void RenderCallback()
{
...
if (gScene && !bPause)
{
GetPhysicsResults();
ProcessInputs();
StartPhysics();
}
…
}
...
void ProcessInputs()
{
ProcessForceKeys();
// Show debug wireframes
if (bDebugWireframeMode)
{
if (gScene) gDebugRenderer.renderData(*gScene->getDebugRenderable());
}
}
1. Selecting Actors
Press ‘r’ to call SelectNextActor to select other actor. The selected actor is rendered in
wireframe mode. The actor with NX_TRIGGER_ENABLE flag and static actor can’t be
selected.
void SelectNextActor()
{
NxU32 nbActors = gScene->getNbActors();
NxActor** actors = gScene->getActors();
for(NxU32 i = 0; i < nbActors; i++)
{
if (actors[i] == gSelectedActor)
{
NxU32 j = 1;
gSelectedActor = actors[(i+j)%nbActors];
while (!IsSelectable(gSelectedActor))
{
Copyright (c) 2008 NVIDIA Corporation. All rights reserved.
http://www.NVIDIA.com
10
j++;
gSelectedActor = actors[(i+j)%nbActors];
}
break;
}
}
}
2. Applying Forces to the Actors
Our first call is to ProcessForceKeys(), where we call ApplyForceToActor() on our actor.
// Force globals
NxVec3
gForceVec(0,0,0);
NxReal
gForceStrength = 20000;
bool
bForceMode = true;
…
// Keyboard globals
#define MAX_KEYS 256
bool gKeys[MAX_KEYS];
…
void ProcessForceKeys()
{
// Process force keys
for (int i = 0; i < MAX_KEYS; i++)
{
if (!gKeys[i]) { continue; }
switch (i)
{
…
// Force controls
…
case 'j': {gForceVec = ApplyForceToActor(gSelectedActor, NxVec3(1,0,0),
gForceStrength); break; }
…
}
}
}
...
void ProcessInputs()
{
ProcessForceKeys();
...
}
Copyright (c) 2008 NVIDIA Corporation. All rights reserved.
http://www.NVIDIA.com
11
ApplyForceToActor() calls NxActor::addForce() to add forces to the box through
keyboard input.
NxVec3 ApplyForceToActor(NxActor* actor, const NxVec3& forceDir, const NxReal
forceStrength)
{
NxVec3 forceVec = forceStrength*forceDir*gDeltaTime;
actor->addForce(forceVec);
return forceVec;
}
Every time we hit “j”, we call box->addForce(NxVec3(gForceStrength,0,0)) and a force
of gForceStrength = 20000 is applied continuously to the box at its center along the
positive x-axis each frame. Note, when running the simulation, you start out facing
down the positive z-axis of the scene marked in blue. The positive y-axis is in green
going up and the positive x-axis is in red going to the left. All axes in the SDK are set
up and rendered in this manner. “j” now imparts a force that pushes the box to the left.
The force is shown as a yellow arrow. Note using the “umijkl” buttons, the force is
constant, applied at the center of the box, and always faces along the global x, y, or zaxis.
3. Resetting the Position of the Actors
Next we call NxActor::setGlobalPosition() to set the position of the box in
ProcessKeys().
// Keyboard globals
#define MAX_KEYS 256
bool gKeys[MAX_KEYS];
…
void ProcessKeys()
{
// Process keys
for (int i = 0; i < MAX_KEYS; i++)
{
if (!gKeys[i]) { continue; }
switch (i)
{
…
// Return box to (0,5,0)
case 't': { gSelectedActor->setGlobalPosition(NxVec3(0,5,0)); break; }
…
}
}
}
Copyright (c) 2008 NVIDIA Corporation. All rights reserved.
http://www.NVIDIA.com
12
Every time we hit “t”, we call NxActor::setGlobalPosition(NxVec3(0,5,0)) on our box
actor. This places the actor at a position 5 units above the origin.
As with adding forces, we need to do this in between the NxScene::fetchResults() call in
GetPhysicsResults() and the NxScene::simulate() call in StartPhysics()). It is an input to
the physics scene which we need to perform while the scene is not being calculated by
the hardware.
4. Debugging the Objects
After processing possible calls to add forces to and set the position of the box, we call the
following code.
void ProcessInputs()
{
…
// Show debug wireframes
if (bDebugWireframeMode)
{
if (gScene) gDebugRenderer.renderData(*gScene->getDebugRenderable());
}
}
Hitting “b” in the demo toggles these wireframes on and off. The call
gDebugRenderer.renderData() renders wireframes in the scene that we set up to visualize
in InitNx() in order to see the collision shapes and actor axes in the scene. You can see
the DebugRenderer::renderData() function in DebugRenderer.cpp.
void DebugRenderer::renderData(const NxDebugRenderable& data) const
{
glLineWidth(1.0f);
glPushMatrix();
glDisable(GL_LIGHTING);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// Render points
NxU32 NbPoints = data.getNbPoints();
if(NbPoints)
{
...
}
Copyright (c) 2008 NVIDIA Corporation. All rights reserved.
http://www.NVIDIA.com
13
// Render lines
NxU32 NbLines = data.getNbLines();
if(NbLines)
{
...
}
// Render triangles
NxU32 NbTris = data.getNbTriangles();
if(NbTris)
{
...
}
// Reset the color
glColor3f(1,1,1);
glEnable(GL_LIGHTING);
glPopMatrix();
}
Note that drawing these debug wireframes is for debug mode only. The drawing is not
optimal because it is not done in parallel with the physics simulation, i.e., the physics
simulation is idle when you do the debug rendering.
For more information on the Debug Renderer, see “Lesson 301: Debug Renderer”.
13 Starting the Simulation
Finally, we call StartPhysics() to start the next frame of the simulation.
void RenderCallback()
{
...
if (gScene && !bPause)
{
...
StartPhysics();
}
…
}
...
void StartPhysics()
{
// Update the time step
Copyright (c) 2008 NVIDIA Corporation. All rights reserved.
http://www.NVIDIA.com
14
gDeltaTime = UpdateTime();
// Start collision and dynamics for delta time since the last frame
gScene->simulate(gDeltaTime);
gScene->flushStream();
}
StartPhysics() calls UpdateTime(), which gets deltaTime, the time step since the last
scene. We call NxScene::simulate(deltaTime) and NxScene::flushStream() to run the
simulation for the time step.
NxScene::simulate() is point of entry to the PhysX physics solver and the heart of the
simulation. The SDK simulates the scene we have constructed for deltaTime. All
computation for the simulation takes place on the hardware and gets retrieved by the next
call to NxScene::fetchResults() which we call from GetPhysicsResults().
14 Drawing the Objects
After we call GetPhysicsResults(), ProcessInputs(), and StartPhysics()in
RenderCallback(), we draw the objects in the scene from gCameraPos (0,5,-15) facing
gCameraForward (0,0,1), so 5 meters above and 15 meters behind the origin along the zaxis, and facing the origin along positive z. We draw the actors and their shadows on the
ground plane with the following code.
void RenderActors(bool shadows)
{
// Render all the actors in the scene
NxU32 nbActors = gScene->getNbActors();
NxActor** actors = gScene->getActors();
while (nbActors--)
{
NxActor* actor = *actors++;
DrawActor(actor);
// Handle shadows
if (shadows)
{
DrawActorShadow(actor);
}
}
}
void RenderCallback()
{
…
Copyright (c) 2008 NVIDIA Corporation. All rights reserved.
http://www.NVIDIA.com
15
RenderActors(bShadows);
…
}
DrawActor() and DrawActorShadow() loop through all the shapes in the actor, drawing
each shape and its shadow. The code for drawing the different types of shapes is in
DrawShapes.cpp. You can look at it, but it’s not important for the lesson right now, just
know this is where the actors get drawn.
15 Drawing the Forces
The force that gets applied to the box is returned to gForceVec. In RenderCallback(), we
call DrawForce() to draw an arrow representing the force applied to the box.
void ProcessForceKeys ()
{
// Process force keys
for (int i = 0; i < MAX_KEYS; i++)
{
if (!gKeys[i]) { continue; }
switch (i)
{
…
// Force controls
case 'i': {gForceVec = ApplyForceToActor(gSelectedActor, NxVec3(0,0,1),
gForceStrength); break; }
case 'k': {gForceVec = ApplyForceToActor(gSelectedActor, NxVec3(0,0,-1),
gForceStrength); break; }
case 'j': {gForceVec = ApplyForceToActor(gSelectedActor, NxVec3(1,0,0),
gForceStrength); break; }
case 'l': {gForceVec = ApplyForceToActor(gSelectedActor, NxVec3(-1,0,0),
gForceStrength); break; }
case 'u': {gForceVec = ApplyForceToActor(gSelectedActor,NxVec3(0,1,0),
gForceStrength); break; }
case 'm': {gForceVec = ApplyForceToActor(gSelectedActor,NxVec3(0,-1,0),
gForceStrength); break; }
}
}
}
...
void ProcessInputs()
{
ProcessForceKeys();
…
Copyright (c) 2008 NVIDIA Corporation. All rights reserved.
http://www.NVIDIA.com
16
}
...
void DrawForce(NxActor* actor, NxVec3& forceVec, const NxVec3& color)
{
// Draw only if the force is large enough
NxReal force = forceVec.magnitude();
if (force < 0.1f) return;
forceVec = 3*forceVec/force;
NxVec3 pos = actor->getCMassGlobalPosition();
DrawArrow(pos, pos + forceVec, color);
}
...
void RenderCallback()
{
...
if (gScene && !bPause)
{
...
ProcessInputs();
...
}
...
DrawForce(box, gForceVec, NxVec3(1,1,0));
gForceVec = NxVec3(0,0,0);
…
}
This code draws a yellow arrow originating from the center of mass of the box and
extending 3 meters in the direction of the axis-aligned force.
16 Resetting the Scene and Shutting Down
Run the simulation for a while and hit F10. You will notice the box appears back in its
starting position, falling to the ground as before. Hitting F10 resets the scene, calling
ResetNx() which calls ReleaseNx() to shut down the SDK and then InitNx() to start it up
again.
// Physics SDK globals
NxPhysicsSDK* gPhysicsSDK = NULL;
NxScene* gScene = NULL;
…
void SpecialCallback(int key, int x, int y)
{
Copyright (c) 2008 NVIDIA Corporation. All rights reserved.
http://www.NVIDIA.com
17
switch (key)
{
// Reset PhysX
case GLUT_KEY_F10: ResetNx(); return;
}
}
void ReleaseNx()
{
if (gScene)
{
GetPhysicsResults(); // Make sure to fetchResults() before shutting down
gPhysicsSDK->releaseScene(*gScene);
}
if (gPhysicsSDK) gPhysicsSDK->release();
}
void ResetNx()
{
ReleaseNx();
InitNx();
}
ReleaseNx() calls GetPhysicsResults() which calls NxScene::fetchResults(), which waits
for the card to finish processing the scene. It then calls NxPhysicsSDK::releaseScene()
which deletes all the objects in the scene and then deletes the scene itself. It then calls
NxPhysicsSDK::release() which shuts down the SDK.
ReleaseNx() is also called after glutMainLoop() to shut down the SDK before exiting.
17 Major Application Functions
The major functions of interest in the application are:
1. RenderCallback()
Calls GetPhysicsResults(), ProcessInputs(), and StartPhysics() each frame to simulate
the scene. Places the camera with SetupCamera(). Draws the actors in the scene
with RenderActors(). Draws the user supplied force to objects in the scene with
DrawForce().
2. GetPhysicsResults()
Calls NxScene::fetchResults() to retrieve the results of the last frame of simulation.
Copyright (c) 2008 NVIDIA Corporation. All rights reserved.
http://www.NVIDIA.com
18
3. ProcessInputs()
Gets keyboard input from ProcessForceKeys(). Calls
NxDebugRenderer::renderData() to draw debug wireframes on the actors.
4. StartPhysics()
Calls UpdateTime() to get gDeltaTime, the time since the last frame of the scene was
rendered. Calls NxScene::simulate(gDeltaTime) and NxScene::flushStream() to run
the simulation for gDeltaTime.
5. InitNx()
Initializes the PhysX SDK with NxCreatePhysicsSDK(). Adds simulation-wide
parameters with NxPhysicsSDK::setParameter(). Adds new materials to the SDK by
calling NxScene::getMaterialFromIndex() and adjusting the material properties using
NxMaterial::setRestitution(), ::setStaticFriction(), and ::setDynamicFriction().
Creates the scene with NxPhysicsSDK::createScene(). Constructs the actors in the
scene with CreateGroundPlane() and CreateBox(), both of which call
NxScene::createActor(). Sets the current time with UpdateTime(). Begins the
simulation with StartPhysics().
6. gDebugRenderer.renderData()
Renders wireframes to visualize debug wireframes on the actors such as collision
shapes and actor axes.
7. ReleaseNx()
Calls GetPhysicsResults() to close out the simulation. Calls
NxPhysicsSDK::releaseScene() to shut down the scene and NxPhysicsSDK::release()
to shut down the SDK.
18 Conclusion and Playing Around
You have completed a basic application using the PhysX SDK. Congratulations! You
have taken your first step into a larger world. Experiment as much as you can with your
creation. Use the “umijkl” keys to push the box around the plane and use the “qzwasd”
keys to follow it around with the camera.
There is a lot of information in this lesson and it is fairly comprehensive as it covers an
entire working application with everything from initializing the SDK, initializing the
scene, creating an actor, applying forces to the actor through keyboard inputs, drawing
the actor, running the simulation, drawing forces applied to the actor, and drawing debug
wireframes for the objects. Don’t panic if there are some things you don’t understand
Copyright (c) 2008 NVIDIA Corporation. All rights reserved.
http://www.NVIDIA.com
19
right now. Everything will become more apparent with practice as you continue to use
the SDK.
In future lessons, we will use the same framework as this lesson and introduce one or two
new features per lesson until we have covered all the features in the SDK.
19 Related Classes, Functions, and Parameters
NxCreatePhysicsSDK()
NxPhysicsSDK
createScene()
setParameter()
visualize()
releaseScene()
release()
NxMaterial
setRestitution()
setStaticFriction()
setDynamicFriction()
NxSceneDesc
gravity
simType
NxScene
getMaterialFromIndex()
createActor()
simulate()
flushStream()
fetchResults()
NxPlaneShapeDesc
NxBoxShapeDesc
Dimensions
NxSphereShapeDesc
radius
NxCapsuleShapeDesc
radius
height
Copyright (c) 2008 NVIDIA Corporation. All rights reserved.
http://www.NVIDIA.com
20
NxBodyDesc
NxActorDesc
shapes
body
density
globalPose
NxActor
setGlobalPosition()
getCMassGlobalPosition()
addForce()
NxDebugRenderable
getNbPoints()
getPoints()
getNbLines()
getLines()
getNbTriangles()
getTriangles()
NxDebugPoint
color
p
NxDebugLine
color
p0
p1
NxDebugTriangle
color
p0
p1
p2
NxParameter
NX_SKIN_WIDTH
NX_VISUALIZE_COLLISION_SHAPES
NX_VISUALIZE_ACTOR_AXES
NxSimulationStatus
NX_RIGID_BODY_FINISHED
Copyright (c) 2008 NVIDIA Corporation. All rights reserved.
http://www.NVIDIA.com
21
21 Relationship between localPose and globalPose
In CreateBox, CreateSphere and CreateCapsule functions, there are two variables:
localPose and globalPose need to be noted. See the following snippet:
NxCapsuleShapeDesc capsuleDesc;
capsuleDesc.radius
= 0.55f;
capsuleDesc.height
= 0.75f;
capsuleDesc.localPose.t = NxVec3(0, 0, 0);
//Rotate capsule shape
NxQuat quat(45, NxVec3(0, 0, 1));
NxMat33 m33(quat);
capsuleDesc.localPose.M = m33;
actorDesc.shapes.pushBack(&capsuleDesc);
actorDesc.body
= &bodyDesc;
actorDesc.density
= 10.0f;
actorDesc.globalPose.t
=NxVec3(6.0f,capsuleStartHeight,0);
Here, globalPose is the coordinate in world coordinate System; localPose is the
coordinate based on globalPose. See the below illustration:
Y’
Y
Z
Z’
Copyright (c) 2008 NVIDIA Corporation. All rights reserved.
http://www.NVIDIA.com
22
localPose
X’
globalPose
X
World Coordinate System
Copyright (c) 2008 NVIDIA Corporation. All rights reserved.
http://www.NVIDIA.com
23