Skip to content

Instantly share code, notes, and snippets.

@imcj
Last active May 20, 2017 07:24
Show Gist options
  • Select an option

  • Save imcj/4712689 to your computer and use it in GitHub Desktop.

Select an option

Save imcj/4712689 to your computer and use it in GitHub Desktop.
#include <iostream>
#include <vector>
#include <time.h>
#define _USE_MATH_DEFINES
#include <math.h>
#include "Frustum.h"
#include <GL/freeglut.h>
#include <PxPhysicsAPI.h>
#include <PxExtensionsAPI.h>
#include <PxDefaultErrorCallback.h>
#include <PxDefaultAllocator.h>
#include <PxDefaultSimulationFilterShader.h>
#include <PxDefaultCpuDispatcher.h>
#include <PxShapeExt.h>
#include <PxSimpleFactory.h>
using namespace std;
#pragma comment(lib, "PhysX3_x86.lib")
#pragma comment(lib, "PxTask.lib")
#pragma comment(lib, "Foundation.lib")
#pragma comment(lib, "PhysX3Extensions.lib")
#pragma comment(lib, "GeomUtils.lib")
//const int WINDOW_WIDTH=1024, WINDOW_HEIGHT=768;
static PxPhysics* gPhysicsSDK = NULL;
static PxDefaultErrorCallback gDefaultErrorCallback;
static PxDefaultAllocator gDefaultAllocatorCallback;
static PxSimulationFilterShader gDefaultFilterShader = PxDefaultSimulationFilterShader;
static PxMaterial* gDefaultMaterial = NULL;
int windowWidth = 1024;
int windowHeight = 768;
PxScene* gScene = NULL;
PxReal myTimestep = 1.0f/60.0f;
vector<PxActor*> gActors;
unsigned int gGeoType = 1;
bool gDrawWireframe = false;
bool gDrawBoundBox = false;
int gTotalActors = 0;
int gDrawedActors = 0;
const float DEG2RAD = (float)M_PI / 180.0f;
PxParticleFluid* gWater = NULL;
struct WaterParticle
{
PxVec3 *positions;
PxVec3 *velocity;
int numParticles;
PxU32 *indices;
int indexCount;
PxStrideIterator<PxU32> indexBuffer;
};
vector<WaterParticle> gWaterParticles;
// For mouse dragging
int oldX=0, oldY=0;
float rX=15, rY=0;
float fps=0;
int startTime=0;
int totalFrames=0;
int state =1 ;
float dist=-5;
// For culling
CFrustum* gFrustum = NULL;
float Deg2Rad(float degree)
{
return degree * DEG2RAD;
}
float RandomRadius()
{
return (float)(rand() % 360);
}
void SetOrthoForFont()
{
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
gluOrtho2D(0, (GLdouble)windowWidth, (GLdouble)windowHeight, 0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void ResetPerspectiveProjection()
{
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
}
void AddBox(PxVec3 pos, PxVec3 dimensions)
{
// Create cube
PxReal density = 1.0f;
PxTransform transform(PxVec3(0.0f, 10.0f, 0.0f), PxQuat(Deg2Rad(RandomRadius()), PxVec3(0,1,0)));
PxBoxGeometry geometry(dimensions);
PxRigidDynamic *actor = PxCreateDynamic(*gPhysicsSDK, transform, geometry, *gDefaultMaterial, density);
actor->setAngularDamping(0.75);
actor->setLinearVelocity(PxVec3(0,-10,0));
actor->setMass(5.0f);
if (!actor)
cerr<<"create box actor failed!"<<endl;
gScene->addActor(*actor);
gActors.push_back(actor);
}
void AddBoxStatic(PxVec3 pos, PxVec3 dimensions)
{
// Create cube
PxTransform transform(pos, PxQuat::createIdentity());
PxBoxGeometry geometry(dimensions);
PxRigidStatic *actor = PxCreateStatic(*gPhysicsSDK, transform, geometry, *gDefaultMaterial);
if (!actor)
cerr<<"create box static actor failed!"<<endl;
gScene->addActor(*actor);
gActors.push_back(actor);
}
void AddSphere()
{
// Create sphere
PxReal density = 1.0f;
PxTransform transform(PxVec3(0.0f, 10.0f, 0.0f), PxQuat::createIdentity());
PxSphereGeometry geometry(0.5);
PxRigidDynamic *actor = PxCreateDynamic(*gPhysicsSDK, transform, geometry, *gDefaultMaterial, density);
actor->setAngularDamping(0.75);
actor->setLinearVelocity(PxVec3(0,-10,0));
actor->setMass(5.0f);
if (!actor)
cerr<<"create sphere actor failed!"<<endl;
gScene->addActor(*actor);
gActors.push_back(actor);
}
void AddCapsule()
{
// Create capsule
PxReal density = 1.0f;
PxTransform transform(PxVec3(0.0f, 10.0f, 0.0f), PxQuat(Deg2Rad(RandomRadius()), PxVec3(0,1,0)));
PxCapsuleGeometry geometry(0.5, 1.0);
PxRigidDynamic *actor = PxCreateDynamic(*gPhysicsSDK, transform, geometry, *gDefaultMaterial, density);
actor->setAngularDamping(0.75);
actor->setLinearVelocity(PxVec3(0,-10,0));
actor->setMass(5.0f);
if (!actor)
cerr<<"create capsule actor failed!"<<endl;
gScene->addActor(*actor);
gActors.push_back(actor);
}
void AddWater()
{
WaterParticle wp;
wp.numParticles = 1;
wp.indexCount = 1;
wp.indices = new PxU32[1];
wp.indices[0] = 0;
wp.positions = new PxVec3[1];
wp.positions[0].x = 0.0f;
wp.positions[0].y = 3.0f;
wp.positions[0].z = 0.0f;
wp.velocity = new PxVec3[1];
wp.velocity[0].x = 0.0f;
wp.velocity[0].y = -1.0f;
wp.velocity[0].z = 0.0f;
PxParticleCreationData particleCreationData;
particleCreationData.numParticles = wp.numParticles;
particleCreationData.positionBuffer = PxStrideIterator<const PxVec3>(wp.positions);
particleCreationData.velocityBuffer = PxStrideIterator<const PxVec3>(wp.velocity);
wp.indexBuffer = PxStrideIterator<PxU32>(wp.indices);
PxU32 numCreated = gWater->createParticles(particleCreationData, &wp.indexBuffer);
if (numCreated > 0)
{
gWaterParticles.push_back(wp);
}
else
{
delete wp.velocity;
delete wp.positions;
delete wp.indices;
}
}
void AddPlane()
{
// Create ground plane
PxReal d = 0.0f;
PxTransform pose = PxTransform(PxVec3(0.0f, 0, 0.0f),PxQuat(PxHalfPi, PxVec3(0.0f, 0.0f, 1.0f)));
PxRigidStatic* plane = gPhysicsSDK->createRigidStatic(pose);
if (!plane)
cerr<<"create plane failed!"<<endl;
PxShape* shape = plane->createShape(PxPlaneGeometry(), *gDefaultMaterial);
if (!shape)
cerr<<"create shape failed!"<<endl;
gScene->addActor(*plane);
gActors.push_back(plane);
}
void ClearScene()
{
for (long index=0; index<(long)gActors.size(); ++index)
{
PxActor* act = gActors.at(index);
gScene->removeActor(*act);
act->release();
}
gActors.clear();
}
void ClearWater()
{
// Release water particles
for (long index=0; index<(long)gWaterParticles.size(); ++index)
{
delete gWaterParticles[index].indices;
delete gWaterParticles[index].positions;
delete gWaterParticles[index].velocity;
}
gWaterParticles.clear();
}
void ResetScene()
{
// Release actors
ClearScene();
ClearWater();
// Add plane
AddPlane();
// Add becken
AddBoxStatic(PxVec3(0.0f, 0.1f, 0.0f), PxVec3(3.0f,0.1f,3.0f));
AddBoxStatic(PxVec3(2.9f, 0.3f, 0.0f), PxVec3(0.1f, 0.3f, 3.0f));
AddBoxStatic(PxVec3(-2.9f, 0.3f, 0.0f), PxVec3(0.1f, 0.3f, 3.0f));
AddBoxStatic(PxVec3(0.0f, 0.3f, -2.9f), PxVec3(3.0f, 0.3f, 0.1f));
AddBoxStatic(PxVec3(0.0f, 0.3f, 2.9f), PxVec3(3.0f, 0.3f, 0.1f));
// Create fluid particle system
PxParticleFluidDesc particleSystemDesc(gPhysicsSDK->getTolerancesScale());
particleSystemDesc.maxParticles = 10000;
particleSystemDesc.particleBaseFlags = PxParticleBaseFlag::eGPU | PxParticleBaseFlag::eCOLLISION_TWOWAY;
gWater = gPhysicsSDK->createParticleFluid(particleSystemDesc);
if (gWater)
{
gScene->addActor(*gWater);
gActors.push_back(gWater);
}
}
void InitializePhysX() {
// Create Physics SDK
gPhysicsSDK = PxCreatePhysics(PX_PHYSICS_VERSION, gDefaultAllocatorCallback, gDefaultErrorCallback, PxTolerancesScale() );
if(gPhysicsSDK == NULL) {
cerr<<"Error creating PhysX3 device."<<endl;
cerr<<"Exiting..."<<endl;
exit(1);
}
// Initialize PhysX Extensions
if(!PxInitExtensions(*gPhysicsSDK))
cerr<< "PxInitExtensions failed!" <<endl;
// Connect to visual debugger
PxExtensionVisualDebugger::connect(gPhysicsSDK->getPvdConnectionManager(),"localhost",5425, 10000, true);
// Create the scene
PxSceneDesc sceneDesc(gPhysicsSDK->getTolerancesScale());
sceneDesc.gravity=PxVec3(0.0f, -9.8f, 0.0f);
if(!sceneDesc.cpuDispatcher) {
PxDefaultCpuDispatcher* mCpuDispatcher = PxDefaultCpuDispatcherCreate(1);
if(!mCpuDispatcher)
cerr<<"PxDefaultCpuDispatcherCreate failed!"<<endl;
sceneDesc.cpuDispatcher = mCpuDispatcher;
}
if(!sceneDesc.filterShader)
sceneDesc.filterShader = gDefaultFilterShader;
gScene = gPhysicsSDK->createScene(sceneDesc);
if (!gScene)
cerr<<"createScene failed!"<<endl;
gScene->setVisualizationParameter(PxVisualizationParameter::eSCALE, 1.0);
gScene->setVisualizationParameter(PxVisualizationParameter::eCOLLISION_SHAPES, 1.0f);
gDefaultMaterial = gPhysicsSDK->createMaterial(0.5,0.5,0.5);
// Reset scene
ResetScene();
}
void getColumnMajor(PxMat33 m, PxVec3 t, float* mat) {
mat[0] = m.column0[0];
mat[1] = m.column0[1];
mat[2] = m.column0[2];
mat[3] = 0;
mat[4] = m.column1[0];
mat[5] = m.column1[1];
mat[6] = m.column1[2];
mat[7] = 0;
mat[8] = m.column2[0];
mat[9] = m.column2[1];
mat[10] = m.column2[2];
mat[11] = 0;
mat[12] = t[0];
mat[13] = t[1];
mat[14] = t[2];
mat[15] = 1;
}
void RenderSpacedBitmapString(
int x,
int y,
int spacing,
void *font,
char *string)
{
char *c;
int x1=x;
for (c=string; *c != '\0'; c++) {
glRasterPos2i(x1,y);
glutBitmapCharacter(font, *c);
x1 = x1 + glutBitmapWidth(font,*c) + spacing;
}
}
void DrawGLCube(float hx, float hy, float hz)
{
glBegin(GL_QUADS); // Draw The Cube Using quads
glNormal3f(0.0f, 1.0f, 0.0f);
glVertex3f( hx, hy,-hz); // Top Right Of The Quad (Top)
glVertex3f(-hx, hy,-hz); // Top Left Of The Quad (Top)
glVertex3f(-hx, hy, hz); // Bottom Left Of The Quad (Top)
glVertex3f( hx, hy, hz); // Bottom Right Of The Quad (Top)
glNormal3f(0.0f, -1.0f, 0.0f);
glVertex3f( hx,-hy, hz); // Top Right Of The Quad (Bottom)
glVertex3f(-hx,-hy, hz); // Top Left Of The Quad (Bottom)
glVertex3f(-hx,-hy,-hz); // Bottom Left Of The Quad (Bottom)
glVertex3f( hx,-hy,-hz); // Bottom Right Of The Quad (Bottom)
glNormal3f(0.0f, 0.0, 1.0f);
glVertex3f( hx, hy, hz); // Top Right Of The Quad (Front)
glVertex3f(-hx, hy, hz); // Top Left Of The Quad (Front)
glVertex3f(-hx,-hy, hz); // Bottom Left Of The Quad (Front)
glVertex3f( hx,-hy, hz); // Bottom Right Of The Quad (Front)
glNormal3f(0.0f, 0.0, -1.0f);
glVertex3f( hx,-hy,-hz); // Top Right Of The Quad (Back)
glVertex3f(-hx,-hy,-hz); // Top Left Of The Quad (Back)
glVertex3f(-hx, hy,-hz); // Bottom Left Of The Quad (Back)
glVertex3f( hx, hy,-hz); // Bottom Right Of The Quad (Back)
glNormal3f(-1.0f, 0.0, 0.0f);
glVertex3f(-hx, hy, hz); // Top Right Of The Quad (Left)
glVertex3f(-hx, hy,-hz); // Top Left Of The Quad (Left)
glVertex3f(-hx,-hy,-hz); // Bottom Left Of The Quad (Left)
glVertex3f(-hx,-hy, hz); // Bottom Right Of The Quad (Left)
glNormal3f(1.0f, 0.0, 0.0f);
glVertex3f( hx, hy,-hz); // Top Right Of The Quad (Right)
glVertex3f( hx, hy, hz); // Top Left Of The Quad (Right)
glVertex3f( hx,-hy, hz); // Bottom Left Of The Quad (Right)
glVertex3f( hx,-hy,-hz); // Bottom Right Of The Quad (Right)
glEnd(); // End Drawing The Cube
}
void DrawAxes()
{
//To prevent the view from disturbed on repaint
//this push matrix call stores the current matrix state
//and restores it once we are done with the arrow rendering
glPushMatrix();
glColor3f(0,0,1);
glPushMatrix();
glTranslatef(0,0, 0.8f);
glutSolidCone(0.0325,0.2, 4,1);
//Draw label
glTranslatef(0,0.0625,0.225f);
RenderSpacedBitmapString(0,0,0,GLUT_BITMAP_HELVETICA_10, "Z");
glPopMatrix();
glColor3f(1,0,0);
glRotatef(90,0,1,0);
glPushMatrix();
glTranslatef(0,0,0.8f);
glutSolidCone(0.0325,0.2, 4,1);
//Draw label
glTranslatef(0,0.0625,0.225f);
RenderSpacedBitmapString(0,0,0,GLUT_BITMAP_HELVETICA_10, "X");
glPopMatrix();
glutSolidCone(0.0225,1, 4,1);
glColor3f(0,1,0);
glRotatef(90,-1,0,0);
glPushMatrix();
glTranslatef(0,0, 0.8f);
glutSolidCone(0.0325,0.2, 4,1);
//Draw label
glTranslatef(0,0.0625,0.225f);
RenderSpacedBitmapString(0,0,0,GLUT_BITMAP_HELVETICA_10, "Y");
glPopMatrix();
glutSolidCone(0.0225,1, 4,1);
glPopMatrix();
}
void DrawGrid(int GRID_SIZE)
{
glBegin(GL_LINES);
glColor3f(0.25f, 0.25f, 0.25f);
for(int i=-GRID_SIZE;i<=GRID_SIZE;i++)
{
glVertex3f((float)i,0,(float)-GRID_SIZE);
glVertex3f((float)i,0,(float)GRID_SIZE);
glVertex3f((float)-GRID_SIZE,0,(float)i);
glVertex3f((float)GRID_SIZE,0,(float)i);
}
glEnd();
}
void UpdatePhysX()
{
gScene->simulate(myTimestep);
// Fetch results from scene
while(!gScene->fetchResults() )
{
// Nothing todo
}
}
void DrawBox(PxShape* pShape) {
GLfloat mat_diffuse_1[4]={0,0,1.0f,0};
GLfloat mat_diffuse_2[4]={0.85f,0,0,0};
if (pShape->getActor().isRigidStatic())
{
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mat_diffuse_1);
glColor4fv(mat_diffuse_1);
}
else
{
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mat_diffuse_2);
glColor4fv(mat_diffuse_2);
}
PxTransform pT = PxShapeExt::getGlobalPose(*pShape);
PxBoxGeometry bg;
pShape->getBoxGeometry(bg);
PxMat33 m = PxMat33(pT.q );
float mat[16];
getColumnMajor(m,pT.p, mat);
glPushMatrix();
glMultMatrixf(mat);
DrawGLCube(bg.halfExtents.x,bg.halfExtents.y, bg.halfExtents.z);
glPopMatrix();
}
void DrawSphere(PxShape* pShape) {
GLfloat mat_diffuse[4]={0,0.85f,0,0};
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mat_diffuse);
glColor4fv(mat_diffuse);
PxTransform pT = PxShapeExt::getGlobalPose(*pShape);
PxSphereGeometry sg;
pShape->getSphereGeometry(sg);
PxMat33 m = PxMat33(pT.q );
float mat[16];
getColumnMajor(m,pT.p, mat);
glPushMatrix();
glMultMatrixf(mat);
glutSolidSphere(sg.radius, 16, 16);
glPopMatrix();
}
void DrawCapsule(PxShape* pShape) {
GLfloat mat_diffuse[4]={0.85f,0,0.85f,0};
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mat_diffuse);
glColor4fv(mat_diffuse);
PxTransform pT = PxShapeExt::getGlobalPose(*pShape);
PxCapsuleGeometry cg;
pShape->getCapsuleGeometry(cg);
PxMat33 m = PxMat33(pT.q );
float mat[16];
getColumnMajor(m,pT.p, mat);
glPushMatrix();
glMultMatrixf(mat);
glRotatef(90,0,1,0);
glTranslatef(0, 0, -cg.halfHeight);
glutSolidCylinder(cg.radius, 2*cg.halfHeight, 16, 16);
glutSolidSphere(cg.radius, 16, 16);
glTranslatef(0, 0, 2*cg.halfHeight);
glutSolidSphere(cg.radius, 16, 16);
glPopMatrix();
}
void DrawShape(PxShape* shape)
{
PxGeometryType::Enum type = shape->getGeometryType();
switch(type)
{
case PxGeometryType::eBOX:
DrawBox(shape);
break;
case PxGeometryType::eSPHERE:
DrawSphere(shape);
break;
case PxGeometryType::eCAPSULE:
DrawCapsule(shape);
break;
}
}
void DrawBounds(const PxBounds3 &bounds)
{
PxVec3 center = bounds.getCenter();
PxVec3 scale = bounds.getDimensions();
GLfloat mat_diffuse[4]={0.0f,1,1,0};
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mat_diffuse);
glColor4fv(mat_diffuse);
if (!gDrawWireframe)
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glPushMatrix();
glTranslatef(center.x, center.y, center.z);
DrawGLCube(scale.x / 2, scale.y / 2, scale.z / 2);
glPopMatrix();
if (!gDrawWireframe)
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
void DrawParticleFluid(PxParticleFluid* fluid)
{
GLfloat mat_diffuse[4]={0.34f,0.85f,0,0};
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mat_diffuse);
glColor4fv(mat_diffuse);
PxParticleFluidReadData* rd = fluid->lockParticleFluidReadData();
if (rd)
{
PxStrideIterator<const PxParticleFlags> flagsIt(rd->flagsBuffer);
PxStrideIterator<const PxVec3> positionIt(rd->positionBuffer);
for (unsigned i = 0; i < rd->validParticleRange; ++i, ++flagsIt, ++positionIt)
{
if (*flagsIt & PxParticleFlag::eVALID)
{
const PxVec3& position = *positionIt;
glPushMatrix();
glTranslatef(position.x, position.y, position.z);
glutSolidSphere(0.1f, 16, 16);
glPopMatrix();
}
}
rd->unlock();
}
}
void DrawActor(PxActor* actor)
{
PxBounds3 bounds = actor->getWorldBounds();
if (gFrustum->ContainsBounds(bounds))
{
gDrawedActors++;
if (actor->isRigidActor())
{
PxRigidActor* rigActor = (PxRigidActor*)actor;
PxU32 nShapes = rigActor->getNbShapes();
PxShape** shapes = new PxShape*[nShapes];
rigActor->getShapes(shapes, nShapes);
while (nShapes--)
{
DrawShape(shapes[nShapes]);
}
delete [] shapes;
}
else if (actor->isParticleFluid())
{
DrawParticleFluid((PxParticleFluid*)actor);
}
if (gDrawBoundBox)
{
DrawBounds(bounds);
}
}
}
void RenderActors()
{
// Render all the actors in the scene
for (long index=0; index<(long)gActors.size(); ++index)
{
PxActor* act = gActors.at(index);
DrawActor(act);
}
}
void ShutdownPhysX() {
ClearScene();
ClearWater();
gScene->release();
gDefaultMaterial->release();
gPhysicsSDK->release();
}
void InitGL() {
glShadeModel(GL_SMOOTH);
glEnable(GL_CULL_FACE);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
GLfloat ambient[4]={0.25f,0.25f,0.25f,0.25f};
GLfloat diffuse[4]={1,1,1,1};
GLfloat specular[4] = {1.0, 1.0, 1.0, 1.0};
glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, specular);
glDisable(GL_LIGHTING);
glDisable(GL_DEPTH_TEST);
}
void OnReshape(int nw, int nh)
{
glViewport(0,0,nw, nh);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60, (GLfloat)nw / (GLfloat)nh, 0.1f, 1000.0f);
glMatrixMode(GL_MODELVIEW);
}
const char* GetGeometryType(unsigned int state)
{
switch (state)
{
case 1:
return "Box\0";
case 2:
return "Sphere\0";
case 3:
return "Capsule\0";
case 4:
return "Water\0";
default:
return "Unknown";
}
}
static PxMat44 Mat44Rotate(const float Angle, const PxVec3& Axis)
{
PxMat44 M;
float CosinusAngle,SinusAngle;
M = PxMat44::createIdentity();
CosinusAngle = cos(Angle);
SinusAngle = sin(Angle);
M[0][0] = CosinusAngle+(1-CosinusAngle)*Axis.x*Axis.x;
M[1][0] = (1-CosinusAngle)*Axis.x*Axis.y-Axis.z*SinusAngle;
M[2][0] = (1-CosinusAngle)*Axis.x*Axis.z+Axis.y*SinusAngle;
M[0][1] = (1-CosinusAngle)*Axis.x*Axis.z+Axis.z*SinusAngle;
M[1][1] = CosinusAngle+(1-CosinusAngle)*Axis.y*Axis.y;
M[2][1] = (1-CosinusAngle)*Axis.y*Axis.z-Axis.x*SinusAngle;
M[0][2] = (1-CosinusAngle)*Axis.x*Axis.z-Axis.y*SinusAngle;
M[1][2] = (1-CosinusAngle)*Axis.y*Axis.z+Axis.x*SinusAngle;
M[2][2] = CosinusAngle+(1-CosinusAngle)*Axis.z*Axis.z;
return M;
}
void Update()
{
float proj[16];
float modl[16];
glGetFloatv( GL_PROJECTION_MATRIX, proj );
glGetFloatv( GL_MODELVIEW_MATRIX, modl );
gFrustum->Update(proj, modl);
}
char buffer[MAX_PATH];
void OnRender() {
if (!gScene) return;
//Calculate fps
totalFrames++;
int current = glutGet(GLUT_ELAPSED_TIME);
if((current-startTime)>1000)
{
float elapsedTime = float(current-startTime);
fps = ((totalFrames * 1000.0f)/ elapsedTime) ;
myTimestep = 1.0f / fps;
startTime = current;
totalFrames=0;
}
// Update counters
gTotalActors = gActors.size();
gDrawedActors = 0;
// Update PhysX
UpdatePhysX();
// Clear color and depth buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Reset modelview matrix
glLoadIdentity();
/*
PxMat44 modelview = PxMat44::createIdentity();
modelview.setPosition(PxVec3(0,0,dist));
PxMat44 rotation = Mat44Rotate(Deg2Rad(rX), PxVec3(1,0,0));
rotation = rotation * Mat44Rotate(Deg2Rad(rY), PxVec3(0,1,0));
modelview = modelview * rotation;
glLoadMatrixf(modelview.front());
*/
// Set Camera
glTranslatef(0,0,dist);
glRotatef(rX, 1, 0, 0);
glRotatef(rY, 0, 1, 0);
// Update
Update();
// Enable depth testing
glEnable(GL_DEPTH_TEST);
// Draw the grid and axes
DrawAxes();
DrawGrid(40);
// Wireframe or not? Depends if lighting is enabled or not
if (gDrawWireframe)
{
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glDisable(GL_LIGHTING);
}
else
{
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glEnable(GL_LIGHTING);
}
// Render actors
RenderActors();
// Disable lighting and depth test for font rendering
glDisable(GL_LIGHTING);
glDisable(GL_DEPTH_TEST);
// Prepare for font rendering
SetOrthoForFont();
glColor3f(1,1,1);
// Render text
sprintf_s(buffer, "FPS: %3.2f",fps);
RenderSpacedBitmapString(20,20,0,GLUT_BITMAP_HELVETICA_12,buffer);
sprintf_s(buffer, "Drawed actors: %d of %d", gDrawedActors, gTotalActors);
RenderSpacedBitmapString(20,32,0,GLUT_BITMAP_HELVETICA_12,buffer);
sprintf_s(buffer, "Water particles: %d", gWaterParticles.size());
RenderSpacedBitmapString(20,44,0,GLUT_BITMAP_HELVETICA_12,buffer);
sprintf_s(buffer, "Controls:");
RenderSpacedBitmapString(20,80,0,GLUT_BITMAP_HELVETICA_12,buffer);
sprintf_s(buffer, "Geometry type (1-3): %s", GetGeometryType(gGeoType));
RenderSpacedBitmapString(20,92,0,GLUT_BITMAP_HELVETICA_12,buffer);
sprintf_s(buffer, "Draw Wireframe (W): %s", gDrawWireframe ? "enabled" : "disabled");
RenderSpacedBitmapString(20,104,0,GLUT_BITMAP_HELVETICA_12,buffer);
sprintf_s(buffer, "Draw Boundbox (B): %s", gDrawBoundBox ? "enabled" : "disabled");
RenderSpacedBitmapString(20,116,0,GLUT_BITMAP_HELVETICA_12,buffer);
sprintf_s(buffer, "New actor (Space)");
RenderSpacedBitmapString(20,128,0,GLUT_BITMAP_HELVETICA_12,buffer);
// Reset projection for 3d rendering
ResetPerspectiveProjection();
glutSwapBuffers();
}
void Mouse(int button, int s, int x, int y)
{
if (s == GLUT_DOWN)
{
oldX = x;
oldY = y;
}
if(button == GLUT_MIDDLE_BUTTON)
state = 0;
else
state = 1;
}
void Motion(int x, int y)
{
if (state == 0)
dist *= (1 + (y - oldY)/60.0f);
else
{
rY += (x - oldX)/5.0f;
rX += (y - oldY)/5.0f;
}
oldX = x;
oldY = y;
glutPostRedisplay();
}
void AddActorByState(unsigned int state)
{
switch (state)
{
case 1:
AddBox(PxVec3(0.0f, 10.0f, 0.0f), PxVec3(0.5,0.5,0.5));
break;
case 2:
AddSphere();
break;
case 3:
AddCapsule();
break;
case 4:
AddWater();
break;
default:
break;
}
}
void KeyUp(unsigned char key, int x, int y)
{
switch (key)
{
case 27:
{
exit(0);
break;
}
case 49:
case 50:
case 51:
case 52:
{
gGeoType = 1 + (key - 49);
break;
}
case 114:
{
ResetScene();
break;
}
case 98:
{
gDrawBoundBox = !gDrawBoundBox;
break;
}
case 119:
{
gDrawWireframe = !gDrawWireframe;
break;
}
default:
break;
}
}
void KeyDown(unsigned char key, int x, int y)
{
switch (key)
{
case 32:
{
AddActorByState(gGeoType);
break;
}
default:
break;
}
}
void OnIdle() {
glutPostRedisplay();
}
void OnShutdown() {
printf("Shutdown PhysX\n");
ShutdownPhysX();
delete gFrustum;
}
void main(int argc, char** argv) {
atexit(OnShutdown);
srand ( (unsigned int)time(NULL) );
printf("Initialize Window\n");
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowSize(windowWidth, windowHeight);
glutCreateWindow("Playing around with physx");
glutDisplayFunc(OnRender);
glutIdleFunc(OnIdle);
glutReshapeFunc(OnReshape);
glutMouseFunc(Mouse);
glutMotionFunc(Motion);
glutKeyboardUpFunc(KeyUp);
glutKeyboardFunc(KeyDown);
printf("Initialize OpenGL\n");
InitGL();
gFrustum = new CFrustum();
printf("Initialize PhysX\n");
InitializePhysX();
printf("Main loop\n");
glutMainLoop();
}
#define NOMINMAX
#ifdef WIN32
#include <windows.h>
#include <GL/gl.h>
#include <GL/glut.h>
#elif LINUX
#include <GL/gl.h>
#include <GL/glut.h>
#elif __APPLE__
#include <OpenGL/gl.h>
#include <GLUT/glut.h>
#elif __CELLOS_LV2__
#include <GL/glut.h>
#endif
#include <stdio.h>
// Physics code
#undef random
#include "NxPhysics.h"
//#include "ErrorStream.h"
#pragma comment( lib, "PhysXLoader.lib" )
static bool gPause = false;
static NxPhysicsSDK* gPhysicsSDK = NULL;
static NxScene* gScene = NULL;
static NxVec3 gDefaultGravity(0.0f, -9.81f, 0.0f);
static float gRatio=1.0f;
static void InitNx()
{
// Initialize PhysicsSDK
gPhysicsSDK = NxCreatePhysicsSDK(NX_PHYSICS_SDK_VERSION, 0, NULL);
if(!gPhysicsSDK) return;
gPhysicsSDK->setParameter(NX_MIN_SEPARATION_FOR_PENALTY, -0.05f);
// Create a scene
NxSceneDesc sceneDesc;
sceneDesc.gravity = gDefaultGravity;
sceneDesc.broadPhase = NX_BROADPHASE_COHERENT;
sceneDesc.collisionDetection = true;
gScene = gPhysicsSDK->createScene(sceneDesc);
NxMaterial * defaultMaterial = gScene->getMaterialFromIndex(0);
defaultMaterial->setRestitution(0.9f);
defaultMaterial->setStaticFriction(0.1f);
defaultMaterial->setDynamicFriction(0.1f);
// Create ground plane
NxPlaneShapeDesc PlaneDesc;
PlaneDesc.d = -5.0f;
NxActorDesc ActorDesc;
ActorDesc.shapes.pushBack(&PlaneDesc);
gScene->createActor(ActorDesc);
//CreateCube(NxVec3(0.0,20.0,0.0),5);
// Create body
//////////////////////////////////////////////////////////////
int size = 5;
NxBodyDesc BodyDesc;
BodyDesc.angularDamping = 0.5f;
// BodyDesc.maxAngularVelocity = 10.0f;
BodyDesc.linearVelocity = NxVec3(0.0f,0.0f,0.0f);
NxBoxShapeDesc BoxDesc;
BoxDesc.dimensions = NxVec3(float(size), float(size), float(size));
NxActorDesc BoxActorDesc;
BoxActorDesc.shapes.pushBack(&BoxDesc);
BoxActorDesc.body = &BodyDesc;
BoxActorDesc.density = 0.10f;
BoxActorDesc.globalPose.t = NxVec3(0.0,20.0,0.0);
gScene->createActor(BoxActorDesc)->userData = (void*)size;
}
static void RenderCallback()
{
// Clear buffers
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Setup camera
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0f, 1.0, 1.0f, 10000.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0.0, 5.1, 50.0, 0.0, 0.0, 0.0, 0.0f, 1.0f, 0.0f);
gScene->fetchResults(NX_RIGID_BODY_FINISHED);
gScene->simulate(1/60.0f);
gScene->flushStream();
// Keep physics & graphics in sync
int nbActors = gScene->getNbActors();
NxActor** actors = gScene->getActors();
while(nbActors--)
{
NxActor* actor = *actors++;
if(!actor->userData) continue;
glPushMatrix();
float glmat[16];
actor->getGlobalPose().getColumnMajor44(glmat);
glMultMatrixf(glmat);
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
glutWireCube(float(int(actor->userData))*2.0f);
glPopMatrix();
}
glutSwapBuffers();
}
int main(int argc, char** argv)
{
// Initialize Glut
printf("PhysX, Hello World!");
glutInit(&argc, argv);
glutInitWindowSize(512, 512);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
int mainHandle = glutCreateWindow("PhysX, Hello World!");
glutSetWindow(mainHandle);
glutDisplayFunc(RenderCallback);
glutIdleFunc(RenderCallback);
// Setup default render states
glClearColor(0.3f, 0.4f, 0.5f, 1.0);
glEnable(GL_DEPTH_TEST);
glEnable(GL_COLOR_MATERIAL);
glEnable(GL_CULL_FACE);
glEnable(GL_LIGHTING);
// Physics code
InitNx();
// ~Physics code
// Run
glutMainLoop();
if(gPhysicsSDK && gScene) gPhysicsSDK->releaseScene(*gScene);
gPhysicsSDK->release();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment