Skip to content

Instantly share code, notes, and snippets.

@mcleary
Created July 11, 2016 13:31
Show Gist options
  • Save mcleary/6b68522819a340772013542aeb0ec445 to your computer and use it in GitHub Desktop.
Save mcleary/6b68522819a340772013542aeb0ec445 to your computer and use it in GitHub Desktop.
Simple code that shows how to setup and use the NVIDIA Physx Engine.
//
// main.cpp
// PhysX-Test
//
// Created by Thales Sabino on 10/25/14.
//
//
#define _DEBUG
#include <iostream>
#include <vector>
#include <PxPhysicsAPI.h>
#include <GLUT/glut.h>
#include <OpenGL/OpenGL.h>
#include <mc/mcmath.h>
#include <mc/utils/timer.h>
using namespace mc;
using namespace std;
using namespace physx;
static PxDefaultAllocator gDefaultAllocatorCallback;
static PxDefaultErrorCallback gDefaultErrorCallback;
static PxPhysics* gPxPhysics;
static PxScene* gPxScene;
float camX = 100.5f;
float camY = 180.5f;
float camZ = 120.0;
float camSpeed = 1.0f;
struct Viewport
{
int x, y, w, h;
}
g_viewport{0, 0, 800, 600};
void glut_reshape(int w, int h)
{
g_viewport.w = w;
g_viewport.h = h;
glViewport(g_viewport.x, g_viewport.y, g_viewport.w, g_viewport.h);
Mat4f proj = perspective(45.0f, (float)g_viewport.w/(float)g_viewport.h, 1.0f, 10000.0f);
glMatrixMode(GL_PROJECTION);
glLoadMatrixf(proj.ptr());
glutPostRedisplay();
glMatrixMode(GL_MODELVIEW);
}
ostream& operator << (ostream& out, const PxVec3& v)
{
out << "PxVec3(" << v.x << "," << v.y << "," << v.z << ")";
return out;
}
void render_scene()
{
vector<PxShape*> shape_list(gPxPhysics->getNbShapes());
gPxPhysics->getShapes(shape_list.data(), (PxU32)shape_list.size());
glColor3f(1,1,1);
for(PxShape* shape : shape_list)
{
PxRigidDynamic* actor = (PxRigidDynamic*)shape->getActor();
PxVec3 v = actor->getGlobalPose().p;
PxReal angle;
PxVec3 axis;
actor->getGlobalPose().q.toRadiansAndUnitAxis(angle, axis);
glPushMatrix();
glTranslatef(v.x, v.y, v.z);
glRotatef(toDeg(angle), axis.x, axis.y, axis.z);
PxGeometryHolder geometry = shape->getGeometry();
switch (geometry.getType())
{
case PxGeometryType::eSPHERE:
glutSolidSphere(geometry.sphere().radius, 15, 15);
break;
case PxGeometryType::eBOX:
glutSolidCube(geometry.box().halfExtents.x * 2);
break;
case PxGeometryType::eCAPSULE:
glScalef(1.0f, 1.0f, 4.0f);
glutSolidSphere(geometry.sphere().radius, 15, 15);
//glutSolidTeapot(geometry.capsule().radius);
break;
default:
break;
}
glPopMatrix();
}
}
void glut_display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Mat4f view = lookAt(Vec3f(camX, camY, camZ), Vec3f(0.0f, 0.0f, 0.0f), Vec3f::unitY());
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadMatrixf(view.ptr());
// Render objects
glEnable(GL_LIGHTING);
render_scene();
static float axis_size = 100.0f;
glDisable(GL_LIGHTING);
glBegin(GL_LINES);
glColor3f(1, 0, 0);
glVertex3f(0, 0, 0);
glVertex3f(axis_size, 0, 0);
glColor3f(0, 1, 0);
glVertex3f(0, 0, 0);
glVertex3f(0, axis_size, 0);
glColor3f(0, 0, 1);
glVertex3f(0, 0, 0);
glVertex3f(0, 0, axis_size);
glEnd();
glPopMatrix();
glutSwapBuffers();
}
void glut_keypress(unsigned char key, int, int)
{
switch(key)
{
case 'w':
camY += camSpeed;
break;
case 's':
camY -= camSpeed;
break;
case 'a':
camX -= camSpeed;
break;
case 'd':
camX += camSpeed;
break;
}
glutPostRedisplay();
}
bool simulate(PxReal dt)
{
static PxReal gAccumulator = 0.0f;
static const PxReal gStepSize = 1.0f / 60.0f;
gAccumulator += dt;
if(gAccumulator < gStepSize)
{
return false;
}
gAccumulator -= gStepSize;
gPxScene->simulate(gStepSize);
return true;
}
void glut_idle()
{
static Timer timer;
if(simulate(timer.elapesed_sec()))
{
gPxScene->fetchResults(true);
}
timer.restart();
glutPostRedisplay();
}
void populate_scene()
{
PxMaterial* pxMaterial = gPxPhysics->createMaterial(1.5f, 1.5f, 0.5f);
if(!pxMaterial)
{
cout << "PxMaterial creation failed!" << endl;
exit(1);
}
srand(1);
const int N_BOXES_X = 10;
const int N_BOXES_Y = 150;
const PxReal box_spacing = 2.5f;
PxReal box_size = 4.0f;
for(int i = 0; i < N_BOXES_X; ++i)
{
for(int j = 0; j < N_BOXES_Y; ++j)
{
PxTransform box_transform(PxVec3(i * box_size * box_spacing, j * box_size * box_spacing + 4, 0));
PxTransform transform = box_transform;
transform.p = transform.transform(PxVec3(-50 + rand() % 4, rand() % 7, rand() % 6));
if(rand() % 2 == 0)
{
PxSphereGeometry sphere_geometry = PxSphereGeometry(box_size);
PxRigidDynamic* sphere_actor = PxCreateDynamic(*gPxPhysics, transform, sphere_geometry, *pxMaterial, 1.0f);
gPxScene->addActor(*sphere_actor);
}
else if(rand() % 3 == 0)
{
PxBoxGeometry box_geometry = PxBoxGeometry(PxVec3(box_size));
PxRigidDynamic* box_actor = PxCreateDynamic(*gPxPhysics, transform, box_geometry, *pxMaterial, 1.0f);
gPxScene->addActor(*box_actor);
}
else
{
PxCapsuleGeometry capsule_geometry = PxCapsuleGeometry(2, 2);
PxRigidDynamic* capsule_actor = PxCreateDynamic(*gPxPhysics, transform, capsule_geometry, *pxMaterial, 1.0f);
gPxScene->addActor(*capsule_actor);
}
}
}
// create ground
gPxScene->addActor(*PxCreatePlane(*gPxPhysics, PxPlane(PxVec3(0, 1, 0).getNormalized(), 0), *pxMaterial));
// invisible box
gPxScene->addActor(*PxCreatePlane(*gPxPhysics, PxPlane(PxVec3(0, 0, -1).getNormalized(), 50), *pxMaterial));
gPxScene->addActor(*PxCreatePlane(*gPxPhysics, PxPlane(PxVec3(0, 0, 1).getNormalized(), 50), *pxMaterial));
gPxScene->addActor(*PxCreatePlane(*gPxPhysics, PxPlane(PxVec3(-1, 0, 0).getNormalized(), 50), *pxMaterial));
gPxScene->addActor(*PxCreatePlane(*gPxPhysics, PxPlane(PxVec3(1, 0, 0).getNormalized(), 50), *pxMaterial));
}
void glut_initGL(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowSize(g_viewport.w, g_viewport.h);
glutInitWindowPosition(10, 10);
glutCreateWindow("McLeary NVIDIA PhysX Test");
glutReshapeWindow(800, 600);
glutReshapeFunc(glut_reshape);
glutDisplayFunc(glut_display);
glutIdleFunc(glut_idle);
glutKeyboardFunc(glut_keypress);
glClearColor(0.2f, 0.2f, 0.2f, 1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
glShadeModel(GL_SMOOTH);
GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat mat_shininess[] = { 50.0 };
GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 };
glShadeModel (GL_SMOOTH);
glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_DEPTH_TEST);
glutMainLoop();
}
int main(int argc, char * argv[])
{
PxFoundation* pxFoundation = PxCreateFoundation(PX_PHYSICS_VERSION, gDefaultAllocatorCallback, gDefaultErrorCallback);
if(!pxFoundation)
{
cout << "PxFoundation creation failed!" << endl;
return EXIT_FAILURE;
}
PxProfileZoneManager* pxProfileZoneManager = &PxProfileZoneManager::createProfileZoneManager(pxFoundation);
if(!pxProfileZoneManager)
{
cout << "PxProfileZoneManager creation failed!" << endl;
return EXIT_FAILURE;
}
bool bRecordMemoryAllocations = true;
gPxPhysics = PxCreatePhysics(PX_PHYSICS_VERSION, *pxFoundation, PxTolerancesScale(), bRecordMemoryAllocations, pxProfileZoneManager);
if(!gPxPhysics)
{
cout << "PxPhysics creation failed!" << endl;
return EXIT_FAILURE;
}
if(!PxInitExtensions(*gPxPhysics))
{
cout << "PxInitExtensions failed" << endl;
return EXIT_FAILURE;
}
PxCpuDispatcher* pxCpuDispatcher;
PxSceneDesc pxSceneDesc(gPxPhysics->getTolerancesScale());
pxSceneDesc.gravity = PxVec3(0.0f, -90.81f, 0.0f);
if(!pxSceneDesc.cpuDispatcher)
{
pxCpuDispatcher = PxDefaultCpuDispatcherCreate(1);
if(!pxCpuDispatcher)
{
cout << "PxCpuDispatcher creation failed!" << endl;
return EXIT_FAILURE;
}
pxSceneDesc.cpuDispatcher = pxCpuDispatcher;
}
if(!pxSceneDesc.filterShader)
{
pxSceneDesc.filterShader = PxDefaultSimulationFilterShader;
}
gPxScene = gPxPhysics->createScene(pxSceneDesc);
if(!gPxScene)
{
cout << "PxScene creation Failed!" << endl;
return EXIT_FAILURE;
}
populate_scene();
glut_initGL(argc, argv);
PxCloseExtensions();
gPxPhysics->release();
pxFoundation->release();
return EXIT_SUCCESS;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment