Physx journey (1) -- nxboxes row-by-row Analysis
It is really lucky to learn new things without detours. So I want to say: It's great to have an SDK!
Nxboxes is the 1st example of physx. It is necessary to perform row-by-row analysis on it. When we fully understand the use of each line of code, we will get started.
# Include <stdio. h>
# Include <Gl/glut. h>
# Include "nxphysics. H"
# Pragma comment (Lib, "C:/program files/NVIDIA Corporation/NVIDIA physx SDK/v2.8.1/sdks/lib/Win32/physxloader. lib ")
# Pragma comment (Lib, "E:/work/test_bin/extern_library/lib/debug/freeglut. lib ")
# Define nominmax
# Include <windows. h>
// # Include "errorstream. H"
# Include <windows. h>
// # Include "perfrenderer. H"
// # Include "utilities. H"
// # Include "samplesvrdsettings. H"
// Physics
Static nxphysicssdk * gphysicssdk = NULL; // physx interface pointer
Static nxscene * gscene = NULL; // scenario pointer
// Static perfrenderer gperfrenderer;
/*
Class used for statistics before rendering
This class has only two external methods:
Bool toggleenable (); // display/hide Switch
Void render (const nxprofiledata * prof, int width, int height );
About nxprofiledata:
/Brief array of profiling data.
Performance data array.
Profilezones points to an array of numzones profile zones. zones are sorted such that the parent zones always come before their children.
Some zones have multiple parents (Code called from multiple places) in which case only the relationship to the first parent is displayed.
Returned by nxscene: readprofiledata ().
About profilezones
/Brief names for a number of profile zones that shoshould always be available. can be used with nxprofiledata: getnamedzone ()
<B> platform: </B>
/Li pc sw: Yes
/Li PPU: Yes
/Li PS3: No
/Li xb360: No
Enum nxprofilezonename
{
Nx_pz_client_frame ,//! <Clock start is in client thread, just before scene thread was kicked off; clock end is when client CILS fetchresults ().
Nx_pz_cpu_simulate ,//! <Maximum time of simulation thread (NF) Scene: Simulate (nxu32), over all CPU scenes inside the nxscene.
Nx_pz_ppu0_simulate ,//! <Maximum time of simulation thread over all PPU # scenes inside the nxscene.
Nx_pz_ppu1_simulate,
Nx_pz_ppu2_simulate,
Nx_pz_ppu3_simulate,
Nx_pz_total_simulation = 0x10 ,//! <Clock start is in client thread, just before scene thread was kicked off; clock end is in simulation thread when it finishes.
};
*/
// Rendering
Static nxvec3 geye (500000f, 500000f, 500000f); // camera location
Static nxvec3 gdir (-0.6f,-0.2f,-0.7f); // camera direction
Static nxvec3 gviewy; // orientation of the camera's "Left translation"
Static int gmousex = 0; // The current X coordinate of the mouse (ABS)
Static int gmousey = 0; // The current y coordinate of the mouse (ABS)
Static bool initnx () // This function initializes physx
{
// Initialize physicssdk
Nxphysicssdkdesc DESC; // device descriptor, used to specify the degree of data sharing between hardware and scenarios "?
Nxsdkcreateerror errorcode = nxce_no_error; // call the error message returned by nxcreatephysicssdk ()
/*
Enum nxsdkcreateerror
{
Nxce_no_error = 0, // No error
Nxce_physx_not_found = 1, // The physx library cannot be found, and the physx driver is not installed.
Nxce_wrong_version = 2, // the SDK version does not match the driver version
Nxce_descriptor_invalid = 3, // the descriptor is invalid.
Nxce_connection_error = 4, // communication with the device fails.
Nxce_reset_error = 5, // device not reset (initialized)
Nxce_in_use_error = 6, // The device is being used by another program
Nxce_bundle_error = 7 // congratulations, your physical accelerator card is broken
};
*/
Gphysicssdk = nxcreatephysicssdk (nx_physics_sdk_version, null,/* New errorstream () */null, DESC, & errorcode); // create an interface pointer.
If (gphysicssdk = NULL) // if an error occurs, print the error message.
{
// Printf ("/nsdk create error (% d-% s ). /nunable to initialize the physx SDK, exiting the sample. /n ", errorcode, getnxsdkcreateerror (errorcode ));
Return false;
}
// Visualized remote debugger settings... never played...
// # If samples_use_vrd
//// Set the IP address and port of the visual remote debugger. (Defined in samplecommoncode/samplesvrdsettings. h file)
// If (gphysicssdk-> getfoundationsdk (). getremotedebugger ())
// Gphysicssdk-> getfoundationsdk (). getremotedebugger ()-> connect (samples_vrd_host, samples_vrd_port, samples_vrd_eventmask );
// # Endif
// Set the variable. The skin thickness is 0.05. The actual result is that the collision body of the role is reduced by 0.05.
Gphysicssdk-> setparameter (nx_skin_width, 0.05f );
// Create a scene
Nxscenedesc scenedesc; // declare a scenario Descriptor
Scenedesc. Gravity = nxvec3 (0.0f,-9.81f, 0.0f); // sets the acceleration of gravity.
Gscene = gphysicssdk-> createscene (scenedesc); // use the scenario descriptor to create a scenario.
If (gscene = NULL) // handle errors
{
Printf ("/nerror: unable to create a physx scene, exiting the sample./n ");
Return false;
}
// Set default material // set the material
// There is always a default material (Index = 0), and the material cannot be released. Calling releasematerial (defaultmaterial) will have no effect.
Nxmaterial * defaultmaterial = gscene-> getmaterialfromindex (0 );
Defaultmaterial-> setrestitution (0.0f); // you can specify the restoration coefficient.
Defaultmaterial-> setstaticfriction (0.5f); // you can specify the static friction coefficient.
Defaultmaterial-> setdynamicfriction (0.5f); // you can specify the dynamic friction coefficient.
// Create ground plane // create a piece as a floor
Nxplaneshapedesc planedesc; // The part descriptor is obvious.
Nxactordesc actordesc; // role Descriptor
Actordesc. shapes. pushback (& planedesc); // Add the part descriptor to the role descriptor.
Gscene-> createactor (actordesc); // create a role
Return true;
}
// This function is used for cleanup
Static void exitnx ()
{
If (gphysicssdk! = NULL)
{
If (gscene! = NULL) gphysicssdk-> releasescene (* gscene); // release scenario
Gscene = NULL;
Nxreleasephysicssdk (gphysicssdk); // release physx
Gphysicssdk = NULL;
}
}
// Create a cube
Static void createcube (const nxvec3 & Pos, int size = 2, const nxvec3 * initialvelocity = NULL)
{
If (gscene = NULL) return;
// Create body // create a Rigid Body
Nxbodydesc bodydesc; // Rigid Body Descriptor
Bodydesc. angulardamping = 0.5f; // rotation Attenuation
If (initialvelocity) bodydesc. linearvelocity = * initialvelocity; // (along a certain direction) Speed
Nxboxshapedesc boxdesc; // box Descriptor
Boxdesc. Dimensions = nxvec3 (float) size, (float) size, (float) size); // set the volume of the box
Nxactordesc actordesc; // role Descriptor
Actordesc. shapes. pushback (& boxdesc); // Add the box descriptor to the role descriptor.
Actordesc. Body = & bodydesc; // sets the rigid body descriptor.
Actordesc. density = 10.0f; // sets the density.
Actordesc. globalpose. t = Pos; // sets the current coordinate of an object (World coordinate system)
Gscene-> createactor (actordesc)-> userdata = (void *) size_t (size); // create a role
// Printf ("Total: % d actors/N", gscene-> getnbactors ());
}
// Create a large square
Static void createcubefromeye (INT size)
{
Nxvec3 T = geye; // point
Nxvec3 vel = gdir; // direction
Vel. normalize (); // Normalization
Vel * = 200366f; // speed in this direction (200 unit vectors)
Createcube (T, size, & VEL); // create a square
}
// Create a pyramid
Static void createstack (INT size)
{
Const float cubesize = 2.0f;
Const float spacing =-2.0f * gphysicssdk-> getparameter (nx_skin_width); // reduce the size produced by scaling.
// As long as you know the meaning of "skin thickness", the following code is just an algorithm to make these squares closely arranged.
Nxvec3 pos (0.0f, cubesize, 0.0f );
Float offset =-size * (cubesize * 2.0f + spacing) * 0.5f;
While (size)
{
For (INT I = 0; I <size; I ++)
{
POs. x = offset + (float) I * (cubesize * 2.0f + spacing );
Createcube (Pos, (INT) cubesize );
}
Offset + = cubesize;
POs. Y + = (cubesize * 2.0f + spacing );
Size --;
}
}
// Create a stick
Static void createtower (INT size)
{
Const float cubesize = 2.0f;
Const float spacing = 0.01f;
Nxvec3 pos (0.0f, cubesize, 0.0f );
While (size)
{
Createcube (Pos, (INT) cubesize );
POs. Y + = (cubesize * 2.0f + spacing );
Size --;
}
}
// Keyboard callback function
Static void keyboardcallback (unsigned char key, int X, int y)
{
Switch (key)
{
Case 27: // The esc ascii code is 27.
Exit (0 );
Break;
Case '0 ':
// Gperfrenderer. toggleenable ();
Break;
Case '':
Createcube (nxvec3 (0.0f, 20366f, 0.0f), 1); // create a square with a size of 1 and a speed of 0 at (, 0 ).
Break;
Case's ':
Case's ':
Createstack (10 );
Break;
Case 'B ':
Case 'B ':
Createstack (30 );
Break;
Case 'T ':
Case 'T ':
Createtower (30 );
Break;
Case 'W ':
Case 'W ':
Createcubefromeye (8 );
Break;
Case 'q ':
Case 'q ':
{
Nxactor ** actors = gscene-> getactors ();
If (gscene-> getnbactors ()> 1 ){
Gscene-> releaseactor (* actors [gscene-> getnbactors ()-1]);
}
}
Break;
Case glu_key_up: Case '8': geye + = gdir * 2.0f; break;
Case glu_key_down: Case '2': geye-= gdir * 2.0f; break;
Case glu_key_left: Case '4': geye-= gviewy * 2.0f; break;
Case glu_key_right: Case '6': geye + = gviewy * 2.0f; break;
}
}
// Keyboard callback function
Static void arrowkeycallback (INT key, int X, int y)
{
Keyboardcallback (Key, x, y );
}
// Mouse callback function
Static void mousecallback (INT button, int state, int X, int y)
{
Gmousex = X;
Gmousey = y;
}
// What is the motion callback function?
Static void motioncallback (int x, int y)
{
Int dx = gmousex-X;
Int DY = gmousey-y;
Gdir. normalize ();
Gviewy. Cross (gdir, nxvec3 (0, 1, 0 ));
Nxquat qx (nxpif32 * DX * 20/180 running f, nxvec3 (0, 1 ));
QX. Rotate (gdir );
Nxquat QY (nxpif32 * dy * 20/180 running f, gviewy );
QY. Rotate (gdir );
Gmousex = X;
Gmousey = y;
}
// Rendering callback function
// When the last result is submitted to the rendering queue for rendering, the CPU is idle.
Static void rendercallback ()
{
Static DWORD elapsedtime = 0;
If (gscene = NULL) return;
// Start simulation (Non Blocking)
If (elapsedtime! = 0)
{
Elapsedtime =: gettickcount ()-elapsedtime;
}
Gscene-> simulate (elapsedtime * 0.001f); // simulates all physical computing tasks.
# Pragma region OpenGL Problems
// Clear Buffers
Glclear (gl_color_buffer_bit | gl_depth_buffer_bit );
// Setup Projection Matrix
Glmatrixmode (gl_projection );
Glloadidentity ();
Gluperspective (601_f, (float) gluget (glu_window_width)/(float) gluget (glu_window_height), 1.0f, limit F );
Glulookat (geye. x, geye. y, geye. z, geye. X + gdir. x, geye. Y + gdir. y, geye. Z + gdir. z, 0.0f, 1.0f, 0.0f );
// Setup modelview Matrix
Glmatrixmode (gl_modelview );
Glloadidentity ();
// Render all actors
Int nbactors = gscene-> getnbactors (); // obtain the total number of roles
Nxactor ** actors = gscene-> getactors (); // get the role queue pointer
While (nbactors --) // do not render the floor, because the code can be written to ensure that 1st must be the floor, so no detection is performed here.
{
Nxactor * Actor = * actors ++; // Iteration
If (! Actor-> userdata) continue; // If the role's "user-defined data" pointer is not empty, it is not rendered
// Rendering role
// Render actor
Glpushmatrix ();
Float glmat [16];
Actor-> getglobalpose (). getcolumnmajor44 (glmat );
Glmultmatrixf (glmat );
Glcolor4f (1.0f, 1.0f, 1.0f, 1.0f); // set the color.
Glusolidcube (float (size_t (actor-> userdata) * 2.0f); // Rendering
Glpopmatrix ();
// Render shadow
Glpushmatrix ();
Const static float shadowmat [] = };
Glmultmatrixf (shadowmat );
Glmultmatrixf (glmat );
Gldisable (gl_lighting );
Glcolor4f (0.1f, 0.2f, 0.3f, 1.0f );
Glusolidcube (float (size_t (actor-> userdata) * 2.0f );
Glable (gl_lighting );
Glpopmatrix ();
}
# Pragma endregion OpenGL Problems
// Fetch simulation results
Gscene-> flushstream ();
Gscene-> fetchresults (nx_rigid_body_finished, true );
Elapsedtime =: gettickcount ();
// Print profile results (if enabled)
// Gperfrenderer. Render (gscene-> readprofiledata (true), glget (gl_window_width), glget (gl_window_height ));
Gluswapbuffers ();
}
Static void reshapecallback (INT width, int height)
{
Glviewport (0, 0, width, height );
}
Static void idlecallback ()
{
Glupostredisplay ();
}
Int main (INT argc, char ** argv)
{
// Initialize glut
Printf ("Use the arrow keys or 2, 4, 6 and 8 to move the camera./N ");
Printf ("use the mouse to rotate the camera./N ");
Printf ("press the keys W, T, S, B and space to create varous things./N ");
Printf ("Press Q to destroy the last thing created./N ");
Printf ("press 0 to toggle the frame rate display./N ");
Gluinit (& argc, argv );
Gluinitwindowsize (512,512 );
Fig );
Int mainhandle = fig ("sampleboxes ");
Glusetwindow (mainhandle );
Gludisplayfunc (rendercallback );
Glureshapefunc (reshapecallback );
Glutidlefunc (idlecallback );
Glukeyboardfunc (keyboardcallback );
Gluspecialfunc (arrowkeycallback );
Glumousefunc (mousecallback );
Glumotionfunc (motioncallback );
Motioncallback (0, 0 );
Atexit (exitnx );
// Setup default render states
Glclearcolor (0.3f, 0.4f, 0.5f, 1.0 );
Glenable (gl_depth_test );
Glable (gl_color_material );
// Setup Lighting
Glable (gl_lighting );
Float ambientcolor [] = {0.0f, 0.1f, 0.2f, 0.0f };
Float diffusecolor [] = {1.0f, 1.0f, 1.0f, 0.0f };
Float specularcolor [] = {0.0f, 0.0f, 0.0f, 0.0f };
Float position [] = {1000000f, 1000000f, 4000000f, 1.0f };
Gllightfv (gl_light0, gl_ambient, ambientcolor );
Gllightfv (gl_light0, gl_diffuse, diffusecolor );
Gllightfv (gl_light0, gl_specular, specularcolor );
Gllightfv (gl_light0, gl_position, position );
Glable (gl_light0 );
// Initialize physics scene and start the application main loop if scene was created
If (initnx ())
Glumainloop ();
Return 0;
}