Improve rendering of testbed application (flat shading, 3 light sources, ...)

This commit is contained in:
Daniel Chappuis 2019-10-21 07:22:18 +02:00
parent bcb4febb16
commit 43b818573a
24 changed files with 2588 additions and 2237 deletions

View File

@ -84,12 +84,6 @@ Box::Box(const openglframework::Vector3& size, float mass, reactphysics3d::Dynam
const std::string& meshFolderPath) const std::string& meshFolderPath)
: PhysicsObject(meshFolderPath + "cube.obj") { : PhysicsObject(meshFolderPath + "cube.obj") {
// Load the mesh from a file
openglframework::MeshReaderWriter::loadMeshFromFile(meshFolderPath + "cube.obj", *this);
// Calculate the normals of the mesh
calculateNormals();
// Initialize the size of the box // Initialize the size of the box
mSize[0] = size.x * 0.5f; mSize[0] = size.x * 0.5f;
mSize[1] = size.y * 0.5f; mSize[1] = size.y * 0.5f;
@ -200,8 +194,7 @@ void Box::render(openglframework::Shader& shader, const openglframework::Matrix4
} }
// Create the Vertex Buffer Objects used to render to box with OpenGL. // Create the Vertex Buffer Objects used to render to box with OpenGL.
/// We create two VBOs (one for vertices and one for indices) to render all the boxes /// We create two VBOs (one for vertices and one for indices) to render the box
/// in the simulation.
void Box::createVBOAndVAO() { void Box::createVBOAndVAO() {
// Create the VBO for the vertices data // Create the VBO for the vertices data
@ -227,7 +220,7 @@ void Box::createVBOAndVAO() {
mVBOTextureCoords.unbind(); mVBOTextureCoords.unbind();
} }
// Create th VBO for the indices data // Create the VBO for the indices data
mVBOIndices.create(); mVBOIndices.create();
mVBOIndices.bind(); mVBOIndices.bind();
size_t sizeIndices = mIndices[0].size() * sizeof(unsigned int); size_t sizeIndices = mIndices[0].size() * sizeof(unsigned int);

View File

@ -25,6 +25,7 @@
// Libraries // Libraries
#include "ConvexMesh.h" #include "ConvexMesh.h"
#include <unordered_set>
// Constructor // Constructor
ConvexMesh::ConvexMesh(rp3d::CollisionWorld* world, const std::string& meshPath) ConvexMesh::ConvexMesh(rp3d::CollisionWorld* world, const std::string& meshPath)
@ -39,6 +40,19 @@ ConvexMesh::ConvexMesh(rp3d::CollisionWorld* world, const std::string& meshPath)
mPolygonFaces = new rp3d::PolygonVertexArray::PolygonFace[getNbFaces(0)]; mPolygonFaces = new rp3d::PolygonVertexArray::PolygonFace[getNbFaces(0)];
rp3d::PolygonVertexArray::PolygonFace* face = mPolygonFaces; rp3d::PolygonVertexArray::PolygonFace* face = mPolygonFaces;
for (int f=0; f < getNbFaces(0); f++) { for (int f=0; f < getNbFaces(0); f++) {
for (int v = 0; v < 3; v++) {
const openglframework::Vector3 vertex = mVertices[mIndices[0][f*3 + v]];
int vIndex = findVertexIndex(mConvexMeshVertices, vertex);
if (vIndex == -1) {
vIndex = mConvexMeshVertices.size();
mConvexMeshVertices.push_back(vertex);
}
mConvexMeshIndices.push_back(vIndex);
}
face->indexBase = f * 3; face->indexBase = f * 3;
face->nbVertices = 3; face->nbVertices = 3;
face++; face++;
@ -46,8 +60,8 @@ ConvexMesh::ConvexMesh(rp3d::CollisionWorld* world, const std::string& meshPath)
// Create the polygon vertex array // Create the polygon vertex array
mPolygonVertexArray = mPolygonVertexArray =
new rp3d::PolygonVertexArray(getNbVertices(), &(mVertices[0]), sizeof(openglframework::Vector3), new rp3d::PolygonVertexArray(mConvexMeshVertices.size(), &(mConvexMeshVertices[0]), sizeof(openglframework::Vector3),
&(mIndices[0][0]), sizeof(int), &(mConvexMeshIndices[0]), sizeof(int),
getNbFaces(0), mPolygonFaces, getNbFaces(0), mPolygonFaces,
rp3d::PolygonVertexArray::VertexDataType::VERTEX_FLOAT_TYPE, rp3d::PolygonVertexArray::VertexDataType::VERTEX_FLOAT_TYPE,
rp3d::PolygonVertexArray::IndexDataType::INDEX_INTEGER_TYPE); rp3d::PolygonVertexArray::IndexDataType::INDEX_INTEGER_TYPE);
@ -86,6 +100,19 @@ ConvexMesh::ConvexMesh(float mass, rp3d::DynamicsWorld* dynamicsWorld, const std
mPolygonFaces = new rp3d::PolygonVertexArray::PolygonFace[getNbFaces(0)]; mPolygonFaces = new rp3d::PolygonVertexArray::PolygonFace[getNbFaces(0)];
rp3d::PolygonVertexArray::PolygonFace* face = mPolygonFaces; rp3d::PolygonVertexArray::PolygonFace* face = mPolygonFaces;
for (int f=0; f < getNbFaces(0); f++) { for (int f=0; f < getNbFaces(0); f++) {
for (int v = 0; v < 3; v++) {
const openglframework::Vector3 vertex = mVertices[mIndices[0][f*3 + v]];
int vIndex = findVertexIndex(mConvexMeshVertices, vertex);
if (vIndex == -1) {
vIndex = mConvexMeshVertices.size();
mConvexMeshVertices.push_back(vertex);
}
mConvexMeshIndices.push_back(vIndex);
}
face->indexBase = f * 3; face->indexBase = f * 3;
face->nbVertices = 3; face->nbVertices = 3;
face++; face++;
@ -93,8 +120,8 @@ ConvexMesh::ConvexMesh(float mass, rp3d::DynamicsWorld* dynamicsWorld, const std
// Create the polygon vertex array // Create the polygon vertex array
mPolygonVertexArray = mPolygonVertexArray =
new rp3d::PolygonVertexArray(getNbVertices(), &(mVertices[0]), sizeof(openglframework::Vector3), new rp3d::PolygonVertexArray(mConvexMeshVertices.size(), &(mConvexMeshVertices[0]), sizeof(openglframework::Vector3),
&(mIndices[0][0]), sizeof(int), &(mConvexMeshIndices[0]), sizeof(int),
getNbFaces(0), mPolygonFaces, getNbFaces(0), mPolygonFaces,
rp3d::PolygonVertexArray::VertexDataType::VERTEX_FLOAT_TYPE, rp3d::PolygonVertexArray::VertexDataType::VERTEX_FLOAT_TYPE,
rp3d::PolygonVertexArray::IndexDataType::INDEX_INTEGER_TYPE); rp3d::PolygonVertexArray::IndexDataType::INDEX_INTEGER_TYPE);
@ -254,3 +281,16 @@ void ConvexMesh::createVBOAndVAO() {
// Unbind the VAO // Unbind the VAO
mVAO.unbind(); mVAO.unbind();
} }
// Return the index of a given vertex in the mesh
int ConvexMesh::findVertexIndex(const std::vector<openglframework::Vector3>& vertices, const openglframework::Vector3& vertex) {
for (int i = 0; i < vertices.size(); i++) {
if (vertices[i] == vertex) {
return i;
}
}
return -1;
}

View File

@ -69,11 +69,21 @@ class ConvexMesh : public PhysicsObject {
/// Vertex Array Object for the vertex data /// Vertex Array Object for the vertex data
openglframework::VertexArrayObject mVAO; openglframework::VertexArrayObject mVAO;
/// Array with the vertices of the convex mesh
/// (only the vertices used for the physics shape, not duplicate vertices used for rendering)
std::vector<openglframework::Vector3> mConvexMeshVertices;
/// Array with the vertex indices of the convex mesh (used for the physics shape)
std::vector<int> mConvexMeshIndices;
// -------------------- Methods -------------------- // // -------------------- Methods -------------------- //
// Create the Vertex Buffer Objects used to render with OpenGL. /// Create the Vertex Buffer Objects used to render with OpenGL.
void createVBOAndVAO(); void createVBOAndVAO();
/// Return the index of a given vertex in the mesh
int findVertexIndex(const std::vector<openglframework::Vector3>& vertices, const openglframework::Vector3& vertex);
public : public :
// -------------------- Methods -------------------- // // -------------------- Methods -------------------- //

View File

@ -40,8 +40,12 @@ PhysicsObject::PhysicsObject(const std::string& meshPath) : PhysicsObject() {
// Load the mesh from a file // Load the mesh from a file
openglframework::MeshReaderWriter::loadMeshFromFile(meshPath, *this); openglframework::MeshReaderWriter::loadMeshFromFile(meshPath, *this);
// Calculate the normals of the mesh // If the mesh file do not have normals
calculateNormals(); if (mNormals.empty()) {
// Calculate the normals of the mesh
calculateNormals();
}
} }
// Compute the new transform matrix // Compute the new transform matrix

View File

@ -1,125 +1,205 @@
# Blender v2.66 (sub 0) OBJ File: '' # Blender v2.80 (sub 75) OBJ File: ''
# www.blender.org # www.blender.org
v 0.000000 -1.000000 0.000000 v 0.000000 -1.000000 -0.000000
v 0.723607 -0.447220 0.525725
v -0.276388 -0.447220 0.850649
v -0.894426 -0.447216 0.000000
v -0.276388 -0.447220 -0.850649
v 0.723607 -0.447220 -0.525725
v 0.276388 0.447220 0.850649
v -0.723607 0.447220 0.525725
v -0.723607 0.447220 -0.525725
v 0.276388 0.447220 -0.850649
v 0.894426 0.447216 0.000000
v 0.000000 1.000000 0.000000
v 0.425323 -0.850654 0.309011 v 0.425323 -0.850654 0.309011
v 0.262869 -0.525738 0.809012
v -0.162456 -0.850654 0.499995 v -0.162456 -0.850654 0.499995
v 0.425323 -0.850654 -0.309011 v 0.723607 -0.447220 0.525725
v 0.850648 -0.525736 0.000000 v 0.850648 -0.525736 -0.000000
v -0.688189 -0.525736 0.499997 v -0.525730 -0.850652 -0.000000
v -0.525730 -0.850652 0.000000
v -0.688189 -0.525736 -0.499997
v -0.162456 -0.850654 -0.499995 v -0.162456 -0.850654 -0.499995
v 0.262869 -0.525738 -0.809012 v 0.425323 -0.850654 -0.309011
v 0.951058 0.000000 -0.309013 v 0.951058 -0.000000 0.309013
v 0.951058 0.000000 0.309013 v -0.276388 -0.447220 0.850649
v 0.587786 0.000000 0.809017 v 0.262869 -0.525738 0.809012
v 0.000000 0.000000 1.000000 v 0.000000 -0.000000 1.000000
v -0.587786 0.000000 0.809017 v -0.894426 -0.447216 -0.000000
v -0.951058 0.000000 0.309013 v -0.688189 -0.525736 0.499997
v -0.951058 0.000000 -0.309013 v -0.951058 -0.000000 0.309013
v -0.276388 -0.447220 -0.850649
v -0.688189 -0.525736 -0.499997
v -0.587786 0.000000 -0.809017 v -0.587786 0.000000 -0.809017
v 0.000000 0.000000 -1.000000 v 0.723607 -0.447220 -0.525725
v 0.262869 -0.525738 -0.809012
v 0.587786 0.000000 -0.809017 v 0.587786 0.000000 -0.809017
v 0.587786 -0.000000 0.809017
v -0.587786 -0.000000 0.809017
v -0.951058 0.000000 -0.309013
v 0.000000 0.000000 -1.000000
v 0.951058 0.000000 -0.309013
v 0.276388 0.447220 0.850649
v 0.688189 0.525736 0.499997 v 0.688189 0.525736 0.499997
v 0.162456 0.850654 0.499995
v -0.723607 0.447220 0.525725
v -0.262869 0.525738 0.809012 v -0.262869 0.525738 0.809012
v -0.425323 0.850654 0.309011
v -0.723607 0.447220 -0.525725
v -0.850648 0.525736 0.000000 v -0.850648 0.525736 0.000000
v -0.425323 0.850654 -0.309011
v 0.276388 0.447220 -0.850649
v -0.262869 0.525738 -0.809012 v -0.262869 0.525738 -0.809012
v 0.162456 0.850654 -0.499995
v 0.894426 0.447216 0.000000
v 0.688189 0.525736 -0.499997 v 0.688189 0.525736 -0.499997
v 0.525730 0.850652 0.000000 v 0.525730 0.850652 0.000000
v 0.162456 0.850654 0.499995 v 0.000000 1.000000 0.000000
v -0.425323 0.850654 0.309011 vn 0.1024 -0.9435 0.3151
v -0.425323 0.850654 -0.309011 vn 0.7002 -0.6617 0.2680
v 0.162456 0.850654 -0.499995 vn -0.2680 -0.9435 0.1947
vn -0.2680 -0.9435 -0.1947
vn 0.1024 -0.9435 -0.3151
vn 0.9050 -0.3304 0.2680
vn 0.0247 -0.3304 0.9435
vn -0.8897 -0.3304 0.3151
vn -0.5746 -0.3304 -0.7488
vn 0.5346 -0.3304 -0.7779
vn 0.8026 -0.1256 0.5831
vn -0.3066 -0.1256 0.9435
vn -0.9921 -0.1256 -0.0000
vn -0.3066 -0.1256 -0.9435
vn 0.8026 -0.1256 -0.5831
vn 0.4089 0.6617 0.6284
vn -0.4713 0.6617 0.5831
vn -0.7002 0.6617 -0.2680
vn 0.0385 0.6617 -0.7488
vn 0.7240 0.6617 -0.1947
vn -0.0385 -0.6617 0.7488
vn 0.1876 -0.7947 0.5773
vn 0.4713 -0.6617 0.5831
vn 0.7002 -0.6617 -0.2680
vn 0.6071 -0.7947 0.0000
vn 0.3313 -0.9435 -0.0000
vn -0.7240 -0.6617 0.1947
vn -0.4911 -0.7947 0.3568
vn -0.4089 -0.6617 0.6284
vn -0.4089 -0.6617 -0.6284
vn -0.4911 -0.7947 -0.3568
vn -0.7240 -0.6617 -0.1947
vn 0.4713 -0.6617 -0.5831
vn 0.1876 -0.7947 -0.5773
vn -0.0385 -0.6617 -0.7488
vn 0.9921 0.1256 0.0000
vn 0.9822 -0.1876 -0.0000
vn 0.9050 -0.3304 -0.2680
vn 0.3066 0.1256 0.9435
vn 0.3035 -0.1876 0.9342
vn 0.5346 -0.3304 0.7779
vn -0.8026 0.1256 0.5831
vn -0.7947 -0.1876 0.5773
vn -0.5746 -0.3304 0.7488
vn -0.8026 0.1256 -0.5831
vn -0.7947 -0.1876 -0.5773
vn -0.8897 -0.3304 -0.3151
vn 0.3066 0.1256 -0.9435
vn 0.3035 -0.1876 -0.9342
vn 0.0247 -0.3304 -0.9435
vn 0.5746 0.3304 0.7488
vn 0.7947 0.1876 0.5773
vn 0.8897 0.3304 0.3151
vn -0.5346 0.3304 0.7779
vn -0.3035 0.1876 0.9342
vn -0.0247 0.3304 0.9435
vn -0.9050 0.3304 -0.2680
vn -0.9822 0.1876 0.0000
vn -0.9050 0.3304 0.2680
vn -0.0247 0.3304 -0.9435
vn -0.3035 0.1876 -0.9342
vn -0.5346 0.3304 -0.7779
vn 0.8897 0.3304 -0.3151
vn 0.7947 0.1876 -0.5773
vn 0.5746 0.3304 -0.7488
vn 0.2680 0.9435 0.1947
vn 0.4911 0.7947 0.3568
vn 0.7240 0.6617 0.1947
vn -0.1024 0.9435 0.3151
vn -0.1876 0.7947 0.5773
vn 0.0385 0.6617 0.7488
vn -0.3313 0.9435 0.0000
vn -0.6071 0.7947 0.0000
vn -0.7002 0.6617 0.2680
vn -0.1024 0.9435 -0.3151
vn -0.1876 0.7947 -0.5773
vn -0.4713 0.6617 -0.5831
vn 0.2680 0.9435 -0.1947
vn 0.4911 0.7947 -0.3568
vn 0.4089 0.6617 -0.6284
s off s off
f 1 13 15 f 1//1 2//1 3//1
f 2 13 17 f 4//2 2//2 5//2
f 1 15 19 f 1//3 3//3 6//3
f 1 19 21 f 1//4 6//4 7//4
f 1 21 16 f 1//5 7//5 8//5
f 2 17 24 f 4//6 5//6 9//6
f 3 14 26 f 10//7 11//7 12//7
f 4 18 28 f 13//8 14//8 15//8
f 5 20 30 f 16//9 17//9 18//9
f 6 22 32 f 19//10 20//10 21//10
f 2 24 25 f 4//11 9//11 22//11
f 3 26 27 f 10//12 12//12 23//12
f 4 28 29 f 13//13 15//13 24//13
f 5 30 31 f 16//14 18//14 25//14
f 6 32 23 f 19//15 21//15 26//15
f 7 33 39 f 27//16 28//16 29//16
f 8 34 40 f 30//17 31//17 32//17
f 9 35 41 f 33//18 34//18 35//18
f 10 36 42 f 36//19 37//19 38//19
f 11 37 38 f 39//20 40//20 41//20
f 15 14 3 f 3//21 11//21 10//21
f 15 13 14 f 3//22 2//22 11//22
f 13 2 14 f 2//23 4//23 11//23
f 17 16 6 f 5//24 8//24 19//24
f 17 13 16 f 5//25 2//25 8//25
f 13 1 16 f 2//26 1//26 8//26
f 19 18 4 f 6//27 14//27 13//27
f 19 15 18 f 6//28 3//28 14//28
f 15 3 18 f 3//29 10//29 14//29
f 21 20 5 f 7//30 17//30 16//30
f 21 19 20 f 7//31 6//31 17//31
f 19 4 20 f 6//32 13//32 17//32
f 16 22 6 f 8//33 20//33 19//33
f 16 21 22 f 8//34 7//34 20//34
f 21 5 22 f 7//35 16//35 20//35
f 24 23 11 f 9//36 26//36 39//36
f 24 17 23 f 9//37 5//37 26//37
f 17 6 23 f 5//38 19//38 26//38
f 26 25 7 f 12//39 22//39 27//39
f 26 14 25 f 12//40 11//40 22//40
f 14 2 25 f 11//41 4//41 22//41
f 28 27 8 f 15//42 23//42 30//42
f 28 18 27 f 15//43 14//43 23//43
f 18 3 27 f 14//44 10//44 23//44
f 30 29 9 f 18//45 24//45 33//45
f 30 20 29 f 18//46 17//46 24//46
f 20 4 29 f 17//47 13//47 24//47
f 32 31 10 f 21//48 25//48 36//48
f 32 22 31 f 21//49 20//49 25//49
f 22 5 31 f 20//50 16//50 25//50
f 25 33 7 f 22//51 28//51 27//51
f 25 24 33 f 22//52 9//52 28//52
f 24 11 33 f 9//53 39//53 28//53
f 27 34 8 f 23//54 31//54 30//54
f 27 26 34 f 23//55 12//55 31//55
f 26 7 34 f 12//56 27//56 31//56
f 29 35 9 f 24//57 34//57 33//57
f 29 28 35 f 24//58 15//58 34//58
f 28 8 35 f 15//59 30//59 34//59
f 31 36 10 f 25//60 37//60 36//60
f 31 30 36 f 25//61 18//61 37//61
f 30 9 36 f 18//62 33//62 37//62
f 23 37 11 f 26//63 40//63 39//63
f 23 32 37 f 26//64 21//64 40//64
f 32 10 37 f 21//65 36//65 40//65
f 39 38 12 f 29//66 41//66 42//66
f 39 33 38 f 29//67 28//67 41//67
f 33 11 38 f 28//68 39//68 41//68
f 40 39 12 f 32//69 29//69 42//69
f 40 34 39 f 32//70 31//70 29//70
f 34 7 39 f 31//71 27//71 29//71
f 41 40 12 f 35//72 32//72 42//72
f 41 35 40 f 35//73 34//73 32//73
f 35 8 40 f 34//74 30//74 32//74
f 42 41 12 f 38//75 35//75 42//75
f 42 36 41 f 38//76 37//76 35//76
f 36 9 41 f 37//77 33//77 35//77
f 38 42 12 f 41//78 38//78 42//78
f 38 37 42 f 41//79 40//79 38//79
f 37 10 42 f 40//80 36//80 38//80

View File

@ -1,17 +1,43 @@
# Blender v2.72 (sub 0) OBJ File: '' # Blender v2.80 (sub 75) OBJ File: ''
# www.blender.org # www.blender.org
v -1.000000 -1.000000 1.000000
v -1.000000 -1.000000 -1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 -1.000000 1.000000
v -1.000000 1.000000 1.000000
v -1.000000 1.000000 -1.000000
v 1.000000 1.000000 -1.000000 v 1.000000 1.000000 -1.000000
v 1.000000 -1.000000 -1.000000
v 1.000000 1.000000 1.000000 v 1.000000 1.000000 1.000000
v 1.000000 -1.000000 1.000000
v -1.000000 1.000000 -1.000000
v -1.000000 -1.000000 -1.000000
v -1.000000 1.000000 1.000000
v -1.000000 -1.000000 1.000000
vt 0.375000 0.000000
vt 0.625000 0.000000
vt 0.625000 0.250000
vt 0.375000 0.250000
vt 0.375000 0.250000
vt 0.625000 0.250000
vt 0.625000 0.500000
vt 0.375000 0.500000
vt 0.625000 0.750000
vt 0.375000 0.750000
vt 0.625000 0.750000
vt 0.625000 1.000000
vt 0.375000 1.000000
vt 0.125000 0.500000
vt 0.375000 0.500000
vt 0.375000 0.750000
vt 0.125000 0.750000
vt 0.625000 0.500000
vt 0.875000 0.500000
vt 0.875000 0.750000
vn 0.0000 1.0000 0.0000
vn 0.0000 0.0000 1.0000
vn -1.0000 0.0000 0.0000
vn 0.0000 -1.0000 0.0000
vn 1.0000 0.0000 0.0000
vn 0.0000 0.0000 -1.0000
s off s off
f 5 6 2 1 f 1/1/1 5/2/1 7/3/1 3/4/1
f 6 7 3 2 f 4/5/2 3/6/2 7/7/2 8/8/2
f 7 8 4 3 f 8/8/3 7/7/3 5/9/3 6/10/3
f 8 5 1 4 f 6/10/4 2/11/4 4/12/4 8/13/4
f 1 2 3 4 f 2/14/5 1/15/5 3/16/5 4/17/5
f 8 7 6 5 f 6/18/6 5/19/6 1/20/6 2/11/6

View File

@ -31,6 +31,8 @@
#include <cctype> #include <cctype>
#include <map> #include <map>
#include <algorithm> #include <algorithm>
#include <unordered_map>
#include <tuple>
using namespace openglframework; using namespace openglframework;
using namespace std; using namespace std;
@ -112,6 +114,7 @@ void MeshReaderWriter::loadOBJFile(const string &filename, Mesh& meshToCreate) {
std::vector<uint> normalsIndices; std::vector<uint> normalsIndices;
std::vector<uint> uvsIndices; std::vector<uint> uvsIndices;
// ---------- Collect the data from the file ---------- // // ---------- Collect the data from the file ---------- //
// For each line of the file // For each line of the file
@ -142,7 +145,7 @@ void MeshReaderWriter::loadOBJFile(const string &filename, Mesh& meshToCreate) {
line = buffer; line = buffer;
found1 = (int)line.find("/"); found1 = (int)line.find("/");
bool isFaceQuad = false; bool isFaceQuad = false;
int foundNext = (int)line.substr(found1+1).find("/"); found2 = (int)line.substr(found1+1).find("/");
// If the face definition is of the form "f v1 v2 v3 v4" // If the face definition is of the form "f v1 v2 v3 v4"
if(found1 == string::npos) { if(found1 == string::npos) {
@ -150,11 +153,21 @@ void MeshReaderWriter::loadOBJFile(const string &filename, Mesh& meshToCreate) {
if (nbVertices == 4) isFaceQuad = true; if (nbVertices == 4) isFaceQuad = true;
} }
// If the face definition is of the form "f v1// v2// v3// v4//" // If the face definition is of the form "f v1// v2// v3// v4//"
else if (foundNext == 0) { else if (found2 == 0 && (int)line.substr(found1+found2+1).find(" ") == 0) {
int nbVertices = sscanf(buffer.c_str(), "%*s %d// %d// %d// %d//", &id1, &id2, &id3, &id4); int nbVertices = sscanf(buffer.c_str(), "%*s %d// %d// %d// %d//", &id1, &id2, &id3, &id4);
if (nbVertices == 4) isFaceQuad = true; if (nbVertices == 4) isFaceQuad = true;
} }
else { // If the face definition contains vertices and texture coordinates else { // If the face definition contains vertices and (texture coordinates or normals)
tId1 = -1;
tId2 = -1;
tId3 = -1;
tId4 = -1;
nId1 = -1;
nId2 = -1;
nId3 = -1;
nId4 = -1;
//get the part of the string until the second index //get the part of the string until the second index
tmp = line.substr(found1+1); tmp = line.substr(found1+1);
@ -166,6 +179,7 @@ void MeshReaderWriter::loadOBJFile(const string &filename, Mesh& meshToCreate) {
if(found2 == string::npos) { if(found2 == string::npos) {
int n = sscanf(buffer.c_str(), "%*s %d/%d %d/%d %d/%d %d/%d", &id1, &tId1, &id2, &tId2, &id3, &tId3, &id4, &tId4); int n = sscanf(buffer.c_str(), "%*s %d/%d %d/%d %d/%d %d/%d", &id1, &tId1, &id2, &tId2, &id3, &tId3, &id4, &tId4);
if (n == 8) isFaceQuad = true; if (n == 8) isFaceQuad = true;
uvsIndices.push_back(tId1-1); uvsIndices.push_back(tId1-1);
uvsIndices.push_back(tId2-1); uvsIndices.push_back(tId2-1);
uvsIndices.push_back(tId3-1); uvsIndices.push_back(tId3-1);
@ -174,8 +188,11 @@ void MeshReaderWriter::loadOBJFile(const string &filename, Mesh& meshToCreate) {
else { else {
tmp = line.substr(found1+1); tmp = line.substr(found1+1);
found2 = (int)tmp.find("/"); found2 = (int)tmp.find("/");
if (found2 > 1000) {
int test = 2;
}
// If the face definition is of the form "f vert1/normal1 vert2/normal2 ..." // If the face definition is of the form "f vert1//normal1 vert2//normal2 ..."
if(found2 == 0) { if(found2 == 0) {
int n = sscanf(buffer.c_str(), "%*s %d//%d %d//%d %d//%d %d//%d", &id1, &nId1, &id2, &nId2, &id3, &nId3, &id4, &nId4); int n = sscanf(buffer.c_str(), "%*s %d//%d %d//%d %d//%d %d//%d", &id1, &nId1, &id2, &nId2, &id3, &nId3, &id4, &nId4);
if (n == 8) isFaceQuad = true; if (n == 8) isFaceQuad = true;
@ -213,39 +230,84 @@ void MeshReaderWriter::loadOBJFile(const string &filename, Mesh& meshToCreate) {
// Destroy the current mesh // Destroy the current mesh
meshToCreate.destroy(); meshToCreate.destroy();
// This is used to create duplicate vertices if a vertex with index "i" from a face does not
// have same texture coordinates or normals as a previous vertex with index "i".
unordered_map<tuple<int, int, int>, uint> mapVertNormTexToVertexIndex;
// Mesh data // Mesh data
vector<std::vector<uint> > meshIndices; vector<std::vector<uint> > meshIndices;
vector<Vector3> meshVertices;
vector<Vector3> meshNormals; vector<Vector3> meshNormals;
if (!normals.empty()) meshNormals = vector<Vector3>(vertices.size(), Vector3(0, 0, 0)); //if (!normals.empty()) meshNormals = vector<Vector3>(vertices.size(), Vector3(0, 0, 0));
vector<Vector2> meshUVs; vector<Vector2> meshUVs;
if (!uvs.empty()) meshUVs = vector<Vector2>(vertices.size(), Vector2(0, 0)); //if (!uvs.empty()) meshUVs = vector<Vector2>(vertices.size(), Vector2(0, 0));
// We cannot load mesh with several parts for the moment // We cannot load mesh with several parts for the moment
uint meshPart = 0; uint meshPart = 0;
const bool hasNormals = !normalsIndices.empty() && !normals.empty();
const bool hasUvs = !uvsIndices.empty() && !uvs.empty();
// Fill in the vertex indices // Fill in the vertex indices
// We also triangulate each quad face // We also triangulate each quad face
meshIndices.push_back(std::vector<uint>()); meshIndices.push_back(std::vector<uint>());
for(size_t i = 0, j = 0; i < verticesIndices.size(); j++) { for(size_t i = 0, j = 0; i < verticesIndices.size(); j++) {
// Get the current vertex IDs // 3 if the current vertices form a triangle and 4 if they form a quad
uint i1 = verticesIndices[i]; const int nbVertices = isQuad[j] ? 4 : 3;
uint i2 = verticesIndices[i+1];
uint i3 = verticesIndices[i+2];
int newVerticesIndices[4] = { -1, -1, -1, -1 };
// For each vertex, we check if there is already a vertex with same UV and normals.
for (int v = 0; v < nbVertices; v++) {
int normalIndex = hasNormals ? normalsIndices[i + v] : -1;
int uvIndex = hasUvs ? uvsIndices[i + v] : -1;
// If the vertex with same UV and normal doesn't exist yet in the map
tuple<int, int, int> key = std::make_tuple(verticesIndices[i+v], normalIndex, uvIndex);
auto itFound = mapVertNormTexToVertexIndex.find(key);
if (itFound == mapVertNormTexToVertexIndex.end()) {
// Create a new vertex
newVerticesIndices[v]= meshVertices.size();
meshVertices.push_back(vertices[verticesIndices[i+v]]);
if (hasNormals) {
meshNormals.push_back(normals[normalsIndices[i+v]]);
}
if (hasUvs) {
meshUVs.push_back(uvs[uvsIndices[i+v]]);
}
mapVertNormTexToVertexIndex.insert(std::make_pair(key, newVerticesIndices[v]));
}
else {
// Get the vertex index to use
newVerticesIndices[v] = itFound->second;
}
}
// Get the current vertex IDs
uint i1 = newVerticesIndices[0];
uint i2 = newVerticesIndices[1];
uint i3 = newVerticesIndices[2];
uint i4 = newVerticesIndices[3];
/*
// Add the vertex normal // Add the vertex normal
if (!normalsIndices.empty() && !normals.empty()) { if (hasNormals) {
meshNormals[i1] = normals[normalsIndices[i]]; meshNormals[i1] = normals[normalsIndices[i]];
meshNormals[i2] = normals[normalsIndices[i+1]]; meshNormals[i2] = normals[normalsIndices[i+1]];
meshNormals[i3] = normals[normalsIndices[i+2]]; meshNormals[i3] = normals[normalsIndices[i+2]];
} }
// Add the vertex UV texture coordinates // Add the vertex UV texture coordinates
if (!uvsIndices.empty() && !uvs.empty()) { if (hasUvs) {
meshUVs[i1] = uvs[uvsIndices[i]]; meshUVs[i1] = uvs[uvsIndices[i]];
meshUVs[i2] = uvs[uvsIndices[i+1]]; meshUVs[i2] = uvs[uvsIndices[i+1]];
meshUVs[i3] = uvs[uvsIndices[i+2]]; meshUVs[i3] = uvs[uvsIndices[i+2]];
} }
*/
// If the current vertex not in a quad (it is part of a triangle) // If the current vertex not in a quad (it is part of a triangle)
if (!isQuad[j]) { if (!isQuad[j]) {
@ -259,11 +321,10 @@ void MeshReaderWriter::loadOBJFile(const string &filename, Mesh& meshToCreate) {
} }
else { // If the current vertex is in a quad else { // If the current vertex is in a quad
Vector3 v1 = vertices[i1]; Vector3 v1 = meshVertices[i1];
Vector3 v2 = vertices[i2]; Vector3 v2 = meshVertices[i2];
Vector3 v3 = vertices[i3]; Vector3 v3 = meshVertices[i3];
uint i4 = verticesIndices[i+3]; Vector3 v4 = meshVertices[i4];
Vector3 v4 = vertices[i4];
Vector3 v13 = v3-v1; Vector3 v13 = v3-v1;
Vector3 v12 = v2-v1; Vector3 v12 = v2-v1;
@ -288,6 +349,7 @@ void MeshReaderWriter::loadOBJFile(const string &filename, Mesh& meshToCreate) {
meshIndices[meshPart].push_back(i4); meshIndices[meshPart].push_back(i4);
} }
/*
// Add the vertex normal // Add the vertex normal
if (!normalsIndices.empty() && !normals.empty()) { if (!normalsIndices.empty() && !normals.empty()) {
meshNormals[i4] = normals[normalsIndices[i]]; meshNormals[i4] = normals[normalsIndices[i]];
@ -297,17 +359,18 @@ void MeshReaderWriter::loadOBJFile(const string &filename, Mesh& meshToCreate) {
if (!uvsIndices.empty() && !uvs.empty()) { if (!uvsIndices.empty() && !uvs.empty()) {
meshUVs[i4] = uvs[uvsIndices[i]]; meshUVs[i4] = uvs[uvsIndices[i]];
} }
*/
i+=4; i+=4;
} }
} }
assert(meshNormals.empty() || meshNormals.size() == vertices.size()); assert(meshNormals.empty() || meshNormals.size() == meshVertices.size());
assert(meshUVs.empty() || meshUVs.size() == vertices.size()); assert(meshUVs.empty() || meshUVs.size() == meshVertices.size());
// Set the data to the mesh // Set the data to the mesh
meshToCreate.setIndices(meshIndices); meshToCreate.setIndices(meshIndices);
meshToCreate.setVertices(vertices); meshToCreate.setVertices(meshVertices);
meshToCreate.setNormals(meshNormals); meshToCreate.setNormals(meshNormals);
meshToCreate.setUVs(meshUVs); meshToCreate.setUVs(meshUVs);
} }

View File

@ -93,4 +93,15 @@ class VertexMergingDataComparison {
} }
namespace std {
template<>
struct hash<std::tuple<int, int, int>>
{
size_t operator()(const std::tuple<int, int, int>& key) const
{
return std::get<0>(key) ^ std::get<1>(key) ^ std::get<2>(key);
}
};
}
#endif #endif

View File

@ -95,6 +95,11 @@ class Shader {
// to set it, an assert will occur) // to set it, an assert will occur)
void setIntUniform(const std::string& variableName, int value, bool errorIfMissing = true) const; void setIntUniform(const std::string& variableName, int value, bool errorIfMissing = true) const;
// Set an array of int uniform values to this shader (be careful if the uniform is not
// used in the shader, the compiler will remove it, then when you will try
// to set it, an assert will occur)
void setIntArrayUniform(const std::string& variableName, GLint* values, int nbValues, bool errorIfMissing = true) const;
// Set a vector 2 uniform value to this shader (be careful if the uniform is not // Set a vector 2 uniform value to this shader (be careful if the uniform is not
// used in the shader, the compiler will remove it, then when you will try // used in the shader, the compiler will remove it, then when you will try
// to set it, an assert will occur) // to set it, an assert will occur)
@ -159,7 +164,7 @@ inline GLint Shader::getUniformLocation(const std::string& variableName, bool er
std::cerr << "Error in vertex shader " << mFilenameVertexShader << " or in fragment shader" std::cerr << "Error in vertex shader " << mFilenameVertexShader << " or in fragment shader"
<< mFilenameFragmentShader << " : No Uniform variable : " << variableName << mFilenameFragmentShader << " : No Uniform variable : " << variableName
<< std::endl; << std::endl;
throw std::logic_error("Error in Shader"); //throw std::logic_error("Error in Shader");
} }
return location; return location;
@ -209,6 +214,16 @@ inline void Shader::setIntUniform(const std::string& variableName, int value, bo
} }
} }
// Set an array of int uniform values to this shader (be careful if the uniform is not
// used in the shader, the compiler will remove it, then when you will try
// to set it, an assert will occur)
inline void Shader::setIntArrayUniform(const std::string& variableName, GLint* values, int nbValues, bool errorIfMissing) const {
assert(mProgramObjectID != 0);
GLint location = getUniformLocation(variableName, errorIfMissing);
if (location != -1) {
glUniform1iv(location, nbValues, values);
}
}
// Set a vector 2 uniform value to this shader (be careful if the uniform is not // Set a vector 2 uniform value to this shader (be careful if the uniform is not
// used in the shader, the compiler will remove it, then when you will try // used in the shader, the compiler will remove it, then when you will try
// to set it, an assert will occur) // to set it, an assert will occur)

View File

@ -1,350 +1,350 @@
/******************************************************************************** /********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com * * ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2016 Daniel Chappuis * * Copyright (c) 2010-2016 Daniel Chappuis *
********************************************************************************* *********************************************************************************
* * * *
* This software is provided 'as-is', without any express or implied warranty. * * This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the * * In no event will the authors be held liable for any damages arising from the *
* use of this software. * * use of this software. *
* * * *
* Permission is granted to anyone to use this software for any purpose, * * Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it * * including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: * * freely, subject to the following restrictions: *
* * * *
* 1. The origin of this software must not be misrepresented; you must not claim * * 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a * * that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be * * product, an acknowledgment in the product documentation would be *
* appreciated but is not required. * * appreciated but is not required. *
* * * *
* 2. Altered source versions must be plainly marked as such, and must not be * * 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. * * misrepresented as being the original software. *
* * * *
* 3. This notice may not be removed or altered from any source distribution. * * 3. This notice may not be removed or altered from any source distribution. *
* * * *
********************************************************************************/ ********************************************************************************/
// Libraries // Libraries
#include "CollisionDetectionScene.h" #include "CollisionDetectionScene.h"
#include "constraint/ContactPoint.h" #include "constraint/ContactPoint.h"
#include "collision/ContactManifold.h" #include "collision/ContactManifold.h"
// Namespaces // Namespaces
using namespace openglframework; using namespace openglframework;
using namespace collisiondetectionscene; using namespace collisiondetectionscene;
// Constructor // Constructor
CollisionDetectionScene::CollisionDetectionScene(const std::string& name, EngineSettings& settings) CollisionDetectionScene::CollisionDetectionScene(const std::string& name, EngineSettings& settings)
: SceneDemo(name, settings, SCENE_RADIUS, false), mMeshFolderPath("meshes/"), : SceneDemo(name, settings, SCENE_RADIUS, false), mMeshFolderPath("meshes/"),
mContactManager(mPhongShader, mMeshFolderPath), mContactManager(mPhongShader, mMeshFolderPath),
mAreNormalsDisplayed(false) { mAreNormalsDisplayed(false) {
mSelectedShapeIndex = 0; mSelectedShapeIndex = 0;
mIsContactPointsDisplayed = true; mIsContactPointsDisplayed = true;
mIsWireframeEnabled = true; mIsWireframeEnabled = true;
// Compute the radius and the center of the scene // Compute the radius and the center of the scene
openglframework::Vector3 center(0, 0, 0); openglframework::Vector3 center(0, 0, 0);
// Set the center of the scene // Set the center of the scene
setScenePosition(center, SCENE_RADIUS); setScenePosition(center, SCENE_RADIUS);
rp3d::WorldSettings worldSettings; rp3d::WorldSettings worldSettings;
worldSettings.worldName = name; worldSettings.worldName = name;
// Create the dynamics world for the physics simulation // Create the dynamics world for the physics simulation
mPhysicsWorld = new rp3d::CollisionWorld(worldSettings); mPhysicsWorld = new rp3d::CollisionWorld(worldSettings);
// ---------- Sphere 1 ---------- // // ---------- Sphere 1 ---------- //
// Create a sphere and a corresponding collision body in the dynamics world // Create a sphere and a corresponding collision body in the dynamics world
mSphere1 = new Sphere(4, mPhysicsWorld, mMeshFolderPath); mSphere1 = new Sphere(4, mPhysicsWorld, mMeshFolderPath);
mAllShapes.push_back(mSphere1); mAllShapes.push_back(mSphere1);
// Set the color // Set the color
mSphere1->setColor(mGreyColorDemo); mSphere1->setColor(mObjectColorDemo);
mSphere1->setSleepingColor(mRedColorDemo); mSphere1->setSleepingColor(mSleepingColorDemo);
//mSphere1->setScaling(0.5f); //mSphere1->setScaling(0.5f);
mPhysicsObjects.push_back(mSphere1); mPhysicsObjects.push_back(mSphere1);
// ---------- Sphere 2 ---------- // // ---------- Sphere 2 ---------- //
// Create a sphere and a corresponding collision body in the dynamics world // Create a sphere and a corresponding collision body in the dynamics world
mSphere2 = new Sphere(2, mPhysicsWorld, mMeshFolderPath); mSphere2 = new Sphere(2, mPhysicsWorld, mMeshFolderPath);
mAllShapes.push_back(mSphere2); mAllShapes.push_back(mSphere2);
// Set the color // Set the color
mSphere2->setColor(mGreyColorDemo); mSphere2->setColor(mObjectColorDemo);
mSphere2->setSleepingColor(mRedColorDemo); mSphere2->setSleepingColor(mSleepingColorDemo);
mPhysicsObjects.push_back(mSphere2); mPhysicsObjects.push_back(mSphere2);
// ---------- Capsule 1 ---------- // // ---------- Capsule 1 ---------- //
// Create a cylinder and a corresponding collision body in the dynamics world // Create a cylinder and a corresponding collision body in the dynamics world
mCapsule1 = new Capsule(CAPSULE_RADIUS, CAPSULE_HEIGHT, mPhysicsWorld, mMeshFolderPath); mCapsule1 = new Capsule(CAPSULE_RADIUS, CAPSULE_HEIGHT, mPhysicsWorld, mMeshFolderPath);
mAllShapes.push_back(mCapsule1); mAllShapes.push_back(mCapsule1);
// Set the color // Set the color
mCapsule1->setColor(mGreyColorDemo); mCapsule1->setColor(mObjectColorDemo);
mCapsule1->setSleepingColor(mRedColorDemo); mCapsule1->setSleepingColor(mSleepingColorDemo);
mPhysicsObjects.push_back(mCapsule1); mPhysicsObjects.push_back(mCapsule1);
// ---------- Capsule 2 ---------- // // ---------- Capsule 2 ---------- //
// Create a cylinder and a corresponding collision body in the dynamics world // Create a cylinder and a corresponding collision body in the dynamics world
mCapsule2 = new Capsule(CAPSULE_RADIUS, CAPSULE_HEIGHT, mPhysicsWorld, mMeshFolderPath); mCapsule2 = new Capsule(CAPSULE_RADIUS, CAPSULE_HEIGHT, mPhysicsWorld, mMeshFolderPath);
mAllShapes.push_back(mCapsule2); mAllShapes.push_back(mCapsule2);
// Set the color // Set the color
mCapsule2->setColor(mGreyColorDemo); mCapsule2->setColor(mObjectColorDemo);
mCapsule2->setSleepingColor(mRedColorDemo); mCapsule2->setSleepingColor(mSleepingColorDemo);
mPhysicsObjects.push_back(mCapsule2); mPhysicsObjects.push_back(mCapsule2);
// ---------- Concave Mesh ---------- // // ---------- Concave Mesh ---------- //
// Create a convex mesh and a corresponding collision body in the dynamics world // Create a convex mesh and a corresponding collision body in the dynamics world
mConcaveMesh = new ConcaveMesh(mPhysicsWorld, mMeshFolderPath + "city.obj"); mConcaveMesh = new ConcaveMesh(mPhysicsWorld, mMeshFolderPath + "city.obj");
mAllShapes.push_back(mConcaveMesh); mAllShapes.push_back(mConcaveMesh);
// Set the color // Set the color
mConcaveMesh->setColor(mGreyColorDemo); mConcaveMesh->setColor(mObjectColorDemo);
mConcaveMesh->setSleepingColor(mRedColorDemo); mConcaveMesh->setSleepingColor(mSleepingColorDemo);
mPhysicsObjects.push_back(mConcaveMesh); mPhysicsObjects.push_back(mConcaveMesh);
// ---------- Box 1 ---------- // // ---------- Box 1 ---------- //
// Create a cylinder and a corresponding collision body in the dynamics world // Create a cylinder and a corresponding collision body in the dynamics world
mBox1 = new Box(BOX_SIZE, mPhysicsWorld, mMeshFolderPath); mBox1 = new Box(BOX_SIZE, mPhysicsWorld, mMeshFolderPath);
mAllShapes.push_back(mBox1); mAllShapes.push_back(mBox1);
// Set the color // Set the color
mBox1->setColor(mGreyColorDemo); mBox1->setColor(mObjectColorDemo);
mBox1->setSleepingColor(mRedColorDemo); mBox1->setSleepingColor(mSleepingColorDemo);
mPhysicsObjects.push_back(mBox1); mPhysicsObjects.push_back(mBox1);
// ---------- Box 2 ---------- // // ---------- Box 2 ---------- //
// Create a cylinder and a corresponding collision body in the dynamics world // Create a cylinder and a corresponding collision body in the dynamics world
mBox2 = new Box(openglframework::Vector3(3, 2, 5), mPhysicsWorld, mMeshFolderPath); mBox2 = new Box(openglframework::Vector3(3, 2, 5), mPhysicsWorld, mMeshFolderPath);
mAllShapes.push_back(mBox2); mAllShapes.push_back(mBox2);
// Set the color // Set the color
mBox2->setColor(mGreyColorDemo); mBox2->setColor(mObjectColorDemo);
mBox2->setSleepingColor(mRedColorDemo); mBox2->setSleepingColor(mSleepingColorDemo);
mPhysicsObjects.push_back(mBox2); mPhysicsObjects.push_back(mBox2);
// ---------- Convex Mesh ---------- // // ---------- Convex Mesh ---------- //
// Create a convex mesh and a corresponding collision body in the dynamics world // Create a convex mesh and a corresponding collision body in the dynamics world
mConvexMesh = new ConvexMesh(mPhysicsWorld, mMeshFolderPath + "convexmesh.obj"); mConvexMesh = new ConvexMesh(mPhysicsWorld, mMeshFolderPath + "convexmesh.obj");
mAllShapes.push_back(mConvexMesh); mAllShapes.push_back(mConvexMesh);
// Set the color // Set the color
mConvexMesh->setColor(mGreyColorDemo); mConvexMesh->setColor(mObjectColorDemo);
mConvexMesh->setSleepingColor(mRedColorDemo); mConvexMesh->setSleepingColor(mSleepingColorDemo);
mPhysicsObjects.push_back(mConvexMesh); mPhysicsObjects.push_back(mConvexMesh);
// ---------- Heightfield ---------- // // ---------- Heightfield ---------- //
// Create a convex mesh and a corresponding collision body in the dynamics world // Create a convex mesh and a corresponding collision body in the dynamics world
mHeightField = new HeightField(mPhysicsWorld); mHeightField = new HeightField(mPhysicsWorld);
// Set the color // Set the color
mHeightField->setColor(mGreyColorDemo); mHeightField->setColor(mObjectColorDemo);
mHeightField->setSleepingColor(mRedColorDemo); mHeightField->setSleepingColor(mSleepingColorDemo);
mPhysicsObjects.push_back(mHeightField); mPhysicsObjects.push_back(mHeightField);
mAllShapes[mSelectedShapeIndex]->setColor(mBlueColorDemo); mAllShapes[mSelectedShapeIndex]->setColor(mObjectColorDemo);
} }
// Reset the scene // Reset the scene
void CollisionDetectionScene::reset() { void CollisionDetectionScene::reset() {
mSphere1->setTransform(rp3d::Transform(rp3d::Vector3(15, 5, 0), rp3d::Quaternion::identity())); mSphere1->setTransform(rp3d::Transform(rp3d::Vector3(15, 5, 0), rp3d::Quaternion::identity()));
mSphere2->setTransform(rp3d::Transform(rp3d::Vector3(0, 6, 0), rp3d::Quaternion::identity())); mSphere2->setTransform(rp3d::Transform(rp3d::Vector3(0, 6, 0), rp3d::Quaternion::identity()));
mCapsule1->setTransform(rp3d::Transform(rp3d::Vector3(-8, 7, 0), rp3d::Quaternion::identity())); mCapsule1->setTransform(rp3d::Transform(rp3d::Vector3(-8, 7, 0), rp3d::Quaternion::identity()));
mCapsule2->setTransform(rp3d::Transform(rp3d::Vector3(11, -8, 0), rp3d::Quaternion::identity())); mCapsule2->setTransform(rp3d::Transform(rp3d::Vector3(11, -8, 0), rp3d::Quaternion::identity()));
mBox1->setTransform(rp3d::Transform(rp3d::Vector3(-4, -7, 0), rp3d::Quaternion::identity())); mBox1->setTransform(rp3d::Transform(rp3d::Vector3(-4, -7, 0), rp3d::Quaternion::identity()));
mBox2->setTransform(rp3d::Transform(rp3d::Vector3(0, 9, 0), rp3d::Quaternion::identity())); mBox2->setTransform(rp3d::Transform(rp3d::Vector3(0, 9, 0), rp3d::Quaternion::identity()));
mConvexMesh->setTransform(rp3d::Transform(rp3d::Vector3(-5, 0, 0), rp3d::Quaternion::identity())); mConvexMesh->setTransform(rp3d::Transform(rp3d::Vector3(-5, 0, 0), rp3d::Quaternion::identity()));
mConcaveMesh->setTransform(rp3d::Transform(rp3d::Vector3(0, 15, 0), rp3d::Quaternion::identity())); mConcaveMesh->setTransform(rp3d::Transform(rp3d::Vector3(0, 15, 0), rp3d::Quaternion::identity()));
mHeightField->setTransform(rp3d::Transform(rp3d::Vector3(0, -22, 0), rp3d::Quaternion::identity())); mHeightField->setTransform(rp3d::Transform(rp3d::Vector3(0, -22, 0), rp3d::Quaternion::identity()));
} }
// Destructor // Destructor
CollisionDetectionScene::~CollisionDetectionScene() { CollisionDetectionScene::~CollisionDetectionScene() {
// Destroy the box rigid body from the dynamics world // Destroy the box rigid body from the dynamics world
//mPhysicsWorld->destroyCollisionBody(mBox->getCollisionBody()); //mPhysicsWorld->destroyCollisionBody(mBox->getCollisionBody());
//delete mBox; //delete mBox;
// Destroy the spheres // Destroy the spheres
mPhysicsWorld->destroyCollisionBody(mSphere1->getCollisionBody()); mPhysicsWorld->destroyCollisionBody(mSphere1->getCollisionBody());
delete mSphere1; delete mSphere1;
mPhysicsWorld->destroyCollisionBody(mSphere2->getCollisionBody()); mPhysicsWorld->destroyCollisionBody(mSphere2->getCollisionBody());
delete mSphere2; delete mSphere2;
mPhysicsWorld->destroyCollisionBody(mCapsule1->getCollisionBody()); mPhysicsWorld->destroyCollisionBody(mCapsule1->getCollisionBody());
delete mCapsule1; delete mCapsule1;
mPhysicsWorld->destroyCollisionBody(mCapsule2->getCollisionBody()); mPhysicsWorld->destroyCollisionBody(mCapsule2->getCollisionBody());
delete mCapsule2; delete mCapsule2;
mPhysicsWorld->destroyCollisionBody(mBox1->getCollisionBody()); mPhysicsWorld->destroyCollisionBody(mBox1->getCollisionBody());
delete mBox1; delete mBox1;
mPhysicsWorld->destroyCollisionBody(mBox2->getCollisionBody()); mPhysicsWorld->destroyCollisionBody(mBox2->getCollisionBody());
delete mBox2; delete mBox2;
mPhysicsWorld->destroyCollisionBody(mConvexMesh->getCollisionBody()); mPhysicsWorld->destroyCollisionBody(mConvexMesh->getCollisionBody());
delete mConvexMesh; delete mConvexMesh;
mPhysicsWorld->destroyCollisionBody(mConcaveMesh->getCollisionBody()); mPhysicsWorld->destroyCollisionBody(mConcaveMesh->getCollisionBody());
delete mConcaveMesh; delete mConcaveMesh;
mPhysicsWorld->destroyCollisionBody(mHeightField->getCollisionBody()); mPhysicsWorld->destroyCollisionBody(mHeightField->getCollisionBody());
delete mHeightField; delete mHeightField;
mContactManager.resetPoints(); mContactManager.resetPoints();
// Destroy the static data for the visual contact points // Destroy the static data for the visual contact points
VisualContactPoint::destroyStaticData(); VisualContactPoint::destroyStaticData();
// Destroy the collision world // Destroy the collision world
delete mPhysicsWorld; delete mPhysicsWorld;
} }
// Take a step for the simulation // Take a step for the simulation
void CollisionDetectionScene::update() { void CollisionDetectionScene::update() {
mContactManager.resetPoints(); mContactManager.resetPoints();
mPhysicsWorld->testCollision(&mContactManager); mPhysicsWorld->testCollision(&mContactManager);
SceneDemo::update(); SceneDemo::update();
} }
void CollisionDetectionScene::selectNextShape() { void CollisionDetectionScene::selectNextShape() {
uint previousIndex = mSelectedShapeIndex; uint previousIndex = mSelectedShapeIndex;
mSelectedShapeIndex++; mSelectedShapeIndex++;
if (mSelectedShapeIndex >= mAllShapes.size()) { if (mSelectedShapeIndex >= mAllShapes.size()) {
mSelectedShapeIndex = 0; mSelectedShapeIndex = 0;
} }
mAllShapes[previousIndex]->setColor(mGreyColorDemo); mAllShapes[previousIndex]->setColor(mObjectColorDemo);
mAllShapes[mSelectedShapeIndex]->setColor(mBlueColorDemo); mAllShapes[mSelectedShapeIndex]->setColor(mSelectedObjectColorDemo);
} }
// Called when a keyboard event occurs // Called when a keyboard event occurs
bool CollisionDetectionScene::keyboardEvent(int key, int scancode, int action, int mods) { bool CollisionDetectionScene::keyboardEvent(int key, int scancode, int action, int mods) {
// If the space key has been pressed // If the space key has been pressed
if (key == GLFW_KEY_SPACE && action == GLFW_PRESS) { if (key == GLFW_KEY_SPACE && action == GLFW_PRESS) {
selectNextShape(); selectNextShape();
return true; return true;
} }
float stepDist = 0.2f; float stepDist = 0.2f;
float stepAngle = 15 * (3.14f / 180.0f); float stepAngle = 15 * (3.14f / 180.0f);
if (key == GLFW_KEY_RIGHT && action == GLFW_PRESS) { if (key == GLFW_KEY_RIGHT && action == GLFW_PRESS) {
rp3d::Transform transform = mAllShapes[mSelectedShapeIndex]->getTransform(); rp3d::Transform transform = mAllShapes[mSelectedShapeIndex]->getTransform();
transform.setPosition(transform.getPosition() + rp3d::Vector3(stepDist, 0, 0)); transform.setPosition(transform.getPosition() + rp3d::Vector3(stepDist, 0, 0));
mAllShapes[mSelectedShapeIndex]->setTransform(transform); mAllShapes[mSelectedShapeIndex]->setTransform(transform);
} }
else if (key == GLFW_KEY_LEFT && action == GLFW_PRESS) { else if (key == GLFW_KEY_LEFT && action == GLFW_PRESS) {
rp3d::Transform transform = mAllShapes[mSelectedShapeIndex]->getTransform(); rp3d::Transform transform = mAllShapes[mSelectedShapeIndex]->getTransform();
transform.setPosition(transform.getPosition() + rp3d::Vector3(-stepDist, 0, 0)); transform.setPosition(transform.getPosition() + rp3d::Vector3(-stepDist, 0, 0));
mAllShapes[mSelectedShapeIndex]->setTransform(transform); mAllShapes[mSelectedShapeIndex]->setTransform(transform);
} }
else if (key == GLFW_KEY_UP && action == GLFW_PRESS) { else if (key == GLFW_KEY_UP && action == GLFW_PRESS) {
rp3d::Transform transform = mAllShapes[mSelectedShapeIndex]->getTransform(); rp3d::Transform transform = mAllShapes[mSelectedShapeIndex]->getTransform();
transform.setPosition(transform.getPosition() + rp3d::Vector3(0, stepDist, 0)); transform.setPosition(transform.getPosition() + rp3d::Vector3(0, stepDist, 0));
mAllShapes[mSelectedShapeIndex]->setTransform(transform); mAllShapes[mSelectedShapeIndex]->setTransform(transform);
} }
else if (key == GLFW_KEY_DOWN && action == GLFW_PRESS) { else if (key == GLFW_KEY_DOWN && action == GLFW_PRESS) {
rp3d::Transform transform = mAllShapes[mSelectedShapeIndex]->getTransform(); rp3d::Transform transform = mAllShapes[mSelectedShapeIndex]->getTransform();
transform.setPosition(transform.getPosition() + rp3d::Vector3(0, -stepDist, 0)); transform.setPosition(transform.getPosition() + rp3d::Vector3(0, -stepDist, 0));
mAllShapes[mSelectedShapeIndex]->setTransform(transform); mAllShapes[mSelectedShapeIndex]->setTransform(transform);
} }
else if (key == GLFW_KEY_Z && action == GLFW_PRESS) { else if (key == GLFW_KEY_Z && action == GLFW_PRESS) {
rp3d::Transform transform = mAllShapes[mSelectedShapeIndex]->getTransform(); rp3d::Transform transform = mAllShapes[mSelectedShapeIndex]->getTransform();
transform.setPosition(transform.getPosition() + rp3d::Vector3(0, 0, stepDist)); transform.setPosition(transform.getPosition() + rp3d::Vector3(0, 0, stepDist));
mAllShapes[mSelectedShapeIndex]->setTransform(transform); mAllShapes[mSelectedShapeIndex]->setTransform(transform);
} }
else if (key == GLFW_KEY_H && action == GLFW_PRESS) { else if (key == GLFW_KEY_H && action == GLFW_PRESS) {
rp3d::Transform transform = mAllShapes[mSelectedShapeIndex]->getTransform(); rp3d::Transform transform = mAllShapes[mSelectedShapeIndex]->getTransform();
transform.setPosition(transform.getPosition() + rp3d::Vector3(0, 0, -stepDist)); transform.setPosition(transform.getPosition() + rp3d::Vector3(0, 0, -stepDist));
mAllShapes[mSelectedShapeIndex]->setTransform(transform); mAllShapes[mSelectedShapeIndex]->setTransform(transform);
} }
else if (key == GLFW_KEY_A && action == GLFW_PRESS) { else if (key == GLFW_KEY_A && action == GLFW_PRESS) {
rp3d::Transform transform = mAllShapes[mSelectedShapeIndex]->getTransform(); rp3d::Transform transform = mAllShapes[mSelectedShapeIndex]->getTransform();
transform.setOrientation(rp3d::Quaternion::fromEulerAngles(0, stepAngle, 0) * transform.getOrientation()); transform.setOrientation(rp3d::Quaternion::fromEulerAngles(0, stepAngle, 0) * transform.getOrientation());
mAllShapes[mSelectedShapeIndex]->setTransform(transform); mAllShapes[mSelectedShapeIndex]->setTransform(transform);
} }
else if (key == GLFW_KEY_D && action == GLFW_PRESS) { else if (key == GLFW_KEY_D && action == GLFW_PRESS) {
rp3d::Transform transform = mAllShapes[mSelectedShapeIndex]->getTransform(); rp3d::Transform transform = mAllShapes[mSelectedShapeIndex]->getTransform();
transform.setOrientation(rp3d::Quaternion::fromEulerAngles(0, -stepAngle, 0) * transform.getOrientation()); transform.setOrientation(rp3d::Quaternion::fromEulerAngles(0, -stepAngle, 0) * transform.getOrientation());
mAllShapes[mSelectedShapeIndex]->setTransform(transform); mAllShapes[mSelectedShapeIndex]->setTransform(transform);
} }
else if (key == GLFW_KEY_W && action == GLFW_PRESS) { else if (key == GLFW_KEY_W && action == GLFW_PRESS) {
rp3d::Transform transform = mAllShapes[mSelectedShapeIndex]->getTransform(); rp3d::Transform transform = mAllShapes[mSelectedShapeIndex]->getTransform();
transform.setOrientation(rp3d::Quaternion::fromEulerAngles(stepAngle, 0, 0) * transform.getOrientation()); transform.setOrientation(rp3d::Quaternion::fromEulerAngles(stepAngle, 0, 0) * transform.getOrientation());
mAllShapes[mSelectedShapeIndex]->setTransform(transform); mAllShapes[mSelectedShapeIndex]->setTransform(transform);
} }
else if (key == GLFW_KEY_S && action == GLFW_PRESS) { else if (key == GLFW_KEY_S && action == GLFW_PRESS) {
rp3d::Transform transform = mAllShapes[mSelectedShapeIndex]->getTransform(); rp3d::Transform transform = mAllShapes[mSelectedShapeIndex]->getTransform();
transform.setOrientation(rp3d::Quaternion::fromEulerAngles(-stepAngle, 0, 0) * transform.getOrientation()); transform.setOrientation(rp3d::Quaternion::fromEulerAngles(-stepAngle, 0, 0) * transform.getOrientation());
mAllShapes[mSelectedShapeIndex]->setTransform(transform); mAllShapes[mSelectedShapeIndex]->setTransform(transform);
} }
else if (key == GLFW_KEY_F && action == GLFW_PRESS) { else if (key == GLFW_KEY_F && action == GLFW_PRESS) {
rp3d::Transform transform = mAllShapes[mSelectedShapeIndex]->getTransform(); rp3d::Transform transform = mAllShapes[mSelectedShapeIndex]->getTransform();
transform.setOrientation(rp3d::Quaternion::fromEulerAngles(0, 0, stepAngle) * transform.getOrientation()); transform.setOrientation(rp3d::Quaternion::fromEulerAngles(0, 0, stepAngle) * transform.getOrientation());
mAllShapes[mSelectedShapeIndex]->setTransform(transform); mAllShapes[mSelectedShapeIndex]->setTransform(transform);
} }
else if (key == GLFW_KEY_G && action == GLFW_PRESS) { else if (key == GLFW_KEY_G && action == GLFW_PRESS) {
rp3d::Transform transform = mAllShapes[mSelectedShapeIndex]->getTransform(); rp3d::Transform transform = mAllShapes[mSelectedShapeIndex]->getTransform();
transform.setOrientation(rp3d::Quaternion::fromEulerAngles(0, 0, -stepAngle) * transform.getOrientation()); transform.setOrientation(rp3d::Quaternion::fromEulerAngles(0, 0, -stepAngle) * transform.getOrientation());
mAllShapes[mSelectedShapeIndex]->setTransform(transform); mAllShapes[mSelectedShapeIndex]->setTransform(transform);
} }
return false; return false;
} }
// This method will be called for each reported contact point // This method will be called for each reported contact point
void ContactManager::notifyContact(const CollisionCallbackInfo& collisionCallbackInfo) { void ContactManager::notifyContact(const CollisionCallbackInfo& collisionCallbackInfo) {
// For each contact manifold // For each contact manifold
rp3d::ContactManifoldListElement* manifoldElement = collisionCallbackInfo.contactManifoldElements; rp3d::ContactManifoldListElement* manifoldElement = collisionCallbackInfo.contactManifoldElements;
while (manifoldElement != nullptr) { while (manifoldElement != nullptr) {
// Get the contact manifold // Get the contact manifold
rp3d::ContactManifold* contactManifold = manifoldElement->getContactManifold(); rp3d::ContactManifold* contactManifold = manifoldElement->getContactManifold();
// For each contact point // For each contact point
rp3d::ContactPoint* contactPoint = contactManifold->getContactPoints(); rp3d::ContactPoint* contactPoint = contactManifold->getContactPoints();
while (contactPoint != nullptr) { while (contactPoint != nullptr) {
// Contact normal // Contact normal
rp3d::Vector3 normal = contactPoint->getNormal(); rp3d::Vector3 normal = contactPoint->getNormal();
openglframework::Vector3 contactNormal(normal.x, normal.y, normal.z); openglframework::Vector3 contactNormal(normal.x, normal.y, normal.z);
rp3d::Vector3 point1 = contactPoint->getLocalPointOnShape1(); rp3d::Vector3 point1 = contactPoint->getLocalPointOnShape1();
point1 = collisionCallbackInfo.proxyShape1->getLocalToWorldTransform() * point1; point1 = collisionCallbackInfo.proxyShape1->getLocalToWorldTransform() * point1;
openglframework::Vector3 position1(point1.x, point1.y, point1.z); openglframework::Vector3 position1(point1.x, point1.y, point1.z);
mContactPoints.push_back(ContactPoint(position1, contactNormal, openglframework::Color::red())); mContactPoints.push_back(ContactPoint(position1, contactNormal, openglframework::Color::red()));
rp3d::Vector3 point2 = contactPoint->getLocalPointOnShape2(); rp3d::Vector3 point2 = contactPoint->getLocalPointOnShape2();
point2 = collisionCallbackInfo.proxyShape2->getLocalToWorldTransform() * point2; point2 = collisionCallbackInfo.proxyShape2->getLocalToWorldTransform() * point2;
openglframework::Vector3 position2(point2.x, point2.y, point2.z); openglframework::Vector3 position2(point2.x, point2.y, point2.z);
mContactPoints.push_back(ContactPoint(position2, contactNormal, openglframework::Color::blue())); mContactPoints.push_back(ContactPoint(position2, contactNormal, openglframework::Color::blue()));
contactPoint = contactPoint->getNext(); contactPoint = contactPoint->getNext();
} }
manifoldElement = manifoldElement->getNext(); manifoldElement = manifoldElement->getNext();
} }
} }

View File

@ -57,8 +57,8 @@ CollisionShapesScene::CollisionShapesScene(const std::string& name, EngineSettin
Dumbbell* dumbbell = new Dumbbell(getDynamicsWorld(), meshFolderPath); Dumbbell* dumbbell = new Dumbbell(getDynamicsWorld(), meshFolderPath);
// Set the box color // Set the box color
dumbbell->setColor(mDemoColors[i % mNbDemoColors]); dumbbell->setColor(mObjectColorDemo);
dumbbell->setSleepingColor(mRedColorDemo); dumbbell->setSleepingColor(mSleepingColorDemo);
// Change the material properties of the rigid body // Change the material properties of the rigid body
rp3d::Material& material = dumbbell->getRigidBody()->getMaterial(); rp3d::Material& material = dumbbell->getRigidBody()->getMaterial();
@ -76,8 +76,8 @@ CollisionShapesScene::CollisionShapesScene(const std::string& name, EngineSettin
Box* box = new Box(BOX_SIZE, BOX_MASS, getDynamicsWorld(), mMeshFolderPath); Box* box = new Box(BOX_SIZE, BOX_MASS, getDynamicsWorld(), mMeshFolderPath);
// Set the box color // Set the box color
box->setColor(mDemoColors[i % mNbDemoColors]); box->setColor(mObjectColorDemo);
box->setSleepingColor(mRedColorDemo); box->setSleepingColor(mSleepingColorDemo);
// Change the material properties of the rigid body // Change the material properties of the rigid body
rp3d::Material& material = box->getRigidBody()->getMaterial(); rp3d::Material& material = box->getRigidBody()->getMaterial();
@ -98,8 +98,8 @@ CollisionShapesScene::CollisionShapesScene(const std::string& name, EngineSettin
sphere->getRigidBody()->getMaterial().setRollingResistance(rp3d::decimal(0.08)); sphere->getRigidBody()->getMaterial().setRollingResistance(rp3d::decimal(0.08));
// Set the box color // Set the box color
sphere->setColor(mDemoColors[i % mNbDemoColors]); sphere->setColor(mObjectColorDemo);
sphere->setSleepingColor(mRedColorDemo); sphere->setSleepingColor(mSleepingColorDemo);
// Change the material properties of the rigid body // Change the material properties of the rigid body
rp3d::Material& material = sphere->getRigidBody()->getMaterial(); rp3d::Material& material = sphere->getRigidBody()->getMaterial();
@ -120,8 +120,8 @@ CollisionShapesScene::CollisionShapesScene(const std::string& name, EngineSettin
capsule->getRigidBody()->getMaterial().setRollingResistance(rp3d::decimal(0.08f)); capsule->getRigidBody()->getMaterial().setRollingResistance(rp3d::decimal(0.08f));
// Set the box color // Set the box color
capsule->setColor(mDemoColors[i % mNbDemoColors]); capsule->setColor(mObjectColorDemo);
capsule->setSleepingColor(mRedColorDemo); capsule->setSleepingColor(mSleepingColorDemo);
// Change the material properties of the rigid body // Change the material properties of the rigid body
rp3d::Material& material = capsule->getRigidBody()->getMaterial(); rp3d::Material& material = capsule->getRigidBody()->getMaterial();
@ -139,8 +139,8 @@ CollisionShapesScene::CollisionShapesScene(const std::string& name, EngineSettin
ConvexMesh* mesh = new ConvexMesh(MESH_MASS, getDynamicsWorld(), meshFolderPath + "convexmesh.obj"); ConvexMesh* mesh = new ConvexMesh(MESH_MASS, getDynamicsWorld(), meshFolderPath + "convexmesh.obj");
// Set the box color // Set the box color
mesh->setColor(mDemoColors[i % mNbDemoColors]); mesh->setColor(mObjectColorDemo);
mesh->setSleepingColor(mRedColorDemo); mesh->setSleepingColor(mSleepingColorDemo);
// Change the material properties of the rigid body // Change the material properties of the rigid body
rp3d::Material& material = mesh->getRigidBody()->getMaterial(); rp3d::Material& material = mesh->getRigidBody()->getMaterial();
@ -157,8 +157,8 @@ CollisionShapesScene::CollisionShapesScene(const std::string& name, EngineSettin
mPhysicsObjects.push_back(mFloor); mPhysicsObjects.push_back(mFloor);
// Set the box color // Set the box color
mFloor->setColor(mGreyColorDemo); mFloor->setColor(mFloorColorDemo);
mFloor->setSleepingColor(mGreyColorDemo); mFloor->setSleepingColor(mFloorColorDemo);
// The floor must be a static rigid body // The floor must be a static rigid body
mFloor->getRigidBody()->setType(rp3d::BodyType::STATIC); mFloor->getRigidBody()->setType(rp3d::BodyType::STATIC);

View File

@ -58,8 +58,8 @@ ConcaveMeshScene::ConcaveMeshScene(const std::string& name, EngineSettings& sett
Dumbbell* dumbbell = new Dumbbell(getDynamicsWorld(), meshFolderPath); Dumbbell* dumbbell = new Dumbbell(getDynamicsWorld(), meshFolderPath);
// Set the box color // Set the box color
dumbbell->setColor(mDemoColors[i % mNbDemoColors]); dumbbell->setColor(mObjectColorDemo);
dumbbell->setSleepingColor(mRedColorDemo); dumbbell->setSleepingColor(mSleepingColorDemo);
// Change the material properties of the rigid body // Change the material properties of the rigid body
rp3d::Material& material = dumbbell->getRigidBody()->getMaterial(); rp3d::Material& material = dumbbell->getRigidBody()->getMaterial();
@ -77,8 +77,8 @@ ConcaveMeshScene::ConcaveMeshScene(const std::string& name, EngineSettings& sett
Box* box = new Box(BOX_SIZE, BOX_MASS, getDynamicsWorld(), mMeshFolderPath); Box* box = new Box(BOX_SIZE, BOX_MASS, getDynamicsWorld(), mMeshFolderPath);
// Set the box color // Set the box color
box->setColor(mDemoColors[i % mNbDemoColors]); box->setColor(mObjectColorDemo);
box->setSleepingColor(mRedColorDemo); box->setSleepingColor(mSleepingColorDemo);
// Change the material properties of the rigid body // Change the material properties of the rigid body
rp3d::Material& material = box->getRigidBody()->getMaterial(); rp3d::Material& material = box->getRigidBody()->getMaterial();
@ -99,8 +99,8 @@ ConcaveMeshScene::ConcaveMeshScene(const std::string& name, EngineSettings& sett
sphere->getRigidBody()->getMaterial().setRollingResistance(rp3d::decimal(0.08)); sphere->getRigidBody()->getMaterial().setRollingResistance(rp3d::decimal(0.08));
// Set the box color // Set the box color
sphere->setColor(mDemoColors[i % mNbDemoColors]); sphere->setColor(mObjectColorDemo);
sphere->setSleepingColor(mRedColorDemo); sphere->setSleepingColor(mSleepingColorDemo);
// Change the material properties of the rigid body // Change the material properties of the rigid body
rp3d::Material& material = sphere->getRigidBody()->getMaterial(); rp3d::Material& material = sphere->getRigidBody()->getMaterial();
@ -121,8 +121,8 @@ ConcaveMeshScene::ConcaveMeshScene(const std::string& name, EngineSettings& sett
capsule->getRigidBody()->getMaterial().setRollingResistance(rp3d::decimal(0.08)); capsule->getRigidBody()->getMaterial().setRollingResistance(rp3d::decimal(0.08));
// Set the box color // Set the box color
capsule->setColor(mDemoColors[i % mNbDemoColors]); capsule->setColor(mObjectColorDemo);
capsule->setSleepingColor(mRedColorDemo); capsule->setSleepingColor(mSleepingColorDemo);
// Change the material properties of the rigid body // Change the material properties of the rigid body
rp3d::Material& material = capsule->getRigidBody()->getMaterial(); rp3d::Material& material = capsule->getRigidBody()->getMaterial();
@ -140,8 +140,8 @@ ConcaveMeshScene::ConcaveMeshScene(const std::string& name, EngineSettings& sett
ConvexMesh* mesh = new ConvexMesh(MESH_MASS, getDynamicsWorld(), meshFolderPath + "convexmesh.obj"); ConvexMesh* mesh = new ConvexMesh(MESH_MASS, getDynamicsWorld(), meshFolderPath + "convexmesh.obj");
// Set the box color // Set the box color
mesh->setColor(mDemoColors[i % mNbDemoColors]); mesh->setColor(mObjectColorDemo);
mesh->setSleepingColor(mRedColorDemo); mesh->setSleepingColor(mSleepingColorDemo);
// Change the material properties of the rigid body // Change the material properties of the rigid body
rp3d::Material& material = mesh->getRigidBody()->getMaterial(); rp3d::Material& material = mesh->getRigidBody()->getMaterial();
@ -164,8 +164,8 @@ ConcaveMeshScene::ConcaveMeshScene(const std::string& name, EngineSettings& sett
mConcaveMesh->getRigidBody()->setType(rp3d::BodyType::STATIC); mConcaveMesh->getRigidBody()->setType(rp3d::BodyType::STATIC);
// Set the box color // Set the box color
mConcaveMesh->setColor(mGreyColorDemo); mConcaveMesh->setColor(mFloorColorDemo);
mConcaveMesh->setSleepingColor(mGreyColorDemo); mConcaveMesh->setSleepingColor(mFloorColorDemo);
mPhysicsObjects.push_back(mConcaveMesh); mPhysicsObjects.push_back(mConcaveMesh);

View File

@ -1,139 +1,139 @@
/******************************************************************************** /********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com * * ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2016 Daniel Chappuis * * Copyright (c) 2010-2016 Daniel Chappuis *
********************************************************************************* *********************************************************************************
* * * *
* This software is provided 'as-is', without any express or implied warranty. * * This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the * * In no event will the authors be held liable for any damages arising from the *
* use of this software. * * use of this software. *
* * * *
* Permission is granted to anyone to use this software for any purpose, * * Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it * * including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: * * freely, subject to the following restrictions: *
* * * *
* 1. The origin of this software must not be misrepresented; you must not claim * * 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a * * that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be * * product, an acknowledgment in the product documentation would be *
* appreciated but is not required. * * appreciated but is not required. *
* * * *
* 2. Altered source versions must be plainly marked as such, and must not be * * 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. * * misrepresented as being the original software. *
* * * *
* 3. This notice may not be removed or altered from any source distribution. * * 3. This notice may not be removed or altered from any source distribution. *
* * * *
********************************************************************************/ ********************************************************************************/
// Libraries // Libraries
#include "CubesScene.h" #include "CubesScene.h"
// Namespaces // Namespaces
using namespace openglframework; using namespace openglframework;
using namespace cubesscene; using namespace cubesscene;
// Constructor // Constructor
CubesScene::CubesScene(const std::string& name, EngineSettings& settings) CubesScene::CubesScene(const std::string& name, EngineSettings& settings)
: SceneDemo(name, settings, SCENE_RADIUS) { : SceneDemo(name, settings, SCENE_RADIUS) {
// Compute the radius and the center of the scene // Compute the radius and the center of the scene
openglframework::Vector3 center(0, 5, 0); openglframework::Vector3 center(0, 5, 0);
// Set the center of the scene // Set the center of the scene
setScenePosition(center, SCENE_RADIUS); setScenePosition(center, SCENE_RADIUS);
// Gravity vector in the dynamics world // Gravity vector in the dynamics world
rp3d::Vector3 gravity(0, rp3d::decimal(-9.81), 0); rp3d::Vector3 gravity(0, rp3d::decimal(-9.81), 0);
rp3d::WorldSettings worldSettings; rp3d::WorldSettings worldSettings;
worldSettings.worldName = name; worldSettings.worldName = name;
// Create the dynamics world for the physics simulation // Create the dynamics world for the physics simulation
mPhysicsWorld = new rp3d::DynamicsWorld(gravity, worldSettings); mPhysicsWorld = new rp3d::DynamicsWorld(gravity, worldSettings);
// Create all the cubes of the scene // Create all the cubes of the scene
for (int i=0; i<NB_CUBES; i++) { for (int i=0; i<NB_CUBES; i++) {
// Create a cube and a corresponding rigid in the dynamics world // Create a cube and a corresponding rigid in the dynamics world
Box* cube = new Box(BOX_SIZE, BOX_MASS, getDynamicsWorld(), mMeshFolderPath); Box* cube = new Box(BOX_SIZE, BOX_MASS, getDynamicsWorld(), mMeshFolderPath);
// Set the box color // Set the box color
cube->setColor(mDemoColors[i % mNbDemoColors]); cube->setColor(mObjectColorDemo);
cube->setSleepingColor(mRedColorDemo); cube->setSleepingColor(mSleepingColorDemo);
// Change the material properties of the rigid body // Change the material properties of the rigid body
rp3d::Material& material = cube->getRigidBody()->getMaterial(); rp3d::Material& material = cube->getRigidBody()->getMaterial();
material.setBounciness(rp3d::decimal(0.4)); material.setBounciness(rp3d::decimal(0.4));
// Add the box the list of box in the scene // Add the box the list of box in the scene
mBoxes.push_back(cube); mBoxes.push_back(cube);
mPhysicsObjects.push_back(cube); mPhysicsObjects.push_back(cube);
} }
// ------------------------- FLOOR ----------------------- // // ------------------------- FLOOR ----------------------- //
// Create the floor // Create the floor
mFloor = new Box(FLOOR_SIZE, FLOOR_MASS, getDynamicsWorld(), mMeshFolderPath); mFloor = new Box(FLOOR_SIZE, FLOOR_MASS, getDynamicsWorld(), mMeshFolderPath);
mFloor->setColor(mGreyColorDemo); mFloor->setColor(mFloorColorDemo);
mFloor->setSleepingColor(mGreyColorDemo); mFloor->setSleepingColor(mFloorColorDemo);
// The floor must be a static rigid body // The floor must be a static rigid body
mFloor->getRigidBody()->setType(rp3d::BodyType::STATIC); mFloor->getRigidBody()->setType(rp3d::BodyType::STATIC);
mPhysicsObjects.push_back(mFloor); mPhysicsObjects.push_back(mFloor);
// Get the physics engine parameters // Get the physics engine parameters
mEngineSettings.isGravityEnabled = getDynamicsWorld()->isGravityEnabled(); mEngineSettings.isGravityEnabled = getDynamicsWorld()->isGravityEnabled();
rp3d::Vector3 gravityVector = getDynamicsWorld()->getGravity(); rp3d::Vector3 gravityVector = getDynamicsWorld()->getGravity();
mEngineSettings.gravity = openglframework::Vector3(gravityVector.x, gravityVector.y, gravityVector.z); mEngineSettings.gravity = openglframework::Vector3(gravityVector.x, gravityVector.y, gravityVector.z);
mEngineSettings.isSleepingEnabled = getDynamicsWorld()->isSleepingEnabled(); mEngineSettings.isSleepingEnabled = getDynamicsWorld()->isSleepingEnabled();
mEngineSettings.sleepLinearVelocity = getDynamicsWorld()->getSleepLinearVelocity(); mEngineSettings.sleepLinearVelocity = getDynamicsWorld()->getSleepLinearVelocity();
mEngineSettings.sleepAngularVelocity = getDynamicsWorld()->getSleepAngularVelocity(); mEngineSettings.sleepAngularVelocity = getDynamicsWorld()->getSleepAngularVelocity();
mEngineSettings.nbPositionSolverIterations = getDynamicsWorld()->getNbIterationsPositionSolver(); mEngineSettings.nbPositionSolverIterations = getDynamicsWorld()->getNbIterationsPositionSolver();
mEngineSettings.nbVelocitySolverIterations = getDynamicsWorld()->getNbIterationsVelocitySolver(); mEngineSettings.nbVelocitySolverIterations = getDynamicsWorld()->getNbIterationsVelocitySolver();
mEngineSettings.timeBeforeSleep = getDynamicsWorld()->getTimeBeforeSleep(); mEngineSettings.timeBeforeSleep = getDynamicsWorld()->getTimeBeforeSleep();
} }
// Destructor // Destructor
CubesScene::~CubesScene() { CubesScene::~CubesScene() {
// Destroy all the cubes of the scene // Destroy all the cubes of the scene
for (std::vector<Box*>::iterator it = mBoxes.begin(); it != mBoxes.end(); ++it) { for (std::vector<Box*>::iterator it = mBoxes.begin(); it != mBoxes.end(); ++it) {
// Destroy the corresponding rigid body from the dynamics world // Destroy the corresponding rigid body from the dynamics world
getDynamicsWorld()->destroyRigidBody((*it)->getRigidBody()); getDynamicsWorld()->destroyRigidBody((*it)->getRigidBody());
// Destroy the cube // Destroy the cube
delete (*it); delete (*it);
} }
// Destroy the rigid body of the floor // Destroy the rigid body of the floor
getDynamicsWorld()->destroyRigidBody(mFloor->getRigidBody()); getDynamicsWorld()->destroyRigidBody(mFloor->getRigidBody());
// Destroy the floor // Destroy the floor
delete mFloor; delete mFloor;
// Destroy the dynamics world // Destroy the dynamics world
delete getDynamicsWorld(); delete getDynamicsWorld();
} }
// Reset the scene // Reset the scene
void CubesScene::reset() { void CubesScene::reset() {
float radius = 2.0f; float radius = 2.0f;
// Create all the cubes of the scene // Create all the cubes of the scene
std::vector<Box*>::iterator it; std::vector<Box*>::iterator it;
int i = 0; int i = 0;
for (it = mBoxes.begin(); it != mBoxes.end(); ++it) { for (it = mBoxes.begin(); it != mBoxes.end(); ++it) {
// Position of the cubes // Position of the cubes
float angle = i * 30.0f; float angle = i * 30.0f;
rp3d::Vector3 position(radius * std::cos(angle), rp3d::Vector3 position(radius * std::cos(angle),
10 + i * (BOX_SIZE.y + 0.3f), 10 + i * (BOX_SIZE.y + 0.3f),
0); 0);
(*it)->setTransform(rp3d::Transform(position, rp3d::Quaternion::identity())); (*it)->setTransform(rp3d::Transform(position, rp3d::Quaternion::identity()));
i++; i++;
} }
mFloor->setTransform(rp3d::Transform(rp3d::Vector3::zero(), rp3d::Quaternion::identity())); mFloor->setTransform(rp3d::Transform(rp3d::Vector3::zero(), rp3d::Quaternion::identity()));
} }

View File

@ -58,8 +58,8 @@ CubeStackScene::CubeStackScene(const std::string& name, EngineSettings& settings
Box* cube = new Box(BOX_SIZE, BOX_MASS, getDynamicsWorld(), mMeshFolderPath); Box* cube = new Box(BOX_SIZE, BOX_MASS, getDynamicsWorld(), mMeshFolderPath);
// Set the box color // Set the box color
cube->setColor(mDemoColors[i % mNbDemoColors]); cube->setColor(mObjectColorDemo);
cube->setSleepingColor(mRedColorDemo); cube->setSleepingColor(mSleepingColorDemo);
// Change the material properties of the rigid body // Change the material properties of the rigid body
rp3d::Material& material = cube->getRigidBody()->getMaterial(); rp3d::Material& material = cube->getRigidBody()->getMaterial();
@ -75,8 +75,8 @@ CubeStackScene::CubeStackScene(const std::string& name, EngineSettings& settings
// Create the floor // Create the floor
mFloor = new Box(FLOOR_SIZE, FLOOR_MASS, getDynamicsWorld(), mMeshFolderPath); mFloor = new Box(FLOOR_SIZE, FLOOR_MASS, getDynamicsWorld(), mMeshFolderPath);
mFloor->setColor(mGreyColorDemo); mFloor->setColor(mFloorColorDemo);
mFloor->setSleepingColor(mGreyColorDemo); mFloor->setSleepingColor(mFloorColorDemo);
// The floor must be a static rigid body // The floor must be a static rigid body
mFloor->getRigidBody()->setType(rp3d::BodyType::STATIC); mFloor->getRigidBody()->setType(rp3d::BodyType::STATIC);

View File

@ -57,8 +57,8 @@ HeightFieldScene::HeightFieldScene(const std::string& name, EngineSettings& sett
Dumbbell* dumbbell = new Dumbbell(getDynamicsWorld(), meshFolderPath); Dumbbell* dumbbell = new Dumbbell(getDynamicsWorld(), meshFolderPath);
// Set the box color // Set the box color
dumbbell->setColor(mDemoColors[i % mNbDemoColors]); dumbbell->setColor(mObjectColorDemo);
dumbbell->setSleepingColor(mRedColorDemo); dumbbell->setSleepingColor(mSleepingColorDemo);
// Change the material properties of the rigid body // Change the material properties of the rigid body
rp3d::Material& material = dumbbell->getRigidBody()->getMaterial(); rp3d::Material& material = dumbbell->getRigidBody()->getMaterial();
@ -76,8 +76,8 @@ HeightFieldScene::HeightFieldScene(const std::string& name, EngineSettings& sett
Box* box = new Box(BOX_SIZE, BOX_MASS, getDynamicsWorld(), mMeshFolderPath); Box* box = new Box(BOX_SIZE, BOX_MASS, getDynamicsWorld(), mMeshFolderPath);
// Set the box color // Set the box color
box->setColor(mDemoColors[i % mNbDemoColors]); box->setColor(mObjectColorDemo);
box->setSleepingColor(mRedColorDemo); box->setSleepingColor(mSleepingColorDemo);
// Change the material properties of the rigid body // Change the material properties of the rigid body
rp3d::Material& material = box->getRigidBody()->getMaterial(); rp3d::Material& material = box->getRigidBody()->getMaterial();
@ -98,8 +98,8 @@ HeightFieldScene::HeightFieldScene(const std::string& name, EngineSettings& sett
sphere->getRigidBody()->getMaterial().setRollingResistance(0.08f); sphere->getRigidBody()->getMaterial().setRollingResistance(0.08f);
// Set the box color // Set the box color
sphere->setColor(mDemoColors[i % mNbDemoColors]); sphere->setColor(mObjectColorDemo);
sphere->setSleepingColor(mRedColorDemo); sphere->setSleepingColor(mSleepingColorDemo);
// Change the material properties of the rigid body // Change the material properties of the rigid body
rp3d::Material& material = sphere->getRigidBody()->getMaterial(); rp3d::Material& material = sphere->getRigidBody()->getMaterial();
@ -120,8 +120,8 @@ HeightFieldScene::HeightFieldScene(const std::string& name, EngineSettings& sett
capsule->getRigidBody()->getMaterial().setRollingResistance(0.08f); capsule->getRigidBody()->getMaterial().setRollingResistance(0.08f);
// Set the box color // Set the box color
capsule->setColor(mDemoColors[i % mNbDemoColors]); capsule->setColor(mObjectColorDemo);
capsule->setSleepingColor(mRedColorDemo); capsule->setSleepingColor(mSleepingColorDemo);
// Change the material properties of the rigid body // Change the material properties of the rigid body
rp3d::Material& material = capsule->getRigidBody()->getMaterial(); rp3d::Material& material = capsule->getRigidBody()->getMaterial();
@ -139,8 +139,8 @@ HeightFieldScene::HeightFieldScene(const std::string& name, EngineSettings& sett
ConvexMesh* mesh = new ConvexMesh(MESH_MASS, getDynamicsWorld(), meshFolderPath + "convexmesh.obj"); ConvexMesh* mesh = new ConvexMesh(MESH_MASS, getDynamicsWorld(), meshFolderPath + "convexmesh.obj");
// Set the box color // Set the box color
mesh->setColor(mDemoColors[i % mNbDemoColors]); mesh->setColor(mObjectColorDemo);
mesh->setSleepingColor(mRedColorDemo); mesh->setSleepingColor(mSleepingColorDemo);
// Change the material properties of the rigid body // Change the material properties of the rigid body
rp3d::Material& material = mesh->getRigidBody()->getMaterial(); rp3d::Material& material = mesh->getRigidBody()->getMaterial();
@ -165,8 +165,8 @@ HeightFieldScene::HeightFieldScene(const std::string& name, EngineSettings& sett
mPhysicsObjects.push_back(mHeightField); mPhysicsObjects.push_back(mHeightField);
// Set the color // Set the color
mHeightField->setColor(mGreyColorDemo); mHeightField->setColor(mFloorColorDemo);
mHeightField->setSleepingColor(mGreyColorDemo); mHeightField->setSleepingColor(mFloorColorDemo);
// Change the material properties of the rigid body // Change the material properties of the rigid body
rp3d::Material& material = mHeightField->getRigidBody()->getMaterial(); rp3d::Material& material = mHeightField->getRigidBody()->getMaterial();

View File

@ -214,8 +214,8 @@ void JointsScene::createBallAndSocketJoints() {
mBallAndSocketJointChainBoxes[i]->setTransform(rp3d::Transform(positionBox, rp3d::Quaternion::identity())); mBallAndSocketJointChainBoxes[i]->setTransform(rp3d::Transform(positionBox, rp3d::Quaternion::identity()));
// Set the box color // Set the box color
mBallAndSocketJointChainBoxes[i]->setColor(mDemoColors[i % mNbDemoColors]); mBallAndSocketJointChainBoxes[i]->setColor(mObjectColorDemo);
mBallAndSocketJointChainBoxes[i]->setSleepingColor(mRedColorDemo); mBallAndSocketJointChainBoxes[i]->setSleepingColor(mSleepingColorDemo);
// The fist box cannot move (static body) // The fist box cannot move (static body)
if (i == 0) { if (i == 0) {
@ -266,8 +266,8 @@ void JointsScene::createSliderJoint() {
mSliderJointBottomBox->setTransform(rp3d::Transform(positionBox1, rp3d::Quaternion::identity())); mSliderJointBottomBox->setTransform(rp3d::Transform(positionBox1, rp3d::Quaternion::identity()));
// Set the box color // Set the box color
mSliderJointBottomBox->setColor(mBlueColorDemo); mSliderJointBottomBox->setColor(mObjectColorDemo);
mSliderJointBottomBox->setSleepingColor(mRedColorDemo); mSliderJointBottomBox->setSleepingColor(mSleepingColorDemo);
// The fist box cannot move // The fist box cannot move
mSliderJointBottomBox->getRigidBody()->setType(rp3d::BodyType::STATIC); mSliderJointBottomBox->getRigidBody()->setType(rp3d::BodyType::STATIC);
@ -288,8 +288,8 @@ void JointsScene::createSliderJoint() {
mSliderJointTopBox->setTransform(rp3d::Transform(positionBox2, rp3d::Quaternion::identity())); mSliderJointTopBox->setTransform(rp3d::Transform(positionBox2, rp3d::Quaternion::identity()));
// Set the box color // Set the box color
mSliderJointTopBox->setColor(mOrangeColorDemo); mSliderJointTopBox->setColor(mObjectColorDemo);
mSliderJointTopBox->setSleepingColor(mRedColorDemo); mSliderJointTopBox->setSleepingColor(mSleepingColorDemo);
// Change the material properties of the rigid body // Change the material properties of the rigid body
rp3d::Material& material2 = mSliderJointTopBox->getRigidBody()->getMaterial(); rp3d::Material& material2 = mSliderJointTopBox->getRigidBody()->getMaterial();
@ -330,8 +330,8 @@ void JointsScene::createPropellerHingeJoint() {
mPropellerBox->setTransform(rp3d::Transform(positionBox1, rp3d::Quaternion::identity())); mPropellerBox->setTransform(rp3d::Transform(positionBox1, rp3d::Quaternion::identity()));
// Set the box color // Set the box color
mPropellerBox->setColor(mYellowColorDemo); mPropellerBox->setColor(mObjectColorDemo);
mPropellerBox->setSleepingColor(mRedColorDemo); mPropellerBox->setSleepingColor(mSleepingColorDemo);
// Change the material properties of the rigid body // Change the material properties of the rigid body
rp3d::Material& material = mPropellerBox->getRigidBody()->getMaterial(); rp3d::Material& material = mPropellerBox->getRigidBody()->getMaterial();
@ -371,8 +371,8 @@ void JointsScene::createFixedJoints() {
mFixedJointBox1->setTransform(rp3d::Transform(positionBox1, rp3d::Quaternion::identity())); mFixedJointBox1->setTransform(rp3d::Transform(positionBox1, rp3d::Quaternion::identity()));
// Set the box color // Set the box color
mFixedJointBox1->setColor(mPinkColorDemo); mFixedJointBox1->setColor(mObjectColorDemo);
mFixedJointBox1->setSleepingColor(mRedColorDemo); mFixedJointBox1->setSleepingColor(mSleepingColorDemo);
// Change the material properties of the rigid body // Change the material properties of the rigid body
rp3d::Material& material1 = mFixedJointBox1->getRigidBody()->getMaterial(); rp3d::Material& material1 = mFixedJointBox1->getRigidBody()->getMaterial();
@ -389,8 +389,8 @@ void JointsScene::createFixedJoints() {
mFixedJointBox2->setTransform(rp3d::Transform(positionBox2, rp3d::Quaternion::identity())); mFixedJointBox2->setTransform(rp3d::Transform(positionBox2, rp3d::Quaternion::identity()));
// Set the box color // Set the box color
mFixedJointBox2->setColor(mBlueColorDemo); mFixedJointBox2->setColor(mObjectColorDemo);
mFixedJointBox2->setSleepingColor(mRedColorDemo); mFixedJointBox2->setSleepingColor(mSleepingColorDemo);
// Change the material properties of the rigid body // Change the material properties of the rigid body
rp3d::Material& material2 = mFixedJointBox2->getRigidBody()->getMaterial(); rp3d::Material& material2 = mFixedJointBox2->getRigidBody()->getMaterial();
@ -429,8 +429,8 @@ void JointsScene::createFloor() {
mFloor = new Box(FLOOR_SIZE, FLOOR_MASS, getDynamicsWorld(), mMeshFolderPath); mFloor = new Box(FLOOR_SIZE, FLOOR_MASS, getDynamicsWorld(), mMeshFolderPath);
// Set the box color // Set the box color
mFloor->setColor(mGreyColorDemo); mFloor->setColor(mFloorColorDemo);
mFloor->setSleepingColor(mGreyColorDemo); mFloor->setSleepingColor(mFloorColorDemo);
// The floor must be a static rigid body // The floor must be a static rigid body
mFloor->getRigidBody()->setType(rp3d::BodyType::STATIC); mFloor->getRigidBody()->setType(rp3d::BodyType::STATIC);

View File

@ -56,8 +56,8 @@ RaycastScene::RaycastScene(const std::string& name, EngineSettings& settings)
mDumbbell = new Dumbbell(mPhysicsWorld, mMeshFolderPath); mDumbbell = new Dumbbell(mPhysicsWorld, mMeshFolderPath);
// Set the box color // Set the box color
mDumbbell->setColor(mGreyColorDemo); mDumbbell->setColor(mObjectColorDemo);
mDumbbell->setSleepingColor(mRedColorDemo); mDumbbell->setSleepingColor(mSleepingColorDemo);
mPhysicsObjects.push_back(mDumbbell); mPhysicsObjects.push_back(mDumbbell);
// ---------- Box ---------- // // ---------- Box ---------- //
@ -67,8 +67,8 @@ RaycastScene::RaycastScene(const std::string& name, EngineSettings& settings)
mBox->getCollisionBody()->setIsActive(false); mBox->getCollisionBody()->setIsActive(false);
// Set the box color // Set the box color
mBox->setColor(mGreyColorDemo); mBox->setColor(mObjectColorDemo);
mBox->setSleepingColor(mRedColorDemo); mBox->setSleepingColor(mSleepingColorDemo);
mPhysicsObjects.push_back(mBox); mPhysicsObjects.push_back(mBox);
// ---------- Sphere ---------- // // ---------- Sphere ---------- //
@ -77,8 +77,8 @@ RaycastScene::RaycastScene(const std::string& name, EngineSettings& settings)
mSphere = new Sphere(SPHERE_RADIUS, mPhysicsWorld, mMeshFolderPath); mSphere = new Sphere(SPHERE_RADIUS, mPhysicsWorld, mMeshFolderPath);
// Set the color // Set the color
mSphere->setColor(mGreyColorDemo); mSphere->setColor(mObjectColorDemo);
mSphere->setSleepingColor(mRedColorDemo); mSphere->setSleepingColor(mSleepingColorDemo);
mPhysicsObjects.push_back(mSphere); mPhysicsObjects.push_back(mSphere);
// ---------- Capsule ---------- // // ---------- Capsule ---------- //
@ -88,8 +88,8 @@ RaycastScene::RaycastScene(const std::string& name, EngineSettings& settings)
mCapsule = new Capsule(CAPSULE_RADIUS, CAPSULE_HEIGHT, mPhysicsWorld, mMeshFolderPath); mCapsule = new Capsule(CAPSULE_RADIUS, CAPSULE_HEIGHT, mPhysicsWorld, mMeshFolderPath);
// Set the color // Set the color
mCapsule->setColor(mGreyColorDemo); mCapsule->setColor(mObjectColorDemo);
mCapsule->setSleepingColor(mRedColorDemo); mCapsule->setSleepingColor(mSleepingColorDemo);
mPhysicsObjects.push_back(mCapsule); mPhysicsObjects.push_back(mCapsule);
// ---------- Convex Mesh ---------- // // ---------- Convex Mesh ---------- //
@ -98,8 +98,8 @@ RaycastScene::RaycastScene(const std::string& name, EngineSettings& settings)
mConvexMesh = new ConvexMesh(mPhysicsWorld, mMeshFolderPath + "convexmesh.obj"); mConvexMesh = new ConvexMesh(mPhysicsWorld, mMeshFolderPath + "convexmesh.obj");
// Set the color // Set the color
mConvexMesh->setColor(mGreyColorDemo); mConvexMesh->setColor(mObjectColorDemo);
mConvexMesh->setSleepingColor(mRedColorDemo); mConvexMesh->setSleepingColor(mSleepingColorDemo);
mPhysicsObjects.push_back(mConvexMesh); mPhysicsObjects.push_back(mConvexMesh);
// ---------- Concave Mesh ---------- // // ---------- Concave Mesh ---------- //
@ -108,8 +108,8 @@ RaycastScene::RaycastScene(const std::string& name, EngineSettings& settings)
mConcaveMesh = new ConcaveMesh(mPhysicsWorld, mMeshFolderPath + "city.obj"); mConcaveMesh = new ConcaveMesh(mPhysicsWorld, mMeshFolderPath + "city.obj");
// Set the color // Set the color
mConcaveMesh->setColor(mGreyColorDemo); mConcaveMesh->setColor(mObjectColorDemo);
mConcaveMesh->setSleepingColor(mRedColorDemo); mConcaveMesh->setSleepingColor(mSleepingColorDemo);
mPhysicsObjects.push_back(mConcaveMesh); mPhysicsObjects.push_back(mConcaveMesh);
// ---------- Heightfield ---------- // // ---------- Heightfield ---------- //
@ -118,8 +118,8 @@ RaycastScene::RaycastScene(const std::string& name, EngineSettings& settings)
mHeightField = new HeightField(mPhysicsWorld); mHeightField = new HeightField(mPhysicsWorld);
// Set the color // Set the color
mHeightField->setColor(mGreyColorDemo); mHeightField->setColor(mObjectColorDemo);
mHeightField->setSleepingColor(mRedColorDemo); mHeightField->setSleepingColor(mObjectColorDemo);
mPhysicsObjects.push_back(mHeightField); mPhysicsObjects.push_back(mHeightField);
// Create the lines that will be used for raycasting // Create the lines that will be used for raycasting

View File

@ -1,103 +1,115 @@
#version 330 #version 330
/******************************************************************************** /********************************************************************************
* OpenGL-Framework * * OpenGL-Framework *
* Copyright (c) 2015 Daniel Chappuis * * Copyright (c) 2015 Daniel Chappuis *
********************************************************************************* *********************************************************************************
* * * *
* This software is provided 'as-is', without any express or implied warranty. * * This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the * * In no event will the authors be held liable for any damages arising from the *
* use of this software. * * use of this software. *
* * * *
* Permission is granted to anyone to use this software for any purpose, * * Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it * * including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: * * freely, subject to the following restrictions: *
* * * *
* 1. The origin of this software must not be misrepresented; you must not claim * * 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a * * that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be * * product, an acknowledgment in the product documentation would be *
* appreciated but is not required. * * appreciated but is not required. *
* * * *
* 2. Altered source versions must be plainly marked as such, and must not be * * 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. * * misrepresented as being the original software. *
* * * *
* 3. This notice may not be removed or altered from any source distribution. * * 3. This notice may not be removed or altered from any source distribution. *
* * * *
********************************************************************************/ ********************************************************************************/
// Uniform variables // Uniform variables
uniform vec3 lightAmbientColor; // Lights ambient color uniform vec3 lightAmbientColor; // Lights ambient color
uniform vec3 light0PosCameraSpace; // Camera-space position of the light uniform vec3 light0PosCameraSpace; // Camera-space position of the light 0
uniform vec3 light0DiffuseColor; // Light 0 diffuse color uniform vec3 light1PosCameraSpace; // Camera-space position of the light 1
uniform sampler2D textureSampler; // Texture uniform vec3 light2PosCameraSpace; // Camera-space position of the light 2
uniform sampler2D shadowMapSampler; // Shadow map texture sampler uniform vec3 light0DiffuseColor; // Light 0 diffuse color
uniform bool isTexture; // True if we need to use the texture uniform vec3 light1DiffuseColor; // Light 1 diffuse color
uniform vec4 vertexColor; // Vertex color uniform vec3 light2DiffuseColor; // Light 2 diffuse color
uniform bool isShadowEnabled; // True if shadow mapping is enabled uniform sampler2D textureSampler; // Texture
uniform vec2 shadowMapDimension; // Shadow map dimension uniform sampler2D shadowMapSampler[3]; // Shadow map texture sampler
uniform bool isTexture; // True if we need to use the texture
// In variables uniform vec4 vertexColor; // Vertex color
in vec3 vertexPosCameraSpace; // Camera-space position of the vertex uniform bool isShadowEnabled; // True if shadow mapping is enabled
in vec3 vertexNormalCameraSpace; // Vertex normal in camera-space uniform vec2 shadowMapDimension; // Shadow map dimension
in vec2 texCoords; // Texture coordinates
in vec4 shadowMapCoords; // Shadow map texture coords // In variables
in vec3 vertexPosCameraSpace; // Camera-space position of the vertex
// Out variable in vec3 vertexNormalCameraSpace; // Vertex normal in camera-space
out vec4 color; // Output color in vec2 texCoords; // Texture coordinates
in vec4 shadowMapCoords[3]; // Shadow map texture coords
// Texture for PCF Shadow mapping
float textureLookupPCF(sampler2D map, vec2 texCoords, vec2 offset) // Out variable
{ out vec4 color; // Output color
vec2 shadowMapScale = vec2(1.0, 1.0) / shadowMapDimension;
return texture(map, texCoords.xy + offset * shadowMapScale).r; // Texture for PCF Shadow mapping
} float textureLookupPCF(sampler2D map, vec2 texCoords, vec2 offset)
{
void main() { vec2 shadowMapScale = vec2(1.0, 1.0) / shadowMapDimension;
return texture(map, texCoords.xy + offset * shadowMapScale).r;
// Compute the ambient term }
vec3 ambient = lightAmbientColor;
void main() {
// Get the texture color
vec3 textureColor = vertexColor.rgb; // Compute the ambient term
if (isTexture) textureColor = texture(textureSampler, texCoords).rgb; vec3 ambient = lightAmbientColor;
// Compute the surface normal vector // Get the texture color
vec3 N = normalize(vertexNormalCameraSpace); vec3 textureColor = vertexColor.rgb;
if (isTexture) textureColor = texture(textureSampler, texCoords).rgb;
// Compute the diffuse term of light 0
vec3 L0 = normalize(light0PosCameraSpace - vertexPosCameraSpace); // Compute the surface normal vector
float diffuseFactor = max(dot(N, L0), 0.0); vec3 N = normalize(vertexNormalCameraSpace);
vec3 diffuse = light0DiffuseColor * diffuseFactor * textureColor;
color = vec4(ambient, 1);
// Compute shadow factor
float shadow = 1.0; vec3 lightPosCameraSpace[3];
if (isShadowEnabled) { lightPosCameraSpace[0] = light0PosCameraSpace;
shadow = 0.0; lightPosCameraSpace[1] = light1PosCameraSpace;
float bias = 0.0003; lightPosCameraSpace[2] = light2PosCameraSpace;
float shadowBias = -0.000; vec3 lightDiffuseColor[3];
vec4 shadowMapUV = shadowMapCoords; lightDiffuseColor[0] = light0DiffuseColor;
shadowMapUV.z -= shadowBias; lightDiffuseColor[1] = light1DiffuseColor;
vec4 shadowMapCoordsOverW = shadowMapUV / shadowMapUV.w; lightDiffuseColor[2] = light2DiffuseColor;
// PCF Shadow Mapping // For each light source
for (float i=-1; i<=1; i++) { for (int l=0; l < 3; l++) {
for (float j=-1; j<=1; j++) {
float distInShadowMap = textureLookupPCF(shadowMapSampler, shadowMapCoordsOverW.xy, vec2(i, j)) + bias; // Compute the diffuse term of light 0
if (shadowMapCoords.w > 0) { vec3 L0 = normalize(lightPosCameraSpace[l] - vertexPosCameraSpace);
shadow += distInShadowMap < shadowMapCoordsOverW.z ? 0.5 : 1.0; float diffuseFactor = max(dot(N, L0), 0.0);
} vec3 diffuse = lightDiffuseColor[l] * diffuseFactor * textureColor;
}
} // Compute shadow factor
shadow /= 9.0; float shadow = 1.0;
if (isShadowEnabled) {
/* shadow = 0.0;
float distanceInShadowMap = texture(shadowMapSampler, shadowMapCoordsOverW.xy).r + bias; float bias = 0.0003;
if (shadowMapCoords.w > 0) { float shadowBias = -0.000;
shadow = distanceInShadowMap < shadowMapCoordsOverW.z ? 0.5 : 1.0; vec4 shadowMapUV = shadowMapCoords[l];
} shadowMapUV.z -= shadowBias;
*/ vec4 shadowMapCoordsOverW = shadowMapUV / shadowMapUV.w;
}
// PCF Shadow Mapping
// Compute the final color for (float i=-1; i<=1; i++) {
color = vec4(ambient + shadow * diffuse, 1.0); for (float j=-1; j<=1; j++) {
} float distInShadowMap = textureLookupPCF(shadowMapSampler[l], shadowMapCoordsOverW.xy, vec2(i, j)) + bias;
if (shadowMapCoords[l].w > 0) {
shadow += distInShadowMap < shadowMapCoordsOverW.z ? 0.5 : 1.0;
}
}
}
shadow /= 9.0;
}
// Compute the final color
color += vec4(shadow * diffuse, 0.0);
}
}

View File

@ -1,64 +1,78 @@
#version 330 #version 330
/******************************************************************************** /********************************************************************************
* OpenGL-Framework * * OpenGL-Framework *
* Copyright (c) 2015 Daniel Chappuis * * Copyright (c) 2015 Daniel Chappuis *
********************************************************************************* *********************************************************************************
* * * *
* This software is provided 'as-is', without any express or implied warranty. * * This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the * * In no event will the authors be held liable for any damages arising from the *
* use of this software. * * use of this software. *
* * * *
* Permission is granted to anyone to use this software for any purpose, * * Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it * * including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: * * freely, subject to the following restrictions: *
* * * *
* 1. The origin of this software must not be misrepresented; you must not claim * * 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a * * that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be * * product, an acknowledgment in the product documentation would be *
* appreciated but is not required. * * appreciated but is not required. *
* * * *
* 2. Altered source versions must be plainly marked as such, and must not be * * 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. * * misrepresented as being the original software. *
* * * *
* 3. This notice may not be removed or altered from any source distribution. * * 3. This notice may not be removed or altered from any source distribution. *
* * * *
********************************************************************************/ ********************************************************************************/
// Uniform variables // Uniform variables
uniform mat4 localToWorldMatrix; // Local-space to world-space matrix uniform mat4 localToWorldMatrix; // Local-space to world-space matrix
uniform mat4 worldToCameraMatrix; // World-space to camera-space matrix uniform mat4 worldToCameraMatrix; // World-space to camera-space matrix
uniform mat4 worldToLight0CameraMatrix; // World-space to light0 camera-space matrix (for shadow mapping) uniform mat4 worldToLight0CameraMatrix; // World-space to light0 camera-space matrix (for shadow mapping)
uniform mat4 projectionMatrix; // Projection matrix uniform mat4 worldToLight1CameraMatrix; // World-space to light1 camera-space matrix (for shadow mapping)
uniform mat3 normalMatrix; // Normal matrix uniform mat4 worldToLight2CameraMatrix; // World-space to light2 camera-space matrix (for shadow mapping)
uniform mat4 shadowMapProjectionMatrix; // Shadow map projection matrix uniform mat4 projectionMatrix; // Projection matrix
uniform mat3 normalMatrix; // Normal matrix
// In variables uniform mat4 shadowMapLight0ProjectionMatrix; // Shadow map projection matrix for light 0
in vec4 vertexPosition; uniform mat4 shadowMapLight1ProjectionMatrix; // Shadow map projection matrix for light 1
in vec3 vertexNormal; uniform mat4 shadowMapLight2ProjectionMatrix; // Shadow map projection matrix for light 2
in vec2 textureCoords;
// In variables
// Out variables in vec4 vertexPosition;
out vec3 vertexPosCameraSpace; // Camera-space position of the vertex in vec3 vertexNormal;
out vec3 vertexNormalCameraSpace; // Vertex normal in camera-space in vec2 textureCoords;
out vec2 texCoords; // Texture coordinates
out vec4 shadowMapCoords; // Shadow map texture coords // Out variables
out vec3 vertexPosCameraSpace; // Camera-space position of the vertex
void main() { out vec3 vertexNormalCameraSpace; // Vertex normal in camera-space
out vec2 texCoords; // Texture coordinates
// Compute the vertex position out vec4 shadowMapCoords[3]; // Shadow map texture coords
vec4 positionCameraSpace = worldToCameraMatrix * localToWorldMatrix * vertexPosition;
vertexPosCameraSpace = positionCameraSpace.xyz; void main() {
// Compute the world surface normal // Compute the vertex position
vertexNormalCameraSpace = normalMatrix * vertexNormal; vec4 positionCameraSpace = worldToCameraMatrix * localToWorldMatrix * vertexPosition;
vertexPosCameraSpace = positionCameraSpace.xyz;
// Get the texture coordinates
texCoords = textureCoords; // Compute the world surface normal
vertexNormalCameraSpace = normalMatrix * vertexNormal;
// Compute the texture coords of the vertex in the shadow map
shadowMapCoords = shadowMapProjectionMatrix * worldToLight0CameraMatrix * localToWorldMatrix * vertexPosition; // Get the texture coordinates
texCoords = textureCoords;
// Compute the clip-space vertex coordinates
gl_Position = projectionMatrix * positionCameraSpace; // Compute the texture coords of the vertex in the shadow map
} mat4 worldToLightCameraMatrix[3];
worldToLightCameraMatrix[0] = worldToLight0CameraMatrix;
worldToLightCameraMatrix[1] = worldToLight1CameraMatrix;
worldToLightCameraMatrix[2] = worldToLight2CameraMatrix;
mat4 shadowMapProjectionMatrix[3];
shadowMapProjectionMatrix[0] = shadowMapLight0ProjectionMatrix;
shadowMapProjectionMatrix[1] = shadowMapLight1ProjectionMatrix;
shadowMapProjectionMatrix[2] = shadowMapLight2ProjectionMatrix;
for (int l=0; l < 3; l++) {
shadowMapCoords[l] = shadowMapProjectionMatrix[l] * worldToLightCameraMatrix[l] * localToWorldMatrix * vertexPosition;
}
// Compute the clip-space vertex coordinates
gl_Position = projectionMatrix * positionCameraSpace;
}

View File

@ -1,49 +1,64 @@
/******************************************************************************** /********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com * * ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2016 Daniel Chappuis * * Copyright (c) 2010-2016 Daniel Chappuis *
********************************************************************************* *********************************************************************************
* * * *
* This software is provided 'as-is', without any express or implied warranty. * * This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the * * In no event will the authors be held liable for any damages arising from the *
* use of this software. * * use of this software. *
* * * *
* Permission is granted to anyone to use this software for any purpose, * * Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it * * including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: * * freely, subject to the following restrictions: *
* * * *
* 1. The origin of this software must not be misrepresented; you must not claim * * 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a * * that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be * * product, an acknowledgment in the product documentation would be *
* appreciated but is not required. * * appreciated but is not required. *
* * * *
* 2. Altered source versions must be plainly marked as such, and must not be * * 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. * * misrepresented as being the original software. *
* * * *
* 3. This notice may not be removed or altered from any source distribution. * * 3. This notice may not be removed or altered from any source distribution. *
* * * *
********************************************************************************/ ********************************************************************************/
// Libraries // Libraries
#include "TestbedApplication.h" #include "TestbedApplication.h"
#include "nanogui/nanogui.h" #include "nanogui/nanogui.h"
using namespace nanogui; using namespace nanogui;
// Main function // Main function
int main(int argc, char** argv) { int main(int argc, char** argv) {
nanogui::init(); nanogui::init();
{ {
// Create and start the testbed application bool isFullscreen = false;
bool isFullscreen = false;
nanogui::ref<TestbedApplication> application = new TestbedApplication(isFullscreen); // Get the primary monitor
application->setVisible(true); GLFWmonitor* monitor = glfwGetPrimaryMonitor();
const GLFWvidmode* mode = glfwGetVideoMode(monitor);
nanogui::mainloop();
} // Window size
int windowWidth = mode->width;
nanogui::shutdown(); int windowHeight = mode->height;
return 0; if (!isFullscreen) {
}
windowWidth *= 0.9;
windowHeight *= 0.9;
}
// Create and start the testbed application
nanogui::ref<TestbedApplication> application = new TestbedApplication(isFullscreen, windowWidth, windowHeight);
application->setVisible(true);
nanogui::mainloop();
}
nanogui::shutdown();
return 0;
}

View File

@ -1,460 +1,522 @@
/******************************************************************************** /********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com * * ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2016 Daniel Chappuis * * Copyright (c) 2010-2016 Daniel Chappuis *
********************************************************************************* *********************************************************************************
* * * *
* This software is provided 'as-is', without any express or implied warranty. * * This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the * * In no event will the authors be held liable for any damages arising from the *
* use of this software. * * use of this software. *
* * * *
* Permission is granted to anyone to use this software for any purpose, * * Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it * * including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: * * freely, subject to the following restrictions: *
* * * *
* 1. The origin of this software must not be misrepresented; you must not claim * * 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a * * that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be * * product, an acknowledgment in the product documentation would be *
* appreciated but is not required. * * appreciated but is not required. *
* * * *
* 2. Altered source versions must be plainly marked as such, and must not be * * 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. * * misrepresented as being the original software. *
* * * *
* 3. This notice may not be removed or altered from any source distribution. * * 3. This notice may not be removed or altered from any source distribution. *
* * * *
********************************************************************************/ ********************************************************************************/
// Libraries // Libraries
#include "SceneDemo.h" #include "SceneDemo.h"
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#include "AABB.h" #include "AABB.h"
#include "constraint/ContactPoint.h" #include "constraint/ContactPoint.h"
#include "collision/ContactManifold.h" #include "collision/ContactManifold.h"
using namespace openglframework; using namespace openglframework;
int SceneDemo::shadowMapTextureLevel = 0; int SceneDemo::shadowMapTextureLevel = 0;
openglframework::Color SceneDemo::mGreyColorDemo = Color(0.70f, 0.70f, 0.7f, 1.0f); openglframework::Color SceneDemo::mObjectColorDemo = Color(0.76f, 0.67f, 0.47f, 1.0f);
openglframework::Color SceneDemo::mYellowColorDemo = Color(0.9f, 0.88f, 0.145f, 1.0f); openglframework::Color SceneDemo::mFloorColorDemo = Color(0.47f, 0.48f, 0.49f, 1.0f);
openglframework::Color SceneDemo::mBlueColorDemo = Color(0, 0.66f, 0.95f, 1.0f); openglframework::Color SceneDemo::mSleepingColorDemo = Color(1.0f, 0.25f, 0.25f, 1.0f);
openglframework::Color SceneDemo::mOrangeColorDemo = Color(0.9f, 0.35f, 0, 1.0f); openglframework::Color SceneDemo::mSelectedObjectColorDemo = Color(0.09f, 0.59f, 0.88f, 1.0f);
openglframework::Color SceneDemo::mPinkColorDemo = Color(0.83f, 0.48f, 0.64f, 1.0f);
openglframework::Color SceneDemo::mRedColorDemo = Color(0.95f, 0, 0, 1.0f); // Constructor
int SceneDemo::mNbDemoColors = 4; SceneDemo::SceneDemo(const std::string& name, EngineSettings& settings, float sceneRadius, bool isShadowMappingEnabled)
openglframework::Color SceneDemo::mDemoColors[] = {SceneDemo::mYellowColorDemo, SceneDemo::mBlueColorDemo, : Scene(name, settings, isShadowMappingEnabled), mIsShadowMappingInitialized(false),
SceneDemo::mOrangeColorDemo, SceneDemo::mPinkColorDemo}; mDepthShader("shaders/depth.vert", "shaders/depth.frag"),
mPhongShader("shaders/phong.vert", "shaders/phong.frag"),
// Constructor mColorShader("shaders/color.vert", "shaders/color.frag"),
SceneDemo::SceneDemo(const std::string& name, EngineSettings& settings, float sceneRadius, bool isShadowMappingEnabled) mQuadShader("shaders/quad.vert", "shaders/quad.frag"),
: Scene(name, settings, isShadowMappingEnabled), mIsShadowMappingInitialized(false), mVBOQuad(GL_ARRAY_BUFFER), mMeshFolderPath("meshes/"),
mDepthShader("shaders/depth.vert", "shaders/depth.frag"), mPhysicsWorld(nullptr) {
mPhongShader("shaders/phong.vert", "shaders/phong.frag"),
mColorShader("shaders/color.vert", "shaders/color.frag"), shadowMapTextureLevel++;
mQuadShader("shaders/quad.vert", "shaders/quad.frag"),
mVBOQuad(GL_ARRAY_BUFFER), mMeshFolderPath("meshes/"), // Move the lights
mPhysicsWorld(nullptr) { float lightsRadius = 30.0f;
float lightsHeight = 20.0f;
shadowMapTextureLevel++; mLight0.translateWorld(Vector3(0 * lightsRadius, lightsHeight, 1 * lightsRadius));
mLight1.translateWorld(Vector3(0.95f * lightsRadius, lightsHeight, -0.3f * lightsRadius));
// Move the light0 mLight2.translateWorld(Vector3(-0.58f * lightsRadius, lightsHeight, -0.81f * lightsRadius));
mLight0.translateWorld(Vector3(-2, 35, 40));
// Set the lights colors
// Camera at light0 postion for the shadow map mLight0.setDiffuseColor(Color(0.6f, 0.6f, 0.6f, 1.0f));
mShadowMapLightCamera.translateWorld(mLight0.getOrigin()); mLight1.setDiffuseColor(Color(0.6f, 0.6f, 0.6f, 1.0f));
mShadowMapLightCamera.rotateLocal(Vector3(1, 0, 0), -PI / 4.0f); mLight2.setDiffuseColor(Color(0.6f, 0.6f, 0.6f, 1.0f));
mShadowMapLightCamera.rotateWorld(Vector3(0, 1, 0), PI / 8.0f);
mShadowMapLightCameras[0].translateWorld(mLight0.getOrigin());
mShadowMapLightCamera.setDimensions(SHADOWMAP_WIDTH, SHADOWMAP_HEIGHT); mShadowMapLightCameras[0].rotateLocal(Vector3(1, 0, 0), -PI / 4.0f);
mShadowMapLightCamera.setFieldOfView(80.0f);
mShadowMapLightCamera.setSceneRadius(100); mShadowMapLightCameras[1].translateWorld(mLight1.getOrigin());
mShadowMapLightCameras[1].rotateLocal(Vector3(0, 1, 0), -5.0f * PI/3.7f);
mShadowMapBiasMatrix.setAllValues(0.5, 0.0, 0.0, 0.5, mShadowMapLightCameras[1].rotateLocal(Vector3(1, 0, 0), -PI/4.0f);
0.0, 0.5, 0.0, 0.5,
0.0, 0.0, 0.5, 0.5, mShadowMapLightCameras[2].translateWorld(mLight2.getOrigin());
0.0, 0.0, 0.0, 1.0); mShadowMapLightCameras[2].rotateLocal(Vector3(0, 1, 0), 5 * PI/4.0f);
mShadowMapLightCameras[2].rotateLocal(Vector3(1, 0 , 0), -PI/4.0f);
// Create the Shadow map FBO and texture
if (mIsShadowMappingEnabled) { for (int i = 0; i < NB_SHADOW_MAPS; i++) {
createShadowMapFBOAndTexture(); mShadowMapLightCameras[i].setDimensions(SHADOWMAP_WIDTH, SHADOWMAP_HEIGHT);
} mShadowMapLightCameras[i].setFieldOfView(100.0f);
mShadowMapLightCameras[i].setSceneRadius(100);
createQuadVBO(); }
// Init rendering for the AABBs mShadowMapBiasMatrix.setAllValues(0.5, 0.0, 0.0, 0.5,
AABB::init(); 0.0, 0.5, 0.0, 0.5,
0.0, 0.0, 0.5, 0.5,
VisualContactPoint::createStaticData(mMeshFolderPath); 0.0, 0.0, 0.0, 1.0);
}
// Create the Shadow map FBO and texture
// Destructor if (mIsShadowMappingEnabled) {
SceneDemo::~SceneDemo() { createShadowMapFBOAndTexture();
}
mShadowMapTexture.destroy();
mFBOShadowMap.destroy(); createQuadVBO();
mVBOQuad.destroy();
// Init rendering for the AABBs
mDepthShader.destroy(); AABB::init();
mPhongShader.destroy();
mQuadShader.destroy(); VisualContactPoint::createStaticData(mMeshFolderPath);
mColorShader.destroy(); }
// Destroy the contact points // Destructor
removeAllContactPoints(); SceneDemo::~SceneDemo() {
// Destroy rendering data for the AABB
AABB::destroy(); for (int i = 0; i < NB_SHADOW_MAPS; i++) {
mShadowMapTexture[i].destroy();
VisualContactPoint::destroyStaticData(); mFBOShadowMap[i].destroy();
} }
// Update the scene mVBOQuad.destroy();
void SceneDemo::update() {
mDepthShader.destroy();
// Update the contact points mPhongShader.destroy();
updateContactPoints(); mQuadShader.destroy();
mColorShader.destroy();
// Update the position and orientation of the physics objects
for (std::vector<PhysicsObject*>::iterator it = mPhysicsObjects.begin(); it != mPhysicsObjects.end(); ++it) { // Destroy the contact points
removeAllContactPoints();
// Update the transform used for the rendering
(*it)->updateTransform(mInterpolationFactor); // Destroy rendering data for the AABB
} AABB::destroy();
}
VisualContactPoint::destroyStaticData();
// Update the physics world (take a simulation step) }
// Can be called several times per frame
void SceneDemo::updatePhysics() { // Update the scene
void SceneDemo::update() {
if (getDynamicsWorld() != nullptr) {
// Update the contact points
// Take a simulation step updateContactPoints();
getDynamicsWorld()->update(mEngineSettings.timeStep);
} // Update the position and orientation of the physics objects
} for (std::vector<PhysicsObject*>::iterator it = mPhysicsObjects.begin(); it != mPhysicsObjects.end(); ++it) {
// Render the scene (in multiple passes for shadow mapping) // Update the transform used for the rendering
void SceneDemo::render() { (*it)->updateTransform(mInterpolationFactor);
}
const Color& diffCol = mLight0.getDiffuseColor(); }
glEnable(GL_DEPTH_TEST); // Update the physics world (take a simulation step)
glEnable(GL_CULL_FACE); // Can be called several times per frame
void SceneDemo::updatePhysics() {
// ---------- Render the scene to generate the shadow map (first pass) ----------- //
if (getDynamicsWorld() != nullptr) {
const Matrix4 shadowMapProjMatrix = mShadowMapLightCamera.getProjectionMatrix();
const openglframework::Matrix4 worldToLightCameraMatrix = mShadowMapLightCamera.getTransformMatrix().getInverse(); // Take a simulation step
getDynamicsWorld()->update(mEngineSettings.timeStep);
// If Shadow Mapping is enabled }
if (mIsShadowMappingEnabled) { }
// Culling switching, rendering only backface, this is done to avoid self-shadowing // Render the scene (in multiple passes for shadow mapping)
glCullFace(GL_BACK); void SceneDemo::render() {
mFBOShadowMap.bind(); glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
// Bind the shader
mDepthShader.bind(); Matrix4 shadowMapProjMatrix[NB_SHADOW_MAPS];
openglframework::Matrix4 worldToLightCameraMatrix[NB_SHADOW_MAPS];
// Set the variables of the shader for (int i = 0; i < NB_SHADOW_MAPS; i++) {
mDepthShader.setMatrix4x4Uniform("projectionMatrix", shadowMapProjMatrix);
shadowMapProjMatrix[i] = mShadowMapLightCameras[i].getProjectionMatrix();
// Set the viewport to render into the shadow map texture worldToLightCameraMatrix[i] = mShadowMapLightCameras[i].getTransformMatrix().getInverse();
glViewport(0, 0, SHADOWMAP_WIDTH, SHADOWMAP_HEIGHT); }
// Clear previous frame values // ---------- Render the scene to generate the shadow map (first pass) ----------- //
glClear(GL_DEPTH_BUFFER_BIT);
// If Shadow Mapping is enabled
// Disable color rendering, we only want to write to the Z-Buffer if (mIsShadowMappingEnabled) {
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
// Culling switching, rendering only backface, this is done to avoid self-shadowing
// Render the objects of the scene glCullFace(GL_BACK);
renderSinglePass(mDepthShader, worldToLightCameraMatrix);
// For each shadow map
// Unbind the shader for (int i = 0; i < NB_SHADOW_MAPS; i++) {
mDepthShader.unbind();
mFBOShadowMap[i].bind();
mFBOShadowMap.unbind();
// Bind the shader
glDisable(GL_POLYGON_OFFSET_FILL); mDepthShader.bind();
}
// Set the variables of the shader
// ---------- Render the scene for final rendering (second pass) ----------- // mDepthShader.setMatrix4x4Uniform("projectionMatrix", shadowMapProjMatrix[i]);
glCullFace(GL_BACK); // Set the viewport to render into the shadow map texture
glViewport(0, 0, SHADOWMAP_WIDTH, SHADOWMAP_HEIGHT);
// Get the world-space to camera-space matrix
const openglframework::Matrix4 worldToCameraMatrix = mCamera.getTransformMatrix().getInverse(); // Clear previous frame values
glClear(GL_DEPTH_BUFFER_BIT);
mPhongShader.bind();
// Disable color rendering, we only want to write to the Z-Buffer
if (mIsShadowMappingEnabled) mShadowMapTexture.bind(); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
const GLuint textureUnit = 0;
// Render the objects of the scene
// Set the variables of the phong shader renderSinglePass(mDepthShader, worldToLightCameraMatrix[i]);
mPhongShader.setMatrix4x4Uniform("projectionMatrix", mCamera.getProjectionMatrix());
mPhongShader.setMatrix4x4Uniform("shadowMapProjectionMatrix", mShadowMapBiasMatrix * shadowMapProjMatrix); // Unbind the shader
mPhongShader.setMatrix4x4Uniform("worldToLight0CameraMatrix", worldToLightCameraMatrix); mDepthShader.unbind();
mPhongShader.setVector3Uniform("light0PosCameraSpace", worldToCameraMatrix * mLight0.getOrigin());
mPhongShader.setVector3Uniform("lightAmbientColor", Vector3(0.4f, 0.4f, 0.4f)); mFBOShadowMap[i].unbind();
mPhongShader.setVector3Uniform("light0DiffuseColor", Vector3(diffCol.r, diffCol.g, diffCol.b)); }
mPhongShader.setIntUniform("shadowMapSampler", textureUnit);
mPhongShader.setIntUniform("isShadowEnabled", mIsShadowMappingEnabled); glDisable(GL_POLYGON_OFFSET_FILL);
mPhongShader.setVector2Uniform("shadowMapDimension", Vector2(SHADOWMAP_WIDTH, SHADOWMAP_HEIGHT)); }
mPhongShader.unbind();
// ---------- Render the scene for final rendering (second pass) ----------- //
// Set the variables of the color shader
mColorShader.bind(); glCullFace(GL_BACK);
mColorShader.setMatrix4x4Uniform("projectionMatrix", mCamera.getProjectionMatrix());
mColorShader.unbind(); // Get the world-space to camera-space matrix
const openglframework::Matrix4 worldToCameraMatrix = mCamera.getTransformMatrix().getInverse();
// Set the viewport to render the scene
glViewport(mViewportX, mViewportY, mViewportWidth, mViewportHeight); mPhongShader.bind();
//Enabling color write (previously disabled for light POV z-buffer rendering) // Is shadow mapping is enabled
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); GLint textureUnits[NB_SHADOW_MAPS];
if (mIsShadowMappingEnabled) {
// Clear previous frame values
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); for (int i = 0; i < NB_SHADOW_MAPS; i++) {
mShadowMapTexture[i].bind();
// Render the objects of the scene }
renderSinglePass(mPhongShader, worldToCameraMatrix); for (int i = 0; i < NB_SHADOW_MAPS; i++) {
textureUnits[i] = mShadowMapTexture[i].getUnit();
// Render the contact points }
if (mIsContactPointsDisplayed) { }
renderContactPoints(mPhongShader, worldToCameraMatrix);
} // Set the variables of the phong shader
mPhongShader.setMatrix4x4Uniform("projectionMatrix", mCamera.getProjectionMatrix());
// Render the AABBs mPhongShader.setMatrix4x4Uniform("shadowMapLight0ProjectionMatrix", mShadowMapBiasMatrix * shadowMapProjMatrix[0]);
if (mIsAABBsDisplayed) { mPhongShader.setMatrix4x4Uniform("shadowMapLight1ProjectionMatrix", mShadowMapBiasMatrix * shadowMapProjMatrix[1]);
renderAABBs(worldToCameraMatrix); mPhongShader.setMatrix4x4Uniform("shadowMapLight2ProjectionMatrix", mShadowMapBiasMatrix * shadowMapProjMatrix[2]);
} mPhongShader.setMatrix4x4Uniform("worldToLight0CameraMatrix", worldToLightCameraMatrix[0]);
mPhongShader.setMatrix4x4Uniform("worldToLight1CameraMatrix", worldToLightCameraMatrix[1]);
if (mIsShadowMappingEnabled) mShadowMapTexture.unbind(); mPhongShader.setMatrix4x4Uniform("worldToLight2CameraMatrix", worldToLightCameraMatrix[2]);
mPhongShader.unbind(); mPhongShader.setVector3Uniform("light0PosCameraSpace", worldToCameraMatrix * mLight0.getOrigin());
mPhongShader.setVector3Uniform("light1PosCameraSpace", worldToCameraMatrix * mLight1.getOrigin());
//drawTextureQuad(); mPhongShader.setVector3Uniform("light2PosCameraSpace", worldToCameraMatrix * mLight2.getOrigin());
} mPhongShader.setVector3Uniform("lightAmbientColor", Vector3(0.3f, 0.3f, 0.3f));
mPhongShader.setVector3Uniform("light0DiffuseColor", Vector3(mLight0.getDiffuseColor().r, mLight0.getDiffuseColor().g, mLight0.getDiffuseColor().b));
// Render the scene in a single pass mPhongShader.setVector3Uniform("light1DiffuseColor", Vector3(mLight1.getDiffuseColor().r, mLight1.getDiffuseColor().g, mLight1.getDiffuseColor().b));
void SceneDemo::renderSinglePass(openglframework::Shader& shader, const openglframework::Matrix4& worldToCameraMatrix) { mPhongShader.setVector3Uniform("light2DiffuseColor", Vector3(mLight2.getDiffuseColor().r, mLight2.getDiffuseColor().g, mLight2.getDiffuseColor().b));
mPhongShader.setIntArrayUniform("shadowMapSampler", textureUnits, NB_SHADOW_MAPS);
if (mIsWireframeEnabled) { mPhongShader.setIntUniform("isShadowEnabled", mIsShadowMappingEnabled);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); mPhongShader.setVector2Uniform("shadowMapDimension", Vector2(SHADOWMAP_WIDTH, SHADOWMAP_HEIGHT));
} mPhongShader.unbind();
// Bind the shader // Set the variables of the color shader
shader.bind(); mColorShader.bind();
mColorShader.setMatrix4x4Uniform("projectionMatrix", mCamera.getProjectionMatrix());
// Render all the physics objects of the scene mColorShader.unbind();
for (std::vector<PhysicsObject*>::iterator it = mPhysicsObjects.begin(); it != mPhysicsObjects.end(); ++it) {
(*it)->render(mIsWireframeEnabled ? mColorShader : shader, worldToCameraMatrix); // Set the viewport to render the scene
} glViewport(mViewportX, mViewportY, mViewportWidth, mViewportHeight);
// Unbind the shader //Enabling color write (previously disabled for light POV z-buffer rendering)
shader.unbind(); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
if (mIsWireframeEnabled) { // Clear previous frame values
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
} // Render the objects of the scene
renderSinglePass(mPhongShader, worldToCameraMatrix);
// Create the Shadow map FBO and texture
void SceneDemo::createShadowMapFBOAndTexture() { // Render the contact points
if (mIsContactPointsDisplayed) {
// Create the texture for the depth values renderContactPoints(mPhongShader, worldToCameraMatrix);
mShadowMapTexture.create(SHADOWMAP_WIDTH, SHADOWMAP_HEIGHT, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, }
GL_UNSIGNED_BYTE, GL_NEAREST, GL_NEAREST, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, NULL);
// Render the AABBs
// Create the FBO for the shadow map if (mIsAABBsDisplayed) {
mFBOShadowMap.create(0, 0, false); renderAABBs(worldToCameraMatrix);
mFBOShadowMap.bind(); }
// Tell OpenGL that we won't bind a color texture with the currently binded FBO // Is shadow mapping is enabled
glDrawBuffer(GL_NONE); if (mIsShadowMappingEnabled) {
glReadBuffer(GL_NONE);
for (int i = 0; i < NB_SHADOW_MAPS; i++) {
mFBOShadowMap.attachTexture(GL_DEPTH_ATTACHMENT, mShadowMapTexture.getID()); mShadowMapTexture[i].unbind();
mFBOShadowMap.unbind(); }
}
mIsShadowMappingInitialized = true;
} mPhongShader.unbind();
// Used for debugging shadow maps //drawTextureQuad();
void SceneDemo::createQuadVBO() { }
mVAOQuad.create(); // Render the scene in a single pass
mVAOQuad.bind(); void SceneDemo::renderSinglePass(openglframework::Shader& shader, const openglframework::Matrix4& worldToCameraMatrix) {
static const GLfloat quadVertexData[] = { if (mIsWireframeEnabled) {
-1.0f, -1.0f, 0.0f, glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
1.0f, -1.0f, 0.0f, }
-1.0f, 1.0f, 0.0f,
-1.0f, 1.0f, 0.0f, // Bind the shader
1.0f, -1.0f, 0.0f, shader.bind();
1.0f, 1.0f, 0.0f,
}; // Render all the physics objects of the scene
for (std::vector<PhysicsObject*>::iterator it = mPhysicsObjects.begin(); it != mPhysicsObjects.end(); ++it) {
mVBOQuad.create(); (*it)->render(mIsWireframeEnabled ? mColorShader : shader, worldToCameraMatrix);
mVBOQuad.bind(); }
mVBOQuad.copyDataIntoVBO(sizeof(quadVertexData), quadVertexData, GL_STATIC_DRAW);
mVBOQuad.unbind(); // Unbind the shader
shader.unbind();
mVAOQuad.unbind();
} if (mIsWireframeEnabled) {
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
void SceneDemo::drawTextureQuad() { }
}
glViewport(mViewportX, mViewportY, mViewportWidth, mViewportHeight);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); // Create the Shadow map FBO and texture
void SceneDemo::createShadowMapFBOAndTexture() {
// Clear previous frame values
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // For each shadow map
for (int i = 0; i < NB_SHADOW_MAPS; i++) {
const GLuint textureUnit = 0;
// Create the texture for the depth values
mVAOQuad.bind(); mShadowMapTexture[i].create(SHADOWMAP_WIDTH, SHADOWMAP_HEIGHT, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT,
mQuadShader.bind(); GL_UNSIGNED_BYTE, GL_LINEAR, GL_LINEAR, GL_CLAMP_TO_BORDER, GL_CLAMP_TO_BORDER, NULL);
mShadowMapTexture.bind();
mQuadShader.setIntUniform("textureSampler", textureUnit); mShadowMapTexture[i].setUnit(i);
mVBOQuad.bind();
// Make sure that texture lookups outside the texture coords range will not
GLint vertexPositionLoc = mQuadShader.getAttribLocation("vertexPosition"); // treated as beeing in shadow
glEnableVertexAttribArray(vertexPositionLoc); glBindTexture(GL_TEXTURE_2D, mShadowMapTexture[i].getID());
GLfloat border[] = { 1.0f, 0.0f, 0.0f, 0.0f };
glVertexAttribPointer( glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border);
vertexPositionLoc, // attribute 0. No particular reason for 0, but must match the layout in the shader. glBindTexture(GL_TEXTURE_2D, 0);
3, // size
GL_FLOAT, // type // Create the FBO for the shadow map
GL_FALSE, // normalized? mFBOShadowMap[i].create(0, 0, false);
0, // stride mFBOShadowMap[i].bind();
(void*)0 // array buffer offset
); // Tell OpenGL that we won't bind a color texture with the currently binded FBO
glDrawBuffer(GL_NONE);
// Draw the triangles ! glReadBuffer(GL_NONE);
glDrawArrays(GL_TRIANGLES, 0, 6); // 2*3 indices starting at 0 -> 2 triangles
mFBOShadowMap[i].attachTexture(GL_DEPTH_ATTACHMENT, mShadowMapTexture[i].getID());
glDisableVertexAttribArray(vertexPositionLoc); mFBOShadowMap[i].unbind();
}
mVBOQuad.unbind();
mShadowMapTexture.unbind(); mIsShadowMappingInitialized = true;
mQuadShader.unbind(); }
mVAOQuad.unbind();
} // Used for debugging shadow maps
void SceneDemo::createQuadVBO() {
// Gather and create contact points
void SceneDemo::updateContactPoints() { mVAOQuad.create();
mVAOQuad.bind();
// Remove the previous contact points
removeAllContactPoints(); static const GLfloat quadVertexData[] = {
-1.0f, -1.0f, 0.0f,
if (mIsContactPointsDisplayed) { 1.0f, -1.0f, 0.0f,
-1.0f, 1.0f, 0.0f,
// Get the current contact points of the scene -1.0f, 1.0f, 0.0f,
std::vector<ContactPoint> contactPoints = getContactPoints(); 1.0f, -1.0f, 0.0f,
1.0f, 1.0f, 0.0f,
// For each contact point };
std::vector<ContactPoint>::const_iterator it;
for (it = contactPoints.begin(); it != contactPoints.end(); ++it) { mVBOQuad.create();
mVBOQuad.bind();
// Create a visual contact point for rendering mVBOQuad.copyDataIntoVBO(sizeof(quadVertexData), quadVertexData, GL_STATIC_DRAW);
VisualContactPoint* point = new VisualContactPoint(it->point, mMeshFolderPath, it->point + it->normal, it->color); mVBOQuad.unbind();
mContactPoints.push_back(point);
} mVAOQuad.unbind();
} }
}
void SceneDemo::drawTextureQuad() {
// Render the contact points
void SceneDemo::renderContactPoints(openglframework::Shader& shader, const openglframework::Matrix4& worldToCameraMatrix) { glViewport(mViewportX, mViewportY, mViewportWidth, mViewportHeight);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
// Render all the contact points
for (std::vector<VisualContactPoint*>::iterator it = mContactPoints.begin(); // Clear previous frame values
it != mContactPoints.end(); ++it) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
(*it)->render(mColorShader, worldToCameraMatrix);
}
} const int SHADOW_MAP_TEXTURE_TO_DRAW = 0;
const GLuint textureUnit = SHADOW_MAP_TEXTURE_TO_DRAW;
// Render the AABBs
void SceneDemo::renderAABBs(const openglframework::Matrix4& worldToCameraMatrix) { mVAOQuad.bind();
mQuadShader.bind();
// For each physics object of the scene mShadowMapTexture[SHADOW_MAP_TEXTURE_TO_DRAW].bind();
for (std::vector<PhysicsObject*>::iterator it = mPhysicsObjects.begin(); it != mPhysicsObjects.end(); ++it) { mQuadShader.setIntUniform("textureSampler", textureUnit);
mVBOQuad.bind();
// For each proxy shape of the object
rp3d::ProxyShape* proxyShape = (*it)->getCollisionBody()->getProxyShapesList(); GLint vertexPositionLoc = mQuadShader.getAttribLocation("vertexPosition");
while (proxyShape != nullptr) { glEnableVertexAttribArray(vertexPositionLoc);
// Get the broad-phase AABB corresponding to the proxy shape glVertexAttribPointer(
rp3d::AABB aabb = mPhysicsWorld->getWorldAABB(proxyShape); vertexPositionLoc, // attribute 0. No particular reason for 0, but must match the layout in the shader.
3, // size
openglframework::Vector3 aabbCenter(aabb.getCenter().x, aabb.getCenter().y, aabb.getCenter().z); GL_FLOAT, // type
openglframework::Vector3 aabbMin(aabb.getMin().x, aabb.getMin().y, aabb.getMin().z); GL_FALSE, // normalized?
openglframework::Vector3 aabbMax(aabb.getMax().x, aabb.getMax().y, aabb.getMax().z); 0, // stride
(void*)0 // array buffer offset
// Render the AABB );
AABB::render(aabbCenter, aabbMax - aabbMin, Color::green(), mColorShader, worldToCameraMatrix);
// Draw the triangles !
proxyShape = proxyShape->getNext(); glDrawArrays(GL_TRIANGLES, 0, 6); // 2*3 indices starting at 0 -> 2 triangles
}
} glDisableVertexAttribArray(vertexPositionLoc);
}
mVBOQuad.unbind();
void SceneDemo::removeAllContactPoints() { mShadowMapTexture[SHADOW_MAP_TEXTURE_TO_DRAW].unbind();
mQuadShader.unbind();
// Destroy all the visual contact points mVAOQuad.unbind();
for (std::vector<VisualContactPoint*>::iterator it = mContactPoints.begin(); }
it != mContactPoints.end(); ++it) {
delete (*it); // Gather and create contact points
} void SceneDemo::updateContactPoints() {
mContactPoints.clear();
} // Remove the previous contact points
removeAllContactPoints();
// Return all the contact points of the scene
std::vector<ContactPoint> SceneDemo::computeContactPointsOfWorld(rp3d::DynamicsWorld* world) { if (mIsContactPointsDisplayed) {
std::vector<ContactPoint> contactPoints; // Get the current contact points of the scene
std::vector<ContactPoint> contactPoints = getContactPoints();
// Get the list of contact manifolds from the world
rp3d::List<const rp3d::ContactManifold*> manifolds = world->getContactsList(); // For each contact point
std::vector<ContactPoint>::const_iterator it;
// For each contact manifold for (it = contactPoints.begin(); it != contactPoints.end(); ++it) {
rp3d::List<const rp3d::ContactManifold*>::Iterator it;
for (it = manifolds.begin(); it != manifolds.end(); ++it) { // Create a visual contact point for rendering
VisualContactPoint* point = new VisualContactPoint(it->point, mMeshFolderPath, it->point + it->normal, it->color);
const rp3d::ContactManifold* manifold = *it; mContactPoints.push_back(point);
}
// For each contact point of the manifold }
rp3d::ContactPoint* contactPoint = manifold->getContactPoints(); }
while (contactPoint != nullptr) {
// Render the contact points
rp3d::Vector3 point = manifold->getShape1()->getLocalToWorldTransform() * contactPoint->getLocalPointOnShape1(); void SceneDemo::renderContactPoints(openglframework::Shader& shader, const openglframework::Matrix4& worldToCameraMatrix) {
rp3d::Vector3 normalWorld = contactPoint->getNormal();
openglframework::Vector3 normal = openglframework::Vector3(normalWorld.x, normalWorld.y, normalWorld.z); // Render all the contact points
ContactPoint contact(openglframework::Vector3(point.x, point.y, point.z), normal, openglframework::Color::red()); for (std::vector<VisualContactPoint*>::iterator it = mContactPoints.begin();
contactPoints.push_back(contact); it != mContactPoints.end(); ++it) {
(*it)->render(mColorShader, worldToCameraMatrix);
contactPoint = contactPoint->getNext(); }
} }
} // Render the AABBs
void SceneDemo::renderAABBs(const openglframework::Matrix4& worldToCameraMatrix) {
return contactPoints;
} // For each physics object of the scene
for (std::vector<PhysicsObject*>::iterator it = mPhysicsObjects.begin(); it != mPhysicsObjects.end(); ++it) {
// Update the engine settings
void SceneDemo::updateEngineSettings() { // For each proxy shape of the object
rp3d::ProxyShape* proxyShape = (*it)->getCollisionBody()->getProxyShapesList();
if (getDynamicsWorld() != nullptr) { while (proxyShape != nullptr) {
// Update the physics engine parameters // Get the broad-phase AABB corresponding to the proxy shape
getDynamicsWorld()->setIsGratityEnabled(mEngineSettings.isGravityEnabled); rp3d::AABB aabb = mPhysicsWorld->getWorldAABB(proxyShape);
rp3d::Vector3 gravity(mEngineSettings.gravity.x, mEngineSettings.gravity.y,
mEngineSettings.gravity.z); openglframework::Vector3 aabbCenter(aabb.getCenter().x, aabb.getCenter().y, aabb.getCenter().z);
getDynamicsWorld()->setGravity(gravity); openglframework::Vector3 aabbMin(aabb.getMin().x, aabb.getMin().y, aabb.getMin().z);
getDynamicsWorld()->enableSleeping(mEngineSettings.isSleepingEnabled); openglframework::Vector3 aabbMax(aabb.getMax().x, aabb.getMax().y, aabb.getMax().z);
getDynamicsWorld()->setSleepLinearVelocity(mEngineSettings.sleepLinearVelocity);
getDynamicsWorld()->setSleepAngularVelocity(mEngineSettings.sleepAngularVelocity); // Render the AABB
getDynamicsWorld()->setNbIterationsPositionSolver(mEngineSettings.nbPositionSolverIterations); AABB::render(aabbCenter, aabbMax - aabbMin, Color::green(), mColorShader, worldToCameraMatrix);
getDynamicsWorld()->setNbIterationsVelocitySolver(mEngineSettings.nbVelocitySolverIterations);
getDynamicsWorld()->setTimeBeforeSleep(mEngineSettings.timeBeforeSleep); proxyShape = proxyShape->getNext();
} }
} }
}
void SceneDemo::removeAllContactPoints() {
// Destroy all the visual contact points
for (std::vector<VisualContactPoint*>::iterator it = mContactPoints.begin();
it != mContactPoints.end(); ++it) {
delete (*it);
}
mContactPoints.clear();
}
// Return all the contact points of the scene
std::vector<ContactPoint> SceneDemo::computeContactPointsOfWorld(rp3d::DynamicsWorld* world) {
std::vector<ContactPoint> contactPoints;
// Get the list of contact manifolds from the world
rp3d::List<const rp3d::ContactManifold*> manifolds = world->getContactsList();
// For each contact manifold
rp3d::List<const rp3d::ContactManifold*>::Iterator it;
for (it = manifolds.begin(); it != manifolds.end(); ++it) {
const rp3d::ContactManifold* manifold = *it;
// For each contact point of the manifold
rp3d::ContactPoint* contactPoint = manifold->getContactPoints();
while (contactPoint != nullptr) {
rp3d::Vector3 point = manifold->getShape1()->getLocalToWorldTransform() * contactPoint->getLocalPointOnShape1();
rp3d::Vector3 normalWorld = contactPoint->getNormal();
openglframework::Vector3 normal = openglframework::Vector3(normalWorld.x, normalWorld.y, normalWorld.z);
ContactPoint contact(openglframework::Vector3(point.x, point.y, point.z), normal, openglframework::Color::red());
contactPoints.push_back(contact);
contactPoint = contactPoint->getNext();
}
}
return contactPoints;
}
// Update the engine settings
void SceneDemo::updateEngineSettings() {
if (getDynamicsWorld() != nullptr) {
// Update the physics engine parameters
getDynamicsWorld()->setIsGratityEnabled(mEngineSettings.isGravityEnabled);
rp3d::Vector3 gravity(mEngineSettings.gravity.x, mEngineSettings.gravity.y,
mEngineSettings.gravity.z);
getDynamicsWorld()->setGravity(gravity);
getDynamicsWorld()->enableSleeping(mEngineSettings.isSleepingEnabled);
getDynamicsWorld()->setSleepLinearVelocity(mEngineSettings.sleepLinearVelocity);
getDynamicsWorld()->setSleepAngularVelocity(mEngineSettings.sleepAngularVelocity);
getDynamicsWorld()->setNbIterationsPositionSolver(mEngineSettings.nbPositionSolverIterations);
getDynamicsWorld()->setNbIterationsVelocitySolver(mEngineSettings.nbVelocitySolverIterations);
getDynamicsWorld()->setTimeBeforeSleep(mEngineSettings.timeBeforeSleep);
}
}

View File

@ -1,189 +1,195 @@
/******************************************************************************** /********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com * * ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2016 Daniel Chappuis * * Copyright (c) 2010-2016 Daniel Chappuis *
********************************************************************************* *********************************************************************************
* * * *
* This software is provided 'as-is', without any express or implied warranty. * * This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the * * In no event will the authors be held liable for any damages arising from the *
* use of this software. * * use of this software. *
* * * *
* Permission is granted to anyone to use this software for any purpose, * * Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it * * including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: * * freely, subject to the following restrictions: *
* * * *
* 1. The origin of this software must not be misrepresented; you must not claim * * 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a * * that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be * * product, an acknowledgment in the product documentation would be *
* appreciated but is not required. * * appreciated but is not required. *
* * * *
* 2. Altered source versions must be plainly marked as such, and must not be * * 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. * * misrepresented as being the original software. *
* * * *
* 3. This notice may not be removed or altered from any source distribution. * * 3. This notice may not be removed or altered from any source distribution. *
* * * *
********************************************************************************/ ********************************************************************************/
#ifndef SCENEDEMO_H #ifndef SCENEDEMO_H
#define SCENEDEMO_H #define SCENEDEMO_H
// Libraries // Libraries
#include "Scene.h" #include "Scene.h"
#include "VisualContactPoint.h" #include "VisualContactPoint.h"
#include "reactphysics3d.h" #include "reactphysics3d.h"
#include "PhysicsObject.h" #include "PhysicsObject.h"
// Constants // Constants
const int SHADOWMAP_WIDTH = 2048; const int SHADOWMAP_WIDTH = 2048;
const int SHADOWMAP_HEIGHT = 2048; const int SHADOWMAP_HEIGHT = 2048;
// Class SceneDemo // Class SceneDemo
// Abstract class that represents a 3D scene for the ReactPhysics3D examples. // Abstract class that represents a 3D scene for the ReactPhysics3D examples.
// This scene has a single light source with shadow mapping. // This scene has a single light source with shadow mapping.
class SceneDemo : public Scene { class SceneDemo : public Scene {
protected: protected:
// -------------------- Attributes -------------------- // // -------------------- Constants -------------------- //
/// Light 0 static constexpr int NB_SHADOW_MAPS = 3;
openglframework::Light mLight0;
// -------------------- Attributes -------------------- //
/// True if the shadows FBO, textures have been created
bool mIsShadowMappingInitialized; /// Light 0
openglframework::Light mLight0;
/// FBO for the shadow map
openglframework::FrameBufferObject mFBOShadowMap; /// Light 1
openglframework::Light mLight1;
/// Shadow map texture
openglframework::Texture2D mShadowMapTexture; /// Light 2
openglframework::Light mLight2;
static int shadowMapTextureLevel;
/// True if the shadows FBO, textures have been created
/// All the visual contact points bool mIsShadowMappingInitialized;
std::vector<VisualContactPoint*> mContactPoints;
/// Array of FBO for the shadow maps
/// Shadow map bias matrix openglframework::FrameBufferObject mFBOShadowMap[NB_SHADOW_MAPS];
openglframework::Matrix4 mShadowMapBiasMatrix;
/// Shadow map texture
/// Camera at light0 position for the shadow map openglframework::Texture2D mShadowMapTexture[NB_SHADOW_MAPS];
openglframework::Camera mShadowMapLightCamera;
static int shadowMapTextureLevel;
/// Depth shader to render the shadow map
openglframework::Shader mDepthShader; /// All the visual contact points
std::vector<VisualContactPoint*> mContactPoints;
/// Phong shader
openglframework::Shader mPhongShader; /// Shadow map bias matrix
openglframework::Matrix4 mShadowMapBiasMatrix;
/// Constant color shader
openglframework::Shader mColorShader; /// Cameras at lights position for the shadow maps
openglframework::Camera mShadowMapLightCameras[NB_SHADOW_MAPS];
// TODO : Delete this
openglframework::Shader mQuadShader; /// Depth shader to render the shadow map
openglframework::Shader mDepthShader;
// TODO : Delete this
openglframework::VertexArrayObject mVAOQuad; /// Phong shader
openglframework::Shader mPhongShader;
openglframework::VertexBufferObject mVBOQuad;
/// Constant color shader
static openglframework::Color mGreyColorDemo; openglframework::Shader mColorShader;
static openglframework::Color mYellowColorDemo;
static openglframework::Color mBlueColorDemo; // TODO : Delete this
static openglframework::Color mOrangeColorDemo; openglframework::Shader mQuadShader;
static openglframework::Color mPinkColorDemo;
static openglframework::Color mRedColorDemo; // TODO : Delete this
static openglframework::Color mDemoColors[]; openglframework::VertexArrayObject mVAOQuad;
static int mNbDemoColors;
openglframework::VertexBufferObject mVBOQuad;
std::string mMeshFolderPath;
static openglframework::Color mObjectColorDemo;
std::vector<PhysicsObject*> mPhysicsObjects; static openglframework::Color mFloorColorDemo;
static openglframework::Color mSleepingColorDemo;
rp3d::CollisionWorld* mPhysicsWorld; static openglframework::Color mSelectedObjectColorDemo;
// -------------------- Methods -------------------- // std::string mMeshFolderPath;
// Create the Shadow map FBO and texture std::vector<PhysicsObject*> mPhysicsObjects;
void createShadowMapFBOAndTexture();
rp3d::CollisionWorld* mPhysicsWorld;
// Used for debugging shadow maps
void createQuadVBO(); // -------------------- Methods -------------------- //
// TODO : Delete this // Create the Shadow map FBO and texture
void drawTextureQuad(); void createShadowMapFBOAndTexture();
// Update the contact points // Used for debugging shadow maps
void updateContactPoints(); void createQuadVBO();
// Render the contact points // TODO : Delete this
void renderContactPoints(openglframework::Shader& shader, void drawTextureQuad();
const openglframework::Matrix4& worldToCameraMatrix);
// Update the contact points
void updateContactPoints();
/// Render the AABBs
void renderAABBs(const openglframework::Matrix4& worldToCameraMatrix); // Render the contact points
void renderContactPoints(openglframework::Shader& shader,
/// Remove all contact points const openglframework::Matrix4& worldToCameraMatrix);
void removeAllContactPoints();
/// Return a reference to the dynamics world /// Render the AABBs
rp3d::DynamicsWorld* getDynamicsWorld(); void renderAABBs(const openglframework::Matrix4& worldToCameraMatrix);
/// Return a reference to the dynamics world /// Remove all contact points
const rp3d::DynamicsWorld* getDynamicsWorld() const; void removeAllContactPoints();
public: /// Return a reference to the dynamics world
rp3d::DynamicsWorld* getDynamicsWorld();
// -------------------- Methods -------------------- //
/// Return a reference to the dynamics world
/// Constructor const rp3d::DynamicsWorld* getDynamicsWorld() const;
SceneDemo(const std::string& name, EngineSettings& settings, float sceneRadius, bool isShadowMappingEnabled = true);
public:
/// Destructor
virtual ~SceneDemo() override; // -------------------- Methods -------------------- //
/// Update the scene /// Constructor
virtual void update() override; SceneDemo(const std::string& name, EngineSettings& settings, float sceneRadius, bool isShadowMappingEnabled = true);
/// Update the physics world (take a simulation step) /// Destructor
/// Can be called several times per frame virtual ~SceneDemo() override;
virtual void updatePhysics() override;
/// Update the scene
/// Render the scene (possibly in multiple passes for shadow mapping) virtual void update() override;
virtual void render() override;
/// Update the physics world (take a simulation step)
/// Update the engine settings /// Can be called several times per frame
virtual void updateEngineSettings() override; virtual void updatePhysics() override;
/// Render the scene in a single pass /// Render the scene (possibly in multiple passes for shadow mapping)
virtual void renderSinglePass(openglframework::Shader& shader, const openglframework::Matrix4& worldToCameraMatrix); virtual void render() override;
/// Enabled/Disable the shadow mapping /// Update the engine settings
virtual void setIsShadowMappingEnabled(bool isShadowMappingEnabled) override; virtual void updateEngineSettings() override;
/// Return all the contact points of the scene /// Render the scene in a single pass
std::vector<ContactPoint> computeContactPointsOfWorld(reactphysics3d::DynamicsWorld *world); virtual void renderSinglePass(openglframework::Shader& shader, const openglframework::Matrix4& worldToCameraMatrix);
};
/// Enabled/Disable the shadow mapping
// Enabled/Disable the shadow mapping virtual void setIsShadowMappingEnabled(bool isShadowMappingEnabled) override;
inline void SceneDemo::setIsShadowMappingEnabled(bool isShadowMappingEnabled) {
/// Return all the contact points of the scene
Scene::setIsShadowMappingEnabled(isShadowMappingEnabled); std::vector<ContactPoint> computeContactPointsOfWorld(reactphysics3d::DynamicsWorld *world);
};
if (mIsShadowMappingEnabled && !mIsShadowMappingInitialized) {
createShadowMapFBOAndTexture(); // Enabled/Disable the shadow mapping
} inline void SceneDemo::setIsShadowMappingEnabled(bool isShadowMappingEnabled) {
}
Scene::setIsShadowMappingEnabled(isShadowMappingEnabled);
// Return a reference to the dynamics world
inline rp3d::DynamicsWorld* SceneDemo::getDynamicsWorld() { if (mIsShadowMappingEnabled && !mIsShadowMappingInitialized) {
return dynamic_cast<rp3d::DynamicsWorld*>(mPhysicsWorld); createShadowMapFBOAndTexture();
} }
}
// Return a reference to the dynamics world
inline const rp3d::DynamicsWorld* SceneDemo::getDynamicsWorld() const { // Return a reference to the dynamics world
return dynamic_cast<rp3d::DynamicsWorld*>(mPhysicsWorld); inline rp3d::DynamicsWorld* SceneDemo::getDynamicsWorld() {
} return dynamic_cast<rp3d::DynamicsWorld*>(mPhysicsWorld);
}
#endif
// Return a reference to the dynamics world
inline const rp3d::DynamicsWorld* SceneDemo::getDynamicsWorld() const {
return dynamic_cast<rp3d::DynamicsWorld*>(mPhysicsWorld);
}
#endif

View File

@ -1,393 +1,393 @@
/******************************************************************************** /********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com * * ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2016 Daniel Chappuis * * Copyright (c) 2010-2016 Daniel Chappuis *
********************************************************************************* *********************************************************************************
* * * *
* This software is provided 'as-is', without any express or implied warranty. * * This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the * * In no event will the authors be held liable for any damages arising from the *
* use of this software. * * use of this software. *
* * * *
* Permission is granted to anyone to use this software for any purpose, * * Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it * * including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: * * freely, subject to the following restrictions: *
* * * *
* 1. The origin of this software must not be misrepresented; you must not claim * * 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a * * that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be * * product, an acknowledgment in the product documentation would be *
* appreciated but is not required. * * appreciated but is not required. *
* * * *
* 2. Altered source versions must be plainly marked as such, and must not be * * 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. * * misrepresented as being the original software. *
* * * *
* 3. This notice may not be removed or altered from any source distribution. * * 3. This notice may not be removed or altered from any source distribution. *
* * * *
********************************************************************************/ ********************************************************************************/
// Libraries // Libraries
#include "TestbedApplication.h" #include "TestbedApplication.h"
#include "openglframework.h" #include "openglframework.h"
#include <iostream> #include <iostream>
#include <cstdlib> #include <cstdlib>
#include <sstream> #include <sstream>
#include "cubes/CubesScene.h" #include "cubes/CubesScene.h"
#include "collisiondetection/CollisionDetectionScene.h" #include "collisiondetection/CollisionDetectionScene.h"
#include "joints/JointsScene.h" #include "joints/JointsScene.h"
#include "collisionshapes/CollisionShapesScene.h" #include "collisionshapes/CollisionShapesScene.h"
#include "heightfield/HeightFieldScene.h" #include "heightfield/HeightFieldScene.h"
#include "raycast/RaycastScene.h" #include "raycast/RaycastScene.h"
#include "concavemesh/ConcaveMeshScene.h" #include "concavemesh/ConcaveMeshScene.h"
#include "cubestack/CubeStackScene.h" #include "cubestack/CubeStackScene.h"
using namespace openglframework; using namespace openglframework;
using namespace jointsscene; using namespace jointsscene;
using namespace cubesscene; using namespace cubesscene;
using namespace raycastscene; using namespace raycastscene;
using namespace collisionshapesscene; using namespace collisionshapesscene;
using namespace trianglemeshscene; using namespace trianglemeshscene;
using namespace heightfieldscene; using namespace heightfieldscene;
using namespace collisiondetectionscene; using namespace collisiondetectionscene;
using namespace cubestackscene; using namespace cubestackscene;
// Initialization of static variables // Initialization of static variables
const float TestbedApplication::SCROLL_SENSITIVITY = 0.08f; const float TestbedApplication::SCROLL_SENSITIVITY = 0.08f;
// Constructor // Constructor
TestbedApplication::TestbedApplication(bool isFullscreen) TestbedApplication::TestbedApplication(bool isFullscreen, int windowWidth, int windowHeight)
: Screen(Vector2i(1280, 800), "Testbed ReactPhysics3D", true, isFullscreen, 8, 8, 24, 8, 8), : Screen(Vector2i(windowWidth, windowHeight), "Testbed ReactPhysics3D", true, isFullscreen, 8, 8, 24, 8, 8),
mIsInitialized(false), mGui(this), mCurrentScene(nullptr), mIsInitialized(false), mGui(this), mCurrentScene(nullptr),
mEngineSettings(EngineSettings::defaultSettings()), mEngineSettings(EngineSettings::defaultSettings()),
mFPS(0), mNbFrames(0), mPreviousTime(0), mFPS(0), mNbFrames(0), mPreviousTime(0),
mLastTimeComputedFPS(0), mFrameTime(0), mPhysicsTime(0), mLastTimeComputedFPS(0), mFrameTime(0), mPhysicsTime(0),
mWidth(1280), mHeight(720), mWidth(windowWidth), mHeight(windowHeight),
mSinglePhysicsStepEnabled(false), mSinglePhysicsStepDone(false), mSinglePhysicsStepEnabled(false), mSinglePhysicsStepDone(false),
mWindowToFramebufferRatio(Vector2(1, 1)), mIsShadowMappingEnabled(true), mWindowToFramebufferRatio(Vector2(1, 1)), mIsShadowMappingEnabled(true),
mIsContactPointsDisplayed(false), mIsAABBsDisplayed(false), mIsWireframeEnabled(false), mIsContactPointsDisplayed(false), mIsAABBsDisplayed(false), mIsWireframeEnabled(false),
mIsVSyncEnabled(true) { mIsVSyncEnabled(true) {
init(); init();
resizeEvent(Vector2i(0, 0)); resizeEvent(Vector2i(0, 0));
} }
// Destructor // Destructor
TestbedApplication::~TestbedApplication() { TestbedApplication::~TestbedApplication() {
// Destroy all the scenes // Destroy all the scenes
destroyScenes(); destroyScenes();
} }
// Initialize the viewer // Initialize the viewer
void TestbedApplication::init() { void TestbedApplication::init() {
// Create all the scenes // Create all the scenes
createScenes(); createScenes();
// Initialize the GUI // Initialize the GUI
mGui.init(); mGui.init();
mTimer.start(); mTimer.start();
mIsInitialized = true; mIsInitialized = true;
} }
// Create all the scenes // Create all the scenes
void TestbedApplication::createScenes() { void TestbedApplication::createScenes() {
// Cubes scene // Cubes scene
CubesScene* cubeScene = new CubesScene("Cubes", mEngineSettings); CubesScene* cubeScene = new CubesScene("Cubes", mEngineSettings);
mScenes.push_back(cubeScene); mScenes.push_back(cubeScene);
// Cube Stack scene // Cube Stack scene
CubeStackScene* cubeStackScene = new CubeStackScene("Cube Stack", mEngineSettings); CubeStackScene* cubeStackScene = new CubeStackScene("Cube Stack", mEngineSettings);
mScenes.push_back(cubeStackScene); mScenes.push_back(cubeStackScene);
// Joints scene // Joints scene
JointsScene* jointsScene = new JointsScene("Joints", mEngineSettings); JointsScene* jointsScene = new JointsScene("Joints", mEngineSettings);
mScenes.push_back(jointsScene); mScenes.push_back(jointsScene);
// Collision shapes scene // Collision shapes scene
CollisionShapesScene* collisionShapesScene = new CollisionShapesScene("Collision Shapes", mEngineSettings); CollisionShapesScene* collisionShapesScene = new CollisionShapesScene("Collision Shapes", mEngineSettings);
mScenes.push_back(collisionShapesScene); mScenes.push_back(collisionShapesScene);
// Heightfield shape scene // Heightfield shape scene
HeightFieldScene* heightFieldScene = new HeightFieldScene("Heightfield", mEngineSettings); HeightFieldScene* heightFieldScene = new HeightFieldScene("Heightfield", mEngineSettings);
mScenes.push_back(heightFieldScene); mScenes.push_back(heightFieldScene);
// Raycast scene // Raycast scene
RaycastScene* raycastScene = new RaycastScene("Raycast", mEngineSettings); RaycastScene* raycastScene = new RaycastScene("Raycast", mEngineSettings);
mScenes.push_back(raycastScene); mScenes.push_back(raycastScene);
// Collision Detection scene // Collision Detection scene
CollisionDetectionScene* collisionDetectionScene = new CollisionDetectionScene("Collision Detection", mEngineSettings); CollisionDetectionScene* collisionDetectionScene = new CollisionDetectionScene("Collision Detection", mEngineSettings);
mScenes.push_back(collisionDetectionScene); mScenes.push_back(collisionDetectionScene);
// Concave Mesh scene // Concave Mesh scene
ConcaveMeshScene* concaveMeshScene = new ConcaveMeshScene("Concave Mesh", mEngineSettings); ConcaveMeshScene* concaveMeshScene = new ConcaveMeshScene("Concave Mesh", mEngineSettings);
mScenes.push_back(concaveMeshScene); mScenes.push_back(concaveMeshScene);
assert(mScenes.size() > 0); assert(mScenes.size() > 0);
const int firstSceneIndex = 0; const int firstSceneIndex = 0;
switchScene(mScenes[firstSceneIndex]); switchScene(mScenes[firstSceneIndex]);
} }
// Remove all the scenes // Remove all the scenes
void TestbedApplication::destroyScenes() { void TestbedApplication::destroyScenes() {
for (uint i=0; i<mScenes.size(); i++) { for (uint i=0; i<mScenes.size(); i++) {
delete mScenes[i]; delete mScenes[i];
} }
mCurrentScene = NULL; mCurrentScene = NULL;
} }
void TestbedApplication::updateSinglePhysicsStep() { void TestbedApplication::updateSinglePhysicsStep() {
assert(!mTimer.isRunning()); assert(!mTimer.isRunning());
mCurrentScene->updatePhysics(); mCurrentScene->updatePhysics();
} }
// Update the physics of the current scene // Update the physics of the current scene
void TestbedApplication::updatePhysics() { void TestbedApplication::updatePhysics() {
// Update the elapsed time // Update the elapsed time
mEngineSettings.elapsedTime = mTimer.getPhysicsTime(); mEngineSettings.elapsedTime = mTimer.getPhysicsTime();
if (mTimer.isRunning()) { if (mTimer.isRunning()) {
// Compute the time since the last update() call and update the timer // Compute the time since the last update() call and update the timer
mTimer.update(); mTimer.update();
// While the time accumulator is not empty // While the time accumulator is not empty
while(mTimer.isPossibleToTakeStep(mEngineSettings.timeStep)) { while(mTimer.isPossibleToTakeStep(mEngineSettings.timeStep)) {
// Take a physics simulation step // Take a physics simulation step
mCurrentScene->updatePhysics(); mCurrentScene->updatePhysics();
// Update the timer // Update the timer
mTimer.nextStep(mEngineSettings.timeStep); mTimer.nextStep(mEngineSettings.timeStep);
} }
} }
} }
void TestbedApplication::update() { void TestbedApplication::update() {
double currentTime = glfwGetTime(); double currentTime = glfwGetTime();
// Update the physics // Update the physics
if (mSinglePhysicsStepEnabled && !mSinglePhysicsStepDone) { if (mSinglePhysicsStepEnabled && !mSinglePhysicsStepDone) {
updateSinglePhysicsStep(); updateSinglePhysicsStep();
mSinglePhysicsStepDone = true; mSinglePhysicsStepDone = true;
} }
else { else {
updatePhysics(); updatePhysics();
} }
// Compute the physics update time // Compute the physics update time
mPhysicsTime = glfwGetTime() - currentTime; mPhysicsTime = glfwGetTime() - currentTime;
// Compute the interpolation factor // Compute the interpolation factor
float factor = mTimer.computeInterpolationFactor(mEngineSettings.timeStep); float factor = mTimer.computeInterpolationFactor(mEngineSettings.timeStep);
assert(factor >= 0.0f && factor <= 1.0f); assert(factor >= 0.0f && factor <= 1.0f);
// Notify the scene about the interpolation factor // Notify the scene about the interpolation factor
mCurrentScene->setInterpolationFactor(factor); mCurrentScene->setInterpolationFactor(factor);
// Enable/Disable shadow mapping // Enable/Disable shadow mapping
mCurrentScene->setIsShadowMappingEnabled(mIsShadowMappingEnabled); mCurrentScene->setIsShadowMappingEnabled(mIsShadowMappingEnabled);
// Display/Hide contact points // Display/Hide contact points
mCurrentScene->setIsContactPointsDisplayed(mIsContactPointsDisplayed); mCurrentScene->setIsContactPointsDisplayed(mIsContactPointsDisplayed);
// Display/Hide the AABBs // Display/Hide the AABBs
mCurrentScene->setIsAABBsDisplayed(mIsAABBsDisplayed); mCurrentScene->setIsAABBsDisplayed(mIsAABBsDisplayed);
// Enable/Disable wireframe mode // Enable/Disable wireframe mode
mCurrentScene->setIsWireframeEnabled(mIsWireframeEnabled); mCurrentScene->setIsWireframeEnabled(mIsWireframeEnabled);
// Update the scene // Update the scene
mCurrentScene->update(); mCurrentScene->update();
} }
void TestbedApplication::drawContents() { void TestbedApplication::drawContents() {
update(); update();
int bufferWidth, bufferHeight; int bufferWidth, bufferHeight;
glfwMakeContextCurrent(mGLFWWindow); glfwMakeContextCurrent(mGLFWWindow);
glfwGetFramebufferSize(mGLFWWindow, &bufferWidth, &bufferHeight); glfwGetFramebufferSize(mGLFWWindow, &bufferWidth, &bufferHeight);
// Set the viewport of the scene // Set the viewport of the scene
mCurrentScene->setViewport(0, 0, bufferWidth, bufferHeight); mCurrentScene->setViewport(0, 0, bufferWidth, bufferHeight);
// Render the scene // Render the scene
mCurrentScene->render(); mCurrentScene->render();
// Check the OpenGL errors // Check the OpenGL errors
checkOpenGLErrors(); checkOpenGLErrors();
mGui.update(); mGui.update();
// Compute the current framerate // Compute the current framerate
computeFPS(); computeFPS();
} }
/// Window resize event handler /// Window resize event handler
bool TestbedApplication::resizeEvent(const Vector2i& size) { bool TestbedApplication::resizeEvent(const Vector2i& size) {
if (!mIsInitialized) return false; if (!mIsInitialized) return false;
// Get the framebuffer dimension // Get the framebuffer dimension
int width, height; int width, height;
glfwGetFramebufferSize(mGLFWWindow, &width, &height); glfwGetFramebufferSize(mGLFWWindow, &width, &height);
// Resize the camera viewport // Resize the camera viewport
mCurrentScene->reshape(width, height); mCurrentScene->reshape(width, height);
// Update the window size of the scene // Update the window size of the scene
int windowWidth, windowHeight; int windowWidth, windowHeight;
glfwGetWindowSize(mGLFWWindow, &windowWidth, &windowHeight); glfwGetWindowSize(mGLFWWindow, &windowWidth, &windowHeight);
mCurrentScene->setWindowDimension(windowWidth, windowHeight); mCurrentScene->setWindowDimension(windowWidth, windowHeight);
return true; return true;
} }
// Change the current scene // Change the current scene
void TestbedApplication::switchScene(Scene* newScene) { void TestbedApplication::switchScene(Scene* newScene) {
if (newScene == mCurrentScene) return; if (newScene == mCurrentScene) return;
mCurrentScene = newScene; mCurrentScene = newScene;
// Reset the scene // Reset the scene
mCurrentScene->reset(); mCurrentScene->reset();
mCurrentScene->updateEngineSettings(); mCurrentScene->updateEngineSettings();
resizeEvent(Vector2i(0, 0)); resizeEvent(Vector2i(0, 0));
} }
// Notify that the engine settings have changed // Notify that the engine settings have changed
void TestbedApplication::notifyEngineSetttingsChanged() { void TestbedApplication::notifyEngineSetttingsChanged() {
mCurrentScene->updateEngineSettings(); mCurrentScene->updateEngineSettings();
} }
// Check the OpenGL errors // Check the OpenGL errors
void TestbedApplication::checkOpenGLErrorsInternal(const char* file, int line) { void TestbedApplication::checkOpenGLErrorsInternal(const char* file, int line) {
GLenum glError; GLenum glError;
// Get the OpenGL errors // Get the OpenGL errors
glError = glGetError(); glError = glGetError();
// While there are errors // While there are errors
while (glError != GL_NO_ERROR) { while (glError != GL_NO_ERROR) {
std::string error; std::string error;
switch(glError) { switch(glError) {
case GL_INVALID_OPERATION: error="INVALID_OPERATION"; break; case GL_INVALID_OPERATION: error="INVALID_OPERATION"; break;
case GL_INVALID_ENUM: error="INVALID_ENUM"; break; case GL_INVALID_ENUM: error="INVALID_ENUM"; break;
case GL_INVALID_VALUE: error="INVALID_VALUE"; break; case GL_INVALID_VALUE: error="INVALID_VALUE"; break;
case GL_OUT_OF_MEMORY: error="OUT_OF_MEMORY"; break; case GL_OUT_OF_MEMORY: error="OUT_OF_MEMORY"; break;
case GL_INVALID_FRAMEBUFFER_OPERATION: error="INVALID_FRAMEBUFFER_OPERATION"; break; case GL_INVALID_FRAMEBUFFER_OPERATION: error="INVALID_FRAMEBUFFER_OPERATION"; break;
} }
std::cerr << "OpenGL Error #" << error.c_str() << " - " << file << ": " << line << std::endl; std::cerr << "OpenGL Error #" << error.c_str() << " - " << file << ": " << line << std::endl;
// Get the next error // Get the next error
glError = glGetError(); glError = glGetError();
} }
} }
// Compute the FPS // Compute the FPS
void TestbedApplication::computeFPS() { void TestbedApplication::computeFPS() {
// Note : By default the nanogui library is using glfwWaitEvents() to process // Note : By default the nanogui library is using glfwWaitEvents() to process
// events and sleep to target a framerate of 50 ms (using a thread // events and sleep to target a framerate of 50 ms (using a thread
// sleeping). However, for games we prefer to use glfwPollEvents() // sleeping). However, for games we prefer to use glfwPollEvents()
// instead and remove the update. Therefore the file common.cpp of the // instead and remove the update. Therefore the file common.cpp of the
// nanogui library has been modified to have a faster framerate // nanogui library has been modified to have a faster framerate
mNbFrames++; mNbFrames++;
// Get the number of seconds since start // Get the number of seconds since start
mCurrentTime = glfwGetTime(); mCurrentTime = glfwGetTime();
// Calculate time passed // Calculate time passed
mFrameTime = mCurrentTime - mPreviousTime; mFrameTime = mCurrentTime - mPreviousTime;
double timeInterval = (mCurrentTime - mLastTimeComputedFPS) * 1000.0; double timeInterval = (mCurrentTime - mLastTimeComputedFPS) * 1000.0;
// Update the FPS counter each second // Update the FPS counter each second
if(timeInterval > 1000) { if(timeInterval > 1000) {
// calculate the number of frames per second // calculate the number of frames per second
mFPS = static_cast<double>(mNbFrames) / timeInterval; mFPS = static_cast<double>(mNbFrames) / timeInterval;
mFPS *= 1000.0; mFPS *= 1000.0;
// Reset frame count // Reset frame count
mNbFrames = 0; mNbFrames = 0;
mLastTimeComputedFPS = mCurrentTime; mLastTimeComputedFPS = mCurrentTime;
} }
// Set time // Set time
mPreviousTime = mCurrentTime; mPreviousTime = mCurrentTime;
} }
bool TestbedApplication::keyboardEvent(int key, int scancode, int action, int modifiers) { bool TestbedApplication::keyboardEvent(int key, int scancode, int action, int modifiers) {
if (Screen::keyboardEvent(key, scancode, action, modifiers)) { if (Screen::keyboardEvent(key, scancode, action, modifiers)) {
return true; return true;
} }
// Close application on escape key // Close application on escape key
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) { if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) {
glfwSetWindowShouldClose(mGLFWWindow, GL_TRUE); glfwSetWindowShouldClose(mGLFWWindow, GL_TRUE);
return true; return true;
} }
return mCurrentScene->keyboardEvent(key, scancode, action, modifiers); return mCurrentScene->keyboardEvent(key, scancode, action, modifiers);
} }
// Handle a mouse button event (default implementation: propagate to children) // Handle a mouse button event (default implementation: propagate to children)
bool TestbedApplication::mouseButtonEvent(const Vector2i &p, int button, bool down, int modifiers) { bool TestbedApplication::mouseButtonEvent(const Vector2i &p, int button, bool down, int modifiers) {
if (Screen::mouseButtonEvent(p, button, down, modifiers)) { if (Screen::mouseButtonEvent(p, button, down, modifiers)) {
return true; return true;
} }
// Get the mouse cursor position // Get the mouse cursor position
double x, y; double x, y;
glfwGetCursorPos(mGLFWWindow, &x, &y); glfwGetCursorPos(mGLFWWindow, &x, &y);
return mCurrentScene->mouseButtonEvent(button, down, modifiers, x, y); return mCurrentScene->mouseButtonEvent(button, down, modifiers, x, y);
} }
// Handle a mouse motion event (default implementation: propagate to children) // Handle a mouse motion event (default implementation: propagate to children)
bool TestbedApplication::mouseMotionEvent(const Vector2i &p, const Vector2i &rel, int button, int modifiers) { bool TestbedApplication::mouseMotionEvent(const Vector2i &p, const Vector2i &rel, int button, int modifiers) {
if (Screen::mouseMotionEvent(p, rel, button, modifiers)) { if (Screen::mouseMotionEvent(p, rel, button, modifiers)) {
return true; return true;
} }
int leftButtonState = glfwGetMouseButton(mGLFWWindow, GLFW_MOUSE_BUTTON_LEFT); int leftButtonState = glfwGetMouseButton(mGLFWWindow, GLFW_MOUSE_BUTTON_LEFT);
int rightButtonState = glfwGetMouseButton(mGLFWWindow, GLFW_MOUSE_BUTTON_RIGHT); int rightButtonState = glfwGetMouseButton(mGLFWWindow, GLFW_MOUSE_BUTTON_RIGHT);
int middleButtonState = glfwGetMouseButton(mGLFWWindow, GLFW_MOUSE_BUTTON_MIDDLE); int middleButtonState = glfwGetMouseButton(mGLFWWindow, GLFW_MOUSE_BUTTON_MIDDLE);
int altKeyState = glfwGetKey(mGLFWWindow, GLFW_KEY_LEFT_ALT); int altKeyState = glfwGetKey(mGLFWWindow, GLFW_KEY_LEFT_ALT);
return mCurrentScene->mouseMotionEvent(p[0], p[1], leftButtonState, rightButtonState, return mCurrentScene->mouseMotionEvent(p[0], p[1], leftButtonState, rightButtonState,
middleButtonState, altKeyState); middleButtonState, altKeyState);
} }
// Handle a mouse scroll event (default implementation: propagate to children) // Handle a mouse scroll event (default implementation: propagate to children)
bool TestbedApplication::scrollEvent(const Vector2i &p, const Vector2f &rel) { bool TestbedApplication::scrollEvent(const Vector2i &p, const Vector2f &rel) {
if (Screen::scrollEvent(p, rel)) { if (Screen::scrollEvent(p, rel)) {
return true; return true;
} }
return mCurrentScene->scrollingEvent(rel[0], rel[1], SCROLL_SENSITIVITY); return mCurrentScene->scrollingEvent(rel[0], rel[1], SCROLL_SENSITIVITY);
} }

View File

@ -1,260 +1,260 @@
/******************************************************************************** /********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com * * ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2016 Daniel Chappuis * * Copyright (c) 2010-2016 Daniel Chappuis *
********************************************************************************* *********************************************************************************
* * * *
* This software is provided 'as-is', without any express or implied warranty. * * This software is provided 'as-is', without any express or implied warranty. *
* In no event will the authors be held liable for any damages arising from the * * In no event will the authors be held liable for any damages arising from the *
* use of this software. * * use of this software. *
* * * *
* Permission is granted to anyone to use this software for any purpose, * * Permission is granted to anyone to use this software for any purpose, *
* including commercial applications, and to alter it and redistribute it * * including commercial applications, and to alter it and redistribute it *
* freely, subject to the following restrictions: * * freely, subject to the following restrictions: *
* * * *
* 1. The origin of this software must not be misrepresented; you must not claim * * 1. The origin of this software must not be misrepresented; you must not claim *
* that you wrote the original software. If you use this software in a * * that you wrote the original software. If you use this software in a *
* product, an acknowledgment in the product documentation would be * * product, an acknowledgment in the product documentation would be *
* appreciated but is not required. * * appreciated but is not required. *
* * * *
* 2. Altered source versions must be plainly marked as such, and must not be * * 2. Altered source versions must be plainly marked as such, and must not be *
* misrepresented as being the original software. * * misrepresented as being the original software. *
* * * *
* 3. This notice may not be removed or altered from any source distribution. * * 3. This notice may not be removed or altered from any source distribution. *
* * * *
********************************************************************************/ ********************************************************************************/
#ifndef TESTBED_APPLICATION_H #ifndef TESTBED_APPLICATION_H
#define TESTBED_APPLICATION_H #define TESTBED_APPLICATION_H
// Libraries // Libraries
#include "openglframework.h" #include "openglframework.h"
#include "Gui.h" #include "Gui.h"
#include "Scene.h" #include "Scene.h"
#include "Timer.h" #include "Timer.h"
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
using namespace nanogui; using namespace nanogui;
// Macro for OpenGL errors // Macro for OpenGL errors
#define checkOpenGLErrors() checkOpenGLErrorsInternal(__FILE__,__LINE__) #define checkOpenGLErrors() checkOpenGLErrorsInternal(__FILE__,__LINE__)
/// Class TestbedApplication /// Class TestbedApplication
class TestbedApplication : public Screen { class TestbedApplication : public Screen {
private : private :
// -------------------- Constants -------------------- // // -------------------- Constants -------------------- //
static const float SCROLL_SENSITIVITY; static const float SCROLL_SENSITIVITY;
// -------------------- Attributes -------------------- // // -------------------- Attributes -------------------- //
bool mIsInitialized; bool mIsInitialized;
Gui mGui; Gui mGui;
/// Timer /// Timer
Timer mTimer; Timer mTimer;
/// List of 3D scenes /// List of 3D scenes
std::vector<Scene*> mScenes; std::vector<Scene*> mScenes;
/// Current 3D scene /// Current 3D scene
Scene* mCurrentScene; Scene* mCurrentScene;
/// Physics engine settings /// Physics engine settings
EngineSettings mEngineSettings; EngineSettings mEngineSettings;
/// Current number of frames per seconds /// Current number of frames per seconds
double mFPS; double mFPS;
/// Number of frames during the last second /// Number of frames during the last second
int mNbFrames; int mNbFrames;
/// Current time for fps computation (in seconds) /// Current time for fps computation (in seconds)
double mCurrentTime; double mCurrentTime;
/// Previous time for fps computation (in seconds) /// Previous time for fps computation (in seconds)
double mPreviousTime; double mPreviousTime;
/// Last time the FPS have been computed /// Last time the FPS have been computed
double mLastTimeComputedFPS; double mLastTimeComputedFPS;
/// Update time (in seconds) /// Update time (in seconds)
double mFrameTime; double mFrameTime;
/// Physics update time (in seconds) /// Physics update time (in seconds)
double mPhysicsTime; double mPhysicsTime;
/// Width and height of the window /// Width and height of the window
int mWidth, mHeight; int mWidth, mHeight;
/// True if the next simulation update is a single physics step /// True if the next simulation update is a single physics step
bool mSinglePhysicsStepEnabled; bool mSinglePhysicsStepEnabled;
/// True if the single physics step has been taken already /// True if the single physics step has been taken already
bool mSinglePhysicsStepDone; bool mSinglePhysicsStepDone;
openglframework::Vector2 mWindowToFramebufferRatio; openglframework::Vector2 mWindowToFramebufferRatio;
/// True if shadow mapping is enabled /// True if shadow mapping is enabled
bool mIsShadowMappingEnabled; bool mIsShadowMappingEnabled;
/// True if contact points are displayed /// True if contact points are displayed
bool mIsContactPointsDisplayed; bool mIsContactPointsDisplayed;
/// True if the AABBs of physics objects are displayed /// True if the AABBs of physics objects are displayed
bool mIsAABBsDisplayed; bool mIsAABBsDisplayed;
/// True if the wireframe rendering is enabled /// True if the wireframe rendering is enabled
bool mIsWireframeEnabled; bool mIsWireframeEnabled;
/// True if vsync is enabled /// True if vsync is enabled
bool mIsVSyncEnabled; bool mIsVSyncEnabled;
// -------------------- Methods -------------------- // // -------------------- Methods -------------------- //
/// Private copy-constructor (for the singleton class) /// Private copy-constructor (for the singleton class)
TestbedApplication(TestbedApplication const&); TestbedApplication(TestbedApplication const&);
/// Private assignment operator (for the singleton class) /// Private assignment operator (for the singleton class)
void operator=(TestbedApplication const&); void operator=(TestbedApplication const&);
/// Update the physics of the current scene /// Update the physics of the current scene
void updatePhysics(); void updatePhysics();
/// Update /// Update
void update(); void update();
/// Update the simulation by taking a single physics step /// Update the simulation by taking a single physics step
void updateSinglePhysicsStep(); void updateSinglePhysicsStep();
/// Check the OpenGL errors /// Check the OpenGL errors
static void checkOpenGLErrorsInternal(const char* file, int line); static void checkOpenGLErrorsInternal(const char* file, int line);
/// Compute the FPS /// Compute the FPS
void computeFPS(); void computeFPS();
/// Initialize all the scenes /// Initialize all the scenes
void createScenes(); void createScenes();
/// Remove all the scenes /// Remove all the scenes
void destroyScenes(); void destroyScenes();
/// Return the list of the scenes /// Return the list of the scenes
std::vector<Scene*> getScenes(); std::vector<Scene*> getScenes();
/// Start/stop the simulation /// Start/stop the simulation
void togglePlayPauseSimulation(); void togglePlayPauseSimulation();
/// Play the simulation /// Play the simulation
void playSimulation(); void playSimulation();
/// Pause the simulation /// Pause the simulation
void pauseSimulation(); void pauseSimulation();
/// Restart the simulation /// Restart the simulation
void restartSimulation(); void restartSimulation();
/// Set the variable to know if we need to take a single physics step /// Set the variable to know if we need to take a single physics step
void toggleTakeSinglePhysicsStep(); void toggleTakeSinglePhysicsStep();
public : public :
// -------------------- Methods -------------------- // // -------------------- Methods -------------------- //
/// Private constructor (for the singleton class) /// Private constructor (for the singleton class)
TestbedApplication(bool isFullscreen); TestbedApplication(bool isFullscreen, int windowWidth, int windowHeight);
/// Destructor /// Destructor
virtual ~TestbedApplication() override; virtual ~TestbedApplication() override;
/// Render the content of the application /// Render the content of the application
virtual void drawContents() override; virtual void drawContents() override;
/// Window resize event handler /// Window resize event handler
virtual bool resizeEvent(const Vector2i& size) override; virtual bool resizeEvent(const Vector2i& size) override;
/// Default keyboard event handler /// Default keyboard event handler
virtual bool keyboardEvent(int key, int scancode, int action, int modifiers) override; virtual bool keyboardEvent(int key, int scancode, int action, int modifiers) override;
/// Handle a mouse button event (default implementation: propagate to children) /// Handle a mouse button event (default implementation: propagate to children)
virtual bool mouseButtonEvent(const Vector2i &p, int button, bool down, int modifiers) override; virtual bool mouseButtonEvent(const Vector2i &p, int button, bool down, int modifiers) override;
/// Handle a mouse motion event (default implementation: propagate to children) /// Handle a mouse motion event (default implementation: propagate to children)
virtual bool mouseMotionEvent(const Vector2i &p, const Vector2i &rel, int button, int modifiers) override; virtual bool mouseMotionEvent(const Vector2i &p, const Vector2i &rel, int button, int modifiers) override;
/// Handle a mouse scroll event (default implementation: propagate to children) /// Handle a mouse scroll event (default implementation: propagate to children)
virtual bool scrollEvent(const Vector2i &p, const Vector2f &rel) override; virtual bool scrollEvent(const Vector2i &p, const Vector2f &rel) override;
/// Initialize the application /// Initialize the application
void init(); void init();
/// Change the current scene /// Change the current scene
void switchScene(Scene* newScene); void switchScene(Scene* newScene);
/// Enable/Disable Vertical synchronization /// Enable/Disable Vertical synchronization
void enableVSync(bool enable); void enableVSync(bool enable);
/// Notify that the engine settings have changed /// Notify that the engine settings have changed
void notifyEngineSetttingsChanged(); void notifyEngineSetttingsChanged();
// -------------------- Friendship -------------------- // // -------------------- Friendship -------------------- //
friend class Gui; friend class Gui;
}; };
// Return the list of the scenes // Return the list of the scenes
inline std::vector<Scene*> TestbedApplication::getScenes() { inline std::vector<Scene*> TestbedApplication::getScenes() {
return mScenes; return mScenes;
} }
// Toggle play/pause for the simulation // Toggle play/pause for the simulation
inline void TestbedApplication::togglePlayPauseSimulation() { inline void TestbedApplication::togglePlayPauseSimulation() {
if (mTimer.isRunning()) { if (mTimer.isRunning()) {
mTimer.stop(); mTimer.stop();
} }
else { else {
mTimer.start(); mTimer.start();
} }
} }
// Play the simulation // Play the simulation
inline void TestbedApplication::playSimulation() { inline void TestbedApplication::playSimulation() {
if (!mTimer.isRunning()) mTimer.start(); if (!mTimer.isRunning()) mTimer.start();
} }
// Pause the simulation // Pause the simulation
inline void TestbedApplication::pauseSimulation() { inline void TestbedApplication::pauseSimulation() {
if (mTimer.isRunning()) mTimer.stop(); if (mTimer.isRunning()) mTimer.stop();
} }
// Restart the simulation // Restart the simulation
inline void TestbedApplication::restartSimulation() { inline void TestbedApplication::restartSimulation() {
mCurrentScene->reset(); mCurrentScene->reset();
mTimer.start(); mTimer.start();
} }
// Take a single step of simulation // Take a single step of simulation
inline void TestbedApplication::toggleTakeSinglePhysicsStep() { inline void TestbedApplication::toggleTakeSinglePhysicsStep() {
mSinglePhysicsStepEnabled = true; mSinglePhysicsStepEnabled = true;
mSinglePhysicsStepDone = false; mSinglePhysicsStepDone = false;
if (mTimer.isRunning()) { if (mTimer.isRunning()) {
mSinglePhysicsStepEnabled = false; mSinglePhysicsStepEnabled = false;
} }
} }
// Enable/Disable Vertical synchronization // Enable/Disable Vertical synchronization
inline void TestbedApplication::enableVSync(bool enable) { inline void TestbedApplication::enableVSync(bool enable) {
mIsVSyncEnabled = enable; mIsVSyncEnabled = enable;
if (mIsVSyncEnabled) { if (mIsVSyncEnabled) {
glfwSwapInterval(1); glfwSwapInterval(1);
} }
else { else {
glfwSwapInterval(0); glfwSwapInterval(0);
} }
} }
#endif #endif