diff --git a/testbed/common/Box.cpp b/testbed/common/Box.cpp index 4eefdf9e..3845644a 100644 --- a/testbed/common/Box.cpp +++ b/testbed/common/Box.cpp @@ -33,7 +33,7 @@ openglframework::VertexBufferObject Box::mVBOVertices(GL_ARRAY_BUFFER); openglframework::VertexBufferObject Box::mVBOIndices(GL_ELEMENT_ARRAY_BUFFER); openglframework::VertexArrayObject Box::mVAO; -bool Box::areVBOsCreated = false; +int Box::totalNbBoxes = 0; VertexData Box::mCubeVertices[8] = { {openglframework::Vector3(1,1,1),openglframework::Vector3(1,1,1),openglframework::Color(1,0,0,1)}, {openglframework::Vector3(-1,1,1),openglframework::Vector3(-1,1,1),openglframework::Color(1,0,0,1)}, @@ -95,12 +95,14 @@ Box::Box(const openglframework::Vector3& size, const openglframework::Vector3 &p mRigidBody->addCollisionShape(collisionShape, rp3d::Transform::identity()); // If the Vertex Buffer object has not been created yet - if (!areVBOsCreated) { + if (totalNbBoxes == 0) { // Create the Vertex Buffer createVBOAndVAO(shader); } + totalNbBoxes++; + mTransformMatrix = mTransformMatrix * mScalingMatrix; } @@ -142,26 +144,29 @@ Box::Box(const openglframework::Vector3& size, const openglframework::Vector3 &p mRigidBody = body; // If the Vertex Buffer object has not been created yet - if (!areVBOsCreated) { + if (totalNbBoxes == 0) { + // Create the Vertex Buffer createVBOAndVAO(shader); } + totalNbBoxes++; + mTransformMatrix = mTransformMatrix * mScalingMatrix; } // Destructor Box::~Box() { - if (areVBOsCreated) { + if (totalNbBoxes == 1) { // Destroy the VBOs and VAO mVBOIndices.destroy(); mVBOVertices.destroy(); mVAO.destroy(); - - areVBOsCreated = false; } + + totalNbBoxes--; } // Render the cube at the correct position and with the correct orientation @@ -239,7 +244,6 @@ void Box::createVBOAndVAO(openglframework::Shader& shader) { mVBOVertices.bind(); mVBOVertices.copyDataIntoVBO(sizeof(mCubeVertices), mCubeVertices, GL_STATIC_DRAW); mVBOVertices.unbind(); - size_t test = sizeof(mCubeVertices); // Create th VBO for the indices data mVBOIndices.create(); @@ -268,6 +272,22 @@ void Box::createVBOAndVAO(openglframework::Shader& shader) { // Unbind the shader shader.unbind(); - - areVBOsCreated = true; +} + +// Reset the transform +void Box::resetTransform(const rp3d::Transform& transform) { + + // Reset the transform + mRigidBody->setTransform(transform); + + mRigidBody->setIsSleeping(false); + + // Reset the velocity of the rigid body + rp3d::RigidBody* rigidBody = dynamic_cast(mRigidBody); + if (rigidBody != NULL) { + rigidBody->setLinearVelocity(rp3d::Vector3(0, 0, 0)); + rigidBody->setAngularVelocity(rp3d::Vector3(0, 0, 0)); + } + + updateTransform(1.0f); } diff --git a/testbed/common/Box.h b/testbed/common/Box.h index 7d0b2721..efacafb4 100644 --- a/testbed/common/Box.h +++ b/testbed/common/Box.h @@ -77,8 +77,8 @@ class Box : public openglframework::Object3D { /// Indices of the cube (used to render the box) static GLuint mCubeIndices[36]; - /// True if the VBOs have already been created - static bool areVBOsCreated; + /// Total number of boxes created + static int totalNbBoxes; /// Main color of the box openglframework::Color mColor; @@ -117,6 +117,9 @@ class Box : public openglframework::Object3D { /// Set the color of the box void setColor(const openglframework::Color& color); + + /// Set the position of the box + void resetTransform(const rp3d::Transform& transform); }; // Return a pointer to the collision body of the box diff --git a/testbed/common/Capsule.cpp b/testbed/common/Capsule.cpp index 186970ff..7a38838b 100644 --- a/testbed/common/Capsule.cpp +++ b/testbed/common/Capsule.cpp @@ -26,13 +26,18 @@ // Libraries #include "Capsule.h" +openglframework::VertexBufferObject Capsule::mVBOVertices(GL_ARRAY_BUFFER); +openglframework::VertexBufferObject Capsule::mVBONormals(GL_ARRAY_BUFFER); +openglframework::VertexBufferObject Capsule::mVBOTextureCoords(GL_ARRAY_BUFFER); +openglframework::VertexBufferObject Capsule::mVBOIndices(GL_ELEMENT_ARRAY_BUFFER); +openglframework::VertexArrayObject Capsule::mVAO; +int Capsule::totalNbCapsules = 0; + // Constructor Capsule::Capsule(float radius, float height, const openglframework::Vector3& position, reactphysics3d::CollisionWorld* world, const std::string& meshFolderPath, openglframework::Shader& shader) - : openglframework::Mesh(), mRadius(radius), mHeight(height), mVBOVertices(GL_ARRAY_BUFFER), - mVBONormals(GL_ARRAY_BUFFER), mVBOTextureCoords(GL_ARRAY_BUFFER), - mVBOIndices(GL_ELEMENT_ARRAY_BUFFER), mColor(0.5f, 0.5f, 0.5f, 1.0f) { + : openglframework::Mesh(), mRadius(radius), mHeight(height) { // Load the mesh from a file openglframework::MeshReaderWriter::loadMeshFromFile(meshFolderPath + "capsule.obj", *this); @@ -70,7 +75,11 @@ Capsule::Capsule(float radius, float height, const openglframework::Vector3& pos mTransformMatrix = mTransformMatrix * mScalingMatrix; // Create the VBOs and VAO - createVBOAndVAO(shader); + if (totalNbCapsules == 0) { + createVBOAndVAO(shader); + } + + totalNbCapsules++; } // Constructor @@ -78,8 +87,6 @@ Capsule::Capsule(float radius, float height, const openglframework::Vector3& pos float mass, reactphysics3d::DynamicsWorld* dynamicsWorld, const std::string& meshFolderPath, openglframework::Shader &shader) : openglframework::Mesh(), mRadius(radius), mHeight(height), - mVBOVertices(GL_ARRAY_BUFFER), mVBONormals(GL_ARRAY_BUFFER), - mVBOTextureCoords(GL_ARRAY_BUFFER), mVBOIndices(GL_ELEMENT_ARRAY_BUFFER), mColor(0.5f, 0.5f, 0.5f, 1.0f) { // Load the mesh from a file @@ -118,21 +125,30 @@ Capsule::Capsule(float radius, float height, const openglframework::Vector3& pos mTransformMatrix = mTransformMatrix * mScalingMatrix; // Create the VBOs and VAO - createVBOAndVAO(shader); + if (totalNbCapsules == 0) { + createVBOAndVAO(shader); + } + + totalNbCapsules++; } // Destructor Capsule::~Capsule() { - // Destroy the mesh - destroy(); + if (totalNbCapsules == 1) { - // Destroy the VBOs and VAO - mVBOIndices.destroy(); - mVBOVertices.destroy(); - mVBONormals.destroy(); - mVBOTextureCoords.destroy(); - mVAO.destroy(); + // Destroy the mesh + destroy(); + + // Destroy the VBOs and VAO + mVBOIndices.destroy(); + mVBOVertices.destroy(); + mVBONormals.destroy(); + mVBOTextureCoords.destroy(); + mVAO.destroy(); + } + + totalNbCapsules--; } // Render the sphere at the correct position and with the correct orientation @@ -267,3 +283,21 @@ void Capsule::createVBOAndVAO(openglframework::Shader& shader) { // Unbind the shader shader.unbind(); } + +// Reset the transform +void Capsule::resetTransform(const rp3d::Transform& transform) { + + // Reset the transform + mRigidBody->setTransform(transform); + + mRigidBody->setIsSleeping(false); + + // Reset the velocity of the rigid body + rp3d::RigidBody* rigidBody = dynamic_cast(mRigidBody); + if (rigidBody != NULL) { + rigidBody->setLinearVelocity(rp3d::Vector3(0, 0, 0)); + rigidBody->setAngularVelocity(rp3d::Vector3(0, 0, 0)); + } + + updateTransform(1.0f); +} diff --git a/testbed/common/Capsule.h b/testbed/common/Capsule.h index 143c620d..94486834 100644 --- a/testbed/common/Capsule.h +++ b/testbed/common/Capsule.h @@ -53,19 +53,22 @@ class Capsule : public openglframework::Mesh { rp3d::Transform mPreviousTransform; /// Vertex Buffer Object for the vertices data - openglframework::VertexBufferObject mVBOVertices; + static openglframework::VertexBufferObject mVBOVertices; /// Vertex Buffer Object for the normals data - openglframework::VertexBufferObject mVBONormals; + static openglframework::VertexBufferObject mVBONormals; /// Vertex Buffer Object for the texture coords - openglframework::VertexBufferObject mVBOTextureCoords; + static openglframework::VertexBufferObject mVBOTextureCoords; /// Vertex Buffer Object for the indices - openglframework::VertexBufferObject mVBOIndices; + static openglframework::VertexBufferObject mVBOIndices; /// Vertex Array Object for the vertex data - openglframework::VertexArrayObject mVAO; + static openglframework::VertexArrayObject mVAO; + + // Total number of capsules created + static int totalNbCapsules; /// Color openglframework::Color mColor; @@ -104,6 +107,9 @@ class Capsule : public openglframework::Mesh { /// Render the sphere at the correct position and with the correct orientation void render(openglframework::Shader& shader, const openglframework::Matrix4& worldToCameraMatrix); + + /// Set the position of the box + void resetTransform(const rp3d::Transform& transform); }; // Return a pointer to the collision body of the box diff --git a/testbed/common/Cone.cpp b/testbed/common/Cone.cpp index fbd2aadc..0e98211f 100644 --- a/testbed/common/Cone.cpp +++ b/testbed/common/Cone.cpp @@ -26,13 +26,18 @@ // Libraries #include "Cone.h" +openglframework::VertexBufferObject Cone::mVBOVertices(GL_ARRAY_BUFFER); +openglframework::VertexBufferObject Cone::mVBONormals(GL_ARRAY_BUFFER); +openglframework::VertexBufferObject Cone::mVBOTextureCoords(GL_ARRAY_BUFFER); +openglframework::VertexBufferObject Cone::mVBOIndices(GL_ELEMENT_ARRAY_BUFFER); +openglframework::VertexArrayObject Cone::mVAO; +int Cone::totalNbCones = 0; + // Constructor Cone::Cone(float radius, float height, const openglframework::Vector3 &position, reactphysics3d::CollisionWorld* world, const std::string& meshFolderPath, openglframework::Shader& shader) : openglframework::Mesh(), mRadius(radius), mHeight(height), - mVBOVertices(GL_ARRAY_BUFFER), mVBONormals(GL_ARRAY_BUFFER), - mVBOTextureCoords(GL_ARRAY_BUFFER), mVBOIndices(GL_ELEMENT_ARRAY_BUFFER), mColor(0.5f, 0.5f, 0.5f, 1.0f) { // Load the mesh from a file @@ -71,7 +76,11 @@ Cone::Cone(float radius, float height, const openglframework::Vector3 &position, mTransformMatrix = mTransformMatrix * mScalingMatrix; // Create the VBOs and VAO - createVBOAndVAO(shader); + if (totalNbCones == 0) { + createVBOAndVAO(shader); + } + + totalNbCones++; } // Constructor @@ -79,8 +88,6 @@ Cone::Cone(float radius, float height, const openglframework::Vector3 &position, float mass, reactphysics3d::DynamicsWorld* dynamicsWorld, const std::string& meshFolderPath, openglframework::Shader &shader) : openglframework::Mesh(), mRadius(radius), mHeight(height), - mVBOVertices(GL_ARRAY_BUFFER), mVBONormals(GL_ARRAY_BUFFER), - mVBOTextureCoords(GL_ARRAY_BUFFER), mVBOIndices(GL_ELEMENT_ARRAY_BUFFER), mColor(0.5f, 0.5f, 0.5f, 1.0f) { // Load the mesh from a file @@ -119,21 +126,29 @@ Cone::Cone(float radius, float height, const openglframework::Vector3 &position, mTransformMatrix = mTransformMatrix * mScalingMatrix; // Create the VBOs and VAO - createVBOAndVAO(shader); + if (totalNbCones == 0) { + createVBOAndVAO(shader); + } + + totalNbCones++; } // Destructor Cone::~Cone() { - // Destroy the mesh - destroy(); + if (totalNbCones == 1) { + // Destroy the mesh + destroy(); - // Destroy the VBOs and VAO - mVBOIndices.destroy(); - mVBOVertices.destroy(); - mVBONormals.destroy(); - mVBOTextureCoords.destroy(); - mVAO.destroy(); + // Destroy the VBOs and VAO + mVBOIndices.destroy(); + mVBOVertices.destroy(); + mVBONormals.destroy(); + mVBOTextureCoords.destroy(); + mVAO.destroy(); + } + + totalNbCones--; } // Render the cone at the correct position and with the correct orientation @@ -270,3 +285,21 @@ void Cone::createVBOAndVAO(openglframework::Shader& shader) { shader.unbind(); } +// Reset the transform +void Cone::resetTransform(const rp3d::Transform& transform) { + + // Reset the transform + mRigidBody->setTransform(transform); + + mRigidBody->setIsSleeping(false); + + // Reset the velocity of the rigid body + rp3d::RigidBody* rigidBody = dynamic_cast(mRigidBody); + if (rigidBody != NULL) { + rigidBody->setLinearVelocity(rp3d::Vector3(0, 0, 0)); + rigidBody->setAngularVelocity(rp3d::Vector3(0, 0, 0)); + } + + updateTransform(1.0f); +} + diff --git a/testbed/common/Cone.h b/testbed/common/Cone.h index d3121b53..7d3f17f8 100644 --- a/testbed/common/Cone.h +++ b/testbed/common/Cone.h @@ -53,19 +53,22 @@ class Cone : public openglframework::Mesh { rp3d::Transform mPreviousTransform; /// Vertex Buffer Object for the vertices data - openglframework::VertexBufferObject mVBOVertices; + static openglframework::VertexBufferObject mVBOVertices; /// Vertex Buffer Object for the normals data - openglframework::VertexBufferObject mVBONormals; + static openglframework::VertexBufferObject mVBONormals; /// Vertex Buffer Object for the texture coords - openglframework::VertexBufferObject mVBOTextureCoords; + static openglframework::VertexBufferObject mVBOTextureCoords; /// Vertex Buffer Object for the indices - openglframework::VertexBufferObject mVBOIndices; + static openglframework::VertexBufferObject mVBOIndices; /// Vertex Array Object for the vertex data - openglframework::VertexArrayObject mVAO; + static openglframework::VertexArrayObject mVAO; + + // Total number of cones created + static int totalNbCones; /// Color openglframework::Color mColor; @@ -103,6 +106,9 @@ class Cone : public openglframework::Mesh { /// Render the cone at the correct position and with the correct orientation void render(openglframework::Shader& shader, const openglframework::Matrix4& worldToCameraMatrix); + + /// Set the position of the box + void resetTransform(const rp3d::Transform& transform); }; // Return a pointer to the collision body of the box diff --git a/testbed/common/ConvexMesh.cpp b/testbed/common/ConvexMesh.cpp index e55bad1f..25287c40 100644 --- a/testbed/common/ConvexMesh.cpp +++ b/testbed/common/ConvexMesh.cpp @@ -306,3 +306,21 @@ void ConvexMesh::createVBOAndVAO(openglframework::Shader& shader) { // Unbind the shader shader.unbind(); } + +// Reset the transform +void ConvexMesh::resetTransform(const rp3d::Transform& transform) { + + // Reset the transform + mRigidBody->setTransform(transform); + + mRigidBody->setIsSleeping(false); + + // Reset the velocity of the rigid body + rp3d::RigidBody* rigidBody = dynamic_cast(mRigidBody); + if (rigidBody != NULL) { + rigidBody->setLinearVelocity(rp3d::Vector3(0, 0, 0)); + rigidBody->setAngularVelocity(rp3d::Vector3(0, 0, 0)); + } + + updateTransform(1.0f); +} diff --git a/testbed/common/ConvexMesh.h b/testbed/common/ConvexMesh.h index bf680104..ac586dfb 100644 --- a/testbed/common/ConvexMesh.h +++ b/testbed/common/ConvexMesh.h @@ -94,6 +94,9 @@ class ConvexMesh : public openglframework::Mesh { /// Render the mesh at the correct position and with the correct orientation void render(openglframework::Shader& shader, const openglframework::Matrix4& worldToCameraMatrix); + + /// Set the position of the box + void resetTransform(const rp3d::Transform& transform); }; // Return a pointer to the collision body of the box diff --git a/testbed/common/Cylinder.cpp b/testbed/common/Cylinder.cpp index 02ff1fba..e6e8eed8 100644 --- a/testbed/common/Cylinder.cpp +++ b/testbed/common/Cylinder.cpp @@ -26,14 +26,19 @@ // Libraries #include "Cylinder.h" +openglframework::VertexBufferObject Cylinder::mVBOVertices(GL_ARRAY_BUFFER); +openglframework::VertexBufferObject Cylinder::mVBONormals(GL_ARRAY_BUFFER); +openglframework::VertexBufferObject Cylinder::mVBOTextureCoords(GL_ARRAY_BUFFER); +openglframework::VertexBufferObject Cylinder::mVBOIndices(GL_ELEMENT_ARRAY_BUFFER); +openglframework::VertexArrayObject Cylinder::mVAO; +int Cylinder::totalNbCylinders = 0; + // Constructor Cylinder::Cylinder(float radius, float height, const openglframework::Vector3& position, reactphysics3d::CollisionWorld* world, const std::string& meshFolderPath, openglframework::Shader& shader) : openglframework::Mesh(), mRadius(radius), mHeight(height), - mVBOVertices(GL_ARRAY_BUFFER), mVBONormals(GL_ARRAY_BUFFER), - mVBOTextureCoords(GL_ARRAY_BUFFER), mVBOIndices(GL_ELEMENT_ARRAY_BUFFER), mColor(0.5f, 0.5f, 0.5f, 1.0f) { // Load the mesh from a file @@ -72,7 +77,11 @@ Cylinder::Cylinder(float radius, float height, const openglframework::Vector3& p mTransformMatrix = mTransformMatrix * mScalingMatrix; // Create the VBOs and VAO - createVBOAndVAO(shader); + if (totalNbCylinders == 0) { + createVBOAndVAO(shader); + } + + totalNbCylinders++; } // Constructor @@ -80,8 +89,6 @@ Cylinder::Cylinder(float radius, float height, const openglframework::Vector3& p float mass, reactphysics3d::DynamicsWorld* dynamicsWorld, const std::string& meshFolderPath, openglframework::Shader& shader) : openglframework::Mesh(), mRadius(radius), mHeight(height), - mVBOVertices(GL_ARRAY_BUFFER), mVBONormals(GL_ARRAY_BUFFER), - mVBOTextureCoords(GL_ARRAY_BUFFER), mVBOIndices(GL_ELEMENT_ARRAY_BUFFER), mColor(0.5f, 0.5f, 0.5f, 1.0f) { // Load the mesh from a file @@ -120,21 +127,30 @@ Cylinder::Cylinder(float radius, float height, const openglframework::Vector3& p mRigidBody = body; // Create the VBOs and VAO - createVBOAndVAO(shader); + if (totalNbCylinders == 0) { + createVBOAndVAO(shader); + } + + totalNbCylinders++; } // Destructor Cylinder::~Cylinder() { - // Destroy the mesh - destroy(); + if (totalNbCylinders == 1) { - // Destroy the VBOs and VAO - mVBOIndices.destroy(); - mVBOVertices.destroy(); - mVBONormals.destroy(); - mVBOTextureCoords.destroy(); - mVAO.destroy(); + // Destroy the mesh + destroy(); + + // Destroy the VBOs and VAO + mVBOIndices.destroy(); + mVBOVertices.destroy(); + mVBONormals.destroy(); + mVBOTextureCoords.destroy(); + mVAO.destroy(); + } + + totalNbCylinders--; } // Render the cylinder at the correct position and with the correct orientation @@ -269,3 +285,21 @@ void Cylinder::createVBOAndVAO(openglframework::Shader& shader) { // Unbind the shader shader.unbind(); } + +// Reset the transform +void Cylinder::resetTransform(const rp3d::Transform& transform) { + + // Reset the transform + mRigidBody->setTransform(transform); + + mRigidBody->setIsSleeping(false); + + // Reset the velocity of the rigid body + rp3d::RigidBody* rigidBody = dynamic_cast(mRigidBody); + if (rigidBody != NULL) { + rigidBody->setLinearVelocity(rp3d::Vector3(0, 0, 0)); + rigidBody->setAngularVelocity(rp3d::Vector3(0, 0, 0)); + } + + updateTransform(1.0f); +} diff --git a/testbed/common/Cylinder.h b/testbed/common/Cylinder.h index 021ef009..ab91ad43 100644 --- a/testbed/common/Cylinder.h +++ b/testbed/common/Cylinder.h @@ -53,19 +53,22 @@ class Cylinder : public openglframework::Mesh { rp3d::Transform mPreviousTransform; /// Vertex Buffer Object for the vertices data - openglframework::VertexBufferObject mVBOVertices; + static openglframework::VertexBufferObject mVBOVertices; /// Vertex Buffer Object for the normals data - openglframework::VertexBufferObject mVBONormals; + static openglframework::VertexBufferObject mVBONormals; /// Vertex Buffer Object for the texture coords - openglframework::VertexBufferObject mVBOTextureCoords; + static openglframework::VertexBufferObject mVBOTextureCoords; /// Vertex Buffer Object for the indices - openglframework::VertexBufferObject mVBOIndices; + static openglframework::VertexBufferObject mVBOIndices; /// Vertex Array Object for the vertex data - openglframework::VertexArrayObject mVAO; + static openglframework::VertexArrayObject mVAO; + + // Total number of capsules created + static int totalNbCylinders; /// Color openglframework::Color mColor; @@ -104,6 +107,9 @@ class Cylinder : public openglframework::Mesh { /// Render the cylinder at the correct position and with the correct orientation void render(openglframework::Shader& shader, const openglframework::Matrix4& worldToCameraMatrix); + + /// Set the position of the box + void resetTransform(const rp3d::Transform& transform); }; // Return a pointer to the collision body of the box diff --git a/testbed/common/Dumbbell.cpp b/testbed/common/Dumbbell.cpp index f80a313b..66a9f3c1 100644 --- a/testbed/common/Dumbbell.cpp +++ b/testbed/common/Dumbbell.cpp @@ -26,13 +26,18 @@ // Libraries #include "Dumbbell.h" +openglframework::VertexBufferObject Dumbbell::mVBOVertices(GL_ARRAY_BUFFER); +openglframework::VertexBufferObject Dumbbell::mVBONormals(GL_ARRAY_BUFFER); +openglframework::VertexBufferObject Dumbbell::mVBOTextureCoords(GL_ARRAY_BUFFER); +openglframework::VertexBufferObject Dumbbell::mVBOIndices(GL_ELEMENT_ARRAY_BUFFER); +openglframework::VertexArrayObject Dumbbell::mVAO; +int Dumbbell::totalNbDumbbells = 0; + // Constructor Dumbbell::Dumbbell(const openglframework::Vector3 &position, reactphysics3d::DynamicsWorld* dynamicsWorld, const std::string& meshFolderPath, openglframework::Shader& shader) - : openglframework::Mesh(),mVBOVertices(GL_ARRAY_BUFFER), - mVBONormals(GL_ARRAY_BUFFER), mVBOTextureCoords(GL_ARRAY_BUFFER), - mVBOIndices(GL_ELEMENT_ARRAY_BUFFER), mColor(0.5f, 0.5f, 0.5f, 1.0f) { + : openglframework::Mesh(), mColor(0.5f, 0.5f, 0.5f, 1.0f) { // Load the mesh from a file openglframework::MeshReaderWriter::loadMeshFromFile(meshFolderPath + "dumbbell.obj", *this); @@ -91,16 +96,18 @@ Dumbbell::Dumbbell(const openglframework::Vector3 &position, mTransformMatrix = mTransformMatrix * mScalingMatrix; // Create the VBOs and VAO - createVBOAndVAO(shader); + if (totalNbDumbbells == 0) { + createVBOAndVAO(shader); + } + + totalNbDumbbells++; } // Constructor Dumbbell::Dumbbell(const openglframework::Vector3 &position, reactphysics3d::CollisionWorld* world, const std::string& meshFolderPath, openglframework::Shader& shader) - : openglframework::Mesh(), mVBOVertices(GL_ARRAY_BUFFER), - mVBONormals(GL_ARRAY_BUFFER), mVBOTextureCoords(GL_ARRAY_BUFFER), - mVBOIndices(GL_ELEMENT_ARRAY_BUFFER), mColor(0.5f, 0.5f, 0.5f, 1.0f) { + : openglframework::Mesh(), mColor(0.5f, 0.5f, 0.5f, 1.0f) { // Load the mesh from a file openglframework::MeshReaderWriter::loadMeshFromFile(meshFolderPath + "dumbbell.obj", *this); @@ -155,21 +162,30 @@ Dumbbell::Dumbbell(const openglframework::Vector3 &position, mTransformMatrix = mTransformMatrix * mScalingMatrix; // Create the VBOs and VAO - createVBOAndVAO(shader); + if (totalNbDumbbells == 0) { + createVBOAndVAO(shader); + } + + totalNbDumbbells++; } // Destructor Dumbbell::~Dumbbell() { - // Destroy the mesh - destroy(); + if (totalNbDumbbells == 1) { - // Destroy the VBOs and VAO - mVBOIndices.destroy(); - mVBOVertices.destroy(); - mVBONormals.destroy(); - mVBOTextureCoords.destroy(); - mVAO.destroy(); + // Destroy the mesh + destroy(); + + // Destroy the VBOs and VAO + mVBOIndices.destroy(); + mVBOVertices.destroy(); + mVBONormals.destroy(); + mVBOTextureCoords.destroy(); + mVAO.destroy(); + } + + totalNbDumbbells--; } // Render the sphere at the correct position and with the correct orientation @@ -304,3 +320,21 @@ void Dumbbell::createVBOAndVAO(openglframework::Shader& shader) { // Unbind the shader shader.unbind(); } + +// Reset the transform +void Dumbbell::resetTransform(const rp3d::Transform& transform) { + + // Reset the transform + mBody->setTransform(transform); + + mBody->setIsSleeping(false); + + // Reset the velocity of the rigid body + rp3d::RigidBody* rigidBody = dynamic_cast(mBody); + if (rigidBody != NULL) { + rigidBody->setLinearVelocity(rp3d::Vector3(0, 0, 0)); + rigidBody->setAngularVelocity(rp3d::Vector3(0, 0, 0)); + } + + updateTransform(1.0f); +} diff --git a/testbed/common/Dumbbell.h b/testbed/common/Dumbbell.h index 9bfe8b9e..01c4d15a 100644 --- a/testbed/common/Dumbbell.h +++ b/testbed/common/Dumbbell.h @@ -50,19 +50,22 @@ class Dumbbell : public openglframework::Mesh { rp3d::Transform mPreviousTransform; /// Vertex Buffer Object for the vertices data - openglframework::VertexBufferObject mVBOVertices; + static openglframework::VertexBufferObject mVBOVertices; /// Vertex Buffer Object for the normals data - openglframework::VertexBufferObject mVBONormals; + static openglframework::VertexBufferObject mVBONormals; /// Vertex Buffer Object for the texture coords - openglframework::VertexBufferObject mVBOTextureCoords; + static openglframework::VertexBufferObject mVBOTextureCoords; /// Vertex Buffer Object for the indices - openglframework::VertexBufferObject mVBOIndices; + static openglframework::VertexBufferObject mVBOIndices; /// Vertex Array Object for the vertex data - openglframework::VertexArrayObject mVAO; + static openglframework::VertexArrayObject mVAO; + + // Total number of capsules created + static int totalNbDumbbells; /// Color openglframework::Color mColor; @@ -100,6 +103,9 @@ class Dumbbell : public openglframework::Mesh { /// Render the sphere at the correct position and with the correct orientation void render(openglframework::Shader& shader, const openglframework::Matrix4& worldToCameraMatrix); + + /// Set the position of the box + void resetTransform(const rp3d::Transform& transform); }; // Return a pointer to the rigid body of the sphere diff --git a/testbed/common/Line.cpp b/testbed/common/Line.cpp index 9263c1d6..56280e43 100644 --- a/testbed/common/Line.cpp +++ b/testbed/common/Line.cpp @@ -49,6 +49,10 @@ void Line::render(openglframework::Shader& shader, // Set the model to camera matrix shader.setMatrix4x4Uniform("localToCameraMatrix", worldToCameraMatrix); + // Set the vertex color + openglframework::Vector4 color(1, 0, 0, 1); + shader.setVector4Uniform("vertexColor", color); + glBegin(GL_LINES); glVertex3f(mWorldPoint1.x, mWorldPoint1.y, mWorldPoint1.z); glVertex3f(mWorldPoint2.x, mWorldPoint2.y, mWorldPoint2.z); diff --git a/testbed/common/Sphere.cpp b/testbed/common/Sphere.cpp index 0356ccbb..73ff71a5 100644 --- a/testbed/common/Sphere.cpp +++ b/testbed/common/Sphere.cpp @@ -26,13 +26,18 @@ // Libraries #include "Sphere.h" +openglframework::VertexBufferObject Sphere::mVBOVertices(GL_ARRAY_BUFFER); +openglframework::VertexBufferObject Sphere::mVBONormals(GL_ARRAY_BUFFER); +openglframework::VertexBufferObject Sphere::mVBOTextureCoords(GL_ARRAY_BUFFER); +openglframework::VertexBufferObject Sphere::mVBOIndices(GL_ELEMENT_ARRAY_BUFFER); +openglframework::VertexArrayObject Sphere::mVAO; +int Sphere::totalNbSpheres = 0; + // Constructor Sphere::Sphere(float radius, const openglframework::Vector3 &position, reactphysics3d::CollisionWorld* world, const std::string& meshFolderPath, openglframework::Shader& shader) - : openglframework::Mesh(), mRadius(radius), mVBOVertices(GL_ARRAY_BUFFER), - mVBONormals(GL_ARRAY_BUFFER), mVBOTextureCoords(GL_ARRAY_BUFFER), - mVBOIndices(GL_ELEMENT_ARRAY_BUFFER), mColor(0.5f, 0.5f, 0.5f, 1.0f) { + : openglframework::Mesh(), mRadius(radius), mColor(0.5f, 0.5f, 0.5f, 1.0f) { // Load the mesh from a file openglframework::MeshReaderWriter::loadMeshFromFile(meshFolderPath + "sphere.obj", *this); @@ -70,16 +75,18 @@ Sphere::Sphere(float radius, const openglframework::Vector3 &position, mTransformMatrix = mTransformMatrix * mScalingMatrix; // Create the VBOs and VAO - createVBOAndVAO(shader); + if (totalNbSpheres == 0) { + createVBOAndVAO(shader); + } + + totalNbSpheres++; } // Constructor Sphere::Sphere(float radius, const openglframework::Vector3 &position, float mass, reactphysics3d::DynamicsWorld* world, const std::string& meshFolderPath, openglframework::Shader& shader) - : openglframework::Mesh(), mRadius(radius), mVBOVertices(GL_ARRAY_BUFFER), - mVBONormals(GL_ARRAY_BUFFER), mVBOTextureCoords(GL_ARRAY_BUFFER), - mVBOIndices(GL_ELEMENT_ARRAY_BUFFER), mColor(0.5f, 0.5f, 0.5f, 1.0f) { + : openglframework::Mesh(), mRadius(radius), mColor(0.5f, 0.5f, 0.5f, 1.0f) { // Load the mesh from a file openglframework::MeshReaderWriter::loadMeshFromFile(meshFolderPath + "sphere.obj", *this); @@ -117,21 +124,29 @@ Sphere::Sphere(float radius, const openglframework::Vector3 &position, mTransformMatrix = mTransformMatrix * mScalingMatrix; // Create the VBOs and VAO - createVBOAndVAO(shader); + if (totalNbSpheres == 0) { + createVBOAndVAO(shader); + } + + totalNbSpheres++; } // Destructor Sphere::~Sphere() { - // Destroy the mesh - destroy(); + if (totalNbSpheres == 1) { + // Destroy the mesh + destroy(); - // Destroy the VBOs and VAO - mVBOIndices.destroy(); - mVBOVertices.destroy(); - mVBONormals.destroy(); - mVBOTextureCoords.destroy(); - mVAO.destroy(); + // Destroy the VBOs and VAO + mVBOIndices.destroy(); + mVBOVertices.destroy(); + mVBONormals.destroy(); + mVBOTextureCoords.destroy(); + mVAO.destroy(); + } + + totalNbSpheres--; } // Render the sphere at the correct position and with the correct orientation @@ -266,3 +281,21 @@ void Sphere::createVBOAndVAO(openglframework::Shader& shader) { // Unbind the shader shader.unbind(); } + +// Reset the transform +void Sphere::resetTransform(const rp3d::Transform& transform) { + + // Reset the transform + mRigidBody->setTransform(transform); + + mRigidBody->setIsSleeping(false); + + // Reset the velocity of the rigid body + rp3d::RigidBody* rigidBody = dynamic_cast(mRigidBody); + if (rigidBody != NULL) { + rigidBody->setLinearVelocity(rp3d::Vector3(0, 0, 0)); + rigidBody->setAngularVelocity(rp3d::Vector3(0, 0, 0)); + } + + updateTransform(1.0f); +} diff --git a/testbed/common/Sphere.h b/testbed/common/Sphere.h index 69813c98..7bef7196 100644 --- a/testbed/common/Sphere.h +++ b/testbed/common/Sphere.h @@ -50,19 +50,22 @@ class Sphere : public openglframework::Mesh { rp3d::Transform mPreviousTransform; /// Vertex Buffer Object for the vertices data - openglframework::VertexBufferObject mVBOVertices; + static openglframework::VertexBufferObject mVBOVertices; /// Vertex Buffer Object for the normals data - openglframework::VertexBufferObject mVBONormals; + static openglframework::VertexBufferObject mVBONormals; /// Vertex Buffer Object for the texture coords - openglframework::VertexBufferObject mVBOTextureCoords; + static openglframework::VertexBufferObject mVBOTextureCoords; /// Vertex Buffer Object for the indices - openglframework::VertexBufferObject mVBOIndices; + static openglframework::VertexBufferObject mVBOIndices; /// Vertex Array Object for the vertex data - openglframework::VertexArrayObject mVAO; + static openglframework::VertexArrayObject mVAO; + + // Total number of capsules created + static int totalNbSpheres; /// Color openglframework::Color mColor; @@ -101,6 +104,9 @@ class Sphere : public openglframework::Mesh { /// Render the sphere at the correct position and with the correct orientation void render(openglframework::Shader& shader, const openglframework::Matrix4& worldToCameraMatrix); + + /// Set the position of the box + void resetTransform(const rp3d::Transform& transform); }; // Return a pointer to the collision body of the box diff --git a/testbed/common/VisualContactPoint.cpp b/testbed/common/VisualContactPoint.cpp index 77337192..df8f3bb0 100644 --- a/testbed/common/VisualContactPoint.cpp +++ b/testbed/common/VisualContactPoint.cpp @@ -27,46 +27,65 @@ #include "VisualContactPoint.h" // Initialization of static variables +openglframework::VertexBufferObject VisualContactPoint::mVBOVertices(GL_ARRAY_BUFFER); +openglframework::VertexBufferObject VisualContactPoint::mVBONormals(GL_ARRAY_BUFFER); +openglframework::VertexBufferObject VisualContactPoint::mVBOIndices(GL_ELEMENT_ARRAY_BUFFER); +openglframework::VertexArrayObject VisualContactPoint::mVAO; int VisualContactPoint::mNbTotalPoints = 0; -bool VisualContactPoint::mIsMeshInitialized = false; openglframework::Mesh VisualContactPoint::mMesh; +int VisualContactPoint::totalNbBoxes = 0; // Constructor -VisualContactPoint::VisualContactPoint(const openglframework::Vector3& position) { +VisualContactPoint::VisualContactPoint(const openglframework::Vector3& position, + openglframework::Shader& shader, + const std::string& meshFolderPath) + : mColor(1.0f, 0.0f, 0.0f, 1.0f) { - assert(mIsMeshInitialized); - - // Initialize the position where the sphere will be rendered + // Initialize the position where the mesh will be rendered translateWorld(position); + + // Create the VBOs and VAO + if (totalNbBoxes == 0) { + createStaticData(meshFolderPath); + createVBOAndVAO(shader); + } + + totalNbBoxes++; } // Destructor VisualContactPoint::~VisualContactPoint() { + if (totalNbBoxes == 1) { + + // Destroy the VBOs and VAO + mVBOIndices.destroy(); + mVBOVertices.destroy(); + mVBONormals.destroy(); + mVAO.destroy(); + + destroyStaticData(); + } + + totalNbBoxes--; } // Load and initialize the mesh for all the contact points void VisualContactPoint::createStaticData(const std::string& meshFolderPath) { - if (!mIsMeshInitialized) { + // Load the mesh from a file + openglframework::MeshReaderWriter::loadMeshFromFile(meshFolderPath + "sphere.obj", mMesh); - // Load the mesh from a file - openglframework::MeshReaderWriter::loadMeshFromFile(meshFolderPath + "sphere.obj", mMesh); + // Calculate the normals of the mesh + mMesh.calculateNormals(); - // Calculate the normals of the mesh - mMesh.calculateNormals(); - - mMesh.scaleVertices(VISUAL_CONTACT_POINT_RADIUS); - - mIsMeshInitialized = true; - } + mMesh.scaleVertices(VISUAL_CONTACT_POINT_RADIUS); } // Destroy the mesh for the contact points void VisualContactPoint::destroyStaticData() { mMesh.destroy(); - mIsMeshInitialized = false; } // Render the sphere at the correct position and with the correct orientation @@ -86,29 +105,77 @@ void VisualContactPoint::render(openglframework::Shader& shader, localToCameraMatrix.getUpperLeft3x3Matrix().getInverse().getTranspose(); shader.setMatrix3x3Uniform("normalMatrix", normalMatrix); - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_NORMAL_ARRAY); - if (mMesh.hasTexture()) { - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - } + // Set the vertex color + openglframework::Vector4 color(mColor.r, mColor.g, mColor.b, mColor.a); + shader.setVector4Uniform("vertexColor", color); - glVertexPointer(3, GL_FLOAT, 0, mMesh.getVerticesPointer()); - glNormalPointer(GL_FLOAT, 0, mMesh.getNormalsPointer()); - if(mMesh.hasTexture()) { - glTexCoordPointer(2, GL_FLOAT, 0, mMesh.getUVTextureCoordinatesPointer()); - } + // Bind the VAO + mVAO.bind(); // For each part of the mesh for (unsigned int i=0; isetNbIterationsVelocitySolver(15); - // Create the static data for the visual contact points - VisualContactPoint::createStaticData(meshFolderPath); - float radius = 3.0f; for (int i=0; iresetTransform(transform); + } + + // Create all the boxes of the scene + for (int i=0; iresetTransform(transform); + } + + // Create all the spheres of the scene + for (int i=0; iresetTransform(transform); + } + + // Create all the cones of the scene + for (int i=0; iresetTransform(transform); + } + + // Create all the cylinders of the scene + for (int i=0; iresetTransform(transform); + } + + // Create all the capsules of the scene + for (int i=0; iresetTransform(transform); + } + + // Create all the convex meshes of the scene + for (int i=0; iresetTransform(transform); + } } diff --git a/testbed/scenes/cubes/CubesScene.cpp b/testbed/scenes/cubes/CubesScene.cpp index 7e029977..4842dd34 100644 --- a/testbed/scenes/cubes/CubesScene.cpp +++ b/testbed/scenes/cubes/CubesScene.cpp @@ -65,7 +65,7 @@ CubesScene::CubesScene(const std::string& name) // Position of the cubes float angle = i * 30.0f; openglframework::Vector3 position(radius * cos(angle), - 10 + i * (BOX_SIZE.y + 0.3f), + 30 + i * (BOX_SIZE.y + 0.3f), 0); // Create a cube and a corresponding rigid in the dynamics world @@ -150,8 +150,6 @@ void CubesScene::update() { // Render the scene void CubesScene::render() { - checkOpenGLErrors(); - glEnable(GL_DEPTH_TEST); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_CULL_FACE); @@ -172,49 +170,36 @@ void CubesScene::render() { mPhongShader.setVector3Uniform("light0SpecularColor", Vector3(specCol.r, specCol.g, specCol.b)); mPhongShader.setFloatUniform("shininess", 60.0f); - checkOpenGLErrors(); - // Render all the cubes of the scene for (std::vector::iterator it = mBoxes.begin(); it != mBoxes.end(); ++it) { (*it)->render(mPhongShader, worldToCameraMatrix); } - checkOpenGLErrors(); - // Render the floor mFloor->render(mPhongShader, worldToCameraMatrix); // Unbind the shader mPhongShader.unbind(); - - checkOpenGLErrors(); } // Reset the scene void CubesScene::reset() { -} + float radius = 2.0f; -// Check the OpenGL errors -void CubesScene::checkOpenGLErrors() { - GLenum glError; + for (int i=0; iresetTransform(transform); } } diff --git a/testbed/scenes/cubes/CubesScene.h b/testbed/scenes/cubes/CubesScene.h index 50ebb001..4c3df694 100644 --- a/testbed/scenes/cubes/CubesScene.h +++ b/testbed/scenes/cubes/CubesScene.h @@ -35,7 +35,7 @@ namespace cubesscene { // Constants -const int NB_CUBES = 200; // Number of boxes in the scene +const int NB_CUBES = 20; // Number of boxes in the scene const openglframework::Vector3 BOX_SIZE(2, 2, 2); // Box dimensions in meters const openglframework::Vector3 FLOOR_SIZE(50, 0.5f, 50); // Floor dimensions in meters const float BOX_MASS = 1.0f; // Box mass in kilograms @@ -85,9 +85,6 @@ class CubesScene : public Scene { /// Reset the scene virtual void reset(); - - // Check the OpenGL errors - static void checkOpenGLErrors(); }; } diff --git a/testbed/scenes/joints/JointsScene.cpp b/testbed/scenes/joints/JointsScene.cpp index a8688873..27c09e99 100644 --- a/testbed/scenes/joints/JointsScene.cpp +++ b/testbed/scenes/joints/JointsScene.cpp @@ -187,6 +187,72 @@ void JointsScene::render() { // Reset the scene void JointsScene::reset() { + openglframework::Vector3 positionBox(0, 15, 5); + openglframework::Vector3 boxDimension(1, 1, 1); + + for (int i=0; iresetTransform(transform); + + positionBox.y -= boxDimension.y + 0.5f; + } + + // --------------- Slider Joint --------------- // + + // Position of the box + openglframework::Vector3 positionBox1(0, 2.1f, 0); + rp3d::Vector3 initPosition(positionBox1.x, positionBox1.y, positionBox1.z); + rp3d::Quaternion initOrientation = rp3d::Quaternion::identity(); + rp3d::Transform transformBottomBox(initPosition, initOrientation); + + // Create a box and a corresponding rigid in the dynamics world + mSliderJointBottomBox->resetTransform(transformBottomBox); + + // Position of the box + openglframework::Vector3 positionBox2(0, 4.2f, 0); + initPosition = rp3d::Vector3(positionBox2.x, positionBox2.y, positionBox2.z); + initOrientation = rp3d::Quaternion::identity(); + rp3d::Transform transformTopBox(initPosition, initOrientation); + + // Create a box and a corresponding rigid in the dynamics world + mSliderJointTopBox->resetTransform(transformTopBox); + + // --------------- Propeller Hinge joint --------------- // + + // Position of the box + positionBox1 = openglframework::Vector3(0, 7, 0); + initPosition = rp3d::Vector3(positionBox1.x, positionBox1.y, positionBox1.z); + initOrientation = rp3d::Quaternion::identity(); + rp3d::Transform transformHingeBox(initPosition, initOrientation); + + // Create a box and a corresponding rigid in the dynamics world + mPropellerBox->resetTransform(transformHingeBox); + + // --------------- Fixed joint --------------- // + + // Position of the box + positionBox1 = openglframework::Vector3(5, 7, 0); + initPosition = rp3d::Vector3(positionBox1.x, positionBox1.y, positionBox1.z); + initOrientation = rp3d::Quaternion::identity(); + rp3d::Transform transformFixedBox1(initPosition, initOrientation); + + // Create a box and a corresponding rigid in the dynamics world + mFixedJointBox1->resetTransform(transformFixedBox1); + + // Position of the box + positionBox2 = openglframework::Vector3(-5, 7, 0); + initPosition = rp3d::Vector3(positionBox2.x, positionBox2.y, positionBox2.z); + initOrientation = rp3d::Quaternion::identity(); + rp3d::Transform transformFixedBox2(initPosition, initOrientation); + + // Create a box and a corresponding rigid in the dynamics world + mFixedJointBox2->resetTransform(transformFixedBox2); } // Create the boxes and joints for the Ball-and-Socket joint example diff --git a/testbed/scenes/raycast/RaycastScene.cpp b/testbed/scenes/raycast/RaycastScene.cpp index fcf86c15..774bb1bc 100644 --- a/testbed/scenes/raycast/RaycastScene.cpp +++ b/testbed/scenes/raycast/RaycastScene.cpp @@ -33,9 +33,9 @@ using namespace raycastscene; // Constructor RaycastScene::RaycastScene(const std::string& name) : Scene(name), mLight0(0), mCurrentBodyIndex(-1), mAreNormalsDisplayed(false), - mPhongShader("shaders/phong.vert", "shaders/phong.frag") { - - std::string meshFolderPath("meshes/"); + mPhongShader("shaders/phong.vert", "shaders/phong.frag"), + mMeshFolderPath("meshes/"), mRaycastManager(mPhongShader, mMeshFolderPath), + mVBOVertices(GL_ARRAY_BUFFER) { // Move the light 0 mLight0.translateWorld(Vector3(50, 50, 50)); @@ -50,14 +50,11 @@ RaycastScene::RaycastScene(const std::string& name) // Create the dynamics world for the physics simulation mCollisionWorld = new rp3d::CollisionWorld(); - // Create the static data for the visual contact points - VisualContactPoint::createStaticData(meshFolderPath); - // ---------- Dumbbell ---------- // openglframework::Vector3 position1(0, 0, 0); // Create a convex mesh and a corresponding collision body in the dynamics world - mDumbbell = new Dumbbell(position1, mCollisionWorld, meshFolderPath, mPhongShader); + mDumbbell = new Dumbbell(position1, mCollisionWorld, mMeshFolderPath, mPhongShader); // ---------- Box ---------- // openglframework::Vector3 position2(0, 0, 0); @@ -71,38 +68,41 @@ RaycastScene::RaycastScene(const std::string& name) // Create a sphere and a corresponding collision body in the dynamics world mSphere = new Sphere(SPHERE_RADIUS, position3, mCollisionWorld, - meshFolderPath, mPhongShader); + mMeshFolderPath, mPhongShader); // ---------- Cone ---------- // openglframework::Vector3 position4(0, 0, 0); // Create a cone and a corresponding collision body in the dynamics world mCone = new Cone(CONE_RADIUS, CONE_HEIGHT, position4, mCollisionWorld, - meshFolderPath, mPhongShader); + mMeshFolderPath, mPhongShader); // ---------- Cylinder ---------- // openglframework::Vector3 position5(0, 0, 0); // Create a cylinder and a corresponding collision body in the dynamics world mCylinder = new Cylinder(CYLINDER_RADIUS, CYLINDER_HEIGHT, position5, - mCollisionWorld, meshFolderPath, mPhongShader); + mCollisionWorld, mMeshFolderPath, mPhongShader); // ---------- Capsule ---------- // openglframework::Vector3 position6(0, 0, 0); // Create a cylinder and a corresponding collision body in the dynamics world mCapsule = new Capsule(CAPSULE_RADIUS, CAPSULE_HEIGHT, position6 , - mCollisionWorld, meshFolderPath, mPhongShader); + mCollisionWorld, mMeshFolderPath, mPhongShader); // ---------- Convex Mesh ---------- // openglframework::Vector3 position7(0, 0, 0); // Create a convex mesh and a corresponding collision body in the dynamics world - mConvexMesh = new ConvexMesh(position7, mCollisionWorld, meshFolderPath, mPhongShader); + mConvexMesh = new ConvexMesh(position7, mCollisionWorld, mMeshFolderPath, mPhongShader); // Create the lines that will be used for raycasting createLines(); + // Create the VBO and VAO to render the lines + createVBOAndVAO(mPhongShader); + changeBody(); } @@ -128,6 +128,9 @@ void RaycastScene::createLines() { openglframework::Vector3 point2(0.0f, 0.0f, 0.0f); Line* line = new Line(point1, point2); mLines.push_back(line); + + mLinePoints.push_back(point1); + mLinePoints.push_back(point2); } } } @@ -225,6 +228,10 @@ RaycastScene::~RaycastScene() { ++it) { delete (*it); } + + // Destroy the VBOs and VAO + mVBOVertices.destroy(); + mVAO.destroy(); } // Update the physics world (take a simulation step) @@ -264,25 +271,48 @@ void RaycastScene::render() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_CULL_FACE); - // Get the world-space to camera-space matrix - const openglframework::Matrix4 worldToCameraMatrix = mCamera.getTransformMatrix().getInverse(); - // Bind the shader mPhongShader.bind(); - openglframework::Vector4 grey(0.7, 0.7, 0.7, 1); - mPhongShader.setVector4Uniform("vertexColor", grey); + // Get the world-space to camera-space matrix + const openglframework::Matrix4 worldToCameraMatrix = mCamera.getTransformMatrix().getInverse(); // Set the variables of the shader mPhongShader.setMatrix4x4Uniform("projectionMatrix", mCamera.getProjectionMatrix()); - mPhongShader.setVector3Uniform("light0PosCameraSpace", worldToCameraMatrix * mLight0.getOrigin()); + mPhongShader.setVector3Uniform("light0PosCameraSpace",worldToCameraMatrix * mLight0.getOrigin()); mPhongShader.setVector3Uniform("lightAmbientColor", Vector3(0.3f, 0.3f, 0.3f)); - const Color& diffColLight0 = mLight0.getDiffuseColor(); - const Color& specColLight0 = mLight0.getSpecularColor(); - mPhongShader.setVector3Uniform("light0DiffuseColor", Vector3(diffColLight0.r, diffColLight0.g, diffColLight0.b)); - mPhongShader.setVector3Uniform("light0SpecularColor", Vector3(specColLight0.r, specColLight0.g, specColLight0.b)); - mPhongShader.setFloatUniform("shininess", 200.0f); + const Color& diffCol = mLight0.getDiffuseColor(); + const Color& specCol = mLight0.getSpecularColor(); + mPhongShader.setVector3Uniform("light0DiffuseColor", Vector3(diffCol.r, diffCol.g, diffCol.b)); + mPhongShader.setVector3Uniform("light0SpecularColor", Vector3(specCol.r, specCol.g, specCol.b)); + mPhongShader.setFloatUniform("shininess", 60.0f); + // Set the model to camera matrix + const openglframework::Matrix4 localToCameraMatrix = worldToCameraMatrix; + mPhongShader.setMatrix4x4Uniform("localToCameraMatrix", localToCameraMatrix); + + // Set the normal matrix (inverse transpose of the 3x3 upper-left sub matrix of the + // model-view matrix) + const openglframework::Matrix3 normalMatrix = + localToCameraMatrix.getUpperLeft3x3Matrix().getInverse().getTranspose(); + mPhongShader.setMatrix3x3Uniform("normalMatrix", normalMatrix); + + // Set the vertex color + openglframework::Vector4 color(1, 0, 0, 1); + mPhongShader.setVector4Uniform("vertexColor", color); + + // Bind the VAO + mVAO.bind(); + + // Draw the lines + glDrawArrays(GL_LINES, 0, NB_RAYS); + + // Unbind the VAO + mVAO.unbind(); + + mPhongShader.unbind(); + + // Render the shapes if (mBox->getCollisionBody()->isActive()) mBox->render(mPhongShader, worldToCameraMatrix); if (mSphere->getCollisionBody()->isActive()) mSphere->render(mPhongShader, worldToCameraMatrix); if (mCone->getCollisionBody()->isActive()) mCone->render(mPhongShader, worldToCameraMatrix); @@ -291,7 +321,7 @@ void RaycastScene::render() { if (mConvexMesh->getCollisionBody()->isActive()) mConvexMesh->render(mPhongShader, worldToCameraMatrix); if (mDumbbell->getCollisionBody()->isActive()) mDumbbell->render(mPhongShader, worldToCameraMatrix); - mPhongShader.unbind(); + //mPhongShader.unbind(); mPhongShader.bind(); mPhongShader.setVector3Uniform("light0SpecularColor", Vector3(0, 0, 0)); @@ -299,7 +329,7 @@ void RaycastScene::render() { mPhongShader.setVector4Uniform("vertexColor", redColor); // Render all the raycast hit points - mRaycastManager.render(mPhongShader, worldToCameraMatrix, mAreNormalsDisplayed); + mRaycastManager.render(worldToCameraMatrix, mAreNormalsDisplayed); mPhongShader.unbind(); mPhongShader.bind(); @@ -316,3 +346,45 @@ void RaycastScene::render() { // Unbind the shader mPhongShader.unbind(); } + +// Create the Vertex Buffer Objects used to render with OpenGL. +/// We create two VBOs (one for vertices and one for indices) +void RaycastScene::createVBOAndVAO(openglframework::Shader& shader) { + + // Bind the shader + shader.bind(); + + // Get the location of shader attribute variables + GLint vertexPositionLoc = shader.getAttribLocation("vertexPosition"); + + // Create the VBO for the vertices data + mVBOVertices.create(); + mVBOVertices.bind(); + size_t sizeVertices = mLinePoints.size() * sizeof(openglframework::Vector3); + mVBOVertices.copyDataIntoVBO(sizeVertices, &mLinePoints[0], GL_STATIC_DRAW); + mVBOVertices.unbind(); + + // Create the VAO for both VBOs + mVAO.create(); + mVAO.bind(); + + // Bind the VBO of vertices + mVBOVertices.bind(); + glEnableVertexAttribArray(vertexPositionLoc); + glVertexAttribPointer(vertexPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, (char*)NULL); + + // Unbind the VAO + mVAO.unbind(); + + // Unbind the shader + shader.unbind(); +} + +// Called when a keyboard event occurs +void RaycastScene::keyboardEvent(int key, int scancode, int action, int mods) { + + // If the space key has been pressed + if (key == GLFW_KEY_SPACE && action == GLFW_PRESS) { + changeBody(); + } +} diff --git a/testbed/scenes/raycast/RaycastScene.h b/testbed/scenes/raycast/RaycastScene.h index f3e6ed4d..79fa8c9d 100644 --- a/testbed/scenes/raycast/RaycastScene.h +++ b/testbed/scenes/raycast/RaycastScene.h @@ -70,12 +70,24 @@ class RaycastManager : public rp3d::RaycastCallback { /// All the normals at hit points std::vector mNormals; + /// Shader + openglframework::Shader& mShader; + + /// Contact point mesh folder path + std::string mMeshFolderPath; + public: + RaycastManager(openglframework::Shader& shader, + const std::string& meshFolderPath) + : mShader(shader), mMeshFolderPath(meshFolderPath) { + + } + virtual rp3d::decimal notifyRaycastHit(const rp3d::RaycastInfo& raycastInfo) { rp3d::Vector3 hitPos = raycastInfo.worldPoint; openglframework::Vector3 position(hitPos.x, hitPos.y, hitPos.z); - VisualContactPoint* point = new VisualContactPoint(position); + VisualContactPoint* point = new VisualContactPoint(position, mShader, mMeshFolderPath); mHitPoints.push_back(point); // Create a line to display the normal at hit point @@ -87,14 +99,13 @@ class RaycastManager : public rp3d::RaycastCallback { return raycastInfo.hitFraction; } - void render(openglframework::Shader& shader, - const openglframework::Matrix4& worldToCameraMatrix, + void render(const openglframework::Matrix4& worldToCameraMatrix, bool showNormals) { // Render all the raycast hit points for (std::vector::iterator it = mHitPoints.begin(); it != mHitPoints.end(); ++it) { - (*it)->render(shader, worldToCameraMatrix); + (*it)->render(mShader, worldToCameraMatrix); } if (showNormals) { @@ -102,7 +113,7 @@ class RaycastManager : public rp3d::RaycastCallback { // Render all the normals at hit points for (std::vector::iterator it = mNormals.begin(); it != mNormals.end(); ++it) { - (*it)->render(shader, worldToCameraMatrix); + (*it)->render(mShader, worldToCameraMatrix); } } } @@ -132,15 +143,18 @@ class RaycastScene : public Scene { // -------------------- Attributes -------------------- // - /// Raycast manager - RaycastManager mRaycastManager; - /// Light 0 openglframework::Light mLight0; /// Phong shader openglframework::Shader mPhongShader; + /// Contact point mesh folder path + std::string mMeshFolderPath; + + /// Raycast manager + RaycastManager mRaycastManager; + /// All the raycast lines std::vector mLines; @@ -164,9 +178,22 @@ class RaycastScene : public Scene { /// Collision world used for the physics simulation rp3d::CollisionWorld* mCollisionWorld; + /// All the points to render the lines + std::vector mLinePoints; + + /// Vertex Buffer Object for the vertices data + openglframework::VertexBufferObject mVBOVertices; + + /// Vertex Array Object for the vertex data + openglframework::VertexArrayObject mVAO; + /// Create the raycast lines void createLines(); + // Create the Vertex Buffer Objects used to render with OpenGL. + void createVBOAndVAO(openglframework::Shader& shader); + + public: // -------------------- Methods -------------------- // @@ -195,6 +222,9 @@ class RaycastScene : public Scene { /// Display or not the surface normals at hit points void showHideNormals(); + + /// Called when a keyboard event occurs + virtual void keyboardEvent(int key, int scancode, int action, int mods); }; // Display or not the surface normals at hit points diff --git a/testbed/src/TestbedApplication.cpp b/testbed/src/TestbedApplication.cpp index d58150d0..cdc31397 100644 --- a/testbed/src/TestbedApplication.cpp +++ b/testbed/src/TestbedApplication.cpp @@ -162,7 +162,7 @@ void TestbedApplication::createScenes() { mScenes.push_back(raycastScene); assert(mScenes.size() > 0); - mCurrentScene = mScenes[1]; + mCurrentScene = mScenes[0]; } // Remove all the scenes