1698 lines
51 KiB
C++
1698 lines
51 KiB
C++
// Redistribution and use in source and binary forms, with or without
|
|
// modification, are permitted provided that the following conditions
|
|
// are met:
|
|
// * Redistributions of source code must retain the above copyright
|
|
// notice, this list of conditions and the following disclaimer.
|
|
// * Redistributions in binary form must reproduce the above copyright
|
|
// notice, this list of conditions and the following disclaimer in the
|
|
// documentation and/or other materials provided with the distribution.
|
|
// * Neither the name of NVIDIA CORPORATION nor the names of its
|
|
// contributors may be used to endorse or promote products derived
|
|
// from this software without specific prior written permission.
|
|
//
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
|
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
|
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
//
|
|
// Copyright (c) 2008-2025 NVIDIA Corporation. All rights reserved.
|
|
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
|
|
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
|
|
|
|
#include "foundation/PxPreprocessor.h"
|
|
|
|
#define USE_CUDA_INTEROP (PX_SUPPORT_GPU_PHYSX)
|
|
|
|
#if (PX_SUPPORT_GPU_PHYSX && USE_CUDA_INTEROP)
|
|
#if PX_LINUX && PX_CLANG
|
|
#pragma clang diagnostic push
|
|
#pragma clang diagnostic ignored "-Wdocumentation"
|
|
#endif
|
|
#include "cuda.h"
|
|
#include "SnippetRender.h"
|
|
#include "cudaGL.h"
|
|
#if PX_LINUX && PX_CLANG
|
|
#pragma clang diagnostic pop
|
|
#endif
|
|
#else
|
|
#include "SnippetRender.h"
|
|
#endif
|
|
|
|
#include "SnippetFontRenderer.h"
|
|
#include "SnippetCamera.h"
|
|
#include "foundation/PxArray.h"
|
|
#include "foundation/PxMathUtils.h"
|
|
#include <vector>
|
|
|
|
#define MAX_NUM_ACTOR_SHAPES 128
|
|
#define INITIAL_SCREEN_WIDTH 768
|
|
#define INITIAL_SCREEN_HEIGHT 768
|
|
|
|
using namespace physx;
|
|
|
|
static GLFontRenderer gTexter;
|
|
|
|
static float gCylinderData[]={
|
|
1.0f,0.0f,1.0f,1.0f,0.0f,1.0f,1.0f,0.0f,0.0f,1.0f,0.0f,0.0f,
|
|
0.866025f,0.500000f,1.0f,0.866025f,0.500000f,1.0f,0.866025f,0.500000f,0.0f,0.866025f,0.500000f,0.0f,
|
|
0.500000f,0.866025f,1.0f,0.500000f,0.866025f,1.0f,0.500000f,0.866025f,0.0f,0.500000f,0.866025f,0.0f,
|
|
-0.0f,1.0f,1.0f,-0.0f,1.0f,1.0f,-0.0f,1.0f,0.0f,-0.0f,1.0f,0.0f,
|
|
-0.500000f,0.866025f,1.0f,-0.500000f,0.866025f,1.0f,-0.500000f,0.866025f,0.0f,-0.500000f,0.866025f,0.0f,
|
|
-0.866025f,0.500000f,1.0f,-0.866025f,0.500000f,1.0f,-0.866025f,0.500000f,0.0f,-0.866025f,0.500000f,0.0f,
|
|
-1.0f,-0.0f,1.0f,-1.0f,-0.0f,1.0f,-1.0f,-0.0f,0.0f,-1.0f,-0.0f,0.0f,
|
|
-0.866025f,-0.500000f,1.0f,-0.866025f,-0.500000f,1.0f,-0.866025f,-0.500000f,0.0f,-0.866025f,-0.500000f,0.0f,
|
|
-0.500000f,-0.866025f,1.0f,-0.500000f,-0.866025f,1.0f,-0.500000f,-0.866025f,0.0f,-0.500000f,-0.866025f,0.0f,
|
|
0.0f,-1.0f,1.0f,0.0f,-1.0f,1.0f,0.0f,-1.0f,0.0f,0.0f,-1.0f,0.0f,
|
|
0.500000f,-0.866025f,1.0f,0.500000f,-0.866025f,1.0f,0.500000f,-0.866025f,0.0f,0.500000f,-0.866025f,0.0f,
|
|
0.866026f,-0.500000f,1.0f,0.866026f,-0.500000f,1.0f,0.866026f,-0.500000f,0.0f,0.866026f,-0.500000f,0.0f,
|
|
1.0f,0.0f,1.0f,1.0f,0.0f,1.0f,1.0f,0.0f,0.0f,1.0f,0.0f,0.0f
|
|
};
|
|
|
|
static std::vector<PxVec3>* gVertexBuffer = NULL;
|
|
static int gLastTime = 0;
|
|
static int gFrameCounter = 0;
|
|
static char gTitle[256];
|
|
static bool gWireFrame = false;
|
|
|
|
static PX_FORCE_INLINE void prepareVertexBuffer()
|
|
{
|
|
if(!gVertexBuffer)
|
|
gVertexBuffer = new std::vector<PxVec3>;
|
|
gVertexBuffer->clear();
|
|
}
|
|
|
|
static PX_FORCE_INLINE void pushVertex(const PxVec3& v0, const PxVec3& v1, const PxVec3& v2, const PxVec3& n)
|
|
{
|
|
PX_ASSERT(gVertexBuffer);
|
|
gVertexBuffer->push_back(n); gVertexBuffer->push_back(v0);
|
|
gVertexBuffer->push_back(n); gVertexBuffer->push_back(v1);
|
|
gVertexBuffer->push_back(n); gVertexBuffer->push_back(v2);
|
|
}
|
|
|
|
static PX_FORCE_INLINE void pushVertex(const PxVec3& v0, const PxVec3& v1, const PxVec3& v2, const PxVec3& n0, const PxVec3& n1, const PxVec3& n2, float normalSign = 1)
|
|
{
|
|
PX_ASSERT(gVertexBuffer);
|
|
gVertexBuffer->push_back(normalSign * n0); gVertexBuffer->push_back(v0);
|
|
gVertexBuffer->push_back(normalSign * n1); gVertexBuffer->push_back(v1);
|
|
gVertexBuffer->push_back(normalSign * n2); gVertexBuffer->push_back(v2);
|
|
}
|
|
|
|
static PX_FORCE_INLINE const PxVec3* getVertexBuffer()
|
|
{
|
|
PX_ASSERT(gVertexBuffer);
|
|
return &(*gVertexBuffer)[0];
|
|
}
|
|
|
|
static void releaseVertexBuffer()
|
|
{
|
|
if(gVertexBuffer)
|
|
{
|
|
delete gVertexBuffer;
|
|
gVertexBuffer = NULL;
|
|
}
|
|
}
|
|
|
|
static void renderDeformableVolumeGeometry(const PxTetrahedronMesh& mesh, const PxVec4* deformedPositionsInvMass)
|
|
{
|
|
const int tetFaces[4][3] = { {0,2,1}, {0,1,3}, {0,3,2}, {1,2,3} };
|
|
|
|
//Get the deformed vertices
|
|
//const PxVec3* vertices = mesh.getVertices();
|
|
const PxU32 tetCount = mesh.getNbTetrahedrons();
|
|
const PxU32 has16BitIndices = mesh.getTetrahedronMeshFlags() & PxTetrahedronMeshFlag::e16_BIT_INDICES;
|
|
const void* indexBuffer = mesh.getTetrahedrons();
|
|
|
|
prepareVertexBuffer();
|
|
|
|
const PxU32* intIndices = reinterpret_cast<const PxU32*>(indexBuffer);
|
|
const PxU16* shortIndices = reinterpret_cast<const PxU16*>(indexBuffer);
|
|
PxU32 numTotalTriangles = 0;
|
|
PX_UNUSED(numTotalTriangles);
|
|
|
|
for (PxU32 i = 0; i < tetCount; ++i)
|
|
{
|
|
PxU32 vref[4];
|
|
if (has16BitIndices)
|
|
{
|
|
vref[0] = *shortIndices++;
|
|
vref[1] = *shortIndices++;
|
|
vref[2] = *shortIndices++;
|
|
vref[3] = *shortIndices++;
|
|
}
|
|
else
|
|
{
|
|
vref[0] = *intIndices++;
|
|
vref[1] = *intIndices++;
|
|
vref[2] = *intIndices++;
|
|
vref[3] = *intIndices++;
|
|
}
|
|
|
|
for (PxU32 j = 0; j < 4; ++j)
|
|
{
|
|
const PxVec4& v0 = deformedPositionsInvMass[vref[tetFaces[j][0]]];
|
|
const PxVec4& v1 = deformedPositionsInvMass[vref[tetFaces[j][1]]];
|
|
const PxVec4& v2 = deformedPositionsInvMass[vref[tetFaces[j][2]]];
|
|
|
|
PxVec3 fnormal = (v1.getXYZ() - v0.getXYZ()).cross(v2.getXYZ() - v0.getXYZ());
|
|
fnormal.normalize();
|
|
|
|
pushVertex(v0.getXYZ(), v1.getXYZ(), v2.getXYZ(), fnormal);
|
|
numTotalTriangles++;
|
|
}
|
|
}
|
|
glPushMatrix();
|
|
glScalef(1.0f, 1.0f, 1.0f);
|
|
glEnableClientState(GL_NORMAL_ARRAY);
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
const PxVec3* vertexBuffer = getVertexBuffer();
|
|
glNormalPointer(GL_FLOAT, 2 * 3 * sizeof(float), vertexBuffer);
|
|
glVertexPointer(3, GL_FLOAT, 2 * 3 * sizeof(float), vertexBuffer + 1);
|
|
glDrawArrays(GL_TRIANGLES, 0, int(numTotalTriangles * 3));
|
|
glDisableClientState(GL_VERTEX_ARRAY);
|
|
glDisableClientState(GL_NORMAL_ARRAY);
|
|
glPopMatrix();
|
|
}
|
|
|
|
static void renderGeometry(const PxGeometry& geom)
|
|
{
|
|
if (gWireFrame)
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
|
switch(geom.getType())
|
|
{
|
|
case PxGeometryType::eBOX:
|
|
{
|
|
const PxBoxGeometry& boxGeom = static_cast<const PxBoxGeometry&>(geom);
|
|
glScalef(boxGeom.halfExtents.x, boxGeom.halfExtents.y, boxGeom.halfExtents.z);
|
|
glutSolidCube(2);
|
|
}
|
|
break;
|
|
|
|
case PxGeometryType::eSPHERE:
|
|
{
|
|
const PxSphereGeometry& sphereGeom = static_cast<const PxSphereGeometry&>(geom);
|
|
glutSolidSphere(GLdouble(sphereGeom.radius), 10, 10);
|
|
}
|
|
break;
|
|
|
|
case PxGeometryType::eCAPSULE:
|
|
{
|
|
const PxCapsuleGeometry& capsuleGeom = static_cast<const PxCapsuleGeometry&>(geom);
|
|
const PxF32 radius = capsuleGeom.radius;
|
|
const PxF32 halfHeight = capsuleGeom.halfHeight;
|
|
|
|
//Sphere
|
|
glPushMatrix();
|
|
glTranslatef(halfHeight, 0.0f, 0.0f);
|
|
glScalef(radius,radius,radius);
|
|
glutSolidSphere(1, 10, 10);
|
|
glPopMatrix();
|
|
|
|
//Sphere
|
|
glPushMatrix();
|
|
glTranslatef(-halfHeight, 0.0f, 0.0f);
|
|
glScalef(radius,radius,radius);
|
|
glutSolidSphere(1, 10, 10);
|
|
glPopMatrix();
|
|
|
|
//Cylinder
|
|
glPushMatrix();
|
|
glTranslatef(-halfHeight, 0.0f, 0.0f);
|
|
glScalef(2.0f*halfHeight, radius,radius);
|
|
glRotatef(90.0f,0.0f,1.0f,0.0f);
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
glEnableClientState(GL_NORMAL_ARRAY);
|
|
glVertexPointer(3, GL_FLOAT, 2*3*sizeof(float), gCylinderData);
|
|
glNormalPointer(GL_FLOAT, 2*3*sizeof(float), gCylinderData+3);
|
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, 13*2);
|
|
glDisableClientState(GL_VERTEX_ARRAY);
|
|
glDisableClientState(GL_NORMAL_ARRAY);
|
|
glPopMatrix();
|
|
}
|
|
break;
|
|
|
|
case PxGeometryType::eCONVEXMESH:
|
|
{
|
|
const PxConvexMeshGeometry& convexGeom = static_cast<const PxConvexMeshGeometry&>(geom);
|
|
|
|
//Compute triangles for each polygon.
|
|
const PxVec3& scale = convexGeom.scale.scale;
|
|
PxConvexMesh* mesh = convexGeom.convexMesh;
|
|
const PxU32 nbPolys = mesh->getNbPolygons();
|
|
const PxU8* polygons = mesh->getIndexBuffer();
|
|
const PxVec3* verts = mesh->getVertices();
|
|
PxU32 nbVerts = mesh->getNbVertices();
|
|
PX_UNUSED(nbVerts);
|
|
|
|
prepareVertexBuffer();
|
|
|
|
PxU32 numTotalTriangles = 0;
|
|
for(PxU32 i = 0; i < nbPolys; i++)
|
|
{
|
|
PxHullPolygon data;
|
|
mesh->getPolygonData(i, data);
|
|
|
|
const PxU32 nbTris = PxU32(data.mNbVerts - 2);
|
|
const PxU8 vref0 = polygons[data.mIndexBase + 0];
|
|
PX_ASSERT(vref0 < nbVerts);
|
|
for(PxU32 j=0;j<nbTris;j++)
|
|
{
|
|
const PxU32 vref1 = polygons[data.mIndexBase + 0 + j + 1];
|
|
const PxU32 vref2 = polygons[data.mIndexBase + 0 + j + 2];
|
|
|
|
//generate face normal:
|
|
PxVec3 e0 = verts[vref1] - verts[vref0];
|
|
PxVec3 e1 = verts[vref2] - verts[vref0];
|
|
|
|
PX_ASSERT(vref1 < nbVerts);
|
|
PX_ASSERT(vref2 < nbVerts);
|
|
|
|
PxVec3 fnormal = e0.cross(e1);
|
|
fnormal.normalize();
|
|
|
|
pushVertex(verts[vref0], verts[vref1], verts[vref2], fnormal);
|
|
numTotalTriangles++;
|
|
}
|
|
}
|
|
glPushMatrix();
|
|
glScalef(scale.x, scale.y, scale.z);
|
|
glEnableClientState(GL_NORMAL_ARRAY);
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
const PxVec3* vertexBuffer = getVertexBuffer();
|
|
glNormalPointer(GL_FLOAT, 2*3*sizeof(float), vertexBuffer);
|
|
glVertexPointer(3, GL_FLOAT, 2*3*sizeof(float), vertexBuffer+1);
|
|
glDrawArrays(GL_TRIANGLES, 0, int(numTotalTriangles * 3));
|
|
glPopMatrix();
|
|
}
|
|
break;
|
|
|
|
case PxGeometryType::eTRIANGLEMESH:
|
|
{
|
|
const PxTriangleMeshGeometry& triGeom = static_cast<const PxTriangleMeshGeometry&>(geom);
|
|
|
|
const PxTriangleMesh& mesh = *triGeom.triangleMesh;
|
|
const PxVec3 scale = triGeom.scale.scale;
|
|
|
|
const PxU32 triangleCount = mesh.getNbTriangles();
|
|
const PxU32 has16BitIndices = mesh.getTriangleMeshFlags() & PxTriangleMeshFlag::e16_BIT_INDICES;
|
|
const void* indexBuffer = mesh.getTriangles();
|
|
|
|
const PxVec3* vertices = mesh.getVertices();
|
|
|
|
prepareVertexBuffer();
|
|
|
|
const PxU32* intIndices = reinterpret_cast<const PxU32*>(indexBuffer);
|
|
const PxU16* shortIndices = reinterpret_cast<const PxU16*>(indexBuffer);
|
|
PxU32 numTotalTriangles = 0;
|
|
for(PxU32 i=0; i < triangleCount; ++i)
|
|
{
|
|
PxU32 vref0, vref1, vref2;
|
|
if(has16BitIndices)
|
|
{
|
|
vref0 = *shortIndices++;
|
|
vref1 = *shortIndices++;
|
|
vref2 = *shortIndices++;
|
|
}
|
|
else
|
|
{
|
|
vref0 = *intIndices++;
|
|
vref1 = *intIndices++;
|
|
vref2 = *intIndices++;
|
|
}
|
|
|
|
const PxVec3& v0 = vertices[vref0];
|
|
const PxVec3& v1 = vertices[vref1];
|
|
const PxVec3& v2 = vertices[vref2];
|
|
|
|
PxVec3 fnormal = (v1 - v0).cross(v2 - v0);
|
|
fnormal.normalize();
|
|
|
|
pushVertex(v0, v1, v2, fnormal);
|
|
numTotalTriangles++;
|
|
}
|
|
glPushMatrix();
|
|
glScalef(scale.x, scale.y, scale.z);
|
|
glEnableClientState(GL_NORMAL_ARRAY);
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
const PxVec3* vertexBuffer = getVertexBuffer();
|
|
glNormalPointer(GL_FLOAT, 2*3*sizeof(float), vertexBuffer);
|
|
glVertexPointer(3, GL_FLOAT, 2*3*sizeof(float), vertexBuffer+1);
|
|
glDrawArrays(GL_TRIANGLES, 0, int(numTotalTriangles * 3));
|
|
glDisableClientState(GL_VERTEX_ARRAY);
|
|
glDisableClientState(GL_NORMAL_ARRAY);
|
|
glPopMatrix();
|
|
}
|
|
break;
|
|
|
|
case PxGeometryType::eTETRAHEDRONMESH:
|
|
{
|
|
const int tetFaces[4][3] = { {0,2,1}, {0,1,3}, {0,3,2}, {1,2,3} };
|
|
|
|
const PxTetrahedronMeshGeometry& tetGeom = static_cast<const PxTetrahedronMeshGeometry&>(geom);
|
|
|
|
const PxTetrahedronMesh& mesh = *tetGeom.tetrahedronMesh;
|
|
|
|
//Get the deformed vertices
|
|
const PxVec3* vertices = mesh.getVertices();
|
|
const PxU32 tetCount = mesh.getNbTetrahedrons();
|
|
const PxU32 has16BitIndices = mesh.getTetrahedronMeshFlags() & PxTetrahedronMeshFlag::e16_BIT_INDICES;
|
|
const void* indexBuffer = mesh.getTetrahedrons();
|
|
|
|
prepareVertexBuffer();
|
|
|
|
const PxU32* intIndices = reinterpret_cast<const PxU32*>(indexBuffer);
|
|
const PxU16* shortIndices = reinterpret_cast<const PxU16*>(indexBuffer);
|
|
PxU32 numTotalTriangles = 0;
|
|
for (PxU32 i = 0; i < tetCount; ++i)
|
|
{
|
|
PxU32 vref[4];
|
|
if (has16BitIndices)
|
|
{
|
|
vref[0] = *shortIndices++;
|
|
vref[1] = *shortIndices++;
|
|
vref[2] = *shortIndices++;
|
|
vref[3] = *shortIndices++;
|
|
}
|
|
else
|
|
{
|
|
vref[0] = *intIndices++;
|
|
vref[1] = *intIndices++;
|
|
vref[2] = *intIndices++;
|
|
vref[3] = *intIndices++;
|
|
}
|
|
|
|
for (PxU32 j = 0; j < 4; ++j)
|
|
{
|
|
const PxVec3& v0 = vertices[vref[tetFaces[j][0]]];
|
|
const PxVec3& v1 = vertices[vref[tetFaces[j][1]]];
|
|
const PxVec3& v2 = vertices[vref[tetFaces[j][2]]];
|
|
|
|
PxVec3 fnormal = (v1 - v0).cross(v2 - v0);
|
|
fnormal.normalize();
|
|
|
|
pushVertex(v0, v1, v2, fnormal);
|
|
numTotalTriangles++;
|
|
}
|
|
}
|
|
glPushMatrix();
|
|
glScalef(1.0f, 1.0f, 1.0f);
|
|
glEnableClientState(GL_NORMAL_ARRAY);
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
const PxVec3* vertexBuffer = getVertexBuffer();
|
|
glNormalPointer(GL_FLOAT, 2 * 3 * sizeof(float), vertexBuffer);
|
|
glVertexPointer(3, GL_FLOAT, 2 * 3 * sizeof(float), vertexBuffer + 1);
|
|
glDrawArrays(GL_TRIANGLES, 0, int(numTotalTriangles * 3));
|
|
glDisableClientState(GL_VERTEX_ARRAY);
|
|
glDisableClientState(GL_NORMAL_ARRAY);
|
|
glPopMatrix();
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (gWireFrame)
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
|
}
|
|
|
|
static Snippets::Camera* gCamera = NULL;
|
|
static KeyboardCallback gKbCb = NULL;
|
|
|
|
static PxU32 gScreenWidth = 0;
|
|
static PxU32 gScreenHeight = 0;
|
|
|
|
static void defaultReshapeCallback(int width, int height)
|
|
{
|
|
glViewport(0, 0, width, height);
|
|
gTexter.setScreenResolution(width, height);
|
|
gScreenWidth = width;
|
|
gScreenHeight = height;
|
|
}
|
|
|
|
static void defaultIdleCallback()
|
|
{
|
|
glutPostRedisplay();
|
|
}
|
|
|
|
static bool gMoveCamera = false;
|
|
|
|
static void defaultMotionCallback(int x, int y)
|
|
{
|
|
if(gCamera && gMoveCamera)
|
|
gCamera->handleMotion(x, y);
|
|
}
|
|
|
|
static void defaultMouseCallback(int button, int state, int x, int y)
|
|
{
|
|
if(button==0)
|
|
gMoveCamera = state==0;
|
|
|
|
if(gCamera)
|
|
gCamera->handleMouse(button, state, x, y);
|
|
}
|
|
|
|
static void defaultKeyboardCallback(unsigned char key, int x, int y)
|
|
{
|
|
if(key==27)
|
|
glutLeaveMainLoop();
|
|
|
|
if (key == 110) //n
|
|
gWireFrame = !gWireFrame;
|
|
|
|
const bool status = gCamera ? gCamera->handleKey(key, x, y) : false;
|
|
if(!status && gKbCb)
|
|
gKbCb(key, gCamera ? gCamera->getTransform() : PxTransform(PxIdentity));
|
|
}
|
|
|
|
static void defaultSpecialCallback(int key, int x, int y)
|
|
{
|
|
switch(key)
|
|
{
|
|
case GLUT_KEY_UP: key='W'; break;
|
|
case GLUT_KEY_DOWN: key='S'; break;
|
|
case GLUT_KEY_LEFT: key='A'; break;
|
|
case GLUT_KEY_RIGHT: key='D'; break;
|
|
}
|
|
|
|
const bool status = gCamera ? gCamera->handleKey((unsigned char)key, x, y) : false;
|
|
if(!status && gKbCb)
|
|
gKbCb((unsigned char)key, gCamera ? gCamera->getTransform() : PxTransform(PxIdentity));
|
|
}
|
|
|
|
static ExitCallback gUserExitCB = NULL;
|
|
static void defaultExitCallback()
|
|
{
|
|
releaseVertexBuffer();
|
|
|
|
if(gUserExitCB)
|
|
(gUserExitCB)();
|
|
}
|
|
|
|
static void setupDefaultWindow(const char* name, RenderCallback rdcb)
|
|
{
|
|
char* namestr = new char[strlen(name)+1];
|
|
strcpy(namestr, name);
|
|
int argc = 1;
|
|
char* argv[1] = { namestr };
|
|
|
|
glutInit(&argc, argv);
|
|
|
|
gScreenWidth = INITIAL_SCREEN_WIDTH;
|
|
gScreenHeight = INITIAL_SCREEN_HEIGHT;
|
|
|
|
gTexter.init();
|
|
gTexter.setScreenResolution(gScreenWidth, gScreenHeight);
|
|
gTexter.setColor(1.0f, 1.0f, 1.0f, 1.0f);
|
|
|
|
glutInitWindowSize(gScreenWidth, gScreenHeight);
|
|
glutInitDisplayMode(GLUT_RGB|GLUT_DOUBLE|GLUT_DEPTH);
|
|
int mainHandle = glutCreateWindow(name);
|
|
GLenum err = glewInit();
|
|
if (GLEW_OK != err)
|
|
{
|
|
fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
|
|
}
|
|
glutSetWindow(mainHandle);
|
|
glutReshapeFunc(defaultReshapeCallback);
|
|
glutIdleFunc(defaultIdleCallback);
|
|
glutKeyboardFunc(defaultKeyboardCallback);
|
|
glutSpecialFunc(defaultSpecialCallback);
|
|
glutMouseFunc(defaultMouseCallback);
|
|
glutMotionFunc(defaultMotionCallback);
|
|
if(rdcb)
|
|
glutDisplayFunc(rdcb);
|
|
defaultMotionCallback(0,0);
|
|
|
|
delete[] namestr;
|
|
}
|
|
|
|
static void setupDefaultRenderState()
|
|
{
|
|
// Setup default render states
|
|
// glClearColor(0.3f, 0.4f, 0.5f, 1.0);
|
|
glClearColor(0.2f, 0.2f, 0.2f, 1.0);
|
|
glEnable(GL_DEPTH_TEST);
|
|
glEnable(GL_COLOR_MATERIAL);
|
|
glEnable(GL_CULL_FACE);
|
|
glCullFace(GL_BACK);
|
|
|
|
// Setup lighting
|
|
/* glEnable(GL_LIGHTING);
|
|
PxReal ambientColor[] = { 0.0f, 0.1f, 0.2f, 0.0f };
|
|
PxReal diffuseColor[] = { 1.0f, 1.0f, 1.0f, 0.0f };
|
|
PxReal specularColor[] = { 0.0f, 0.0f, 0.0f, 0.0f };
|
|
PxReal position[] = { 100.0f, 100.0f, 400.0f, 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);
|
|
glEnable(GL_LIGHT0);*/
|
|
}
|
|
|
|
static void InitLighting()
|
|
{
|
|
glEnable(GL_COLOR_MATERIAL);
|
|
glEnable(GL_NORMALIZE);
|
|
|
|
const float zero[] = { 0.0f, 0.0f, 0.0f, 0.0f };
|
|
glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, zero);
|
|
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, zero);
|
|
glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, zero);
|
|
glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, zero);
|
|
glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 0.0f);
|
|
|
|
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, zero);
|
|
|
|
glEnable(GL_LIGHTING);
|
|
PxVec3 Dir(-1.0f, 1.0f, 0.5f);
|
|
// PxVec3 Dir(0.0f, 1.0f, 0.0f);
|
|
Dir.normalize();
|
|
|
|
const float AmbientValue = 0.3f;
|
|
const float ambientColor0[] = { AmbientValue, AmbientValue, AmbientValue, 0.0f };
|
|
glLightfv(GL_LIGHT0, GL_AMBIENT, ambientColor0);
|
|
|
|
const float specularColor0[] = { 0.0f, 0.0f, 0.0f, 0.0f };
|
|
glLightfv(GL_LIGHT0, GL_SPECULAR, specularColor0);
|
|
|
|
const float diffuseColor0[] = { 1.0f, 1.0f, 1.0f, 0.0f };
|
|
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseColor0);
|
|
|
|
const float position0[] = { Dir.x, Dir.y, Dir.z, 0.0f };
|
|
glLightfv(GL_LIGHT0, GL_POSITION, position0);
|
|
|
|
glEnable(GL_LIGHT0);
|
|
|
|
// glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
|
// glColor4f(0.0f, 0.0f, 0.0f, 0.0f);
|
|
|
|
/* glEnable(GL_LIGHTING);
|
|
PxReal ambientColor[] = { 0.0f, 0.1f, 0.2f, 0.0f };
|
|
PxReal diffuseColor[] = { 1.0f, 1.0f, 1.0f, 0.0f };
|
|
PxReal specularColor[] = { 0.0f, 0.0f, 0.0f, 0.0f };
|
|
PxReal position[] = { 100.0f, 100.0f, 400.0f, 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);
|
|
glEnable(GL_LIGHT0);*/
|
|
|
|
if(0)
|
|
{
|
|
glEnable(GL_FOG);
|
|
glFogi(GL_FOG_MODE,GL_LINEAR);
|
|
//glFogi(GL_FOG_MODE,GL_EXP);
|
|
//glFogi(GL_FOG_MODE,GL_EXP2);
|
|
glFogf(GL_FOG_START, 0.0f);
|
|
glFogf(GL_FOG_END, 100.0f);
|
|
glFogf(GL_FOG_DENSITY, 0.005f);
|
|
// glClearColor(0.2f, 0.2f, 0.2f, 1.0);
|
|
// const PxVec3 FogColor(0.2f, 0.2f, 0.2f);
|
|
const PxVec3 FogColor(0.3f, 0.4f, 0.5f);
|
|
// const PxVec3 FogColor(1.0f);
|
|
glFogfv(GL_FOG_COLOR, &FogColor.x);
|
|
}
|
|
}
|
|
|
|
namespace Snippets
|
|
{
|
|
void initFPS()
|
|
{
|
|
gLastTime = glutGet(GLUT_ELAPSED_TIME);
|
|
}
|
|
|
|
void showFPS(int updateIntervalMS, const char* info)
|
|
{
|
|
++gFrameCounter;
|
|
int currentTime = glutGet(GLUT_ELAPSED_TIME);
|
|
if (currentTime - gLastTime > updateIntervalMS)
|
|
{
|
|
if (info)
|
|
sprintf(gTitle, " FPS : %4.0f%s", gFrameCounter * 1000.0 / (currentTime - gLastTime), info);
|
|
else
|
|
sprintf(gTitle, " FPS : %4.0f", gFrameCounter * 1000.0 / (currentTime - gLastTime));
|
|
glutSetWindowTitle(gTitle);
|
|
gLastTime = currentTime;
|
|
gFrameCounter = 0;
|
|
}
|
|
}
|
|
|
|
PxU32 getScreenWidth()
|
|
{
|
|
return gScreenWidth;
|
|
}
|
|
|
|
PxU32 getScreenHeight()
|
|
{
|
|
return gScreenHeight;
|
|
}
|
|
|
|
void enableVSync(bool vsync)
|
|
{
|
|
#if PX_WIN32 || PX_WIN64
|
|
typedef void (APIENTRY * PFNWGLSWAPINTERVALPROC) (GLenum interval);
|
|
PFNWGLSWAPINTERVALPROC wglSwapIntervalEXT = (PFNWGLSWAPINTERVALPROC)wglGetProcAddress("wglSwapIntervalEXT");
|
|
wglSwapIntervalEXT(vsync);
|
|
#else
|
|
PX_UNUSED(vsync);
|
|
#endif
|
|
}
|
|
|
|
void setupDefault(const char* name, Camera* camera, KeyboardCallback kbcb, RenderCallback rdcb, ExitCallback excb)
|
|
{
|
|
gCamera = camera;
|
|
gKbCb = kbcb;
|
|
setupDefaultWindow(name, rdcb);
|
|
setupDefaultRenderState();
|
|
enableVSync(true);
|
|
|
|
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_GLUTMAINLOOP_RETURNS);
|
|
|
|
|
|
gUserExitCB = excb;
|
|
atexit(defaultExitCallback);
|
|
}
|
|
|
|
Camera* getCamera()
|
|
{
|
|
return gCamera;
|
|
}
|
|
|
|
static float gNearClip = 0.0f;
|
|
static float gFarClip = 0.0f;
|
|
static float gFOV = 60.0f;
|
|
|
|
static float gTextScale = 0.0f;
|
|
static float gTextY = 0.0f;
|
|
|
|
PxVec3 computeWorldRayF(float xs, float ys, const PxVec3& camDir)
|
|
{
|
|
const float Width = float(gScreenWidth);
|
|
const float Height = float(gScreenHeight);
|
|
|
|
// Recenter coordinates in camera space ([-1, 1])
|
|
const float u = ((xs - Width*0.5f)/Width)*2.0f;
|
|
const float v = -((ys - Height*0.5f)/Height)*2.0f;
|
|
|
|
// Adjust coordinates according to camera aspect ratio
|
|
const float HTan = tanf(0.25f * fabsf(PxDegToRad(gFOV * 2.0f)));
|
|
const float VTan = HTan*(Width/Height);
|
|
|
|
// Ray in camera space
|
|
const PxVec3 CamRay(VTan*u, HTan*v, 1.0f);
|
|
|
|
// Compute ray in world space
|
|
PxVec3 Right, Up;
|
|
PxComputeBasisVectors(camDir, Right, Up);
|
|
|
|
const PxMat33 invView(-Right, Up, camDir);
|
|
|
|
return invView.transform(CamRay).getNormalized();
|
|
}
|
|
|
|
void startRender(const Camera* camera, float clipNear, float clipFar, float fov, bool setupLighting)
|
|
{
|
|
const PxVec3 cameraEye = camera->getEye();
|
|
const PxVec3 cameraDir = camera->getDir();
|
|
|
|
gNearClip = clipNear;
|
|
gFarClip = clipFar;
|
|
gFOV = fov;
|
|
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
|
|
// Setup camera
|
|
glMatrixMode(GL_PROJECTION);
|
|
glLoadIdentity();
|
|
gluPerspective(GLdouble(fov), GLdouble(glutGet(GLUT_WINDOW_WIDTH)) / GLdouble(glutGet(GLUT_WINDOW_HEIGHT)), GLdouble(clipNear), GLdouble(clipFar));
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glLoadIdentity();
|
|
gluLookAt(GLdouble(cameraEye.x), GLdouble(cameraEye.y), GLdouble(cameraEye.z), GLdouble(cameraEye.x + cameraDir.x), GLdouble(cameraEye.y + cameraDir.y), GLdouble(cameraEye.z + cameraDir.z), 0.0, 1.0, 0.0);
|
|
|
|
glColor4f(0.4f, 0.4f, 0.4f, 1.0f);
|
|
|
|
if(setupLighting)
|
|
InitLighting();
|
|
|
|
gTextScale = 0.0175f * float(INITIAL_SCREEN_HEIGHT) / float(gScreenHeight);
|
|
gTextY = 1.0f - gTextScale;
|
|
gTexter.setColor(1.0f, 1.0f, 1.0f, 1.0f);
|
|
}
|
|
|
|
void finishRender()
|
|
{
|
|
glutSwapBuffers();
|
|
}
|
|
|
|
void print(const char* text)
|
|
{
|
|
gTexter.print(0.0f, gTextY, gTextScale, text);
|
|
gTextY -= gTextScale;
|
|
}
|
|
|
|
const PxVec3 shadowDir(0.0f, -0.7071067f, -0.7071067f);
|
|
const PxReal shadowMat[] = { 1,0,0,0, -shadowDir.x / shadowDir.y,0,-shadowDir.z / shadowDir.y,0, 0,0,1,0, 0,0,0,1 };
|
|
|
|
void renderDeformableVolume(PxDeformableVolume* deformableVolume, const PxVec4* deformedPositionsInvMass, bool shadows, const PxVec3& color)
|
|
{
|
|
PxShape* shape = deformableVolume->getShape();
|
|
|
|
const PxMat44 shapePose(PxIdentity); // (PxShapeExt::getGlobalPose(*shapes[j], *actors[i]));
|
|
const PxGeometry& geom = shape->getGeometry();
|
|
|
|
const PxTetrahedronMeshGeometry& tetGeom = static_cast<const PxTetrahedronMeshGeometry&>(geom);
|
|
|
|
const PxTetrahedronMesh& mesh = *tetGeom.tetrahedronMesh;
|
|
|
|
glPushMatrix();
|
|
glMultMatrixf(&shapePose.column0.x);
|
|
glColor4f(color.x, color.y, color.z, 1.0f);
|
|
renderDeformableVolumeGeometry(mesh, deformedPositionsInvMass);
|
|
glPopMatrix();
|
|
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
|
|
|
if (shadows)
|
|
{
|
|
glPushMatrix();
|
|
glMultMatrixf(shadowMat);
|
|
glMultMatrixf(&shapePose.column0.x);
|
|
glDisable(GL_LIGHTING);
|
|
//glColor4f(0.1f, 0.2f, 0.3f, 1.0f);
|
|
glColor4f(0.1f, 0.1f, 0.1f, 1.0f);
|
|
renderDeformableVolumeGeometry(mesh, deformedPositionsInvMass);
|
|
glEnable(GL_LIGHTING);
|
|
glPopMatrix();
|
|
}
|
|
}
|
|
|
|
|
|
void renderActors(PxRigidActor** actors, const PxU32 numActors, bool shadows, const PxVec3& color, TriggerRender* cb,
|
|
bool changeColorForSleepingActors, bool wireframePass)
|
|
{
|
|
PxShape* shapes[MAX_NUM_ACTOR_SHAPES];
|
|
for(PxU32 i=0;i<numActors;i++)
|
|
{
|
|
const PxU32 nbShapes = actors[i]->getNbShapes();
|
|
PX_ASSERT(nbShapes <= MAX_NUM_ACTOR_SHAPES);
|
|
actors[i]->getShapes(shapes, nbShapes);
|
|
bool sleeping;
|
|
if (changeColorForSleepingActors)
|
|
sleeping = actors[i]->is<PxRigidDynamic>() ? actors[i]->is<PxRigidDynamic>()->isSleeping() : false;
|
|
else
|
|
sleeping = false;
|
|
|
|
for(PxU32 j=0;j<nbShapes;j++)
|
|
{
|
|
const PxMat44 shapePose(PxShapeExt::getGlobalPose(*shapes[j], *actors[i]));
|
|
const PxGeometry& geom = shapes[j]->getGeometry();
|
|
|
|
const bool isTrigger = cb ? cb->isTrigger(shapes[j]) : shapes[j]->getFlags() & PxShapeFlag::eTRIGGER_SHAPE;
|
|
if(isTrigger)
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
|
|
|
// render object
|
|
glPushMatrix();
|
|
glMultMatrixf(&shapePose.column0.x);
|
|
if(sleeping)
|
|
{
|
|
const PxVec3 darkColor = color * 0.25f;
|
|
glColor4f(darkColor.x, darkColor.y, darkColor.z, 1.0f);
|
|
}
|
|
else
|
|
glColor4f(color.x, color.y, color.z, 1.0f);
|
|
renderGeometry(geom);
|
|
glPopMatrix();
|
|
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
|
|
|
if(shadows)
|
|
{
|
|
glPushMatrix();
|
|
glMultMatrixf(shadowMat);
|
|
glMultMatrixf(&shapePose.column0.x);
|
|
glDisable(GL_LIGHTING);
|
|
//glColor4f(0.1f, 0.2f, 0.3f, 1.0f);
|
|
glColor4f(0.1f, 0.1f, 0.1f, 1.0f);
|
|
renderGeometry(geom);
|
|
glEnable(GL_LIGHTING);
|
|
glPopMatrix();
|
|
}
|
|
}
|
|
}
|
|
|
|
if(wireframePass)
|
|
{
|
|
const GLdouble aspect = GLdouble(glutGet(GLUT_WINDOW_WIDTH)) / GLdouble(glutGet(GLUT_WINDOW_HEIGHT));
|
|
glMatrixMode(GL_PROJECTION);
|
|
glLoadIdentity();
|
|
gluPerspective(60.0, aspect, GLdouble(gNearClip*1.005f), GLdouble(gFarClip));
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glDisable(GL_LIGHTING);
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
|
glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
|
|
for(PxU32 i=0;i<numActors;i++)
|
|
{
|
|
const PxU32 nbShapes = actors[i]->getNbShapes();
|
|
PX_ASSERT(nbShapes <= MAX_NUM_ACTOR_SHAPES);
|
|
actors[i]->getShapes(shapes, nbShapes);
|
|
|
|
for(PxU32 j=0;j<nbShapes;j++)
|
|
{
|
|
const PxMat44 shapePose(PxShapeExt::getGlobalPose(*shapes[j], *actors[i]));
|
|
glPushMatrix();
|
|
glMultMatrixf(&shapePose.column0.x);
|
|
renderGeometry(shapes[j]->getGeometry());
|
|
glPopMatrix();
|
|
}
|
|
}
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
|
glEnable(GL_LIGHTING);
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
glLoadIdentity();
|
|
gluPerspective(60.0, aspect, GLdouble(gNearClip), GLdouble(gFarClip));
|
|
glMatrixMode(GL_MODELVIEW);
|
|
}
|
|
}
|
|
|
|
/*static const PxU32 gGeomSizes[] = {
|
|
sizeof(PxSphereGeometry),
|
|
sizeof(PxPlaneGeometry),
|
|
sizeof(PxCapsuleGeometry),
|
|
sizeof(PxBoxGeometry),
|
|
sizeof(PxConvexMeshGeometry),
|
|
sizeof(PxTriangleMeshGeometry),
|
|
sizeof(PxHeightFieldGeometry),
|
|
};
|
|
|
|
void renderGeoms(const PxU32 nbGeoms, const PxGeometry* geoms, const PxTransform* poses, bool shadows, const PxVec3& color)
|
|
{
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
|
const PxVec3 shadowDir(0.0f, -0.7071067f, -0.7071067f);
|
|
const PxReal shadowMat[]={ 1,0,0,0, -shadowDir.x/shadowDir.y,0,-shadowDir.z/shadowDir.y,0, 0,0,1,0, 0,0,0,1 };
|
|
|
|
const PxU8* stream = reinterpret_cast<const PxU8*>(geoms);
|
|
for(PxU32 j=0;j<nbGeoms;j++)
|
|
{
|
|
const PxMat44 shapePose(poses[j]);
|
|
|
|
const PxGeometry& geom = *reinterpret_cast<const PxGeometry*>(stream);
|
|
stream += gGeomSizes[geom.getType()];
|
|
|
|
// render object
|
|
glPushMatrix();
|
|
glMultMatrixf(&shapePose.column0.x);
|
|
glColor4f(color.x, color.y, color.z, 1.0f);
|
|
renderGeometry(geom);
|
|
glPopMatrix();
|
|
|
|
if(shadows)
|
|
{
|
|
glPushMatrix();
|
|
glMultMatrixf(shadowMat);
|
|
glMultMatrixf(&shapePose.column0.x);
|
|
glDisable(GL_LIGHTING);
|
|
glColor4f(0.1f, 0.2f, 0.3f, 1.0f);
|
|
renderGeometry(geom);
|
|
glEnable(GL_LIGHTING);
|
|
glPopMatrix();
|
|
}
|
|
}
|
|
}*/
|
|
|
|
void renderGeoms(const PxU32 nbGeoms, const PxGeometryHolder* geoms, const PxTransform* poses, bool shadows, const PxVec3& color)
|
|
{
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
|
// glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
|
|
//const PxVec3 shadowDir(0.0f, -0.7071067f, -0.7071067f);
|
|
//const PxReal shadowMat[]={ 1,0,0,0, -shadowDir.x/shadowDir.y,0,-shadowDir.z/shadowDir.y,0, 0,0,1,0, 0,0,0,1 };
|
|
|
|
for(PxU32 j=0;j<nbGeoms;j++)
|
|
{
|
|
const PxMat44 shapePose(poses[j]);
|
|
|
|
const PxGeometry& geom = geoms[j].any();
|
|
|
|
// render object
|
|
glPushMatrix();
|
|
glMultMatrixf(&shapePose.column0.x);
|
|
glColor4f(color.x, color.y, color.z, 1.0f);
|
|
renderGeometry(geom);
|
|
glPopMatrix();
|
|
|
|
if(shadows)
|
|
{
|
|
glPushMatrix();
|
|
glMultMatrixf(shadowMat);
|
|
glMultMatrixf(&shapePose.column0.x);
|
|
glDisable(GL_LIGHTING);
|
|
//glColor4f(0.1f, 0.2f, 0.3f, 1.0f);
|
|
glColor4f(0.1f, 0.1f, 0.1f, 1.0f);
|
|
renderGeometry(geom);
|
|
glEnable(GL_LIGHTING);
|
|
glPopMatrix();
|
|
}
|
|
}
|
|
|
|
if(1)
|
|
{
|
|
const GLdouble aspect = GLdouble(glutGet(GLUT_WINDOW_WIDTH)) / GLdouble(glutGet(GLUT_WINDOW_HEIGHT));
|
|
glMatrixMode(GL_PROJECTION);
|
|
glLoadIdentity();
|
|
gluPerspective(60.0, aspect, GLdouble(gNearClip*1.005f), GLdouble(gFarClip));
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glDisable(GL_LIGHTING);
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
|
glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
|
|
|
|
|
|
for(PxU32 j=0;j<nbGeoms;j++)
|
|
{
|
|
const PxMat44 shapePose(poses[j]);
|
|
|
|
const PxGeometry& geom = geoms[j].any();
|
|
|
|
// render object
|
|
glPushMatrix();
|
|
glMultMatrixf(&shapePose.column0.x);
|
|
renderGeometry(geom);
|
|
glPopMatrix();
|
|
}
|
|
|
|
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
|
glEnable(GL_LIGHTING);
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
glLoadIdentity();
|
|
gluPerspective(60.0, aspect, GLdouble(gNearClip), GLdouble(gFarClip));
|
|
glMatrixMode(GL_MODELVIEW);
|
|
}
|
|
}
|
|
|
|
PX_FORCE_INLINE PxVec3 getVec3(const physx::PxU8* data, const PxU32 index, const PxU32 sStrideInBytes)
|
|
{
|
|
return *reinterpret_cast<const PxVec3*>(data + index * sStrideInBytes);
|
|
}
|
|
|
|
void renderMesh(physx::PxU32 /*nbVerts*/, const physx::PxU8* verts, const PxU32 vertsStrideInBytes, physx::PxU32 nbTris, const void* indices, bool has16bitIndices, const physx::PxVec3& color,
|
|
const physx::PxU8* normals, const PxU32 normalsStrideInBytes, bool flipFaceOrientation, bool enableBackFaceCulling = true)
|
|
{
|
|
if (nbTris == 0)
|
|
return;
|
|
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
|
|
|
const PxMat44 idt(PxIdentity);
|
|
glPushMatrix();
|
|
glMultMatrixf(&idt.column0.x);
|
|
glColor4f(color.x, color.y, color.z, 1.0f);
|
|
if (!enableBackFaceCulling)
|
|
glDisable(GL_CULL_FACE);
|
|
{
|
|
prepareVertexBuffer();
|
|
|
|
PxU32 numTotalTriangles = 0;
|
|
PX_UNUSED(numTotalTriangles);
|
|
|
|
for(PxU32 i=0; i <nbTris; ++i)
|
|
{
|
|
PxU32 vref0, vref1, vref2;
|
|
if (has16bitIndices)
|
|
{
|
|
vref0 = ((const PxU16*)indices)[i * 3 + 0];
|
|
vref1 = ((const PxU16*)indices)[i * 3 + 1];
|
|
vref2 = ((const PxU16*)indices)[i * 3 + 2];
|
|
}
|
|
else
|
|
{
|
|
vref0 = ((const PxU32*)indices)[i * 3 + 0];
|
|
vref1 = ((const PxU32*)indices)[i * 3 + 1];
|
|
vref2 = ((const PxU32*)indices)[i * 3 + 2];
|
|
}
|
|
|
|
const PxVec3& v0 = getVec3(verts, vref0, vertsStrideInBytes);
|
|
const PxVec3& v1 = flipFaceOrientation ? getVec3(verts, vref2, vertsStrideInBytes) : getVec3(verts, vref1, vertsStrideInBytes);
|
|
const PxVec3& v2 = flipFaceOrientation ? getVec3(verts, vref1, vertsStrideInBytes) : getVec3(verts, vref2, vertsStrideInBytes);
|
|
|
|
if (normals)
|
|
{
|
|
const PxVec3& n0 = getVec3(normals, vref0, normalsStrideInBytes);
|
|
const PxVec3& n1 = flipFaceOrientation ? getVec3(normals, vref2, normalsStrideInBytes) : getVec3(normals, vref1, normalsStrideInBytes);
|
|
const PxVec3& n2 = flipFaceOrientation ? getVec3(normals, vref1, normalsStrideInBytes) : getVec3(normals, vref2, normalsStrideInBytes);
|
|
pushVertex(v0, v1, v2, n0, n1, n2, flipFaceOrientation ? -1.0f : 1.0f);
|
|
}
|
|
else
|
|
{
|
|
PxVec3 fnormal = (v1 - v0).cross(v2 - v0);
|
|
fnormal.normalize();
|
|
pushVertex(v0, v1, v2, fnormal);
|
|
}
|
|
numTotalTriangles++;
|
|
}
|
|
glScalef(1.0f, 1.0f, 1.0f);
|
|
glEnableClientState(GL_NORMAL_ARRAY);
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
const PxVec3* vertexBuffer = getVertexBuffer();
|
|
glNormalPointer(GL_FLOAT, 2*3*sizeof(float), vertexBuffer);
|
|
glVertexPointer(3, GL_FLOAT, 2*3*sizeof(float), vertexBuffer+1);
|
|
glDrawArrays(GL_TRIANGLES, 0, int(nbTris * 3));
|
|
glDisableClientState(GL_VERTEX_ARRAY);
|
|
glDisableClientState(GL_NORMAL_ARRAY);
|
|
}
|
|
glPopMatrix();
|
|
if (!enableBackFaceCulling)
|
|
glEnable(GL_CULL_FACE);
|
|
|
|
if(0)
|
|
{
|
|
const GLdouble aspect = GLdouble(glutGet(GLUT_WINDOW_WIDTH)) / GLdouble(glutGet(GLUT_WINDOW_HEIGHT));
|
|
glMatrixMode(GL_PROJECTION);
|
|
glLoadIdentity();
|
|
gluPerspective(60.0, aspect, GLdouble(gNearClip*1.005f), GLdouble(gFarClip));
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glDisable(GL_LIGHTING);
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
|
glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
|
|
|
|
glPushMatrix();
|
|
glMultMatrixf(&idt.column0.x);
|
|
|
|
glEnableClientState(GL_NORMAL_ARRAY);
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
const PxVec3* vertexBuffer = getVertexBuffer();
|
|
glNormalPointer(GL_FLOAT, 2*3*sizeof(float), vertexBuffer);
|
|
glVertexPointer(3, GL_FLOAT, 2*3*sizeof(float), vertexBuffer+1);
|
|
glDrawArrays(GL_TRIANGLES, 0, int(nbTris * 3));
|
|
glDisableClientState(GL_VERTEX_ARRAY);
|
|
glDisableClientState(GL_NORMAL_ARRAY);
|
|
|
|
glPopMatrix();
|
|
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
|
glEnable(GL_LIGHTING);
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
glLoadIdentity();
|
|
gluPerspective(60.0, aspect, GLdouble(gNearClip), GLdouble(gFarClip));
|
|
glMatrixMode(GL_MODELVIEW);
|
|
}
|
|
}
|
|
|
|
void renderMesh(physx::PxU32 nbVerts, const physx::PxVec3* verts, physx::PxU32 nbTris, const physx::PxU32* indices, const physx::PxVec3& color, const physx::PxVec3* normals, bool flipFaceOrientation)
|
|
{
|
|
renderMesh(nbVerts, reinterpret_cast<const PxU8*>(verts), sizeof(PxVec3), nbTris, indices, false, color, reinterpret_cast<const PxU8*>(normals), sizeof(PxVec3), flipFaceOrientation);
|
|
}
|
|
|
|
void renderMesh(physx::PxU32 nbVerts, const physx::PxVec4* verts, physx::PxU32 nbTris, const physx::PxU32* indices, const physx::PxVec3& color, const physx::PxVec4* normals, bool flipFaceOrientation)
|
|
{
|
|
renderMesh(nbVerts, reinterpret_cast<const PxU8*>(verts), sizeof(PxVec4), nbTris, indices, false, color, reinterpret_cast<const PxU8*>(normals), sizeof(PxVec4), flipFaceOrientation);
|
|
}
|
|
|
|
void renderMesh(physx::PxU32 nbVerts, const physx::PxVec4* verts, physx::PxU32 nbTris, const void* indices, bool hasSixteenBitIndices,
|
|
const physx::PxVec3& color, const physx::PxVec4* normals, bool flipFaceOrientation, bool enableBackFaceCulling)
|
|
{
|
|
renderMesh(nbVerts, reinterpret_cast<const PxU8*>(verts), sizeof(PxVec4), nbTris, indices, hasSixteenBitIndices,
|
|
color, reinterpret_cast<const PxU8*>(normals), sizeof(PxVec4), flipFaceOrientation, enableBackFaceCulling);
|
|
}
|
|
|
|
void DrawLine(const PxVec3& p0, const PxVec3& p1, const PxVec3& color)
|
|
{
|
|
glDisable(GL_LIGHTING);
|
|
glColor4f(color.x, color.y, color.z, 1.0f);
|
|
const PxVec3 Pts[] = { p0, p1 };
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
glVertexPointer(3, GL_FLOAT, sizeof(PxVec3), &Pts[0].x);
|
|
glDrawArrays(GL_LINES, 0, 2);
|
|
glDisableClientState(GL_VERTEX_ARRAY);
|
|
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
|
glEnable(GL_LIGHTING);
|
|
}
|
|
|
|
const physx::PxVec3 icosahedronPoints[12] = { PxVec3(0, -0.525731, 0.850651),
|
|
PxVec3(0.850651, 0, 0.525731),
|
|
PxVec3(0.850651, 0, -0.525731),
|
|
PxVec3(-0.850651, 0, -0.525731),
|
|
PxVec3(-0.850651, 0, 0.525731),
|
|
PxVec3(-0.525731, 0.850651, 0),
|
|
PxVec3(0.525731, 0.850651, 0),
|
|
PxVec3(0.525731, -0.850651, 0),
|
|
PxVec3(-0.525731, -0.850651, 0),
|
|
PxVec3(0, -0.525731, -0.850651),
|
|
PxVec3(0, 0.525731, -0.850651),
|
|
PxVec3(0, 0.525731, 0.850651) };
|
|
const PxU32 icosahedronIndices[3 * 20] = { 1 ,2 ,6 ,
|
|
1 ,7 ,2 ,
|
|
3 ,4 ,5 ,
|
|
4 ,3 ,8 ,
|
|
6 ,5 ,11 ,
|
|
5 ,6 ,10 ,
|
|
9 ,10 ,2 ,
|
|
10 ,9 ,3 ,
|
|
7 ,8 ,9 ,
|
|
8 ,7 ,0 ,
|
|
11 ,0 ,1 ,
|
|
0 ,11 ,4 ,
|
|
6 ,2 ,10 ,
|
|
1 ,6 ,11 ,
|
|
3 ,5 ,10 ,
|
|
5 ,4 ,11 ,
|
|
2 ,7 ,9 ,
|
|
7 ,1 ,0 ,
|
|
3 ,9 ,8 ,
|
|
4 ,8 ,0 };
|
|
|
|
void DrawIcosahedraPoints(const PxArray<PxVec3>& pts, const PxVec3& color, float radius)
|
|
{
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
|
|
|
const PxMat44 idt(PxIdentity);
|
|
glPushMatrix();
|
|
glMultMatrixf(&idt.column0.x);
|
|
glColor4f(color.x, color.y, color.z, 1.0f);
|
|
PxU32 numTotalTriangles = 0;
|
|
{
|
|
prepareVertexBuffer();
|
|
|
|
for (PxU32 i = 0; i < pts.size(); ++i)
|
|
{
|
|
PxVec3 center = pts[i];
|
|
|
|
for (PxU32 j = 0; j < 20; ++j)
|
|
{
|
|
const PxVec3& v0 = icosahedronPoints[icosahedronIndices[3 * j + 0]] * radius + center;
|
|
const PxVec3& v1 = icosahedronPoints[icosahedronIndices[3 * j + 1]] * radius + center;
|
|
const PxVec3& v2 = icosahedronPoints[icosahedronIndices[3 * j + 2]] * radius + center;
|
|
|
|
{
|
|
PxVec3 fnormal = (v1 - v0).cross(v2 - v0);
|
|
fnormal.normalize();
|
|
pushVertex(v0, v1, v2, fnormal);
|
|
}
|
|
numTotalTriangles++;
|
|
}
|
|
}
|
|
glScalef(1.0f, 1.0f, 1.0f);
|
|
glEnableClientState(GL_NORMAL_ARRAY);
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
const PxVec3* vertexBuffer = getVertexBuffer();
|
|
glNormalPointer(GL_FLOAT, 2 * 3 * sizeof(float), vertexBuffer);
|
|
glVertexPointer(3, GL_FLOAT, 2 * 3 * sizeof(float), vertexBuffer + 1);
|
|
glDrawArrays(GL_TRIANGLES, 0, int(numTotalTriangles * 3));
|
|
glDisableClientState(GL_VERTEX_ARRAY);
|
|
glDisableClientState(GL_NORMAL_ARRAY);
|
|
}
|
|
glPopMatrix();
|
|
}
|
|
|
|
void DrawPoints(const PxArray<PxVec3>& pts, const PxVec3& color, float scale)
|
|
{
|
|
glPointSize(scale);
|
|
glDisable(GL_LIGHTING);
|
|
glColor4f(color.x, color.y, color.z, 1.0f);
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
glVertexPointer(3, GL_FLOAT, sizeof(PxVec3), pts.begin());
|
|
glDrawArrays(GL_POINTS, 0, pts.size());
|
|
glDisableClientState(GL_VERTEX_ARRAY);
|
|
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
|
glEnable(GL_LIGHTING);
|
|
}
|
|
|
|
void DrawPoints(const PxArray<PxVec4>& pts, const PxVec3& color, float scale)
|
|
{
|
|
glPointSize(scale);
|
|
glDisable(GL_LIGHTING);
|
|
glColor4f(color.x, color.y, color.z, 1.0f);
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
glVertexPointer(3, GL_FLOAT, sizeof(PxVec4), pts.begin());
|
|
glDrawArrays(GL_POINTS, 0, pts.size());
|
|
glDisableClientState(GL_VERTEX_ARRAY);
|
|
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
|
glEnable(GL_LIGHTING);
|
|
}
|
|
|
|
void DrawPoints(const physx::PxArray<physx::PxVec3>& pts, const physx::PxArray<physx::PxVec3>& colors, float scale)
|
|
{
|
|
glPointSize(scale);
|
|
glDisable(GL_LIGHTING);
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
glEnableClientState(GL_COLOR_ARRAY);
|
|
glVertexPointer(3, GL_FLOAT, sizeof(PxVec3), pts.begin());
|
|
glColorPointer(3, GL_FLOAT, sizeof(PxVec3), colors.begin());
|
|
glDrawArrays(GL_POINTS, 0, pts.size());
|
|
glDisableClientState(GL_VERTEX_ARRAY);
|
|
glDisableClientState(GL_COLOR_ARRAY);
|
|
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
|
glEnable(GL_LIGHTING);
|
|
}
|
|
|
|
void DrawPoints(const physx::PxArray<physx::PxVec4>& pts, const physx::PxArray<physx::PxVec3>& colors, float scale)
|
|
{
|
|
glPointSize(scale);
|
|
glDisable(GL_LIGHTING);
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
glEnableClientState(GL_COLOR_ARRAY);
|
|
glVertexPointer(3, GL_FLOAT, sizeof(PxVec4), pts.begin());
|
|
glColorPointer(3, GL_FLOAT, sizeof(PxVec3), colors.begin());
|
|
glDrawArrays(GL_POINTS, 0, pts.size());
|
|
glDisableClientState(GL_VERTEX_ARRAY);
|
|
glDisableClientState(GL_COLOR_ARRAY);
|
|
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
|
glEnable(GL_LIGHTING);
|
|
}
|
|
|
|
#if PX_SUPPORT_GPU_PHYSX
|
|
|
|
namespace
|
|
{
|
|
void createVBO(GLuint* vbo, PxU32 size)
|
|
{
|
|
PX_ASSERT(vbo);
|
|
|
|
// create buffer object
|
|
glGenBuffers(1, vbo);
|
|
glBindBuffer(GL_ARRAY_BUFFER, *vbo);
|
|
|
|
// initialize buffer object
|
|
glBufferData(GL_ARRAY_BUFFER, size, 0, GL_DYNAMIC_DRAW);
|
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
}
|
|
|
|
void deleteVBO(GLuint* vbo)
|
|
{
|
|
glBindBuffer(1, *vbo);
|
|
glDeleteBuffers(1, vbo);
|
|
*vbo = 0;
|
|
}
|
|
|
|
#if USE_CUDA_INTEROP
|
|
//Returns the pointer to the cuda buffer
|
|
void* mapCudaGraphicsResource(CUgraphicsResource* vbo_resource, size_t& numBytes, CUstream stream = 0)
|
|
{
|
|
CUresult result0 = cuGraphicsMapResources(1, vbo_resource, stream);
|
|
PX_UNUSED(result0);
|
|
void* dptr;
|
|
CUresult result1 = cuGraphicsResourceGetMappedPointer((CUdeviceptr*)&dptr, &numBytes, *vbo_resource);
|
|
PX_UNUSED(result1);
|
|
return dptr;
|
|
}
|
|
|
|
void unmapCudaGraphicsResource(CUgraphicsResource* vbo_resource, CUstream stream = 0)
|
|
{
|
|
CUresult result2 = cuGraphicsUnmapResources(1, vbo_resource, stream);
|
|
PX_UNUSED(result2);
|
|
}
|
|
#endif
|
|
|
|
} // namespace
|
|
|
|
SharedGLBuffer::SharedGLBuffer() : vbo_res(NULL), devicePointer(NULL), vbo(0), size(0)
|
|
{
|
|
}
|
|
|
|
void SharedGLBuffer::initialize(PxCudaContextManager* contextManager)
|
|
{
|
|
cudaContextManager = contextManager;
|
|
}
|
|
|
|
void SharedGLBuffer::allocate(PxU32 sizeInBytes)
|
|
{
|
|
release();
|
|
createVBO(&vbo, sizeInBytes);
|
|
#if USE_CUDA_INTEROP
|
|
physx::PxCudaInteropRegisterFlags flags = physx::PxCudaInteropRegisterFlags();
|
|
cudaContextManager->acquireContext();
|
|
CUresult result = cuGraphicsGLRegisterBuffer(reinterpret_cast<CUgraphicsResource*>(&vbo_res), vbo, flags);
|
|
PX_UNUSED(result);
|
|
cudaContextManager->releaseContext();
|
|
#endif
|
|
size = sizeInBytes;
|
|
}
|
|
|
|
void SharedGLBuffer::release()
|
|
{
|
|
if (vbo)
|
|
{
|
|
deleteVBO(&vbo);
|
|
vbo = 0;
|
|
}
|
|
#if USE_CUDA_INTEROP
|
|
if (vbo_res)
|
|
{
|
|
cudaContextManager->acquireContext();
|
|
CUresult result = cuGraphicsUnregisterResource(reinterpret_cast<CUgraphicsResource>(vbo_res));
|
|
PX_UNUSED(result);
|
|
cudaContextManager->releaseContext();
|
|
vbo_res = NULL;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
SharedGLBuffer::~SharedGLBuffer()
|
|
{
|
|
//release();
|
|
}
|
|
|
|
void* SharedGLBuffer::map()
|
|
{
|
|
if (devicePointer)
|
|
return devicePointer;
|
|
|
|
#if USE_CUDA_INTEROP
|
|
size_t numBytes;
|
|
cudaContextManager->acquireContext();
|
|
devicePointer = mapCudaGraphicsResource(reinterpret_cast<CUgraphicsResource*>(&vbo_res), numBytes, 0);
|
|
cudaContextManager->releaseContext();
|
|
#else
|
|
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
|
devicePointer = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
|
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
#endif
|
|
return devicePointer;
|
|
}
|
|
|
|
void SharedGLBuffer::unmap()
|
|
{
|
|
if (!devicePointer)
|
|
return;
|
|
#if USE_CUDA_INTEROP
|
|
cudaContextManager->acquireContext();
|
|
unmapCudaGraphicsResource(reinterpret_cast<CUgraphicsResource*>(&vbo_res), 0);
|
|
cudaContextManager->releaseContext();
|
|
#else
|
|
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
|
glUnmapBuffer(GL_ARRAY_BUFFER);
|
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
#endif
|
|
devicePointer = NULL;
|
|
}
|
|
|
|
#endif // PX_SUPPORT_GPU_PHYSX
|
|
|
|
void DrawPoints(GLuint vbo, PxU32 numPoints, const PxVec3& color, float scale, PxU32 coordinatesPerPoint, PxU32 stride, size_t offset)
|
|
{
|
|
glPointSize(scale);
|
|
glDisable(GL_LIGHTING);
|
|
glColor4f(color.x, color.y, color.z, 1.0f);
|
|
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
glVertexPointer(coordinatesPerPoint, GL_FLOAT, stride, (void*)offset /*offsetof(Vertex, pos)*/);
|
|
glDrawArrays(GL_POINTS, 0, numPoints);
|
|
glDisableClientState(GL_VERTEX_ARRAY);
|
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
|
glEnable(GL_LIGHTING);
|
|
}
|
|
|
|
void DrawLines(GLuint vbo, PxU32 numPoints, const PxVec3& color, float scale, PxU32 coordinatesPerPoint, PxU32 stride, size_t offset)
|
|
{
|
|
PX_ASSERT(numPoints % 2 == 0);
|
|
glLineWidth(scale);
|
|
glDisable(GL_LIGHTING);
|
|
glColor4f(color.x, color.y, color.z, 1.0f);
|
|
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
glVertexPointer(coordinatesPerPoint, GL_FLOAT, stride, (void*)offset /*offsetof(Vertex, pos)*/);
|
|
glDrawArrays(GL_LINES, 0, numPoints);
|
|
glDisableClientState(GL_VERTEX_ARRAY);
|
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
|
glEnable(GL_LIGHTING);
|
|
}
|
|
|
|
void DrawMeshIndexed(GLuint vbo, GLuint elementbuffer, GLuint numTriangles, const physx::PxVec3& color, physx::PxU32 stride)
|
|
{
|
|
/*glPushMatrix();
|
|
glScalef(1.0f, 1.0f, 1.0f);*/
|
|
|
|
if(gWireFrame)
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
|
|
|
glColor4f(color.x, color.y, color.z, 1.0f);
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
glVertexPointer(3, GL_FLOAT, stride, (void*)0);
|
|
glEnableClientState(GL_NORMAL_ARRAY);
|
|
glNormalPointer(GL_FLOAT, stride, (void*)(3 * sizeof(float)));
|
|
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer);
|
|
|
|
glDrawElements(GL_TRIANGLES, int(numTriangles * 3), GL_UNSIGNED_INT, (void*)0);
|
|
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
//glPopMatrix();
|
|
if (gWireFrame)
|
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
|
}
|
|
|
|
void DrawMeshIndexedNoNormals(GLuint vbo, GLuint elementbuffer, GLuint numTriangles, const physx::PxVec3& color, physx::PxU32 stride)
|
|
{
|
|
/*glPushMatrix();
|
|
glScalef(1.0f, 1.0f, 1.0f);*/
|
|
|
|
glColor4f(color.x, color.y, color.z, 1.0f);
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
glVertexPointer(3, GL_FLOAT, stride, (void*)0);
|
|
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer);
|
|
|
|
glDrawElements(GL_TRIANGLES, int(numTriangles * 3), GL_UNSIGNED_INT, (void*)0);
|
|
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
//glPopMatrix();
|
|
}
|
|
|
|
void DrawFrame(const PxVec3& pt, float scale)
|
|
{
|
|
DrawLine(pt, pt + PxVec3(scale, 0.0f, 0.0f), PxVec3(1.0f, 0.0f, 0.0f));
|
|
DrawLine(pt, pt + PxVec3(0.0f, scale, 0.0f), PxVec3(0.0f, 1.0f, 0.0f));
|
|
DrawLine(pt, pt + PxVec3(0.0f, 0.0f, scale), PxVec3(0.0f, 0.0f, 1.0f));
|
|
}
|
|
|
|
void DrawBounds(const physx::PxBounds3& box, const physx::PxVec3& color)
|
|
{
|
|
DrawLine(PxVec3(box.minimum.x, box.minimum.y, box.minimum.z), PxVec3(box.maximum.x, box.minimum.y, box.minimum.z), color);
|
|
DrawLine(PxVec3(box.maximum.x, box.minimum.y, box.minimum.z), PxVec3(box.maximum.x, box.maximum.y, box.minimum.z), color);
|
|
DrawLine(PxVec3(box.maximum.x, box.maximum.y, box.minimum.z), PxVec3(box.minimum.x, box.maximum.y, box.minimum.z), color);
|
|
DrawLine(PxVec3(box.minimum.x, box.maximum.y, box.minimum.z), PxVec3(box.minimum.x, box.minimum.y, box.minimum.z), color);
|
|
DrawLine(PxVec3(box.minimum.x, box.minimum.y, box.minimum.z), PxVec3(box.minimum.x, box.minimum.y, box.maximum.z), color);
|
|
DrawLine(PxVec3(box.minimum.x, box.minimum.y, box.maximum.z), PxVec3(box.maximum.x, box.minimum.y, box.maximum.z), color);
|
|
DrawLine(PxVec3(box.maximum.x, box.minimum.y, box.maximum.z), PxVec3(box.maximum.x, box.maximum.y, box.maximum.z), color);
|
|
DrawLine(PxVec3(box.maximum.x, box.maximum.y, box.maximum.z), PxVec3(box.minimum.x, box.maximum.y, box.maximum.z), color);
|
|
DrawLine(PxVec3(box.minimum.x, box.maximum.y, box.maximum.z), PxVec3(box.minimum.x, box.minimum.y, box.maximum.z), color);
|
|
DrawLine(PxVec3(box.minimum.x, box.minimum.y, box.maximum.z), PxVec3(box.minimum.x, box.minimum.y, box.minimum.z), color);
|
|
DrawLine(PxVec3(box.maximum.x, box.minimum.y, box.minimum.z), PxVec3(box.maximum.x, box.minimum.y, box.maximum.z), color);
|
|
DrawLine(PxVec3(box.maximum.x, box.maximum.y, box.minimum.z), PxVec3(box.maximum.x, box.maximum.y, box.maximum.z), color);
|
|
DrawLine(PxVec3(box.minimum.x, box.maximum.y, box.minimum.z), PxVec3(box.minimum.x, box.maximum.y, box.maximum.z), color);
|
|
}
|
|
|
|
void DrawBounds(const PxBounds3& box)
|
|
{
|
|
const PxVec3 color(1.0f, 1.0f, 0.0f);
|
|
DrawBounds(box, color);
|
|
}
|
|
|
|
GLuint CreateTexture(PxU32 width, PxU32 height, const GLubyte* buffer, bool createMipmaps)
|
|
{
|
|
GLuint texId;
|
|
glGenTextures(1, &texId);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, texId);
|
|
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
if(buffer)
|
|
{
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
|
|
if(createMipmaps)
|
|
{
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
|
|
gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
|
|
}
|
|
}
|
|
glBindTexture(GL_TEXTURE_2D, 0);
|
|
return texId;
|
|
}
|
|
|
|
void UpdateTexture(GLuint texId, physx::PxU32 width, physx::PxU32 height, const GLubyte* buffer, bool createMipmaps)
|
|
{
|
|
glBindTexture(GL_TEXTURE_2D, texId);
|
|
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
|
|
if(createMipmaps)
|
|
{
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
|
|
gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
|
|
}
|
|
glBindTexture( GL_TEXTURE_2D, 0);
|
|
}
|
|
|
|
void ReleaseTexture(GLuint texId)
|
|
{
|
|
glDeleteTextures(1, &texId);
|
|
}
|
|
|
|
void DrawRectangle(float x_start, float x_end, float y_start, float y_end, const PxVec3& color_top, const PxVec3& color_bottom, float alpha, PxU32 screen_width, PxU32 screen_height, bool draw_outline, bool texturing)
|
|
{
|
|
if(alpha!=1.0f)
|
|
{
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
glEnable(GL_BLEND);
|
|
}
|
|
else
|
|
{
|
|
glDisable(GL_BLEND);
|
|
}
|
|
glDisable(GL_DEPTH_TEST);
|
|
glDisable(GL_LIGHTING);
|
|
glDisable(GL_CULL_FACE);
|
|
|
|
if(texturing)
|
|
glEnable(GL_TEXTURE_2D);
|
|
else
|
|
glDisable(GL_TEXTURE_2D);
|
|
|
|
{
|
|
glMatrixMode(GL_PROJECTION);
|
|
glPushMatrix();
|
|
glLoadIdentity();
|
|
glOrtho(0, screen_width, 0, screen_height, -1, 1);
|
|
}
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glPushMatrix();
|
|
glLoadIdentity();
|
|
|
|
const float x0 = x_start * float(screen_width);
|
|
const float x1 = x_end * float(screen_width);
|
|
const float y0 = y_start * float(screen_height);
|
|
const float y1 = y_end * float(screen_height);
|
|
|
|
const PxVec3 p0(x0, y0, 0.0f);
|
|
const PxVec3 p1(x0, y1, 0.0f);
|
|
const PxVec3 p2(x1, y1, 0.0f);
|
|
const PxVec3 p3(x1, y0, 0.0f);
|
|
|
|
// const float u = (texture_flags & SQT_FLIP_U) ? 1.0f : 0.0f;
|
|
// const float v = (texture_flags & SQT_FLIP_V) ? 1.0f : 0.0f;
|
|
const float u = 0.0f;
|
|
const float v = 1.0f;
|
|
|
|
const PxVec3 t0(u, v, 0.0f);
|
|
const PxVec3 t1(u, 1.0f - v, 0.0f);
|
|
const PxVec3 t2(1.0f - u, 1.0f - v, 0.0f);
|
|
const PxVec3 t3(1.0f - u, v, 0.0f);
|
|
|
|
glBegin(GL_TRIANGLES);
|
|
glTexCoord2f(t0.x, t0.y);
|
|
glColor4f(color_top.x, color_top.y, color_top.z, alpha);
|
|
glVertex3f(p0.x, p0.y, p0.z);
|
|
|
|
glTexCoord2f(t1.x, t1.y);
|
|
glColor4f(color_bottom.x, color_bottom.y, color_bottom.z, alpha);
|
|
glVertex3f(p1.x, p1.y, p1.z);
|
|
|
|
glTexCoord2f(t2.x, t2.y);
|
|
glColor4f(color_bottom.x, color_bottom.y, color_bottom.z, alpha);
|
|
glVertex3f(p2.x, p2.y, p2.z);
|
|
|
|
glTexCoord2f(t0.x, t0.y);
|
|
glColor4f(color_top.x, color_top.y, color_top.z, alpha);
|
|
glVertex3f(p0.x, p0.y, p0.z);
|
|
|
|
glTexCoord2f(t2.x, t2.y);
|
|
glColor4f(color_bottom.x, color_bottom.y, color_bottom.z, alpha);
|
|
glVertex3f(p2.x, p2.y, p2.z);
|
|
|
|
glTexCoord2f(t3.x, t3.y);
|
|
glColor4f(color_top.x, color_top.y, color_top.z, alpha);
|
|
glVertex3f(p3.x, p3.y, p3.z);
|
|
glEnd();
|
|
|
|
if(draw_outline)
|
|
{
|
|
glDisable(GL_TEXTURE_2D);
|
|
glColor4f(1.0f, 1.0f, 1.0f, alpha);
|
|
glBegin(GL_LINES);
|
|
glVertex3f(p0.x, p0.y, p0.z);
|
|
glVertex3f(p1.x, p1.y, p1.z);
|
|
|
|
glVertex3f(p1.x, p1.y, p1.z);
|
|
glVertex3f(p2.x, p2.y, p2.z);
|
|
|
|
glVertex3f(p2.x, p2.y, p2.z);
|
|
glVertex3f(p3.x, p3.y, p3.z);
|
|
|
|
glVertex3f(p3.x, p3.y, p3.z);
|
|
glVertex3f(p0.x, p0.y, p0.z);
|
|
glEnd();
|
|
}
|
|
|
|
{
|
|
glMatrixMode(GL_PROJECTION);
|
|
glPopMatrix();
|
|
}
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glPopMatrix();
|
|
|
|
glEnable(GL_CULL_FACE);
|
|
glEnable(GL_DEPTH_TEST);
|
|
glEnable(GL_LIGHTING);
|
|
glDisable(GL_BLEND);
|
|
}
|
|
|
|
void DisplayTexture(GLuint texId, PxU32 size, PxU32 margin)
|
|
{
|
|
const PxU32 screenWidth = gScreenWidth;
|
|
const PxU32 screenHeight = gScreenHeight;
|
|
|
|
glBindTexture(GL_TEXTURE_2D, texId);
|
|
// glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD);
|
|
// glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
|
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
|
|
|
// glDisable(GL_CULL_FACE);
|
|
const PxVec3 color(1.0f, 1.0f, 1.0f);
|
|
// const float Alpha = 0.999f;
|
|
// const float Alpha = 0.5f;
|
|
const float Alpha = 1.0f;
|
|
PxU32 PixelSizeX = size;
|
|
PxU32 PixelSizeY = size;
|
|
|
|
if(!size)
|
|
{
|
|
PixelSizeX = gScreenWidth;
|
|
PixelSizeY = gScreenHeight;
|
|
margin = 0;
|
|
}
|
|
|
|
const float x0 = float(screenWidth-PixelSizeX-margin)/float(screenWidth);
|
|
const float y0 = float(screenHeight-PixelSizeY-margin)/float(screenHeight);
|
|
const float x1 = float(screenWidth-margin)/float(screenWidth);
|
|
const float y1 = float(screenHeight-margin)/float(screenHeight);
|
|
|
|
DrawRectangle(x0, x1, y0, y1, color, color, Alpha, screenWidth, screenHeight, false, true);
|
|
|
|
glDisable(GL_TEXTURE_2D);
|
|
}
|
|
|
|
} //namespace Snippets
|
|
|