diff --git a/testbed/CMakeLists.txt b/testbed/CMakeLists.txt index 808ded2f..8d402ad3 100644 --- a/testbed/CMakeLists.txt +++ b/testbed/CMakeLists.txt @@ -110,6 +110,8 @@ SET(SCENES_SOURCES scenes/raycast/RaycastScene.cpp scenes/collisionshapes/CollisionShapesScene.h scenes/collisionshapes/CollisionShapesScene.cpp + scenes/collisiondetection/CollisionDetectionScene.h + scenes/collisiondetection/CollisionDetectionScene.cpp scenes/concavemesh/ConcaveMeshScene.h scenes/concavemesh/ConcaveMeshScene.cpp scenes/heightfield/HeightFieldScene.h diff --git a/testbed/common/Box.cpp b/testbed/common/Box.cpp index 549b86bb..6c8f052d 100644 --- a/testbed/common/Box.cpp +++ b/testbed/common/Box.cpp @@ -32,88 +32,21 @@ // Initialize static variables openglframework::VertexBufferObject Box::mVBOVertices(GL_ARRAY_BUFFER); openglframework::VertexBufferObject Box::mVBONormals(GL_ARRAY_BUFFER); +openglframework::VertexBufferObject Box::mVBOTextureCoords(GL_ARRAY_BUFFER); +openglframework::VertexBufferObject Box::mVBOIndices(GL_ELEMENT_ARRAY_BUFFER); openglframework::VertexArrayObject Box::mVAO; int Box::totalNbBoxes = 0; -GLfloat Box::mCubeVertices[108] = { - -1.0f,-1.0f,-1.0f, // triangle 1 : begin - -1.0f,-1.0f, 1.0f, - -1.0f, 1.0f, 1.0f, // triangle 1 : end - 1.0f, 1.0f,-1.0f, // triangle 2 : begin - -1.0f,-1.0f,-1.0f, - -1.0f, 1.0f,-1.0f, // triangle 2 : end - 1.0f,-1.0f, 1.0f, - -1.0f,-1.0f,-1.0f, - 1.0f,-1.0f,-1.0f, - 1.0f, 1.0f,-1.0f, - 1.0f,-1.0f,-1.0f, - -1.0f,-1.0f,-1.0f, - -1.0f,-1.0f,-1.0f, - -1.0f, 1.0f, 1.0f, - -1.0f, 1.0f,-1.0f, - 1.0f,-1.0f, 1.0f, - -1.0f,-1.0f, 1.0f, - -1.0f,-1.0f,-1.0f, - -1.0f, 1.0f, 1.0f, - -1.0f,-1.0f, 1.0f, - 1.0f,-1.0f, 1.0f, - 1.0f, 1.0f, 1.0f, - 1.0f,-1.0f,-1.0f, - 1.0f, 1.0f,-1.0f, - 1.0f,-1.0f,-1.0f, - 1.0f, 1.0f, 1.0f, - 1.0f,-1.0f, 1.0f, - 1.0f, 1.0f, 1.0f, - 1.0f, 1.0f,-1.0f, - -1.0f, 1.0f,-1.0f, - 1.0f, 1.0f, 1.0f, - -1.0f, 1.0f,-1.0f, - -1.0f, 1.0f, 1.0f, - 1.0f, 1.0f, 1.0f, - -1.0f, 1.0f, 1.0f, - 1.0f,-1.0f, 1.0f -}; -GLfloat Box::mCubeNormals[108] = { - -1.0f, 0.0f, 0.0f, // triangle 1 : begin - -1.0f, 0.0f, 0.0f, - -1.0f, 0.0f, 0.0f, // triangle 1 : end - 0.0f, 0.0f,-1.0f, // triangle 2 : begin - 0.0f, 0.0f,-1.0f, - 0.0f, 0.0f,-1.0f, // triangle 2 : end - 0.0f,-1.0f, 0.0f, - 0.0f,-1.0f, 0.0f, - 0.0f,-1.0f, 0.0f,// - 0.0f, 0.0f,-1.0f, - 0.0f, 0.0f,-1.0f, - 0.0f, 0.0f,-1.0f,// - -1.0f, 0.0f, 0.0f, - -1.0f, 0.0f, 0.0f, - -1.0f, 0.0f,0.0f,// - 0.0f,-1.0f, 0.0f, - 0.0f,-1.0f, 0.0f, - 0.0f,-1.0f, 0.0f,// - 0.0f, 0.0f, 1.0f, - 0.0f, 0.0f, 1.0f, - 0.0f, 0.0f, 1.0f,// - 1.0f, 0.0f, 0.0f, - 1.0f, 0.0f, 0.0f, - 1.0f, 0.0f, 0.0f,// - 1.0f, 0.0f, 0.0f, - 1.0f, 0.0f, 0.0f, - 1.0f, 0.0f, 0.0f,// - 0.0f, 1.0f, 0.0f, - 0.0f, 1.0f, 0.0f, - 0.0f, 1.0f, 0.0f,// - 0.0f, 1.0f, 0.0f, - 0.0f, 1.0f, 0.0f, - 0.0f, 1.0f, 0.0f,// - 0.0f, 0.0f, 1.0f, - 0.0f, 0.0f, 1.0f, - 0.0f, 0.0f, 1.0f// -}; + // Constructor Box::Box(const openglframework::Vector3& size, const openglframework::Vector3 &position, - reactphysics3d::CollisionWorld* world) - : openglframework::Object3D() { + reactphysics3d::CollisionWorld* world, const std::string& meshFolderPath) + : openglframework::Mesh() { + + // 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 mSize[0] = size.x * 0.5f; @@ -161,8 +94,14 @@ Box::Box(const openglframework::Vector3& size, const openglframework::Vector3 &p // Constructor Box::Box(const openglframework::Vector3& size, const openglframework::Vector3& position, - float mass, reactphysics3d::DynamicsWorld* world) - : openglframework::Object3D() { + float mass, reactphysics3d::DynamicsWorld* world, const std::string& meshFolderPath) + : openglframework::Mesh() { + + // 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 mSize[0] = size.x * 0.5f; @@ -226,16 +165,15 @@ Box::~Box() { // Render the cube at the correct position and with the correct orientation void Box::render(openglframework::Shader& shader, - const openglframework::Matrix4& worldToCameraMatrix) { + const openglframework::Matrix4& worldToCameraMatrix, bool wireframe) { - // Bind the VAO - mVAO.bind(); + if (wireframe) { + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + } // Bind the shader shader.bind(); - mVBOVertices.bind(); - // Set the model to camera matrix shader.setMatrix4x4Uniform("localToWorldMatrix", mTransformMatrix); shader.setMatrix4x4Uniform("worldToCameraMatrix", worldToCameraMatrix); @@ -252,20 +190,27 @@ void Box::render(openglframework::Shader& shader, openglframework::Vector4 color(currentColor.r, currentColor.g, currentColor.b, currentColor.a); shader.setVector4Uniform("vertexColor", color, false); + // Bind the VAO + mVAO.bind(); + + mVBOVertices.bind(); + // Get the location of shader attribute variables GLint vertexPositionLoc = shader.getAttribLocation("vertexPosition"); GLint vertexNormalLoc = shader.getAttribLocation("vertexNormal", false); glEnableVertexAttribArray(vertexPositionLoc); - glVertexAttribPointer(vertexPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr); + glVertexAttribPointer(vertexPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, (char*)nullptr); mVBONormals.bind(); + if (vertexNormalLoc != -1) glVertexAttribPointer(vertexNormalLoc, 3, GL_FLOAT, GL_FALSE, 0, (char*)nullptr); if (vertexNormalLoc != -1) glEnableVertexAttribArray(vertexNormalLoc); - if (vertexNormalLoc != -1) glVertexAttribPointer(vertexNormalLoc, 3, GL_FLOAT, GL_FALSE, 0, nullptr); - // Draw the geometry of the box - glDrawArrays(GL_TRIANGLES, 0, 36); + // For each part of the mesh + for (unsigned int i=0; isetColor(mGreyColorDemo); + mSphere1->setSleepingColor(mRedColorDemo); + + // ---------- Sphere 2 ---------- // + openglframework::Vector3 position2(4, 0, 0); + + // Create a sphere and a corresponding collision body in the dynamics world + mSphere2 = new Sphere(4, position2, mCollisionWorld, mMeshFolderPath); + mAllShapesObjects.push_back(mSphere2); + mAllShapesPhysicsObjects.push_back(mSphere2); + + // Set the color + mSphere2->setColor(mGreyColorDemo); + mSphere2->setSleepingColor(mRedColorDemo); + + // ---------- 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, + // mMeshFolderPath); + + // Set the color + //mCone->setColor(mGreyColorDemo); + //mCone->setSleepingColor(mRedColorDemo); + + // ---------- 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, mMeshFolderPath); + + // Set the color + //mCylinder->setColor(mGreyColorDemo); + //mCylinder->setSleepingColor(mRedColorDemo); + + // ---------- 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, mMeshFolderPath); + + // Set the color + //mCapsule->setColor(mGreyColorDemo); + //mCapsule->setSleepingColor(mRedColorDemo); + + // ---------- 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, mMeshFolderPath + "convexmesh.obj"); + + // Set the color + //mConvexMesh->setColor(mGreyColorDemo); + //mConvexMesh->setSleepingColor(mRedColorDemo); + + // ---------- Concave Mesh ---------- // + //openglframework::Vector3 position8(0, 0, 0); + + // Create a convex mesh and a corresponding collision body in the dynamics world + //mConcaveMesh = new ConcaveMesh(position8, mCollisionWorld, mMeshFolderPath + "city.obj"); + + // Set the color + //mConcaveMesh->setColor(mGreyColorDemo); + //mConcaveMesh->setSleepingColor(mRedColorDemo); + + // ---------- Heightfield ---------- // + //openglframework::Vector3 position9(0, 0, 0); + + // Create a convex mesh and a corresponding collision body in the dynamics world + //mHeightField = new HeightField(position9, mCollisionWorld); + + // Set the color + //mHeightField->setColor(mGreyColorDemo); + //mHeightField->setSleepingColor(mRedColorDemo); + + // Create the VBO and VAO to render the lines + createVBOAndVAO(mPhongShader); + + mAllShapesPhysicsObjects[mSelectedShapeIndex]->setColor(mBlueColorDemo); +} + +// Reset the scene +void CollisionDetectionScene::reset() { + +} + +// Destructor +CollisionDetectionScene::~CollisionDetectionScene() { + + // Destroy the shader + mPhongShader.destroy(); + + // Destroy the box rigid body from the dynamics world + //mCollisionWorld->destroyCollisionBody(mBox->getCollisionBody()); + //delete mBox; + + // Destroy the spheres + mCollisionWorld->destroyCollisionBody(mSphere1->getCollisionBody()); + delete mSphere1; + + mCollisionWorld->destroyCollisionBody(mSphere2->getCollisionBody()); + delete mSphere2; + + /* + // Destroy the corresponding rigid body from the dynamics world + mCollisionWorld->destroyCollisionBody(mCone->getCollisionBody()); + delete mCone; + + // Destroy the corresponding rigid body from the dynamics world + mCollisionWorld->destroyCollisionBody(mCylinder->getCollisionBody()); + + // Destroy the sphere + delete mCylinder; + + // Destroy the corresponding rigid body from the dynamics world + mCollisionWorld->destroyCollisionBody(mCapsule->getCollisionBody()); + + // Destroy the sphere + delete mCapsule; + + // Destroy the corresponding rigid body from the dynamics world + mCollisionWorld->destroyCollisionBody(mConvexMesh->getCollisionBody()); + + // Destroy the convex mesh + delete mConvexMesh; + + // Destroy the corresponding rigid body from the dynamics world + mCollisionWorld->destroyCollisionBody(mDumbbell->getCollisionBody()); + + // Destroy the dumbbell + delete mDumbbell; + + // Destroy the corresponding rigid body from the dynamics world + mCollisionWorld->destroyCollisionBody(mConcaveMesh->getCollisionBody()); + + // Destroy the convex mesh + delete mConcaveMesh; + + // Destroy the corresponding rigid body from the dynamics world + mCollisionWorld->destroyCollisionBody(mHeightField->getCollisionBody()); + + // Destroy the convex mesh + delete mHeightField; + */ + + mContactManager.resetPoints(); + + // Destroy the static data for the visual contact points + VisualContactPoint::destroyStaticData(); + + // Destroy the collision world + delete mCollisionWorld; + + // Destroy the VBOs and VAO + mVBOVertices.destroy(); + mVAO.destroy(); +} + +// Update the physics world (take a simulation step) +void CollisionDetectionScene::updatePhysics() { + + +} + +// Take a step for the simulation +void CollisionDetectionScene::update() { + + mContactManager.resetPoints(); + + mCollisionWorld->testCollision(&mContactManager); + + SceneDemo::update(); +} + +// Render the scene +void CollisionDetectionScene::renderSinglePass(openglframework::Shader& shader, + const openglframework::Matrix4& worldToCameraMatrix) { + + /* + // Bind the VAO + mVAO.bind(); + + // Bind the shader + shader.bind(); + + mVBOVertices.bind(); + + // Set the model to camera matrix + const Matrix4 localToCameraMatrix = Matrix4::identity(); + shader.setMatrix4x4Uniform("localToWorldMatrix", localToCameraMatrix); + shader.setMatrix4x4Uniform("worldToCameraMatrix", worldToCameraMatrix); + + // 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(); + shader.setMatrix3x3Uniform("normalMatrix", normalMatrix, false); + + // Set the vertex color + openglframework::Vector4 color(1, 0, 0, 1); + shader.setVector4Uniform("vertexColor", color, false); + + // Get the location of shader attribute variables + GLint vertexPositionLoc = shader.getAttribLocation("vertexPosition"); + + glEnableVertexAttribArray(vertexPositionLoc); + glVertexAttribPointer(vertexPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, (char*)NULL); + + // Draw the lines + glDrawArrays(GL_LINES, 0, NB_RAYS); + + glDisableVertexAttribArray(vertexPositionLoc); + + mVBOVertices.unbind(); + + // Unbind the VAO + mVAO.unbind(); + + shader.unbind(); + */ + + // Render the shapes + if (mSphere1->getCollisionBody()->isActive()) mSphere1->render(shader, worldToCameraMatrix, mIsWireframeEnabled); + if (mSphere2->getCollisionBody()->isActive()) mSphere2->render(shader, worldToCameraMatrix, mIsWireframeEnabled); + + /* + if (mBox->getCollisionBody()->isActive()) mBox->render(shader, worldToCameraMatrix); + if (mCone->getCollisionBody()->isActive()) mCone->render(shader, worldToCameraMatrix); + if (mCylinder->getCollisionBody()->isActive()) mCylinder->render(shader, worldToCameraMatrix); + if (mCapsule->getCollisionBody()->isActive()) mCapsule->render(shader, worldToCameraMatrix); + if (mConvexMesh->getCollisionBody()->isActive()) mConvexMesh->render(shader, worldToCameraMatrix); + if (mDumbbell->getCollisionBody()->isActive()) mDumbbell->render(shader, worldToCameraMatrix); + if (mConcaveMesh->getCollisionBody()->isActive()) mConcaveMesh->render(shader, worldToCameraMatrix); + if (mHeightField->getCollisionBody()->isActive()) mHeightField->render(shader, worldToCameraMatrix); + */ + + shader.unbind(); +} + +// Create the Vertex Buffer Objects used to render with OpenGL. +/// We create two VBOs (one for vertices and one for indices) +void CollisionDetectionScene::createVBOAndVAO(openglframework::Shader& shader) { + + // Bind the shader + shader.bind(); + + // 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(); + + // Unbind the VAO + mVAO.unbind(); + + // Unbind the shader + shader.unbind(); +} + +void CollisionDetectionScene::selectNextShape() { + + int previousIndex = mSelectedShapeIndex; + mSelectedShapeIndex++; + if (mSelectedShapeIndex >= mAllShapesPhysicsObjects.size()) { + mSelectedShapeIndex = 0; + } + + mAllShapesPhysicsObjects[previousIndex]->setColor(mGreyColorDemo); + mAllShapesPhysicsObjects[mSelectedShapeIndex]->setColor(mBlueColorDemo); +} + +// Called when a keyboard event occurs +bool CollisionDetectionScene::keyboardEvent(int key, int scancode, int action, int mods) { + + // If the space key has been pressed + if (key == GLFW_KEY_SPACE && action == GLFW_PRESS) { + selectNextShape(); + return true; + } + + if (key == GLFW_KEY_RIGHT && action == GLFW_PRESS) { + rp3d::Transform transform = mAllShapesPhysicsObjects[mSelectedShapeIndex]->getCollisionBody()->getTransform(); + transform.setPosition(transform.getPosition() + rp3d::Vector3(1, 0, 0)); + mAllShapesObjects[mSelectedShapeIndex]->translateWorld(openglframework::Vector3(1, 0, 0)); + } + + return false; +} diff --git a/testbed/scenes/collisiondetection/CollisionDetectionScene.h b/testbed/scenes/collisiondetection/CollisionDetectionScene.h new file mode 100644 index 00000000..d77cee7f --- /dev/null +++ b/testbed/scenes/collisiondetection/CollisionDetectionScene.h @@ -0,0 +1,235 @@ +/******************************************************************************** +* ReactPhysics3D physics library, http://www.reactphysics3d.com * +* Copyright (c) 2010-2016 Daniel Chappuis * +********************************************************************************* +* * +* 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 * +* use of this software. * +* * +* Permission is granted to anyone to use this software for any purpose, * +* including commercial applications, and to alter it and redistribute it * +* freely, subject to the following restrictions: * +* * +* 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 * +* product, an acknowledgment in the product documentation would be * +* appreciated but is not required. * +* * +* 2. Altered source versions must be plainly marked as such, and must not be * +* misrepresented as being the original software. * +* * +* 3. This notice may not be removed or altered from any source distribution. * +* * +********************************************************************************/ + +#ifndef COLLISION_DETECTION_SCENE_H +#define COLLISION_DETECTION_SCENE_H + +// Libraries +#define _USE_MATH_DEFINES +#include +#include "openglframework.h" +#include "reactphysics3d.h" +#include "SceneDemo.h" +#include "Sphere.h" +#include "Box.h" +#include "Cone.h" +#include "Cylinder.h" +#include "Capsule.h" +#include "Line.h" +#include "ConvexMesh.h" +#include "ConcaveMesh.h" +#include "HeightField.h" +#include "Dumbbell.h" +#include "VisualContactPoint.h" + +namespace collisiondetectionscene { + +// Constants +const float SCENE_RADIUS = 30.0f; +const openglframework::Vector3 BOX_SIZE(4, 2, 1); +const float SPHERE_RADIUS = 3.0f; +const float CONE_RADIUS = 3.0f; +const float CONE_HEIGHT = 5.0f; +const float CYLINDER_RADIUS = 3.0f; +const float CYLINDER_HEIGHT = 5.0f; +const float CAPSULE_RADIUS = 3.0f; +const float CAPSULE_HEIGHT = 5.0f; +const float DUMBBELL_HEIGHT = 5.0f; +const int NB_RAYS = 100; +const float RAY_LENGTH = 30.0f; +const int NB_BODIES = 9; + +// Raycast manager +class ContactManager : public rp3d::CollisionCallback { + + private: + + /// All the visual contact points + std::vector mContactPoints; + + /// All the normals at contact points + std::vector mNormals; + + /// Contact point mesh folder path + std::string mMeshFolderPath; + + public: + + ContactManager(openglframework::Shader& shader, + const std::string& meshFolderPath) + : mMeshFolderPath(meshFolderPath) { + + } + + /// This method will be called for each reported contact point + virtual void notifyContact(const CollisionCallbackInfo& collisionCallbackInfo) override { + + rp3d::Vector3 point1 = collisionCallbackInfo.contactPoint.localPoint1; + point1 = collisionCallbackInfo.proxyShape1->getLocalToWorldTransform() * point1; + openglframework::Vector3 position1(point1.x, point1.y, point1.z); + mContactPoints.push_back(ContactPoint(position1)); + + rp3d::Vector3 point2 = collisionCallbackInfo.contactPoint.localPoint2; + point2 = collisionCallbackInfo.proxyShape2->getLocalToWorldTransform() * point2; + openglframework::Vector3 position2(point2.x, point2.y, point2.z); + mContactPoints.push_back(ContactPoint(position2)); + + // Create a line to display the normal at hit point + rp3d::Vector3 n = collisionCallbackInfo.contactPoint.normal; + openglframework::Vector3 normal(n.x, n.y, n.z); + Line* normalLine = new Line(position1, position1 + normal); + mNormals.push_back(normalLine); + } + + void resetPoints() { + + mContactPoints.clear(); + + // Destroy all the normals + for (std::vector::iterator it = mNormals.begin(); + it != mNormals.end(); ++it) { + delete (*it); + } + mNormals.clear(); + } + + std::vector getContactPoints() const { + return mContactPoints; + } +}; + +// Class CollisionDetectionScene +class CollisionDetectionScene : public SceneDemo { + + private : + + // -------------------- Attributes -------------------- // + + /// Contact point mesh folder path + std::string mMeshFolderPath; + + /// Contact manager + ContactManager mContactManager; + + bool mAreNormalsDisplayed; + + /// All objects on the scene + //Box* mBox; + Sphere* mSphere1; + Sphere* mSphere2; + //Cone* mCone; + //Cylinder* mCylinder; + //Capsule* mCapsule; + //ConvexMesh* mConvexMesh; + //Dumbbell* mDumbbell; + //ConcaveMesh* mConcaveMesh; + //HeightField* mHeightField; + + std::vector mAllShapesObjects; + std::vector mAllShapesPhysicsObjects; + + int mSelectedShapeIndex; + + /// 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 Vertex Buffer Objects used to render with OpenGL. + void createVBOAndVAO(openglframework::Shader& shader); + + /// Select the next shape + void selectNextShape(); + + public: + + // -------------------- Methods -------------------- // + + /// Constructor + CollisionDetectionScene(const std::string& name); + + /// Destructor + virtual ~CollisionDetectionScene() override; + + /// Update the physics world (take a simulation step) + /// Can be called several times per frame + virtual void updatePhysics() override; + + /// Take a step for the simulation + virtual void update() override; + + /// Render the scene in a single pass + virtual void renderSinglePass(openglframework::Shader& shader, + const openglframework::Matrix4& worldToCameraMatrix) override; + + /// Reset the scene + virtual void reset() override; + + /// Display or not the surface normals at hit points + void showHideNormals(); + + /// Called when a keyboard event occurs + virtual bool keyboardEvent(int key, int scancode, int action, int mods) override; + + /// Enabled/Disable the shadow mapping + virtual void setIsShadowMappingEnabled(bool isShadowMappingEnabled) override; + + /// Display/Hide the contact points + virtual void setIsContactPointsDisplayed(bool display) override; + + /// Return all the contact points of the scene + virtual std::vector getContactPoints() const override; +}; + +// Display or not the surface normals at hit points +inline void CollisionDetectionScene::showHideNormals() { + mAreNormalsDisplayed = !mAreNormalsDisplayed; +} + +// Enabled/Disable the shadow mapping +inline void CollisionDetectionScene::setIsShadowMappingEnabled(bool isShadowMappingEnabled) { + SceneDemo::setIsShadowMappingEnabled(false); +} + +// Display/Hide the contact points +inline void CollisionDetectionScene::setIsContactPointsDisplayed(bool display) { + SceneDemo::setIsContactPointsDisplayed(true); +} + +// Return all the contact points of the scene +inline std::vector CollisionDetectionScene::getContactPoints() const { + return mContactManager.getContactPoints(); +} + +} + +#endif diff --git a/testbed/scenes/collisionshapes/CollisionShapesScene.cpp b/testbed/scenes/collisionshapes/CollisionShapesScene.cpp index 5078cd14..e146bd6b 100644 --- a/testbed/scenes/collisionshapes/CollisionShapesScene.cpp +++ b/testbed/scenes/collisionshapes/CollisionShapesScene.cpp @@ -83,7 +83,7 @@ CollisionShapesScene::CollisionShapesScene(const std::string& name) radius * sin(angle)); // Create a sphere and a corresponding rigid in the dynamics world - Box* box = new Box(BOX_SIZE, position , BOX_MASS, mDynamicsWorld); + Box* box = new Box(BOX_SIZE, position , BOX_MASS, mDynamicsWorld, mMeshFolderPath); // Set the box color box->setColor(mDemoColors[i % mNbDemoColors]); @@ -235,7 +235,7 @@ CollisionShapesScene::CollisionShapesScene(const std::string& name) // ---------- Create the floor --------- openglframework::Vector3 floorPosition(0, 0, 0); - mFloor = new Box(FLOOR_SIZE, floorPosition, FLOOR_MASS, mDynamicsWorld); + mFloor = new Box(FLOOR_SIZE, floorPosition, FLOOR_MASS, mDynamicsWorld, mMeshFolderPath); // Set the box color mFloor->setColor(mGreyColorDemo); @@ -461,43 +461,43 @@ void CollisionShapesScene::renderSinglePass(openglframework::Shader& shader, // Render all the boxes of the scene for (std::vector::iterator it = mBoxes.begin(); it != mBoxes.end(); ++it) { - (*it)->render(shader, worldToCameraMatrix); + (*it)->render(shader, worldToCameraMatrix, mIsWireframeEnabled); } // Render all the sphere of the scene for (std::vector::iterator it = mSpheres.begin(); it != mSpheres.end(); ++it) { - (*it)->render(shader, worldToCameraMatrix); + (*it)->render(shader, worldToCameraMatrix, mIsWireframeEnabled); } // Render all the cones of the scene for (std::vector::iterator it = mCones.begin(); it != mCones.end(); ++it) { - (*it)->render(shader, worldToCameraMatrix); + (*it)->render(shader, worldToCameraMatrix, mIsWireframeEnabled); } // Render all the cylinders of the scene for (std::vector::iterator it = mCylinders.begin(); it != mCylinders.end(); ++it) { - (*it)->render(shader, worldToCameraMatrix); + (*it)->render(shader, worldToCameraMatrix, mIsWireframeEnabled); } // Render all the capsules of the scene for (std::vector::iterator it = mCapsules.begin(); it != mCapsules.end(); ++it) { - (*it)->render(shader, worldToCameraMatrix); + (*it)->render(shader, worldToCameraMatrix, mIsWireframeEnabled); } // Render all the convex meshes of the scene for (std::vector::iterator it = mConvexMeshes.begin(); it != mConvexMeshes.end(); ++it) { - (*it)->render(shader, worldToCameraMatrix); + (*it)->render(shader, worldToCameraMatrix, mIsWireframeEnabled); } // Render all the dumbbells of the scene for (std::vector::iterator it = mDumbbells.begin(); it != mDumbbells.end(); ++it) { - (*it)->render(shader, worldToCameraMatrix); + (*it)->render(shader, worldToCameraMatrix, mIsWireframeEnabled); } // Render the floor - mFloor->render(shader, worldToCameraMatrix); + mFloor->render(shader, worldToCameraMatrix, mIsWireframeEnabled); //mConcaveMesh->render(shader, worldToCameraMatrix); diff --git a/testbed/scenes/concavemesh/ConcaveMeshScene.cpp b/testbed/scenes/concavemesh/ConcaveMeshScene.cpp index 41234f3f..9b65893e 100644 --- a/testbed/scenes/concavemesh/ConcaveMeshScene.cpp +++ b/testbed/scenes/concavemesh/ConcaveMeshScene.cpp @@ -58,7 +58,7 @@ ConcaveMeshScene::ConcaveMeshScene(const std::string& name) openglframework::Vector3 boxPosition(-NB_BOXES_X * BOX_SIZE * BOXES_SPACE / 2 + i * BOX_SIZE * BOXES_SPACE, 30, -NB_BOXES_Z * BOX_SIZE * BOXES_SPACE / 2 + j * BOX_SIZE * BOXES_SPACE); // Create a sphere and a corresponding rigid in the dynamics world - mBoxes[i * NB_BOXES_Z + j] = new Box(Vector3(BOX_SIZE, BOX_SIZE, BOX_SIZE) * 0.5f, boxPosition, 80.1, mDynamicsWorld); + mBoxes[i * NB_BOXES_Z + j] = new Box(Vector3(BOX_SIZE, BOX_SIZE, BOX_SIZE) * 0.5f, boxPosition, 80.1, mDynamicsWorld, mMeshFolderPath); // Set the sphere color mBoxes[i * NB_BOXES_Z + j]->setColor(mDemoColors[0]); @@ -160,10 +160,10 @@ void ConcaveMeshScene::renderSinglePass(Shader& shader, const openglframework::M // Bind the shader shader.bind(); - mConcaveMesh->render(shader, worldToCameraMatrix); + mConcaveMesh->render(shader, worldToCameraMatrix, mIsWireframeEnabled); for (int i=0; irender(shader, worldToCameraMatrix); + mBoxes[i]->render(shader, worldToCameraMatrix, mIsWireframeEnabled); } // Unbind the shader diff --git a/testbed/scenes/cubes/CubesScene.cpp b/testbed/scenes/cubes/CubesScene.cpp index f9c8ad77..17af45c1 100644 --- a/testbed/scenes/cubes/CubesScene.cpp +++ b/testbed/scenes/cubes/CubesScene.cpp @@ -1,195 +1,213 @@ -/******************************************************************************** -* ReactPhysics3D physics library, http://www.reactphysics3d.com * -* Copyright (c) 2010-2016 Daniel Chappuis * -********************************************************************************* -* * -* 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 * -* use of this software. * -* * -* Permission is granted to anyone to use this software for any purpose, * -* including commercial applications, and to alter it and redistribute it * -* freely, subject to the following restrictions: * -* * -* 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 * -* product, an acknowledgment in the product documentation would be * -* appreciated but is not required. * -* * -* 2. Altered source versions must be plainly marked as such, and must not be * -* misrepresented as being the original software. * -* * -* 3. This notice may not be removed or altered from any source distribution. * -* * -********************************************************************************/ - -// Libraries -#include "CubesScene.h" - -// Namespaces -using namespace openglframework; -using namespace cubesscene; - -// Constructor -CubesScene::CubesScene(const std::string& name) - : SceneDemo(name, SCENE_RADIUS) { - - // Compute the radius and the center of the scene - openglframework::Vector3 center(0, 5, 0); - - // Set the center of the scene - setScenePosition(center, SCENE_RADIUS); - - // Gravity vector in the dynamics world - rp3d::Vector3 gravity(0, rp3d::decimal(-9.81), 0); - - // Create the dynamics world for the physics simulation - mDynamicsWorld = new rp3d::DynamicsWorld(gravity); - - float radius = 2.0f; - - // Create all the cubes of the scene - for (int i=0; isetColor(mDemoColors[i % mNbDemoColors]); - cube->setSleepingColor(mRedColorDemo); - - // Change the material properties of the rigid body - rp3d::Material& material = cube->getRigidBody()->getMaterial(); - material.setBounciness(rp3d::decimal(0.4)); - - // Add the box the list of box in the scene - mBoxes.push_back(cube); - } - - // Create the floor - openglframework::Vector3 floorPosition(0, 0, 0); - mFloor = new Box(FLOOR_SIZE, floorPosition, FLOOR_MASS, mDynamicsWorld); - mFloor->setColor(mGreyColorDemo); - mFloor->setSleepingColor(mGreyColorDemo); - - // The floor must be a static rigid body - mFloor->getRigidBody()->setType(rp3d::BodyType::STATIC); - - // Change the material properties of the floor rigid body - rp3d::Material& material = mFloor->getRigidBody()->getMaterial(); - material.setBounciness(rp3d::decimal(0.3)); - - // Get the physics engine parameters - mEngineSettings.isGravityEnabled = mDynamicsWorld->isGravityEnabled(); - rp3d::Vector3 gravityVector = mDynamicsWorld->getGravity(); - mEngineSettings.gravity = openglframework::Vector3(gravityVector.x, gravityVector.y, gravityVector.z); - mEngineSettings.isSleepingEnabled = mDynamicsWorld->isSleepingEnabled(); - mEngineSettings.sleepLinearVelocity = mDynamicsWorld->getSleepLinearVelocity(); - mEngineSettings.sleepAngularVelocity = mDynamicsWorld->getSleepAngularVelocity(); - mEngineSettings.nbPositionSolverIterations = mDynamicsWorld->getNbIterationsPositionSolver(); - mEngineSettings.nbVelocitySolverIterations = mDynamicsWorld->getNbIterationsVelocitySolver(); - mEngineSettings.timeBeforeSleep = mDynamicsWorld->getTimeBeforeSleep(); -} - -// Destructor -CubesScene::~CubesScene() { - - // Destroy all the cubes of the scene - for (std::vector::iterator it = mBoxes.begin(); it != mBoxes.end(); ++it) { - - // Destroy the corresponding rigid body from the dynamics world - mDynamicsWorld->destroyRigidBody((*it)->getRigidBody()); - - // Destroy the cube - delete (*it); - } - - // Destroy the rigid body of the floor - mDynamicsWorld->destroyRigidBody(mFloor->getRigidBody()); - - // Destroy the floor - delete mFloor; - - // Destroy the dynamics world - delete mDynamicsWorld; -} - -// Update the physics world (take a simulation step) -void CubesScene::updatePhysics() { - - // Update the physics engine parameters - mDynamicsWorld->setIsGratityEnabled(mEngineSettings.isGravityEnabled); - rp3d::Vector3 gravity(mEngineSettings.gravity.x, mEngineSettings.gravity.y, - mEngineSettings.gravity.z); - mDynamicsWorld->setGravity(gravity); - mDynamicsWorld->enableSleeping(mEngineSettings.isSleepingEnabled); - mDynamicsWorld->setSleepLinearVelocity(mEngineSettings.sleepLinearVelocity); - mDynamicsWorld->setSleepAngularVelocity(mEngineSettings.sleepAngularVelocity); - mDynamicsWorld->setNbIterationsPositionSolver(mEngineSettings.nbPositionSolverIterations); - mDynamicsWorld->setNbIterationsVelocitySolver(mEngineSettings.nbVelocitySolverIterations); - mDynamicsWorld->setTimeBeforeSleep(mEngineSettings.timeBeforeSleep); - - // Take a simulation step - mDynamicsWorld->update(mEngineSettings.timeStep); -} - -// Update the scene -void CubesScene::update() { - - SceneDemo::update(); - - // Update the position and orientation of the boxes - for (std::vector::iterator it = mBoxes.begin(); it != mBoxes.end(); ++it) { - - // Update the transform used for the rendering - (*it)->updateTransform(mInterpolationFactor); - } - - mFloor->updateTransform(mInterpolationFactor); -} - -// Render the scene in a single pass -void CubesScene::renderSinglePass(Shader& shader, const openglframework::Matrix4& worldToCameraMatrix) { - - // Bind the shader - shader.bind(); - - // Render all the cubes of the scene - for (std::vector::iterator it = mBoxes.begin(); it != mBoxes.end(); ++it) { - (*it)->render(shader, worldToCameraMatrix); - } - - // Render the floor - mFloor->render(shader, worldToCameraMatrix); - - // Unbind the shader - shader.unbind(); -} - -// Reset the scene -void CubesScene::reset() { - - float radius = 2.0f; - - for (int i=0; iresetTransform(transform); - } -} +/******************************************************************************** +* ReactPhysics3D physics library, http://www.reactphysics3d.com * +* Copyright (c) 2010-2016 Daniel Chappuis * +********************************************************************************* +* * +* 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 * +* use of this software. * +* * +* Permission is granted to anyone to use this software for any purpose, * +* including commercial applications, and to alter it and redistribute it * +* freely, subject to the following restrictions: * +* * +* 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 * +* product, an acknowledgment in the product documentation would be * +* appreciated but is not required. * +* * +* 2. Altered source versions must be plainly marked as such, and must not be * +* misrepresented as being the original software. * +* * +* 3. This notice may not be removed or altered from any source distribution. * +* * +********************************************************************************/ + +// Libraries +#include "CubesScene.h" + +// Namespaces +using namespace openglframework; +using namespace cubesscene; + +// Constructor +CubesScene::CubesScene(const std::string& name) + : SceneDemo(name, SCENE_RADIUS) { + + // Compute the radius and the center of the scene + openglframework::Vector3 center(0, 5, 0); + + // Set the center of the scene + setScenePosition(center, SCENE_RADIUS); + + // Gravity vector in the dynamics world + rp3d::Vector3 gravity(0, rp3d::decimal(-9.81), 0); + + // Create the dynamics world for the physics simulation + mDynamicsWorld = new rp3d::DynamicsWorld(gravity); + + float radius = 2.0f; + + //// Create all the cubes of the scene + //for (int i=0; isetColor(mDemoColors[i % mNbDemoColors]); + // cube->setSleepingColor(mRedColorDemo); + + // // Change the material properties of the rigid body + // rp3d::Material& material = cube->getRigidBody()->getMaterial(); + // material.setBounciness(rp3d::decimal(0.4)); + + // // Add the box the list of box in the scene + // mBoxes.push_back(cube); + //} + + // ------------------------- FLOOR ----------------------- // + + // Create the floor + openglframework::Vector3 floorPosition(0, 0, 0); + mFloor = new Box(FLOOR_SIZE, floorPosition, FLOOR_MASS, mDynamicsWorld, mMeshFolderPath); + mFloor->setColor(mGreyColorDemo); + mFloor->setSleepingColor(mGreyColorDemo); + + // The floor must be a static rigid body + mFloor->getRigidBody()->setType(rp3d::BodyType::STATIC); + + // Change the material properties of the floor rigid body + //rp3d::Material& material = mFloor->getRigidBody()->getMaterial(); + //material.setBounciness(rp3d::decimal(0.3)); + + // ------------------------- BOX ----------------------- // + + // Create a cube and a corresponding rigid in the dynamics world + Box* cube = new Box(BOX_SIZE, Vector3(0, 10, 0), BOX_MASS, mDynamicsWorld, mMeshFolderPath); + + // Set the box color + cube->setColor(mDemoColors[0]); + cube->setSleepingColor(mRedColorDemo); + + // Change the material properties of the rigid body + //rp3d::Material& material = cube->getRigidBody()->getMaterial(); + //material.setBounciness(rp3d::decimal(0.4)); + + // Add the box the list of box in the scene + mBoxes.push_back(cube); + + // Get the physics engine parameters + mEngineSettings.isGravityEnabled = mDynamicsWorld->isGravityEnabled(); + rp3d::Vector3 gravityVector = mDynamicsWorld->getGravity(); + mEngineSettings.gravity = openglframework::Vector3(gravityVector.x, gravityVector.y, gravityVector.z); + mEngineSettings.isSleepingEnabled = mDynamicsWorld->isSleepingEnabled(); + mEngineSettings.sleepLinearVelocity = mDynamicsWorld->getSleepLinearVelocity(); + mEngineSettings.sleepAngularVelocity = mDynamicsWorld->getSleepAngularVelocity(); + mEngineSettings.nbPositionSolverIterations = mDynamicsWorld->getNbIterationsPositionSolver(); + mEngineSettings.nbVelocitySolverIterations = mDynamicsWorld->getNbIterationsVelocitySolver(); + mEngineSettings.timeBeforeSleep = mDynamicsWorld->getTimeBeforeSleep(); +} + +// Destructor +CubesScene::~CubesScene() { + + // Destroy all the cubes of the scene + for (std::vector::iterator it = mBoxes.begin(); it != mBoxes.end(); ++it) { + + // Destroy the corresponding rigid body from the dynamics world + mDynamicsWorld->destroyRigidBody((*it)->getRigidBody()); + + // Destroy the cube + delete (*it); + } + + // Destroy the rigid body of the floor + mDynamicsWorld->destroyRigidBody(mFloor->getRigidBody()); + + // Destroy the floor + delete mFloor; + + // Destroy the dynamics world + delete mDynamicsWorld; +} + +// Update the physics world (take a simulation step) +void CubesScene::updatePhysics() { + + // Update the physics engine parameters + mDynamicsWorld->setIsGratityEnabled(mEngineSettings.isGravityEnabled); + rp3d::Vector3 gravity(mEngineSettings.gravity.x, mEngineSettings.gravity.y, + mEngineSettings.gravity.z); + mDynamicsWorld->setGravity(gravity); + mDynamicsWorld->enableSleeping(mEngineSettings.isSleepingEnabled); + mDynamicsWorld->setSleepLinearVelocity(mEngineSettings.sleepLinearVelocity); + mDynamicsWorld->setSleepAngularVelocity(mEngineSettings.sleepAngularVelocity); + mDynamicsWorld->setNbIterationsPositionSolver(mEngineSettings.nbPositionSolverIterations); + mDynamicsWorld->setNbIterationsVelocitySolver(mEngineSettings.nbVelocitySolverIterations); + mDynamicsWorld->setTimeBeforeSleep(mEngineSettings.timeBeforeSleep); + + // Take a simulation step + mDynamicsWorld->update(mEngineSettings.timeStep); +} + +// Update the scene +void CubesScene::update() { + + SceneDemo::update(); + + // Update the position and orientation of the boxes + for (std::vector::iterator it = mBoxes.begin(); it != mBoxes.end(); ++it) { + + // Update the transform used for the rendering + (*it)->updateTransform(mInterpolationFactor); + } + + mFloor->updateTransform(mInterpolationFactor); +} + +// Render the scene in a single pass +void CubesScene::renderSinglePass(Shader& shader, const openglframework::Matrix4& worldToCameraMatrix) { + + // Bind the shader + shader.bind(); + + // Render all the cubes of the scene + for (std::vector::iterator it = mBoxes.begin(); it != mBoxes.end(); ++it) { + (*it)->render(shader, worldToCameraMatrix, mIsWireframeEnabled); + } + + // Render the floor + mFloor->render(shader, worldToCameraMatrix, mIsWireframeEnabled); + + // Unbind the shader + shader.unbind(); +} + +// Reset the scene +void CubesScene::reset() { + + float radius = 2.0f; + + for (int i=0; iresetTransform(transform); + } +} diff --git a/testbed/scenes/cubes/CubesScene.h b/testbed/scenes/cubes/CubesScene.h index a07c74d2..4ad57f77 100644 --- a/testbed/scenes/cubes/CubesScene.h +++ b/testbed/scenes/cubes/CubesScene.h @@ -1,96 +1,96 @@ -/******************************************************************************** -* ReactPhysics3D physics library, http://www.reactphysics3d.com * -* Copyright (c) 2010-2016 Daniel Chappuis * -********************************************************************************* -* * -* 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 * -* use of this software. * -* * -* Permission is granted to anyone to use this software for any purpose, * -* including commercial applications, and to alter it and redistribute it * -* freely, subject to the following restrictions: * -* * -* 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 * -* product, an acknowledgment in the product documentation would be * -* appreciated but is not required. * -* * -* 2. Altered source versions must be plainly marked as such, and must not be * -* misrepresented as being the original software. * -* * -* 3. This notice may not be removed or altered from any source distribution. * -* * -********************************************************************************/ - -#ifndef CUBES_SCENE_H -#define CUBES_SCENE_H - -// Libraries -#include "openglframework.h" -#include "reactphysics3d.h" -#include "Box.h" -#include "SceneDemo.h" - -namespace cubesscene { - -// Constants -const float SCENE_RADIUS = 30.0f; // Radius of the scene in meters -const int NB_CUBES = 30; // 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 -const float FLOOR_MASS = 100.0f; // Floor mass in kilograms - -// Class CubesScene -class CubesScene : public SceneDemo { - - protected : - - // -------------------- Attributes -------------------- // - - /// All the boxes of the scene - std::vector mBoxes; - - /// Box for the floor - Box* mFloor; - - /// Dynamics world used for the physics simulation - rp3d::DynamicsWorld* mDynamicsWorld; - - public: - - // -------------------- Methods -------------------- // - - /// Constructor - CubesScene(const std::string& name); - - /// Destructor - virtual ~CubesScene() override; - - /// Update the physics world (take a simulation step) - /// Can be called several times per frame - virtual void updatePhysics() override; - - /// Update the scene (take a simulation step) - virtual void update() override; - - /// Render the scene in a single pass - virtual void renderSinglePass(openglframework::Shader& shader, - const openglframework::Matrix4& worldToCameraMatrix) override; - - /// Reset the scene - virtual void reset() override; - - /// Return all the contact points of the scene - virtual std::vector getContactPoints() const override; -}; - -// Return all the contact points of the scene -inline std::vector CubesScene::getContactPoints() const { - return computeContactPointsOfWorld(mDynamicsWorld); -} - -} - -#endif +/******************************************************************************** +* ReactPhysics3D physics library, http://www.reactphysics3d.com * +* Copyright (c) 2010-2016 Daniel Chappuis * +********************************************************************************* +* * +* 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 * +* use of this software. * +* * +* Permission is granted to anyone to use this software for any purpose, * +* including commercial applications, and to alter it and redistribute it * +* freely, subject to the following restrictions: * +* * +* 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 * +* product, an acknowledgment in the product documentation would be * +* appreciated but is not required. * +* * +* 2. Altered source versions must be plainly marked as such, and must not be * +* misrepresented as being the original software. * +* * +* 3. This notice may not be removed or altered from any source distribution. * +* * +********************************************************************************/ + +#ifndef CUBES_SCENE_H +#define CUBES_SCENE_H + +// Libraries +#include "openglframework.h" +#include "reactphysics3d.h" +#include "Box.h" +#include "SceneDemo.h" + +namespace cubesscene { + +// Constants +const float SCENE_RADIUS = 30.0f; // Radius of the scene in meters +const int NB_CUBES = 30; // Number of boxes in the scene +const openglframework::Vector3 BOX_SIZE(2, 2, 2); // Box dimensions in meters +const openglframework::Vector3 FLOOR_SIZE(5, 5.0, 5); // Floor dimensions in meters +const float BOX_MASS = 1.0f; // Box mass in kilograms +const float FLOOR_MASS = 100.0f; // Floor mass in kilograms + +// Class CubesScene +class CubesScene : public SceneDemo { + + protected : + + // -------------------- Attributes -------------------- // + + /// All the boxes of the scene + std::vector mBoxes; + + /// Box for the floor + Box* mFloor; + + /// Dynamics world used for the physics simulation + rp3d::DynamicsWorld* mDynamicsWorld; + + public: + + // -------------------- Methods -------------------- // + + /// Constructor + CubesScene(const std::string& name); + + /// Destructor + virtual ~CubesScene() override; + + /// Update the physics world (take a simulation step) + /// Can be called several times per frame + virtual void updatePhysics() override; + + /// Update the scene (take a simulation step) + virtual void update() override; + + /// Render the scene in a single pass + virtual void renderSinglePass(openglframework::Shader& shader, + const openglframework::Matrix4& worldToCameraMatrix) override; + + /// Reset the scene + virtual void reset() override; + + /// Return all the contact points of the scene + virtual std::vector getContactPoints() const override; +}; + +// Return all the contact points of the scene +inline std::vector CubesScene::getContactPoints() const { + return computeContactPointsOfWorld(mDynamicsWorld); +} + +} + +#endif diff --git a/testbed/scenes/heightfield/HeightFieldScene.cpp b/testbed/scenes/heightfield/HeightFieldScene.cpp index 3395ac17..5b62f614 100644 --- a/testbed/scenes/heightfield/HeightFieldScene.cpp +++ b/testbed/scenes/heightfield/HeightFieldScene.cpp @@ -54,7 +54,7 @@ HeightFieldScene::HeightFieldScene(const std::string& name) : SceneDemo(name, SC openglframework::Vector3 position(15, 10 + 6 * i, 0); // Create a box and a corresponding rigid in the dynamics world - mBoxes[i] = new Box(Vector3(3, 3, 3), position, 80.1, mDynamicsWorld); + mBoxes[i] = new Box(Vector3(3, 3, 3), position, 80.1, mDynamicsWorld, mMeshFolderPath); // Set the box color mBoxes[i]->setColor(mDemoColors[2]); @@ -156,10 +156,10 @@ void HeightFieldScene::renderSinglePass(Shader& shader, const openglframework::M // Bind the shader shader.bind(); - mHeightField->render(shader, worldToCameraMatrix); + mHeightField->render(shader, worldToCameraMatrix, mIsWireframeEnabled); for (int i=0; irender(shader, worldToCameraMatrix); + mBoxes[i]->render(shader, worldToCameraMatrix, mIsWireframeEnabled); } // Unbind the shader diff --git a/testbed/scenes/joints/JointsScene.cpp b/testbed/scenes/joints/JointsScene.cpp index b1891627..34bb1503 100644 --- a/testbed/scenes/joints/JointsScene.cpp +++ b/testbed/scenes/joints/JointsScene.cpp @@ -163,17 +163,17 @@ void JointsScene::renderSinglePass(openglframework::Shader& shader, shader.bind(); // Render all the boxes - mSliderJointBottomBox->render(shader, worldToCameraMatrix); - mSliderJointTopBox->render(shader, worldToCameraMatrix); - mPropellerBox->render(shader, worldToCameraMatrix); - mFixedJointBox1->render(shader, worldToCameraMatrix); - mFixedJointBox2->render(shader, worldToCameraMatrix); + mSliderJointBottomBox->render(shader, worldToCameraMatrix, mIsWireframeEnabled); + mSliderJointTopBox->render(shader, worldToCameraMatrix, mIsWireframeEnabled); + mPropellerBox->render(shader, worldToCameraMatrix, mIsWireframeEnabled); + mFixedJointBox1->render(shader, worldToCameraMatrix, mIsWireframeEnabled); + mFixedJointBox2->render(shader, worldToCameraMatrix, mIsWireframeEnabled); for (int i=0; irender(shader, worldToCameraMatrix); + mBallAndSocketJointChainBoxes[i]->render(shader, worldToCameraMatrix, mIsWireframeEnabled); } // Render the floor - mFloor->render(shader, worldToCameraMatrix); + mFloor->render(shader, worldToCameraMatrix, mIsWireframeEnabled); // Unbind the shader shader.unbind(); @@ -263,7 +263,7 @@ void JointsScene::createBallAndSocketJoints() { // Create a box and a corresponding rigid in the dynamics world mBallAndSocketJointChainBoxes[i] = new Box(boxDimension, positionBox , boxMass, - mDynamicsWorld); + mDynamicsWorld, mMeshFolderPath); // Set the box color mBallAndSocketJointChainBoxes[i]->setColor(mDemoColors[i % mNbDemoColors]); @@ -312,7 +312,7 @@ void JointsScene::createSliderJoint() { // Create a box and a corresponding rigid in the dynamics world openglframework::Vector3 box1Dimension(2, 4, 2); - mSliderJointBottomBox = new Box(box1Dimension, positionBox1 , BOX_MASS, mDynamicsWorld); + mSliderJointBottomBox = new Box(box1Dimension, positionBox1 , BOX_MASS, mDynamicsWorld, mMeshFolderPath); // Set the box color mSliderJointBottomBox->setColor(mBlueColorDemo); @@ -332,7 +332,7 @@ void JointsScene::createSliderJoint() { // Create a box and a corresponding rigid in the dynamics world openglframework::Vector3 box2Dimension(1.5f, 4, 1.5f); - mSliderJointTopBox = new Box(box2Dimension, positionBox2, BOX_MASS, mDynamicsWorld); + mSliderJointTopBox = new Box(box2Dimension, positionBox2, BOX_MASS, mDynamicsWorld, mMeshFolderPath); // Set the box color mSliderJointTopBox->setColor(mOrangeColorDemo); @@ -372,7 +372,7 @@ void JointsScene::createPropellerHingeJoint() { // Create a box and a corresponding rigid in the dynamics world openglframework::Vector3 boxDimension(10, 1, 1); - mPropellerBox = new Box(boxDimension, positionBox1 , BOX_MASS, mDynamicsWorld); + mPropellerBox = new Box(boxDimension, positionBox1 , BOX_MASS, mDynamicsWorld, mMeshFolderPath); // Set the box color mPropellerBox->setColor(mYellowColorDemo); @@ -411,7 +411,7 @@ void JointsScene::createFixedJoints() { // Create a box and a corresponding rigid in the dynamics world openglframework::Vector3 boxDimension(1.5, 1.5, 1.5); - mFixedJointBox1 = new Box(boxDimension, positionBox1 , BOX_MASS, mDynamicsWorld); + mFixedJointBox1 = new Box(boxDimension, positionBox1 , BOX_MASS, mDynamicsWorld, mMeshFolderPath); // Set the box color mFixedJointBox1->setColor(mPinkColorDemo); @@ -427,7 +427,7 @@ void JointsScene::createFixedJoints() { openglframework::Vector3 positionBox2(-5, 7, 0); // Create a box and a corresponding rigid in the dynamics world - mFixedJointBox2 = new Box(boxDimension, positionBox2 , BOX_MASS, mDynamicsWorld); + mFixedJointBox2 = new Box(boxDimension, positionBox2 , BOX_MASS, mDynamicsWorld, mMeshFolderPath); // Set the box color mFixedJointBox2->setColor(mBlueColorDemo); @@ -466,7 +466,7 @@ void JointsScene::createFloor() { // Create the floor openglframework::Vector3 floorPosition(0, 0, 0); - mFloor = new Box(FLOOR_SIZE, floorPosition, FLOOR_MASS, mDynamicsWorld); + mFloor = new Box(FLOOR_SIZE, floorPosition, FLOOR_MASS, mDynamicsWorld, mMeshFolderPath); // Set the box color mFloor->setColor(mGreyColorDemo); diff --git a/testbed/scenes/raycast/RaycastScene.cpp b/testbed/scenes/raycast/RaycastScene.cpp index 479e0915..58b19055 100644 --- a/testbed/scenes/raycast/RaycastScene.cpp +++ b/testbed/scenes/raycast/RaycastScene.cpp @@ -61,7 +61,7 @@ RaycastScene::RaycastScene(const std::string& name) openglframework::Vector3 position2(0, 0, 0); // Create a box and a corresponding collision body in the dynamics world - mBox = new Box(BOX_SIZE, position2, mCollisionWorld); + mBox = new Box(BOX_SIZE, position2, mCollisionWorld, mMeshFolderPath); mBox->getCollisionBody()->setIsActive(false); // Set the box color @@ -376,15 +376,15 @@ void RaycastScene::renderSinglePass(openglframework::Shader& shader, shader.unbind(); // Render the shapes - if (mBox->getCollisionBody()->isActive()) mBox->render(shader, worldToCameraMatrix); - if (mSphere->getCollisionBody()->isActive()) mSphere->render(shader, worldToCameraMatrix); - if (mCone->getCollisionBody()->isActive()) mCone->render(shader, worldToCameraMatrix); - if (mCylinder->getCollisionBody()->isActive()) mCylinder->render(shader, worldToCameraMatrix); - if (mCapsule->getCollisionBody()->isActive()) mCapsule->render(shader, worldToCameraMatrix); - if (mConvexMesh->getCollisionBody()->isActive()) mConvexMesh->render(shader, worldToCameraMatrix); - if (mDumbbell->getCollisionBody()->isActive()) mDumbbell->render(shader, worldToCameraMatrix); - if (mConcaveMesh->getCollisionBody()->isActive()) mConcaveMesh->render(shader, worldToCameraMatrix); - if (mHeightField->getCollisionBody()->isActive()) mHeightField->render(shader, worldToCameraMatrix); + if (mBox->getCollisionBody()->isActive()) mBox->render(shader, worldToCameraMatrix, mIsWireframeEnabled); + if (mSphere->getCollisionBody()->isActive()) mSphere->render(shader, worldToCameraMatrix, mIsWireframeEnabled); + if (mCone->getCollisionBody()->isActive()) mCone->render(shader, worldToCameraMatrix, mIsWireframeEnabled); + if (mCylinder->getCollisionBody()->isActive()) mCylinder->render(shader, worldToCameraMatrix, mIsWireframeEnabled); + if (mCapsule->getCollisionBody()->isActive()) mCapsule->render(shader, worldToCameraMatrix, mIsWireframeEnabled); + if (mConvexMesh->getCollisionBody()->isActive()) mConvexMesh->render(shader, worldToCameraMatrix, mIsWireframeEnabled); + if (mDumbbell->getCollisionBody()->isActive()) mDumbbell->render(shader, worldToCameraMatrix, mIsWireframeEnabled); + if (mConcaveMesh->getCollisionBody()->isActive()) mConcaveMesh->render(shader, worldToCameraMatrix, mIsWireframeEnabled); + if (mHeightField->getCollisionBody()->isActive()) mHeightField->render(shader, worldToCameraMatrix, mIsWireframeEnabled); shader.unbind(); } diff --git a/testbed/src/Gui.cpp b/testbed/src/Gui.cpp index 499f1fb3..cd9f8f4e 100644 --- a/testbed/src/Gui.cpp +++ b/testbed/src/Gui.cpp @@ -402,6 +402,13 @@ void Gui::createSettingsPanel() { mApp->mIsShadowMappingEnabled = value; }); + // Enable/Disable wireframe mode + CheckBox* checkboxWireframe = new CheckBox(mRenderingPanel, "Wireframe"); + checkboxWireframe->setChecked(mApp->mIsWireframeEnabled); + checkboxWireframe->setCallback([&](bool value) { + mApp->mIsWireframeEnabled = value; + }); + mPhysicsPanel->setVisible(true); mRenderingPanel->setVisible(false); } diff --git a/testbed/src/Scene.cpp b/testbed/src/Scene.cpp index 8031c1f8..e872b3bc 100644 --- a/testbed/src/Scene.cpp +++ b/testbed/src/Scene.cpp @@ -33,7 +33,7 @@ using namespace openglframework; Scene::Scene(const std::string& name, bool isShadowMappingEnabled) : mName(name), mInterpolationFactor(0.0f), mViewportX(0), mViewportY(0), mViewportWidth(0), mViewportHeight(0), mIsShadowMappingEnabled(isShadowMappingEnabled), - mIsContactPointsDisplayed(true) { + mIsContactPointsDisplayed(true), mIsWireframeEnabled(false) { } diff --git a/testbed/src/Scene.h b/testbed/src/Scene.h index bfac3ecb..d51ffec1 100644 --- a/testbed/src/Scene.h +++ b/testbed/src/Scene.h @@ -108,6 +108,9 @@ class Scene { /// True if contact points are displayed bool mIsContactPointsDisplayed; + /// True if we render shapes in wireframe mode + bool mIsWireframeEnabled; + // -------------------- Methods -------------------- // /// Set the scene position (where the camera needs to look at) @@ -199,6 +202,12 @@ class Scene { /// Display/Hide the contact points void virtual setIsContactPointsDisplayed(bool display); + /// Return true if wireframe rendering is enabled + bool getIsWireframeEnabled() const; + + /// Enable/disbale wireframe rendering + void setIsWireframeEnabled(bool isEnabled); + /// Return all the contact points of the scene std::vector virtual getContactPoints() const; }; @@ -267,6 +276,16 @@ inline void Scene::setIsContactPointsDisplayed(bool display) { mIsContactPointsDisplayed = display; } +// Return true if wireframe rendering is enabled +inline bool Scene::getIsWireframeEnabled() const { + return mIsWireframeEnabled; +} + +// Enable/disbale wireframe rendering +inline void Scene::setIsWireframeEnabled(bool isEnabled) { + mIsWireframeEnabled = isEnabled; +} + // Return all the contact points of the scene inline std::vector Scene::getContactPoints() const { diff --git a/testbed/src/TestbedApplication.cpp b/testbed/src/TestbedApplication.cpp index f57aa829..09f464f3 100644 --- a/testbed/src/TestbedApplication.cpp +++ b/testbed/src/TestbedApplication.cpp @@ -30,6 +30,7 @@ #include #include #include "cubes/CubesScene.h" +#include "collisiondetection/CollisionDetectionScene.h" #include "joints/JointsScene.h" #include "collisionshapes/CollisionShapesScene.h" #include "heightfield/HeightFieldScene.h" @@ -43,6 +44,7 @@ using namespace raycastscene; using namespace collisionshapesscene; using namespace trianglemeshscene; using namespace heightfieldscene; +using namespace collisiondetectionscene; // Initialization of static variables const float TestbedApplication::SCROLL_SENSITIVITY = 0.08f; @@ -63,6 +65,7 @@ TestbedApplication::TestbedApplication(bool isFullscreen) mIsShadowMappingEnabled = true; mIsVSyncEnabled = false; mIsContactPointsDisplayed = false; + mIsWireframeEnabled = false; init(); @@ -113,7 +116,11 @@ void TestbedApplication::createScenes() { RaycastScene* raycastScene = new RaycastScene("Raycast"); mScenes.push_back(raycastScene); - // Raycast scene + // Collision Detection scene + CollisionDetectionScene* collisionDetectionScene = new CollisionDetectionScene("Collision Detection"); + mScenes.push_back(collisionDetectionScene); + + // Concave Mesh scene ConcaveMeshScene* concaveMeshScene = new ConcaveMeshScene("Concave Mesh"); mScenes.push_back(concaveMeshScene); @@ -195,6 +202,9 @@ void TestbedApplication::update() { // Display/Hide contact points mCurrentScene->setIsContactPointsDisplayed(mIsContactPointsDisplayed); + // Enable/Disable wireframe mode + mCurrentScene->setIsWireframeEnabled(mIsWireframeEnabled); + // Update the scene mCurrentScene->update(); } diff --git a/testbed/src/TestbedApplication.h b/testbed/src/TestbedApplication.h index dcff0598..93d85ea7 100644 --- a/testbed/src/TestbedApplication.h +++ b/testbed/src/TestbedApplication.h @@ -109,6 +109,9 @@ class TestbedApplication : public Screen { /// True if contact points are displayed bool mIsContactPointsDisplayed; + /// True if the wireframe rendering is enabled + bool mIsWireframeEnabled; + /// True if vsync is enabled bool mIsVSyncEnabled;