Created
July 11, 2016 13:31
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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