Merge branch 'testbed' into develop

This commit is contained in:
Daniel Chappuis 2015-08-11 22:33:54 +02:00
commit 8a26d8a0ca
253 changed files with 9922 additions and 2251 deletions

View File

@ -18,7 +18,7 @@ SET(OUR_EXECUTABLE_OUTPUT_PATH "${PROJECT_BINARY_DIR}/bin")
ENABLE_TESTING()
# Options
OPTION(COMPILE_EXAMPLES "Select this if you want to build the examples" OFF)
OPTION(COMPILE_TESTBED "Select this if you want to build the testbed application" OFF)
OPTION(COMPILE_TESTS "Select this if you want to build the tests" OFF)
OPTION(PROFILING_ENABLED "Select this if you want to compile with enabled profiling" OFF)
OPTION(DOUBLE_PRECISION_ENABLED "Select this if you want to compile using double precision floating
@ -142,10 +142,10 @@ SET (REACTPHYSICS3D_SOURCES
# Create the library
ADD_LIBRARY (reactphysics3d STATIC ${REACTPHYSICS3D_SOURCES})
# If we need to compile the examples
IF(COMPILE_EXAMPLES)
add_subdirectory(examples/)
ENDIF(COMPILE_EXAMPLES)
# If we need to compile the testbed application
IF(COMPILE_TESTBED)
add_subdirectory(testbed/)
ENDIF(COMPILE_TESTBED)
# If we need to compile the tests
IF(COMPILE_TESTS)

View File

@ -1,11 +0,0 @@
# Minimum cmake version required
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
# Set a variable for the directory of the opengl-framework
SET(OPENGLFRAMEWORK_DIR "${CMAKE_CURRENT_SOURCE_DIR}/common/opengl-framework")
ADD_SUBDIRECTORY(common/)
ADD_SUBDIRECTORY(cubes/)
ADD_SUBDIRECTORY(joints/)
ADD_SUBDIRECTORY(collisionshapes/)
ADD_SUBDIRECTORY(raycast/)

View File

@ -1,42 +0,0 @@
# Minimum cmake version required
cmake_minimum_required(VERSION 2.6)
# Project configuration
PROJECT(CollisionShapes)
# Where to build the executables
SET(EXECUTABLE_OUTPUT_PATH "${OUR_EXECUTABLE_OUTPUT_PATH}/collisionshapes")
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${EXECUTABLE_OUTPUT_PATH})
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${EXECUTABLE_OUTPUT_PATH})
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${EXECUTABLE_OUTPUT_PATH})
# Copy the shaders used for the demo into the build directory
FILE(COPY "${OPENGLFRAMEWORK_DIR}/src/shaders/" DESTINATION "${EXECUTABLE_OUTPUT_PATH}/shaders/")
# Copy the meshes used for the demo into the build directory
FILE(COPY "../common/meshes/" DESTINATION "${EXECUTABLE_OUTPUT_PATH}/meshes/")
# Headers
INCLUDE_DIRECTORIES("${OPENGLFRAMEWORK_DIR}/src/" "../common/glfw/include/" "../common/")
# Source files
SET(COLLISION_SHAPES_SOURCES
CollisionShapes.cpp
Scene.cpp
Scene.h
"../common/VisualContactPoint.cpp"
"../common/ConvexMesh.cpp"
"../common/Capsule.cpp"
"../common/Sphere.cpp"
"../common/Cylinder.cpp"
"../common/Cone.cpp"
"../common/Dumbbell.cpp"
"../common/Box.cpp"
"../common/Viewer.cpp"
)
# Create the executable
ADD_EXECUTABLE(collisionshapes ${COLLISION_SHAPES_SOURCES})
# Link with libraries
TARGET_LINK_LIBRARIES(collisionshapes reactphysics3d openglframework glfw ${GLFW_LIBRARIES})

View File

@ -1,152 +0,0 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2015 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 "Scene.h"
#include "../common/Viewer.h"
// Declarations
void simulate();
void render();
void update();
void mouseButton(GLFWwindow* window, int button, int action, int mods);
void mouseMotion(GLFWwindow* window, double x, double y);
void keyboard(GLFWwindow* window, int key, int scancode, int action, int mods);
void scroll(GLFWwindow* window, double xAxis, double yAxis);
void init();
// Namespaces
using namespace openglframework;
// Global variables
Viewer* viewer;
Scene* scene;
// Main function
int main(int argc, char** argv) {
// Create and initialize the Viewer
viewer = new Viewer();
Vector2 windowsSize = Vector2(800, 600);
Vector2 windowsPosition = Vector2(100, 100);
viewer->init(argc, argv, "ReactPhysics3D Examples - Collision Shapes",
windowsSize, windowsPosition, true);
// If the shaders and meshes folders are not specified as an argument
if (argc < 3) {
std::cerr << "Error : You need to specify the shaders folder as the first argument"
<< " and the meshes folder as the second argument" << std::endl;
return 1;
}
// Get the path of the shaders folder
std::string shaderFolderPath(argv[1]);
std::string meshFolderPath(argv[2]);
// Register callback methods
viewer->registerUpdateFunction(update);
viewer->registerKeyboardCallback(keyboard);
viewer->registerMouseButtonCallback(mouseButton);
viewer->registerMouseCursorCallback(mouseMotion);
viewer->registerScrollingCallback(scroll);
// Create the scene
scene = new Scene(viewer, shaderFolderPath, meshFolderPath);
init();
viewer->startMainLoop();
delete viewer;
delete scene;
return 0;
}
// Update function that is called each frame
void update() {
// Take a simulation step
simulate();
// Render
render();
}
// Simulate function
void simulate() {
// Physics simulation
scene->simulate();
viewer->computeFPS();
}
// Initialization
void init() {
// Define the background color (black)
glClearColor(0.0, 0.0, 0.0, 1.0);
}
// Callback method to receive keyboard events
void keyboard(GLFWwindow* window, int key, int scancode, int action, int mods) {
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) {
glfwSetWindowShouldClose(window, GL_TRUE);
}
else if (key == GLFW_KEY_SPACE && action == GLFW_PRESS) {
scene->pauseContinueSimulation();
}
}
// Callback method to receive scrolling events
void scroll(GLFWwindow* window, double xAxis, double yAxis) {
viewer->scrollingEvent(static_cast<float>(yAxis));
}
// Called when a mouse button event occurs
void mouseButton(GLFWwindow* window, int button, int action, int mods) {
viewer->mouseButtonEvent(button, action);
}
// Called when a mouse motion event occurs
void mouseMotion(GLFWwindow* window, double x, double y) {
viewer->mouseMotionEvent(x, y);
}
// Display the scene
void render() {
// Render the scene
scene->render();
// Display the FPS
viewer->displayGUI();
// Check the OpenGL errors
Viewer::checkOpenGLErrors();
}

View File

@ -1,5 +0,0 @@
# Minimum cmake version required
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
ADD_SUBDIRECTORY(opengl-framework/)
ADD_SUBDIRECTORY(glfw/)

View File

@ -1,115 +0,0 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2015 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 "VisualContactPoint.h"
// Initialization of static variables
int VisualContactPoint::mNbTotalPoints = 0;
bool VisualContactPoint::mIsMeshInitialized = false;
openglframework::Mesh VisualContactPoint::mMesh;
// Constructor
VisualContactPoint::VisualContactPoint(const openglframework::Vector3& position) {
assert(mIsMeshInitialized);
// Initialize the position where the sphere will be rendered
translateWorld(position);
}
// Destructor
VisualContactPoint::~VisualContactPoint() {
}
// 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);
// Calculate the normals of the mesh
mMesh.calculateNormals();
mMesh.scaleVertices(VISUAL_CONTACT_POINT_RADIUS);
mIsMeshInitialized = true;
}
}
// 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
void VisualContactPoint::render(openglframework::Shader& shader,
const openglframework::Matrix4& worldToCameraMatrix) {
// Bind the shader
shader.bind();
// Set the model to camera matrix
const openglframework::Matrix4 localToCameraMatrix = worldToCameraMatrix * mTransformMatrix;
shader.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();
shader.setMatrix3x3Uniform("normalMatrix", normalMatrix);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
if (mMesh.hasTexture()) {
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
}
glVertexPointer(3, GL_FLOAT, 0, mMesh.getVerticesPointer());
glNormalPointer(GL_FLOAT, 0, mMesh.getNormalsPointer());
if(mMesh.hasTexture()) {
glTexCoordPointer(2, GL_FLOAT, 0, mMesh.getUVTextureCoordinatesPointer());
}
// For each part of the mesh
for (unsigned int i=0; i<mMesh.getNbParts(); i++) {
glDrawElements(GL_TRIANGLES, mMesh.getNbFaces(i) * 3,
GL_UNSIGNED_INT, mMesh.getIndicesPointer());
}
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
if (mMesh.hasTexture()) {
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
// Unbind the shader
shader.unbind();
}

View File

@ -1,100 +0,0 @@
/********************************************************************************
* OpenGL-Framework *
* Copyright (c) 2013 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 "Light.h"
// Namespaces
using namespace openglframework;
// Constructor
Light::Light(GLuint id)
: mLightID(id), mDiffuseColor(Color::white()),
mSpecularColor(Color::white()), mIsActive(false) {
}
// Constructor
Light::Light(GLuint id, Color diffuseColor, Color specularColor)
: mLightID(id), mDiffuseColor(diffuseColor),
mSpecularColor(specularColor), mIsActive(false) {
}
// Destructor
Light::~Light() {
}
// Initialize the light
void Light::init() {
// Enable the light
enable();
// Set the diffuse and specular color
GLfloat diffuseColor[] = {mDiffuseColor.r, mDiffuseColor.g, mDiffuseColor.b, mDiffuseColor.a};
GLfloat specularColor[] = {mSpecularColor.r,mSpecularColor.g,mSpecularColor.b,mSpecularColor.a};
glLightfv(mLightID, GL_DIFFUSE, diffuseColor);
glLightfv(mLightID, GL_SPECULAR, specularColor);
}
// Create a shadow map associated with this light
bool Light::createShadowMap(uint width, uint height) {
// Destroy the current shadow map
destroyShadowMap();
// Create the Framebuffer object to render the shadow map
bool isFBOCreated = mFBOShadowMap.create(width, height, false);
if (!isFBOCreated) {
std::cerr << "Error : Cannot create the Shadow Map !" << std::endl;
destroyShadowMap();
return false;
}
// Bind the Framebuffer object
mFBOShadowMap.bind(GL_NONE);
// Create the shadow map depth texture
mShadowMap.create(width, height, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE);
// Attache the shadow map texture to the Framebuffer object
mFBOShadowMap.attachTexture(GL_DEPTH_ATTACHMENT_EXT, mShadowMap.getID());
// Unbind the Framebuffer object
mFBOShadowMap.unbind();
// TODO : Change the path of the shader here so that it does not depend on the build folder
bool isShaderCreated = mDepthShader.create("../../opengl-framework/src/shaders/depth.vert",
"../../opengl-framework/src/shaders/depth.vert");
if (!isShaderCreated) {
std::cerr << "Error : Cannot create the Shadow Map !" << std::endl;
destroyShadowMap();
return false;
}
return true;
}

View File

@ -1,34 +0,0 @@
# Minimum cmake version required
cmake_minimum_required(VERSION 2.6)
# Project configuration
PROJECT(Cubes)
# Where to build the executables
SET(EXECUTABLE_OUTPUT_PATH "${OUR_EXECUTABLE_OUTPUT_PATH}/cubes")
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${EXECUTABLE_OUTPUT_PATH})
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${EXECUTABLE_OUTPUT_PATH})
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${EXECUTABLE_OUTPUT_PATH})
# Copy the shaders used for the demo into the build directory
FILE(COPY "${OPENGLFRAMEWORK_DIR}/src/shaders/" DESTINATION "${EXECUTABLE_OUTPUT_PATH}/shaders/")
# Headers
INCLUDE_DIRECTORIES("${OPENGLFRAMEWORK_DIR}/src/" "../common/glfw/include/" "../common/")
# Source files
SET(CUBES_SOURCES
Cubes.cpp
Scene.cpp
Scene.h
"../common/Box.cpp"
"../common/Box.h"
"../common/Viewer.cpp"
"../common/Viewer.h"
)
# Create the executable
ADD_EXECUTABLE(cubes ${CUBES_SOURCES})
# Link with libraries
TARGET_LINK_LIBRARIES(cubes reactphysics3d openglframework glfw ${GLFW_LIBRARIES})

View File

@ -1,148 +0,0 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2015 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 "Scene.h"
#include "Viewer.h"
// Declarations
void simulate();
void render();
void update();
void mouseButton(GLFWwindow* window, int button, int action, int mods);
void mouseMotion(GLFWwindow* window, double x, double y);
void keyboard(GLFWwindow* window, int key, int scancode, int action, int mods);
void scroll(GLFWwindow* window, double xAxis, double yAxis);
void init();
// Namespaces
using namespace openglframework;
// Global variables
Viewer* viewer;
Scene* scene;
// Main function
int main(int argc, char** argv) {
// Create and initialize the Viewer
viewer = new Viewer();
Vector2 windowsSize = Vector2(800, 600);
Vector2 windowsPosition = Vector2(100, 100);
viewer->init(argc, argv, "ReactPhysics3D Examples - Cubes", windowsSize, windowsPosition, true);
// If the shaders folder is not specified as an argument
if (argc < 2) {
std::cerr << "Error : You need to specify the shaders folder as argument !" << std::endl;
return 1;
}
// Get the path of the shaders folder
std::string shaderFolderPath(argv[1]);
// Register callback methods
viewer->registerUpdateFunction(update);
viewer->registerKeyboardCallback(keyboard);
viewer->registerMouseButtonCallback(mouseButton);
viewer->registerMouseCursorCallback(mouseMotion);
viewer->registerScrollingCallback(scroll);
// Create the scene
scene = new Scene(viewer, shaderFolderPath);
init();
viewer->startMainLoop();
delete viewer;
delete scene;
return 0;
}
// Update function that is called each frame
void update() {
// Take a simulation step
simulate();
// Render
render();
}
// Simulate function
void simulate() {
// Physics simulation
scene->simulate();
// Compute the current framerate
viewer->computeFPS();
}
// Initialization
void init() {
// Define the background color (black)
glClearColor(0.0, 0.0, 0.0, 1.0);
}
// Callback method to receive keyboard events
void keyboard(GLFWwindow* window, int key, int scancode, int action, int mods) {
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) {
glfwSetWindowShouldClose(window, GL_TRUE);
}
else if (key == GLFW_KEY_SPACE && action == GLFW_PRESS) {
scene->pauseContinueSimulation();
}
}
// Callback method to receive scrolling events
void scroll(GLFWwindow* window, double xAxis, double yAxis) {
viewer->scrollingEvent(static_cast<float>(yAxis));
}
// Called when a mouse button event occurs
void mouseButton(GLFWwindow* window, int button, int action, int mods) {
viewer->mouseButtonEvent(button, action);
}
// Called when a mouse motion event occurs
void mouseMotion(GLFWwindow* window, double x, double y) {
viewer->mouseMotionEvent(x, y);
}
// Display the scene
void render() {
// Render the scene
scene->render();
// Display the FPS
viewer->displayGUI();
// Check the OpenGL errors
Viewer::checkOpenGLErrors();
}

View File

@ -1,34 +0,0 @@
# Minimum cmake version required
cmake_minimum_required(VERSION 2.6)
# Project configuration
PROJECT(Joints)
# Where to build the executables
SET(EXECUTABLE_OUTPUT_PATH "${OUR_EXECUTABLE_OUTPUT_PATH}/joints")
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${EXECUTABLE_OUTPUT_PATH})
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${EXECUTABLE_OUTPUT_PATH})
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${EXECUTABLE_OUTPUT_PATH})
# Copy the shaders used for the demo into the build directory
FILE(COPY "${OPENGLFRAMEWORK_DIR}/src/shaders/" DESTINATION "${EXECUTABLE_OUTPUT_PATH}/shaders/")
# Headers
INCLUDE_DIRECTORIES("${OPENGLFRAMEWORK_DIR}/src/" "../common/glfw/include/" "../common/")
# Source files
SET(JOINTS_SOURCES
Joints.cpp
Scene.cpp
Scene.h
"../common/Box.cpp"
"../common/Box.h"
"../common/Viewer.cpp"
"../common/Viewer.h"
)
# Create the executable
ADD_EXECUTABLE(joints ${JOINTS_SOURCES})
# Link with libraries
TARGET_LINK_LIBRARIES(joints reactphysics3d openglframework glfw ${GLFW_LIBRARIES})

View File

@ -1,149 +0,0 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2015 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 "Scene.h"
#include "../common/Viewer.h"
// Declarations
void simulate();
void update();
void render();
void mouseButton(GLFWwindow* window, int button, int action, int mods);
void mouseMotion(GLFWwindow* window, double x, double y);
void keyboard(GLFWwindow* window, int key, int scancode, int action, int mods);
void scroll(GLFWwindow* window, double xAxis, double yAxis);
void init();
// Namespaces
using namespace openglframework;
// Global variables
Viewer* viewer;
Scene* scene;
// Main function
int main(int argc, char** argv) {
// Create and initialize the Viewer
viewer = new Viewer();
Vector2 windowsSize = Vector2(800, 600);
Vector2 windowsPosition = Vector2(100, 100);
viewer->init(argc, argv, "ReactPhysics3D Examples - Joints", windowsSize, windowsPosition, true);
// If the shaders folder is not specified as an argument
if (argc < 2) {
std::cerr << "Error : You need to specify the shaders folder as argument !" << std::endl;
return 1;
}
// Get the path of the shaders folder
std::string shaderFolderPath(argv[1]);
// Register callback methods
viewer->registerUpdateFunction(update);
viewer->registerKeyboardCallback(keyboard);
viewer->registerMouseButtonCallback(mouseButton);
viewer->registerMouseCursorCallback(mouseMotion);
viewer->registerScrollingCallback(scroll);
// Create the scene
scene = new Scene(viewer, shaderFolderPath);
init();
viewer->startMainLoop();
delete viewer;
delete scene;
return 0;
}
// Update function that is called each frame
void update() {
// Take a simulation step
simulate();
// Render
render();
}
// Simulate function
void simulate() {
// Physics simulation
scene->simulate();
viewer->computeFPS();
}
// Initialization
void init() {
// Define the background color (black)
glClearColor(0.0, 0.0, 0.0, 1.0);
}
// Callback method to receive keyboard events
void keyboard(GLFWwindow* window, int key, int scancode, int action, int mods) {
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) {
glfwSetWindowShouldClose(window, GL_TRUE);
}
else if (key == GLFW_KEY_SPACE && action == GLFW_PRESS) {
scene->pauseContinueSimulation();
}
}
// Callback method to receive scrolling events
void scroll(GLFWwindow* window, double xAxis, double yAxis) {
viewer->scrollingEvent(static_cast<float>(yAxis));
}
// Called when a mouse button event occurs
void mouseButton(GLFWwindow* window, int button, int action, int mods) {
viewer->mouseButtonEvent(button, action);
}
// Called when a mouse motion event occurs
void mouseMotion(GLFWwindow* window, double x, double y) {
viewer->mouseMotionEvent(x, y);
}
// Display the scene
void render() {
// Render the scene
scene->render();
// Display the FPS
viewer->displayGUI();
// Check the OpenGL errors
Viewer::checkOpenGLErrors();
}

View File

@ -1,43 +0,0 @@
# Minimum cmake version required
cmake_minimum_required(VERSION 2.6)
# Project configuration
PROJECT(Raycast)
# Where to build the executables
SET(EXECUTABLE_OUTPUT_PATH "${OUR_EXECUTABLE_OUTPUT_PATH}/raycast")
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${EXECUTABLE_OUTPUT_PATH})
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${EXECUTABLE_OUTPUT_PATH})
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${EXECUTABLE_OUTPUT_PATH})
# Copy the shaders used for the demo into the build directory
FILE(COPY "${OPENGLFRAMEWORK_DIR}/src/shaders/" DESTINATION "${EXECUTABLE_OUTPUT_PATH}/shaders/")
# Copy the meshes used for the demo into the build directory
FILE(COPY "../common/meshes/" DESTINATION "${EXECUTABLE_OUTPUT_PATH}/meshes/")
# Headers
INCLUDE_DIRECTORIES("${OPENGLFRAMEWORK_DIR}/src/" "../common/glfw/include/" "../common/")
# Source files
SET(RAYCAST_SOURCES
Raycast.cpp
Scene.cpp
Scene.h
"../common/VisualContactPoint.cpp"
"../common/ConvexMesh.cpp"
"../common/Capsule.cpp"
"../common/Sphere.cpp"
"../common/Line.cpp"
"../common/Cylinder.cpp"
"../common/Cone.cpp"
"../common/Dumbbell.cpp"
"../common/Box.cpp"
"../common/Viewer.cpp"
)
# Create the executable
ADD_EXECUTABLE(raycast ${RAYCAST_SOURCES})
# Link with libraries
TARGET_LINK_LIBRARIES(raycast reactphysics3d openglframework glfw ${GLFW_LIBRARIES})

View File

@ -1,155 +0,0 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2015 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 "Scene.h"
#include "../common/Viewer.h"
// Declarations
void simulate();
void render();
void update();
void mouseButton(GLFWwindow* window, int button, int action, int mods);
void mouseMotion(GLFWwindow* window, double x, double y);
void keyboard(GLFWwindow* window, int key, int scancode, int action, int mods);
void scroll(GLFWwindow* window, double xAxis, double yAxis);
void init();
// Namespaces
using namespace openglframework;
// Global variables
Viewer* viewer;
Scene* scene;
// Main function
int main(int argc, char** argv) {
// Create and initialize the Viewer
viewer = new Viewer();
Vector2 windowsSize = Vector2(800, 600);
Vector2 windowsPosition = Vector2(100, 100);
viewer->init(argc, argv, "ReactPhysics3D Examples - Raycast",
windowsSize, windowsPosition, true);
// If the shaders and meshes folders are not specified as an argument
if (argc < 3) {
std::cerr << "Error : You need to specify the shaders folder as the first argument"
<< " and the meshes folder as the second argument" << std::endl;
return 1;
}
// Get the path of the shaders folder
std::string shaderFolderPath(argv[1]);
std::string meshFolderPath(argv[2]);
// Register callback methods
viewer->registerUpdateFunction(update);
viewer->registerKeyboardCallback(keyboard);
viewer->registerMouseButtonCallback(mouseButton);
viewer->registerMouseCursorCallback(mouseMotion);
viewer->registerScrollingCallback(scroll);
// Create the scene
scene = new Scene(viewer, shaderFolderPath, meshFolderPath);
init();
viewer->startMainLoop();
delete viewer;
delete scene;
return 0;
}
// Update function that is called each frame
void update() {
// Take a simulation step
simulate();
// Render
render();
}
// Simulate function
void simulate() {
// Physics simulation
scene->simulate();
viewer->computeFPS();
}
// Initialization
void init() {
// Define the background color (black)
glClearColor(0.0, 0.0, 0.0, 1.0);
}
// Callback method to receive keyboard events
void keyboard(GLFWwindow* window, int key, int scancode, int action, int mods) {
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) {
glfwSetWindowShouldClose(window, GL_TRUE);
}
if (key == GLFW_KEY_SPACE && action == GLFW_PRESS) {
scene->changeBody();
}
if (key == GLFW_KEY_N && action == GLFW_PRESS) {
scene->showHideNormals();
}
}
// Callback method to receive scrolling events
void scroll(GLFWwindow* window, double xAxis, double yAxis) {
viewer->scrollingEvent(static_cast<float>(yAxis));
}
// Called when a mouse button event occurs
void mouseButton(GLFWwindow* window, int button, int action, int mods) {
viewer->mouseButtonEvent(button, action);
}
// Called when a mouse motion event occurs
void mouseMotion(GLFWwindow* window, double x, double y) {
viewer->mouseMotionEvent(x, y);
}
// Display the scene
void render() {
// Render the scene
scene->render();
// Display the FPS
viewer->displayGUI();
// Check the OpenGL errors
Viewer::checkOpenGLErrors();
}

View File

@ -83,9 +83,6 @@ class Body {
/// Private assignment operator
Body& operator=(const Body& body);
/// Set the variable to know whether or not the body is sleeping
virtual void setIsSleeping(bool isSleeping);
public :
// -------------------- Methods -------------------- //
@ -105,6 +102,9 @@ class Body {
/// Set whether or not the body is allowed to go to sleep
void setIsAllowedToSleep(bool isAllowedToSleep);
/// Set the variable to know whether or not the body is sleeping
virtual void setIsSleeping(bool isSleeping);
/// Return whether or not the body is sleeping
bool isSleeping() const;

View File

@ -41,8 +41,6 @@ CollisionBody::CollisionBody(const Transform& transform, CollisionWorld& world,
: Body(id), mType(DYNAMIC), mTransform(transform), mProxyCollisionShapes(NULL),
mNbCollisionShapes(0), mContactManifoldsList(NULL), mWorld(world) {
// Initialize the old transform
mOldTransform = transform;
}
// Destructor

View File

@ -73,9 +73,6 @@ class CollisionBody : public Body {
/// Position and orientation of the body
Transform mTransform;
/// Last position and orientation of the body
Transform mOldTransform;
/// First element of the linked list of proxy collision shapes of this body
ProxyShape* mProxyCollisionShapes;
@ -102,9 +99,6 @@ class CollisionBody : public Body {
/// Remove all the collision shapes
void removeAllCollisionShapes();
/// Update the old transform with the current one.
void updateOldTransform();
/// Update the broad-phase state for this body (because it has moved for instance)
virtual void updateBroadPhaseState() const;
@ -138,7 +132,7 @@ class CollisionBody : public Body {
const Transform& getTransform() const;
/// Set the current position and orientation
void setTransform(const Transform& transform);
virtual void setTransform(const Transform& transform);
/// Add a collision shape to the body.
virtual ProxyShape* addCollisionShape(const CollisionShape& collisionShape,
@ -241,12 +235,6 @@ inline void CollisionBody::setTransform(const Transform& transform) {
updateBroadPhaseState();
}
// Update the old transform with the current one.
/// This is used to compute the interpolated position and orientation of the body
inline void CollisionBody::updateOldTransform() {
mOldTransform = mTransform;
}
// Return the first element of the linked list of contact manifolds involving this body
/**
* @return A pointer to the first element of the linked-list with the contact

View File

@ -265,6 +265,64 @@ void RigidBody::removeCollisionShape(const ProxyShape* proxyShape) {
recomputeMassInformation();
}
// Set the linear velocity of the rigid body.
/**
* @param linearVelocity Linear velocity vector of the body
*/
void RigidBody::setLinearVelocity(const Vector3& linearVelocity) {
// If it is a static body, we do nothing
if (mType == STATIC) return;
// Update the linear velocity of the current body state
mLinearVelocity = linearVelocity;
// If the linear velocity is not zero, awake the body
if (mLinearVelocity.lengthSquare() > decimal(0.0)) {
setIsSleeping(false);
}
}
// Set the angular velocity.
/**
* @param angularVelocity The angular velocity vector of the body
*/
void RigidBody::setAngularVelocity(const Vector3& angularVelocity) {
// If it is a static body, we do nothing
if (mType == STATIC) return;
// Set the angular velocity
mAngularVelocity = angularVelocity;
// If the velocity is not zero, awake the body
if (mAngularVelocity.lengthSquare() > decimal(0.0)) {
setIsSleeping(false);
}
}
// Set the current position and orientation
/**
* @param transform The transformation of the body that transforms the local-space
* of the body into world-space
*/
void RigidBody::setTransform(const Transform& transform) {
// Update the transform of the body
mTransform = transform;
const Vector3 oldCenterOfMass = mCenterOfMassWorld;
// Compute the new center of mass in world-space coordinates
mCenterOfMassWorld = mTransform * mCenterOfMassLocal;
// Update the linear velocity of the center of mass
mLinearVelocity += mAngularVelocity.cross(mCenterOfMassWorld - oldCenterOfMass);
// Update the broad-phase state of the body
updateBroadPhaseState();
}
// Recompute the center of mass, total mass and inertia tensor of the body using all
// the collision shapes attached to the body.
void RigidBody::recomputeMassInformation() {

View File

@ -118,9 +118,6 @@ class RigidBody : public CollisionBody {
/// Update the broad-phase state for this body (because it has moved for instance)
virtual void updateBroadPhaseState() const;
/// Set the variable to know whether or not the body is sleeping
virtual void setIsSleeping(bool isSleeping);
public :
// -------------------- Methods -------------------- //
@ -134,6 +131,9 @@ class RigidBody : public CollisionBody {
/// Set the type of the body (static, kinematic or dynamic)
void setType(BodyType type);
/// Set the current position and orientation
virtual void setTransform(const Transform& transform);
/// Return the mass of the body
decimal getMass() const;
@ -149,6 +149,9 @@ class RigidBody : public CollisionBody {
/// Set the angular velocity.
void setAngularVelocity(const Vector3& angularVelocity);
/// Set the variable to know whether or not the body is sleeping
virtual void setIsSleeping(bool isSleeping);
/// Return the local inertia tensor of the body (in body coordinates)
const Matrix3x3& getInertiaTensorLocal() const;
@ -252,20 +255,6 @@ inline Vector3 RigidBody::getAngularVelocity() const {
return mAngularVelocity;
}
// Set the angular velocity.
/// You should only call this method for a kinematic body. Otherwise, it
/// will do nothing.
/**
* @param angularVelocity The angular velocity vector of the body
*/
inline void RigidBody::setAngularVelocity(const Vector3& angularVelocity) {
// If it is a kinematic body
if (mType == KINEMATIC) {
mAngularVelocity = angularVelocity;
}
}
// Return the local inertia tensor of the body (in local-space coordinates)
/**
* @return The 3x3 inertia tensor matrix of the body (in local-space coordinates)
@ -310,22 +299,6 @@ inline Matrix3x3 RigidBody::getInertiaTensorInverseWorld() const {
mTransform.getOrientation().getMatrix().getTranspose();
}
// Set the linear velocity of the rigid body.
/// You should only call this method for a kinematic body. Otherwise, it
/// will do nothing.
/**
* @param linearVelocity Linear velocity vector of the body
*/
inline void RigidBody::setLinearVelocity(const Vector3& linearVelocity) {
// If it is a kinematic body
if (mType == KINEMATIC) {
// Update the linear velocity of the current body state
mLinearVelocity = linearVelocity;
}
}
// Return true if the gravity needs to be applied to this rigid body
/**
* @return True if the gravity is applied to the body

View File

@ -142,9 +142,6 @@ void DynamicsWorld::update(decimal timeStep) {
// Reset the external force and torque applied to the bodies
resetBodiesForceAndTorque();
// Compute and set the interpolation factor to all the bodies
setInterpolationFactorToAllBodies();
}
// Integrate position and orientation of the rigid bodies.
@ -331,9 +328,6 @@ void DynamicsWorld::integrateRigidBodiesVelocities() {
mConstrainedAngularVelocities[indexBody] *= clamp(angularDamping, decimal(0.0),
decimal(1.0));
// Update the old Transform of the body
bodies[b]->updateOldTransform();
indexBody++;
}
}
@ -958,3 +952,23 @@ void DynamicsWorld::testCollision(CollisionCallback* callback) {
// Perform the collision detection and report contacts
mCollisionDetection.reportCollisionBetweenShapes(callback, emptySet, emptySet);
}
/// Return the list of all contacts of the world
std::vector<const ContactManifold*> DynamicsWorld::getContactsList() const {
std::vector<const ContactManifold*> contactManifolds;
// For each currently overlapping pair of bodies
std::map<overlappingpairid, OverlappingPair*>::const_iterator it;
for (it = mCollisionDetection.mOverlappingPairs.begin();
it != mCollisionDetection.mOverlappingPairs.end(); ++it) {
OverlappingPair* pair = it->second;
// Get the contact manifold
contactManifolds.push_back(pair->getContactManifold());
}
// Return all the contact manifold
return contactManifolds;
}

View File

@ -186,18 +186,18 @@ class DynamicsWorld : public CollisionWorld {
/// Destructor
virtual ~DynamicsWorld();
/// Start the physics simulation
void start();
/// Stop the physics simulation
void stop();
/// Update the physics simulation
void update(decimal timeStep);
/// Get the number of iterations for the velocity constraint solver
uint getNbIterationsVelocitySolver() const;
/// Set the number of iterations for the velocity constraint solver
void setNbIterationsVelocitySolver(uint nbIterations);
/// Get the number of iterations for the position constraint solver
uint getNbIterationsPositionSolver() const;
/// Set the number of iterations for the position constraint solver
void setNbIterationsPositionSolver(uint nbIterations);
@ -226,6 +226,9 @@ class DynamicsWorld : public CollisionWorld {
/// Return the gravity vector of the world
Vector3 getGravity() const;
/// Set the gravity vector of the world
void setGravity(Vector3& gravity);
/// Return if the gravity is on
bool isGravityEnabled() const;
@ -238,9 +241,6 @@ class DynamicsWorld : public CollisionWorld {
/// Return the number of joints in the world
uint getNbJoints() const;
/// Return the current physics time (in seconds)
long double getPhysicsTime() const;
/// Return an iterator to the beginning of the rigid bodies of the physics world
std::set<RigidBody*>::iterator getRigidBodiesBeginIterator();
@ -297,6 +297,9 @@ class DynamicsWorld : public CollisionWorld {
/// Test and report collisions between all shapes of the world
virtual void testCollision(CollisionCallback* callback);
/// Return the list of all contacts of the world
std::vector<const ContactManifold*> getContactsList() const;
// -------------------- Friendship -------------------- //
friend class RigidBody;
@ -313,6 +316,11 @@ inline void DynamicsWorld::resetBodiesForceAndTorque() {
}
}
// Get the number of iterations for the velocity constraint solver
inline uint DynamicsWorld::getNbIterationsVelocitySolver() const {
return mNbVelocitySolverIterations;
}
// Set the number of iterations for the velocity constraint solver
/**
* @param nbIterations Number of iterations for the velocity solver
@ -321,6 +329,11 @@ inline void DynamicsWorld::setNbIterationsVelocitySolver(uint nbIterations) {
mNbVelocitySolverIterations = nbIterations;
}
// Get the number of iterations for the position constraint solver
inline uint DynamicsWorld::getNbIterationsPositionSolver() const {
return mNbPositionSolverIterations;
}
// Set the number of iterations for the position constraint solver
/**
* @param nbIterations Number of iterations for the position solver
@ -375,6 +388,14 @@ inline Vector3 DynamicsWorld::getGravity() const {
return mGravity;
}
// Set the gravity vector of the world
/**
* @param gravity The gravity vector (in meter per seconds squared)
*/
inline void DynamicsWorld::setGravity(Vector3& gravity) {
mGravity = gravity;
}
// Return if the gravity is enaled
/**
* @return True if the gravity is enabled in the world

View File

@ -54,7 +54,9 @@ Vector2::~Vector2() {
Vector2 Vector2::getUnit() const {
decimal lengthVector = length();
assert(lengthVector > MACHINE_EPSILON);
if (lengthVector < MACHINE_EPSILON) {
return *this;
}
// Compute and return the unit vector
decimal lengthInv = decimal(1.0) / lengthVector;

View File

@ -178,7 +178,9 @@ inline decimal Vector2::dot(const Vector2& vector) const {
// Normalize the vector
inline void Vector2::normalize() {
decimal l = length();
assert(l > std::numeric_limits<decimal>::epsilon());
if (l < MACHINE_EPSILON) {
return;
}
x /= l;
y /= l;
}

View File

@ -55,7 +55,9 @@ Vector3::~Vector3() {
Vector3 Vector3::getUnit() const {
decimal lengthVector = length();
assert(lengthVector > MACHINE_EPSILON);
if (lengthVector < MACHINE_EPSILON) {
return *this;
}
// Compute and return the unit vector
decimal lengthInv = decimal(1.0) / lengthVector;

View File

@ -193,7 +193,9 @@ inline Vector3 Vector3::cross(const Vector3& vector) const {
// Normalize the vector
inline void Vector3::normalize() {
decimal l = length();
assert(l > std::numeric_limits<decimal>::epsilon());
if (l < MACHINE_EPSILON) {
return;
}
x /= l;
y /= l;
z /= l;

97
testbed/CMakeLists.txt Normal file
View File

@ -0,0 +1,97 @@
# Minimum cmake version required
cmake_minimum_required(VERSION 2.6)
# Project configuration
PROJECT(Testbed)
# Where to build the executables
SET(EXECUTABLE_OUTPUT_PATH "${OUR_EXECUTABLE_OUTPUT_PATH}/testbed")
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${EXECUTABLE_OUTPUT_PATH})
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${EXECUTABLE_OUTPUT_PATH})
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${EXECUTABLE_OUTPUT_PATH})
ADD_SUBDIRECTORY(opengl-framework/)
ADD_SUBDIRECTORY(glfw/)
# Copy the shaders used for the demo into the build directory
FILE(COPY "shaders/" DESTINATION "${EXECUTABLE_OUTPUT_PATH}/shaders/")
# Copy the meshes used for the demo into the build directory
FILE(COPY "meshes/" DESTINATION "${EXECUTABLE_OUTPUT_PATH}/meshes/")
# Copy the fonts used for the GUI into the build directory
FILE(COPY "imgui/DroidSans.ttf" DESTINATION "${EXECUTABLE_OUTPUT_PATH}")
# Enable C++11 features
SET(CMAKE_CXX_FLAGS "-std=c++0x")
#ADD_DEFINITIONS(-DGL3)
# Headers
INCLUDE_DIRECTORIES("src/" "opengl-framework/src/" "glfw/include/" "common/" "scenes/" "imgui/")
# Testbed source files
SET(TESTBED_SOURCES
src/Main.cpp
src/TestbedApplication.h
src/TestbedApplication.cpp
src/Gui.h
src/Gui.cpp
src/Scene.h
src/Scene.cpp
src/SceneDemo.h
src/SceneDemo.cpp
src/Timer.h
src/Timer.cpp
)
# IMGUI source files
SET(IMGUI_SOURCES
imgui/imgui.cpp
imgui/imgui.h
imgui/imguiRenderGL3.h
imgui/imguiRenderGL3.cpp
imgui/stb_truetype.h
)
# Common source files
SET(COMMON_SOURCES
common/Box.h
common/Box.cpp
common/Cone.h
common/Cone.cpp
common/Sphere.h
common/Sphere.cpp
common/Line.h
common/Line.cpp
common/Capsule.h
common/Capsule.cpp
common/ConvexMesh.h
common/ConvexMesh.cpp
common/Cylinder.h
common/Cylinder.cpp
common/Dumbbell.h
common/Dumbbell.cpp
common/PhysicsObject.h
common/PhysicsObject.cpp
common/VisualContactPoint.h
common/VisualContactPoint.cpp
)
# Examples scenes source files
SET(SCENES_SOURCES
scenes/cubes/CubesScene.h
scenes/cubes/CubesScene.cpp
scenes/joints/JointsScene.h
scenes/joints/JointsScene.cpp
scenes/raycast/RaycastScene.h
scenes/raycast/RaycastScene.cpp
scenes/collisionshapes/CollisionShapesScene.h
scenes/collisionshapes/CollisionShapesScene.cpp
)
# Create the executable
ADD_EXECUTABLE(testbed ${TESTBED_SOURCES} ${SCENES_SOURCES} ${COMMON_SOURCES} ${IMGUI_SOURCES})
# Link with libraries
TARGET_LINK_LIBRARIES(testbed reactphysics3d openglframework glfw ${GLFW_LIBRARIES})

View File

@ -31,35 +31,89 @@
// Initialize static variables
openglframework::VertexBufferObject Box::mVBOVertices(GL_ARRAY_BUFFER);
openglframework::VertexBufferObject Box::mVBOIndices(GL_ELEMENT_ARRAY_BUFFER);
bool Box::areVBOsCreated = false;
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)},
{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)},
{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)},
{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)}
openglframework::VertexBufferObject Box::mVBONormals(GL_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//
};
GLuint Box::mCubeIndices[36] = { 0, 1, 2,
2, 3, 0,
7, 4, 5,
5, 6, 7,
6, 5, 2,
2, 1, 6,
7, 0, 3,
3, 4, 7,
7, 6, 1,
1, 0, 7,
3, 2, 5,
5, 4, 3};
// Constructor
Box::Box(const openglframework::Vector3& size, const openglframework::Vector3 &position,
reactphysics3d::CollisionWorld* world)
: openglframework::Object3D(), mColor(0.5f, 0.5f, 0.5f, 1.0f) {
: openglframework::Object3D() {
// Initialize the size of the box
mSize[0] = size.x * 0.5f;
@ -85,25 +139,30 @@ Box::Box(const openglframework::Vector3& size, const openglframework::Vector3 &p
rp3d::Quaternion initOrientation = rp3d::Quaternion::identity();
rp3d::Transform transform(initPosition, initOrientation);
mPreviousTransform = transform;
// Create a rigid body in the dynamics world
mRigidBody = world->createCollisionBody(transform);
mBody = world->createCollisionBody(transform);
// Add the collision shape to the body
mRigidBody->addCollisionShape(collisionShape, rp3d::Transform::identity());
mBody->addCollisionShape(collisionShape, rp3d::Transform::identity());
// If the Vertex Buffer object has not been created yet
if (!areVBOsCreated) {
if (totalNbBoxes == 0) {
// Create the Vertex Buffer
createVBO();
createVBOAndVAO();
}
totalNbBoxes++;
mTransformMatrix = mTransformMatrix * mScalingMatrix;
}
// Constructor
Box::Box(const openglframework::Vector3& size, const openglframework::Vector3 &position,
Box::Box(const openglframework::Vector3& size, const openglframework::Vector3& position,
float mass, reactphysics3d::DynamicsWorld* world)
: openglframework::Object3D(), mColor(0.5f, 0.5f, 0.5f, 1.0f) {
: openglframework::Object3D() {
// Initialize the size of the box
mSize[0] = size.x * 0.5f;
@ -129,111 +188,145 @@ Box::Box(const openglframework::Vector3& size, const openglframework::Vector3 &p
rp3d::Quaternion initOrientation = rp3d::Quaternion::identity();
rp3d::Transform transform(initPosition, initOrientation);
mPreviousTransform = transform;
// Create a rigid body in the dynamics world
rp3d::RigidBody* body = world->createRigidBody(transform);
// Add the collision shape to the body
body->addCollisionShape(collisionShape, rp3d::Transform::identity(), mass);
mRigidBody = body;
mBody = body;
// If the Vertex Buffer object has not been created yet
if (!areVBOsCreated) {
if (totalNbBoxes == 0) {
// Create the Vertex Buffer
createVBO();
createVBOAndVAO();
}
totalNbBoxes++;
mTransformMatrix = mTransformMatrix * mScalingMatrix;
}
// Destructor
Box::~Box() {
if (totalNbBoxes == 1) {
// Destroy the VBOs and VAO
mVBOVertices.destroy();
mVBONormals.destroy();
mVAO.destroy();
}
totalNbBoxes--;
}
// Render the cube at the correct position and with the correct orientation
void Box::render(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 openglframework::Matrix4 localToCameraMatrix = worldToCameraMatrix * mTransformMatrix;
shader.setMatrix4x4Uniform("localToCameraMatrix", localToCameraMatrix);
shader.setMatrix4x4Uniform("localToWorldMatrix", mTransformMatrix);
shader.setMatrix4x4Uniform("worldToCameraMatrix", worldToCameraMatrix);
// Set the normal matrix (inverse transpose of the 3x3 upper-left sub matrix of the
// model-view matrix)
const openglframework::Matrix4 localToCameraMatrix = worldToCameraMatrix * mTransformMatrix;
const openglframework::Matrix3 normalMatrix =
localToCameraMatrix.getUpperLeft3x3Matrix().getInverse().getTranspose();
shader.setMatrix3x3Uniform("normalMatrix", normalMatrix);
shader.setMatrix3x3Uniform("normalMatrix", normalMatrix, false);
// Set the vertex color
openglframework::Vector4 color(mColor.r, mColor.g, mColor.b, mColor.a);
shader.setVector4Uniform("vertexColor", color);
openglframework::Color currentColor = mBody->isSleeping() ? mSleepingColor : mColor;
openglframework::Vector4 color(currentColor.r, currentColor.g, currentColor.b, currentColor.a);
shader.setVector4Uniform("vertexColor", color, false);
// Bind the vertices VBO
mVBOVertices.bind();
// Get the location of shader attribute variables
GLint vertexPositionLoc = shader.getAttribLocation("vertexPosition");
GLint vertexNormalLoc = shader.getAttribLocation("vertexNormal", false);
// Enable the vertex, normal and color arrays
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableVertexAttribArray(vertexPositionLoc);
glVertexAttribPointer(vertexPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, NULL);
// Set the arrays pointers
glVertexPointer(3, GL_FLOAT, sizeof(VertexData), MEMBER_OFFSET(VertexData, position));
glNormalPointer(GL_FLOAT, sizeof(VertexData), MEMBER_OFFSET(VertexData, normal));
glColorPointer(3, GL_FLOAT, sizeof(VertexData), MEMBER_OFFSET(VertexData, color));
mVBONormals.bind();
// Bind the indices VBO
mVBOIndices.bind();
if (vertexNormalLoc != -1) glEnableVertexAttribArray(vertexNormalLoc);
if (vertexNormalLoc != -1) glVertexAttribPointer(vertexNormalLoc, 3, GL_FLOAT, GL_FALSE, 0, NULL);
// Draw the geometry of the box
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, (char*)NULL);
glDrawArrays(GL_TRIANGLES, 0, 36);
// Unbind the VBOs
glDisableVertexAttribArray(vertexPositionLoc);
if (vertexNormalLoc != -1) glDisableVertexAttribArray(vertexNormalLoc);
mVBONormals.unbind();
mVBOVertices.unbind();
mVBOIndices.unbind();
// Disable the arrays
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
// Unbind the VAO
mVAO.unbind();
// Unbind the shader
shader.unbind();
}
// Update the transform matrix of the box
void Box::updateTransform() {
// Get the interpolated transform of the rigid body
rp3d::Transform transform = mRigidBody->getInterpolatedTransform();
// Compute the transform used for rendering the box
rp3d::decimal matrix[16];
transform.getOpenGLMatrix(matrix);
openglframework::Matrix4 newMatrix(matrix[0], matrix[4], matrix[8], matrix[12],
matrix[1], matrix[5], matrix[9], matrix[13],
matrix[2], matrix[6], matrix[10], matrix[14],
matrix[3], matrix[7], matrix[11], matrix[15]);
// Apply the scaling matrix to have the correct box dimensions
mTransformMatrix = newMatrix * mScalingMatrix;
}
// Create the Vertex Buffer Objects used to render to box with OpenGL.
/// We create two VBOs (one for vertices and one for indices) to render all the boxes
/// in the simulation.
void Box::createVBO() {
void Box::createVBOAndVAO() {
// Create the VBOs
// Create the VBO for the vertices data
mVBOVertices.create();
mVBOIndices.create();
// Copy the data into the VBOs
mVBOVertices.bind();
mVBOVertices.copyDataIntoVBO(sizeof(mCubeVertices), mCubeVertices, GL_STATIC_DRAW);
mVBOIndices.copyDataIntoVBO(sizeof(mCubeIndices), mCubeIndices, GL_STATIC_DRAW);
mVBOVertices.unbind();
areVBOsCreated = true;
// Create th VBO for the normals data
mVBONormals.create();
mVBONormals.bind();
mVBONormals.copyDataIntoVBO(sizeof(mCubeNormals), mCubeNormals, GL_STATIC_DRAW);
mVBONormals.unbind();
// Create the VAO for both VBOs
mVAO.create();
mVAO.bind();
// Bind the VBO of vertices
mVBOVertices.bind();
// Bind the VBO of indices
mVBONormals.bind();
// Unbind the VAO
mVAO.unbind();
}
// Reset the transform
void Box::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<rp3d::RigidBody*>(mBody);
if (rigidBody != NULL) {
rigidBody->setLinearVelocity(rp3d::Vector3(0, 0, 0));
rigidBody->setAngularVelocity(rp3d::Vector3(0, 0, 0));
}
updateTransform(1.0f);
}

View File

@ -29,22 +29,10 @@
// Libraries
#include "openglframework.h"
#include "reactphysics3d.h"
// Structure VertexData
struct VertexData {
/// Vertex position
openglframework::Vector3 position;
/// Vertex normal
openglframework::Vector3 normal;
// Vertex color
openglframework::Color color;
};
#include "PhysicsObject.h"
// Class Box
class Box : public openglframework::Object3D {
class Box : public openglframework::Object3D, public PhysicsObject {
private :
@ -53,34 +41,31 @@ class Box : public openglframework::Object3D {
/// Size of each side of the box
float mSize[3];
/// Rigid body used to simulate the dynamics of the box
rp3d::CollisionBody* mRigidBody;
/// Scaling matrix (applied to a cube to obtain the correct box dimensions)
openglframework::Matrix4 mScalingMatrix;
/// Vertex Buffer Object for the vertices data used to render the box with OpenGL
static openglframework::VertexBufferObject mVBOVertices;
/// Vertex Buffer Object for the indices used to render the box with OpenGL
static openglframework::VertexBufferObject mVBOIndices;
/// Vertex Buffer Object for the normales used to render the box with OpenGL
static openglframework::VertexBufferObject mVBONormals;
/// Vertex data for each vertex of the cube (used to render the box)
static VertexData mCubeVertices[8];
/// Vertex Array Object for the vertex data
static openglframework::VertexArrayObject mVAO;
/// Indices of the cube (used to render the box)
static GLuint mCubeIndices[36];
/// Vertices coordinates of the triangles of the box
static GLfloat mCubeVertices[108];
/// True if the VBOs have already been created
static bool areVBOsCreated;
/// Vertices normals of the triangles of the box
static GLfloat mCubeNormals[108];
/// Main color of the box
openglframework::Color mColor;
/// Total number of boxes created
static int totalNbBoxes;
// -------------------- Methods -------------------- //
/// Create a Vertex Buffer Object to render to box with OpenGL
static void createVBO();
/// Create a the VAO and VBOs to render to box with OpenGL
static void createVBOAndVAO();
public :
@ -97,35 +82,20 @@ class Box : public openglframework::Object3D {
/// Destructor
~Box();
/// Return a pointer to the collision body of the box
reactphysics3d::CollisionBody* getCollisionBody();
/// Return a pointer to the rigid body of the box
reactphysics3d::RigidBody* getRigidBody();
/// Update the transform matrix of the box
void updateTransform();
/// Render the cube at the correct position and with the correct orientation
void render(openglframework::Shader& shader, const openglframework::Matrix4& worldToCameraMatrix);
/// Set the color of the box
void setColor(const openglframework::Color& color);
/// Set the position of the box
void resetTransform(const rp3d::Transform& transform);
/// Update the transform matrix of the object
virtual void updateTransform(float interpolationFactor);
};
// Return a pointer to the collision body of the box
inline rp3d::CollisionBody* Box::getCollisionBody() {
return mRigidBody;
// Update the transform matrix of the object
inline void Box::updateTransform(float interpolationFactor) {
mTransformMatrix = computeTransform(interpolationFactor, mScalingMatrix);
}
// Return a pointer to the rigid body of the box
inline rp3d::RigidBody* Box::getRigidBody() {
return dynamic_cast<rp3d::RigidBody*>(mRigidBody);
}
// Set the color of the box
inline void Box::setColor(const openglframework::Color& color) {
mColor = color;
}
#endif

View File

@ -26,6 +26,13 @@
// 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,
@ -57,13 +64,22 @@ Capsule::Capsule(float radius, float height, const openglframework::Vector3& pos
rp3d::Quaternion initOrientation = rp3d::Quaternion::identity();
rp3d::Transform transform(initPosition, initOrientation);
mPreviousTransform = transform;
// Create a rigid body corresponding in the dynamics world
mRigidBody = world->createCollisionBody(transform);
mBody = world->createCollisionBody(transform);
// Add a collision shape to the body and specify the mass of the shape
mRigidBody->addCollisionShape(collisionShape, rp3d::Transform::identity());
mBody->addCollisionShape(collisionShape, rp3d::Transform::identity());
mTransformMatrix = mTransformMatrix * mScalingMatrix;
// Create the VBOs and VAO
if (totalNbCapsules == 0) {
createVBOAndVAO();
}
totalNbCapsules++;
}
// Constructor
@ -103,16 +119,35 @@ Capsule::Capsule(float radius, float height, const openglframework::Vector3& pos
// Add a collision shape to the body and specify the mass of the shape
body->addCollisionShape(collisionShape, rp3d::Transform::identity(), mass);
mRigidBody = body;
mBody = body;
mTransformMatrix = mTransformMatrix * mScalingMatrix;
// Create the VBOs and VAO
if (totalNbCapsules == 0) {
createVBOAndVAO();
}
totalNbCapsules++;
}
// Destructor
Capsule::~Capsule() {
if (totalNbCapsules == 1) {
// 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
@ -123,57 +158,126 @@ void Capsule::render(openglframework::Shader& shader,
shader.bind();
// Set the model to camera matrix
const openglframework::Matrix4 localToCameraMatrix = worldToCameraMatrix * mTransformMatrix;
shader.setMatrix4x4Uniform("localToCameraMatrix", localToCameraMatrix);
shader.setMatrix4x4Uniform("localToWorldMatrix", mTransformMatrix);
shader.setMatrix4x4Uniform("worldToCameraMatrix", worldToCameraMatrix);
// Set the normal matrix (inverse transpose of the 3x3 upper-left sub matrix of the
// model-view matrix)
const openglframework::Matrix4 localToCameraMatrix = worldToCameraMatrix * mTransformMatrix;
const openglframework::Matrix3 normalMatrix =
localToCameraMatrix.getUpperLeft3x3Matrix().getInverse().getTranspose();
shader.setMatrix3x3Uniform("normalMatrix", normalMatrix);
shader.setMatrix3x3Uniform("normalMatrix", normalMatrix, false);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
if (hasTexture()) {
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
}
// Set the vertex color
openglframework::Color currentColor = mBody->isSleeping() ? mSleepingColor : mColor;
openglframework::Vector4 color(currentColor.r, currentColor.g, currentColor.b, currentColor.a);
shader.setVector4Uniform("vertexColor", color, false);
glVertexPointer(3, GL_FLOAT, 0, getVerticesPointer());
glNormalPointer(GL_FLOAT, 0, getNormalsPointer());
if(hasTexture()) {
glTexCoordPointer(2, GL_FLOAT, 0, getUVTextureCoordinatesPointer());
}
// 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, (char*)NULL);
mVBONormals.bind();
if (vertexNormalLoc != -1) glVertexAttribPointer(vertexNormalLoc, 3, GL_FLOAT, GL_FALSE, 0, (char*)NULL);
if (vertexNormalLoc != -1) glEnableVertexAttribArray(vertexNormalLoc);
// For each part of the mesh
for (unsigned int i=0; i<getNbParts(); i++) {
glDrawElements(GL_TRIANGLES, getNbFaces(i) * 3,
GL_UNSIGNED_INT, getIndicesPointer());
glDrawElements(GL_TRIANGLES, getNbFaces(i) * 3, GL_UNSIGNED_INT, (char*)NULL);
}
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
if (hasTexture()) {
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
glDisableVertexAttribArray(vertexPositionLoc);
if (vertexNormalLoc != -1) glDisableVertexAttribArray(vertexNormalLoc);
mVBONormals.unbind();
mVBOVertices.unbind();
// Unbind the VAO
mVAO.unbind();
// Unbind the shader
shader.unbind();
}
// Update the transform matrix of the sphere
void Capsule::updateTransform() {
// Create the Vertex Buffer Objects used to render with OpenGL.
/// We create two VBOs (one for vertices and one for indices)
void Capsule::createVBOAndVAO() {
// Get the interpolated transform of the rigid body
rp3d::Transform transform = mRigidBody->getInterpolatedTransform();
// Create the VBO for the vertices data
mVBOVertices.create();
mVBOVertices.bind();
size_t sizeVertices = mVertices.size() * sizeof(openglframework::Vector3);
mVBOVertices.copyDataIntoVBO(sizeVertices, getVerticesPointer(), GL_STATIC_DRAW);
mVBOVertices.unbind();
// Compute the transform used for rendering the sphere
rp3d::decimal matrix[16];
transform.getOpenGLMatrix(matrix);
openglframework::Matrix4 newMatrix(matrix[0], matrix[4], matrix[8], matrix[12],
matrix[1], matrix[5], matrix[9], matrix[13],
matrix[2], matrix[6], matrix[10], matrix[14],
matrix[3], matrix[7], matrix[11], matrix[15]);
// Create the VBO for the normals data
mVBONormals.create();
mVBONormals.bind();
size_t sizeNormals = mNormals.size() * sizeof(openglframework::Vector3);
mVBONormals.copyDataIntoVBO(sizeNormals, getNormalsPointer(), GL_STATIC_DRAW);
mVBONormals.unbind();
// Apply the scaling matrix to have the correct sphere dimensions
mTransformMatrix = newMatrix * mScalingMatrix;
if (hasTexture()) {
// Create the VBO for the texture co data
mVBOTextureCoords.create();
mVBOTextureCoords.bind();
size_t sizeTextureCoords = mUVs.size() * sizeof(openglframework::Vector2);
mVBOTextureCoords.copyDataIntoVBO(sizeTextureCoords, getUVTextureCoordinatesPointer(), GL_STATIC_DRAW);
mVBOTextureCoords.unbind();
}
// Create th VBO for the indices data
mVBOIndices.create();
mVBOIndices.bind();
size_t sizeIndices = mIndices[0].size() * sizeof(uint);
mVBOIndices.copyDataIntoVBO(sizeIndices, getIndicesPointer(), GL_STATIC_DRAW);
mVBOIndices.unbind();
// Create the VAO for both VBOs
mVAO.create();
mVAO.bind();
// Bind the VBO of vertices
mVBOVertices.bind();
// Bind the VBO of normals
mVBONormals.bind();
if (hasTexture()) {
// Bind the VBO of texture coords
mVBOTextureCoords.bind();
}
// Bind the VBO of indices
mVBOIndices.bind();
// Unbind the VAO
mVAO.unbind();
}
// Reset the transform
void Capsule::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<rp3d::RigidBody*>(mBody);
if (rigidBody != NULL) {
rigidBody->setLinearVelocity(rp3d::Vector3(0, 0, 0));
rigidBody->setAngularVelocity(rp3d::Vector3(0, 0, 0));
}
updateTransform(1.0f);
}

View File

@ -29,9 +29,10 @@
// Libraries
#include "openglframework.h"
#include "reactphysics3d.h"
#include "PhysicsObject.h"
// Class Sphere
class Capsule : public openglframework::Mesh {
class Capsule : public openglframework::Mesh, public PhysicsObject {
private :
@ -43,14 +44,35 @@ class Capsule : public openglframework::Mesh {
/// Height of the capsule
float mHeight;
/// Rigid body used to simulate the dynamics of the sphere
rp3d::CollisionBody* mRigidBody;
/// Scaling matrix (applied to a sphere to obtain the correct sphere dimensions)
openglframework::Matrix4 mScalingMatrix;
/// Previous transform (for interpolation)
rp3d::Transform mPreviousTransform;
/// Vertex Buffer Object for the vertices data
static openglframework::VertexBufferObject mVBOVertices;
/// Vertex Buffer Object for the normals data
static openglframework::VertexBufferObject mVBONormals;
/// Vertex Buffer Object for the texture coords
static openglframework::VertexBufferObject mVBOTextureCoords;
/// Vertex Buffer Object for the indices
static openglframework::VertexBufferObject mVBOIndices;
/// Vertex Array Object for the vertex data
static openglframework::VertexArrayObject mVAO;
// Total number of capsules created
static int totalNbCapsules;
// -------------------- Methods -------------------- //
// Create the Vertex Buffer Objects used to render with OpenGL.
void createVBOAndVAO();
public :
// -------------------- Methods -------------------- //
@ -67,28 +89,20 @@ class Capsule : public openglframework::Mesh {
/// Destructor
~Capsule();
/// Return a pointer to the collision body of the box
reactphysics3d::CollisionBody* getCollisionBody();
/// Return a pointer to the rigid body of the box
reactphysics3d::RigidBody* getRigidBody();
/// Update the transform matrix of the sphere
void updateTransform();
/// 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);
/// Update the transform matrix of the object
virtual void updateTransform(float interpolationFactor);
};
// Return a pointer to the collision body of the box
inline rp3d::CollisionBody* Capsule::getCollisionBody() {
return mRigidBody;
}
// Return a pointer to the rigid body of the box
inline rp3d::RigidBody* Capsule::getRigidBody() {
return dynamic_cast<rp3d::RigidBody*>(mRigidBody);
// Update the transform matrix of the object
inline void Capsule::updateTransform(float interpolationFactor) {
mTransformMatrix = computeTransform(interpolationFactor, mScalingMatrix);
}
#endif

View File

@ -26,6 +26,13 @@
// 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,
@ -57,13 +64,22 @@ Cone::Cone(float radius, float height, const openglframework::Vector3 &position,
rp3d::Quaternion initOrientation = rp3d::Quaternion::identity();
rp3d::Transform transform(initPosition, initOrientation);
mPreviousTransform = transform;
// Create a rigid body corresponding to the cone in the dynamics world
mRigidBody = world->createCollisionBody(transform);
mBody = world->createCollisionBody(transform);
// Add a collision shape to the body and specify the mass of the shape
mRigidBody->addCollisionShape(collisionShape, rp3d::Transform::identity());
mBody->addCollisionShape(collisionShape, rp3d::Transform::identity());
mTransformMatrix = mTransformMatrix * mScalingMatrix;
// Create the VBOs and VAO
if (totalNbCones == 0) {
createVBOAndVAO();
}
totalNbCones++;
}
// Constructor
@ -103,16 +119,34 @@ Cone::Cone(float radius, float height, const openglframework::Vector3 &position,
// Add a collision shape to the body and specify the mass of the shape
body->addCollisionShape(collisionShape, rp3d::Transform::identity(), mass);
mRigidBody = body;
mBody = body;
mTransformMatrix = mTransformMatrix * mScalingMatrix;
// Create the VBOs and VAO
if (totalNbCones == 0) {
createVBOAndVAO();
}
totalNbCones++;
}
// Destructor
Cone::~Cone() {
if (totalNbCones == 1) {
// Destroy the mesh
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
@ -123,57 +157,126 @@ void Cone::render(openglframework::Shader& shader,
shader.bind();
// Set the model to camera matrix
const openglframework::Matrix4 localToCameraMatrix = worldToCameraMatrix * mTransformMatrix;
shader.setMatrix4x4Uniform("localToCameraMatrix", localToCameraMatrix);
shader.setMatrix4x4Uniform("localToWorldMatrix", mTransformMatrix);
shader.setMatrix4x4Uniform("worldToCameraMatrix", worldToCameraMatrix);
// Set the normal matrix (inverse transpose of the 3x3 upper-left sub matrix of the
// model-view matrix)
const openglframework::Matrix4 localToCameraMatrix = worldToCameraMatrix * mTransformMatrix;
const openglframework::Matrix3 normalMatrix =
localToCameraMatrix.getUpperLeft3x3Matrix().getInverse().getTranspose();
shader.setMatrix3x3Uniform("normalMatrix", normalMatrix);
shader.setMatrix3x3Uniform("normalMatrix", normalMatrix, false);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
if (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, false);
glVertexPointer(3, GL_FLOAT, 0, getVerticesPointer());
glNormalPointer(GL_FLOAT, 0, getNormalsPointer());
if(hasTexture()) {
glTexCoordPointer(2, GL_FLOAT, 0, getUVTextureCoordinatesPointer());
}
// 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, (char*)NULL);
mVBONormals.bind();
if (vertexNormalLoc != -1) glVertexAttribPointer(vertexNormalLoc, 3, GL_FLOAT, GL_FALSE, 0, (char*)NULL);
if (vertexNormalLoc != -1) glEnableVertexAttribArray(vertexNormalLoc);
// For each part of the mesh
for (unsigned int i=0; i<getNbParts(); i++) {
glDrawElements(GL_TRIANGLES, getNbFaces(i) * 3,
GL_UNSIGNED_INT, getIndicesPointer());
glDrawElements(GL_TRIANGLES, getNbFaces(i) * 3, GL_UNSIGNED_INT, (char*)NULL);
}
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
if (hasTexture()) {
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
glDisableVertexAttribArray(vertexPositionLoc);
if (vertexNormalLoc != -1) glDisableVertexAttribArray(vertexNormalLoc);
mVBONormals.unbind();
mVBOVertices.unbind();
// Unbind the VAO
mVAO.unbind();
// Unbind the shader
shader.unbind();
}
// Update the transform matrix of the cone
void Cone::updateTransform() {
// Create the Vertex Buffer Objects used to render with OpenGL.
/// We create two VBOs (one for vertices and one for indices)
void Cone::createVBOAndVAO() {
// Get the interpolated transform of the rigid body
rp3d::Transform transform = mRigidBody->getInterpolatedTransform();
// Create the VBO for the vertices data
mVBOVertices.create();
mVBOVertices.bind();
size_t sizeVertices = mVertices.size() * sizeof(openglframework::Vector3);
mVBOVertices.copyDataIntoVBO(sizeVertices, getVerticesPointer(), GL_STATIC_DRAW);
mVBOVertices.unbind();
// Compute the transform used for rendering the cone
rp3d::decimal matrix[16];
transform.getOpenGLMatrix(matrix);
openglframework::Matrix4 newMatrix(matrix[0], matrix[4], matrix[8], matrix[12],
matrix[1], matrix[5], matrix[9], matrix[13],
matrix[2], matrix[6], matrix[10], matrix[14],
matrix[3], matrix[7], matrix[11], matrix[15]);
// Create the VBO for the normals data
mVBONormals.create();
mVBONormals.bind();
size_t sizeNormals = mNormals.size() * sizeof(openglframework::Vector3);
mVBONormals.copyDataIntoVBO(sizeNormals, getNormalsPointer(), GL_STATIC_DRAW);
mVBONormals.unbind();
// Apply the scaling matrix to have the correct cone dimensions
mTransformMatrix = newMatrix * mScalingMatrix;
if (hasTexture()) {
// Create the VBO for the texture co data
mVBOTextureCoords.create();
mVBOTextureCoords.bind();
size_t sizeTextureCoords = mUVs.size() * sizeof(openglframework::Vector2);
mVBOTextureCoords.copyDataIntoVBO(sizeTextureCoords, getUVTextureCoordinatesPointer(), GL_STATIC_DRAW);
mVBOTextureCoords.unbind();
}
// Create th VBO for the indices data
mVBOIndices.create();
mVBOIndices.bind();
size_t sizeIndices = mIndices[0].size() * sizeof(uint);
mVBOIndices.copyDataIntoVBO(sizeIndices, getIndicesPointer(), GL_STATIC_DRAW);
mVBOIndices.unbind();
// Create the VAO for both VBOs
mVAO.create();
mVAO.bind();
// Bind the VBO of vertices
mVBOVertices.bind();
// Bind the VBO of normals
mVBONormals.bind();
if (hasTexture()) {
// Bind the VBO of texture coords
mVBOTextureCoords.bind();
}
// Bind the VBO of indices
mVBOIndices.bind();
// Unbind the VAO
mVAO.unbind();
}
// Reset the transform
void Cone::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<rp3d::RigidBody*>(mBody);
if (rigidBody != NULL) {
rigidBody->setLinearVelocity(rp3d::Vector3(0, 0, 0));
rigidBody->setAngularVelocity(rp3d::Vector3(0, 0, 0));
}
updateTransform(1.0f);
}

View File

@ -29,9 +29,10 @@
// Libraries
#include "openglframework.h"
#include "reactphysics3d.h"
#include "PhysicsObject.h"
// Class Cone
class Cone : public openglframework::Mesh {
class Cone : public openglframework::Mesh, public PhysicsObject {
private :
@ -43,14 +44,35 @@ class Cone : public openglframework::Mesh {
/// Height of the cone
float mHeight;
/// Rigid body used to simulate the dynamics of the cone
rp3d::CollisionBody* mRigidBody;
/// Scaling matrix (applied to a sphere to obtain the correct cone dimensions)
openglframework::Matrix4 mScalingMatrix;
/// Previous transform (for interpolation)
rp3d::Transform mPreviousTransform;
/// Vertex Buffer Object for the vertices data
static openglframework::VertexBufferObject mVBOVertices;
/// Vertex Buffer Object for the normals data
static openglframework::VertexBufferObject mVBONormals;
/// Vertex Buffer Object for the texture coords
static openglframework::VertexBufferObject mVBOTextureCoords;
/// Vertex Buffer Object for the indices
static openglframework::VertexBufferObject mVBOIndices;
/// Vertex Array Object for the vertex data
static openglframework::VertexArrayObject mVAO;
// Total number of cones created
static int totalNbCones;
// -------------------- Methods -------------------- //
// Create the Vertex Buffer Objects used to render with OpenGL.
void createVBOAndVAO();
public :
// -------------------- Methods -------------------- //
@ -66,28 +88,20 @@ class Cone : public openglframework::Mesh {
/// Destructor
~Cone();
/// Return a pointer to the collision body of the box
reactphysics3d::CollisionBody* getCollisionBody();
/// Return a pointer to the rigid body of the box
reactphysics3d::RigidBody* getRigidBody();
/// Update the transform matrix of the cone
void updateTransform();
/// 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);
/// Update the transform matrix of the object
virtual void updateTransform(float interpolationFactor);
};
// Return a pointer to the collision body of the box
inline rp3d::CollisionBody* Cone::getCollisionBody() {
return mRigidBody;
}
// Return a pointer to the rigid body of the box
inline rp3d::RigidBody* Cone::getRigidBody() {
return dynamic_cast<rp3d::RigidBody*>(mRigidBody);
// Update the transform matrix of the object
inline void Cone::updateTransform(float interpolationFactor) {
mTransformMatrix = computeTransform(interpolationFactor, mScalingMatrix);
}
#endif

View File

@ -30,7 +30,9 @@
ConvexMesh::ConvexMesh(const openglframework::Vector3 &position,
reactphysics3d::CollisionWorld* world,
const std::string& meshFolderPath)
: openglframework::Mesh() {
: openglframework::Mesh(), mVBOVertices(GL_ARRAY_BUFFER),
mVBONormals(GL_ARRAY_BUFFER), mVBOTextureCoords(GL_ARRAY_BUFFER),
mVBOIndices(GL_ELEMENT_ARRAY_BUFFER) {
// Load the mesh from a file
openglframework::MeshReaderWriter::loadMeshFromFile(meshFolderPath + "convexmesh.obj", *this);
@ -79,18 +81,25 @@ ConvexMesh::ConvexMesh(const openglframework::Vector3 &position,
rp3d::Quaternion initOrientation = rp3d::Quaternion::identity();
rp3d::Transform transform(initPosition, initOrientation);
mPreviousTransform = transform;
// Create a rigid body corresponding to the sphere in the dynamics world
mRigidBody = world->createCollisionBody(transform);
mBody = world->createCollisionBody(transform);
// Add a collision shape to the body and specify the mass of the collision shape
mRigidBody->addCollisionShape(collisionShape, rp3d::Transform::identity());
mBody->addCollisionShape(collisionShape, rp3d::Transform::identity());
// Create the VBOs and VAO
createVBOAndVAO();
}
// Constructor
ConvexMesh::ConvexMesh(const openglframework::Vector3 &position, float mass,
reactphysics3d::DynamicsWorld* dynamicsWorld,
const std::string& meshFolderPath)
: openglframework::Mesh() {
: openglframework::Mesh(), mVBOVertices(GL_ARRAY_BUFFER),
mVBONormals(GL_ARRAY_BUFFER), mVBOTextureCoords(GL_ARRAY_BUFFER),
mVBOIndices(GL_ELEMENT_ARRAY_BUFFER) {
// Load the mesh from a file
openglframework::MeshReaderWriter::loadMeshFromFile(meshFolderPath + "convexmesh.obj", *this);
@ -144,7 +153,10 @@ ConvexMesh::ConvexMesh(const openglframework::Vector3 &position, float mass,
// Add a collision shape to the body and specify the mass of the collision shape
body->addCollisionShape(collisionShape, rp3d::Transform::identity(), mass);
mRigidBody = body;
mBody = body;
// Create the VBOs and VAO
createVBOAndVAO();
}
// Destructor
@ -152,6 +164,13 @@ ConvexMesh::~ConvexMesh() {
// Destroy the mesh
destroy();
// Destroy the VBOs and VAO
mVBOIndices.destroy();
mVBOVertices.destroy();
mVBONormals.destroy();
mVBOTextureCoords.destroy();
mVAO.destroy();
}
// Render the sphere at the correct position and with the correct orientation
@ -162,57 +181,125 @@ void ConvexMesh::render(openglframework::Shader& shader,
shader.bind();
// Set the model to camera matrix
const openglframework::Matrix4 localToCameraMatrix = worldToCameraMatrix * mTransformMatrix;
shader.setMatrix4x4Uniform("localToCameraMatrix", localToCameraMatrix);
shader.setMatrix4x4Uniform("localToWorldMatrix", mTransformMatrix);
shader.setMatrix4x4Uniform("worldToCameraMatrix", worldToCameraMatrix);
// Set the normal matrix (inverse transpose of the 3x3 upper-left sub matrix of the
// model-view matrix)
const openglframework::Matrix4 localToCameraMatrix = worldToCameraMatrix * mTransformMatrix;
const openglframework::Matrix3 normalMatrix =
localToCameraMatrix.getUpperLeft3x3Matrix().getInverse().getTranspose();
shader.setMatrix3x3Uniform("normalMatrix", normalMatrix);
shader.setMatrix3x3Uniform("normalMatrix", normalMatrix, false);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
if (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, false);
glVertexPointer(3, GL_FLOAT, 0, getVerticesPointer());
glNormalPointer(GL_FLOAT, 0, getNormalsPointer());
if(hasTexture()) {
glTexCoordPointer(2, GL_FLOAT, 0, getUVTextureCoordinatesPointer());
}
// 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, (char*)NULL);
mVBONormals.bind();
if (vertexNormalLoc != -1) glVertexAttribPointer(vertexNormalLoc, 3, GL_FLOAT, GL_FALSE, 0, (char*)NULL);
if (vertexNormalLoc != -1) glEnableVertexAttribArray(vertexNormalLoc);
// For each part of the mesh
for (unsigned int i=0; i<getNbParts(); i++) {
glDrawElements(GL_TRIANGLES, getNbFaces(i) * 3,
GL_UNSIGNED_INT, getIndicesPointer());
glDrawElements(GL_TRIANGLES, getNbFaces(i) * 3, GL_UNSIGNED_INT, (char*)NULL);
}
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
if (hasTexture()) {
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
glDisableVertexAttribArray(vertexPositionLoc);
if (vertexNormalLoc != -1) glDisableVertexAttribArray(vertexNormalLoc);
mVBONormals.unbind();
mVBOVertices.unbind();
// Unbind the VAO
mVAO.unbind();
// Unbind the shader
shader.unbind();
}
// Update the transform matrix of the sphere
void ConvexMesh::updateTransform() {
// Create the Vertex Buffer Objects used to render with OpenGL.
/// We create two VBOs (one for vertices and one for indices)
void ConvexMesh::createVBOAndVAO() {
// Get the interpolated transform of the rigid body
rp3d::Transform transform = mRigidBody->getInterpolatedTransform();
// Create the VBO for the vertices data
mVBOVertices.create();
mVBOVertices.bind();
size_t sizeVertices = mVertices.size() * sizeof(openglframework::Vector3);
mVBOVertices.copyDataIntoVBO(sizeVertices, getVerticesPointer(), GL_STATIC_DRAW);
mVBOVertices.unbind();
// Compute the transform used for rendering the sphere
rp3d::decimal matrix[16];
transform.getOpenGLMatrix(matrix);
openglframework::Matrix4 newMatrix(matrix[0], matrix[4], matrix[8], matrix[12],
matrix[1], matrix[5], matrix[9], matrix[13],
matrix[2], matrix[6], matrix[10], matrix[14],
matrix[3], matrix[7], matrix[11], matrix[15]);
// Create the VBO for the normals data
mVBONormals.create();
mVBONormals.bind();
size_t sizeNormals = mNormals.size() * sizeof(openglframework::Vector3);
mVBONormals.copyDataIntoVBO(sizeNormals, getNormalsPointer(), GL_STATIC_DRAW);
mVBONormals.unbind();
// Apply the scaling matrix to have the correct sphere dimensions
mTransformMatrix = newMatrix;
if (hasTexture()) {
// Create the VBO for the texture co data
mVBOTextureCoords.create();
mVBOTextureCoords.bind();
size_t sizeTextureCoords = mUVs.size() * sizeof(openglframework::Vector2);
mVBOTextureCoords.copyDataIntoVBO(sizeTextureCoords, getUVTextureCoordinatesPointer(), GL_STATIC_DRAW);
mVBOTextureCoords.unbind();
}
// Create th VBO for the indices data
mVBOIndices.create();
mVBOIndices.bind();
size_t sizeIndices = mIndices[0].size() * sizeof(uint);
mVBOIndices.copyDataIntoVBO(sizeIndices, getIndicesPointer(), GL_STATIC_DRAW);
mVBOIndices.unbind();
// Create the VAO for both VBOs
mVAO.create();
mVAO.bind();
// Bind the VBO of vertices
mVBOVertices.bind();
// Bind the VBO of normals
mVBONormals.bind();
if (hasTexture()) {
// Bind the VBO of texture coords
mVBOTextureCoords.bind();
}
// Bind the VBO of indices
mVBOIndices.bind();
// Unbind the VAO
mVAO.unbind();
}
// Reset the transform
void ConvexMesh::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<rp3d::RigidBody*>(mBody);
if (rigidBody != NULL) {
rigidBody->setLinearVelocity(rp3d::Vector3(0, 0, 0));
rigidBody->setAngularVelocity(rp3d::Vector3(0, 0, 0));
}
updateTransform(1.0f);
}

View File

@ -29,19 +29,38 @@
// Libraries
#include "openglframework.h"
#include "reactphysics3d.h"
#include "PhysicsObject.h"
// Class ConvexMesh
class ConvexMesh : public openglframework::Mesh {
class ConvexMesh : public openglframework::Mesh, public PhysicsObject {
private :
// -------------------- Attributes -------------------- //
/// Rigid body used to simulate the dynamics of the mesh
rp3d::CollisionBody* mRigidBody;
/// Previous transform (for interpolation)
rp3d::Transform mPreviousTransform;
/// Vertex Buffer Object for the vertices data
openglframework::VertexBufferObject mVBOVertices;
/// Vertex Buffer Object for the normals data
openglframework::VertexBufferObject mVBONormals;
/// Vertex Buffer Object for the texture coords
openglframework::VertexBufferObject mVBOTextureCoords;
/// Vertex Buffer Object for the indices
openglframework::VertexBufferObject mVBOIndices;
/// Vertex Array Object for the vertex data
openglframework::VertexArrayObject mVAO;
// -------------------- Methods -------------------- //
// Create the Vertex Buffer Objects used to render with OpenGL.
void createVBOAndVAO();
public :
// -------------------- Methods -------------------- //
@ -57,28 +76,20 @@ class ConvexMesh : public openglframework::Mesh {
/// Destructor
~ConvexMesh();
/// Return a pointer to the collision body of the box
reactphysics3d::CollisionBody* getCollisionBody();
/// Return a pointer to the rigid body of the box
reactphysics3d::RigidBody* getRigidBody();
/// Update the transform matrix of the mesh
void updateTransform();
/// 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);
/// Update the transform matrix of the object
virtual void updateTransform(float interpolationFactor);
};
// Return a pointer to the collision body of the box
inline rp3d::CollisionBody* ConvexMesh::getCollisionBody() {
return mRigidBody;
}
// Return a pointer to the rigid body of the box
inline rp3d::RigidBody* ConvexMesh::getRigidBody() {
return dynamic_cast<rp3d::RigidBody*>(mRigidBody);
// Update the transform matrix of the object
inline void ConvexMesh::updateTransform(float interpolationFactor) {
mTransformMatrix = computeTransform(interpolationFactor, openglframework::Matrix4::identity());
}
#endif

View File

@ -26,6 +26,13 @@
// 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,
@ -57,13 +64,22 @@ Cylinder::Cylinder(float radius, float height, const openglframework::Vector3& p
rp3d::Quaternion initOrientation = rp3d::Quaternion::identity();
rp3d::Transform transform(initPosition, initOrientation);
mPreviousTransform = transform;
// Create a rigid body corresponding to the cylinder in the dynamics world
mRigidBody = world->createCollisionBody(transform);
mBody = world->createCollisionBody(transform);
// Add a collision shape to the body and specify the mass of the shape
mRigidBody->addCollisionShape(collisionShape, rp3d::Transform::identity());
mBody->addCollisionShape(collisionShape, rp3d::Transform::identity());
mTransformMatrix = mTransformMatrix * mScalingMatrix;
// Create the VBOs and VAO
if (totalNbCylinders == 0) {
createVBOAndVAO();
}
totalNbCylinders++;
}
// Constructor
@ -105,14 +121,33 @@ Cylinder::Cylinder(float radius, float height, const openglframework::Vector3& p
mTransformMatrix = mTransformMatrix * mScalingMatrix;
mRigidBody = body;
mBody = body;
// Create the VBOs and VAO
if (totalNbCylinders == 0) {
createVBOAndVAO();
}
totalNbCylinders++;
}
// Destructor
Cylinder::~Cylinder() {
if (totalNbCylinders == 1) {
// 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
@ -123,57 +158,125 @@ void Cylinder::render(openglframework::Shader& shader,
shader.bind();
// Set the model to camera matrix
const openglframework::Matrix4 localToCameraMatrix = worldToCameraMatrix * mTransformMatrix;
shader.setMatrix4x4Uniform("localToCameraMatrix", localToCameraMatrix);
shader.setMatrix4x4Uniform("localToWorldMatrix", mTransformMatrix);
shader.setMatrix4x4Uniform("worldToCameraMatrix", worldToCameraMatrix);
// Set the normal matrix (inverse transpose of the 3x3 upper-left sub matrix of the
// model-view matrix)
const openglframework::Matrix4 localToCameraMatrix = worldToCameraMatrix * mTransformMatrix;
const openglframework::Matrix3 normalMatrix =
localToCameraMatrix.getUpperLeft3x3Matrix().getInverse().getTranspose();
shader.setMatrix3x3Uniform("normalMatrix", normalMatrix);
shader.setMatrix3x3Uniform("normalMatrix", normalMatrix, false);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
if (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, false);
glVertexPointer(3, GL_FLOAT, 0, getVerticesPointer());
glNormalPointer(GL_FLOAT, 0, getNormalsPointer());
if(hasTexture()) {
glTexCoordPointer(2, GL_FLOAT, 0, getUVTextureCoordinatesPointer());
}
// 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, (char*)NULL);
mVBONormals.bind();
if (vertexNormalLoc != -1) glVertexAttribPointer(vertexNormalLoc, 3, GL_FLOAT, GL_FALSE, 0, (char*)NULL);
if (vertexNormalLoc != -1) glEnableVertexAttribArray(vertexNormalLoc);
// For each part of the mesh
for (unsigned int i=0; i<getNbParts(); i++) {
glDrawElements(GL_TRIANGLES, getNbFaces(i) * 3,
GL_UNSIGNED_INT, getIndicesPointer());
glDrawElements(GL_TRIANGLES, getNbFaces(i) * 3, GL_UNSIGNED_INT, (char*)NULL);
}
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
if (hasTexture()) {
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
glDisableVertexAttribArray(vertexPositionLoc);
if (vertexNormalLoc != -1) glDisableVertexAttribArray(vertexNormalLoc);
mVBONormals.unbind();
mVBOVertices.unbind();
// Unbind the VAO
mVAO.unbind();
// Unbind the shader
shader.unbind();
}
// Update the transform matrix of the cylinder
void Cylinder::updateTransform() {
// Create the Vertex Buffer Objects used to render with OpenGL.
/// We create two VBOs (one for vertices and one for indices)
void Cylinder::createVBOAndVAO() {
// Get the interpolated transform of the rigid body
rp3d::Transform transform = mRigidBody->getInterpolatedTransform();
// Create the VBO for the vertices data
mVBOVertices.create();
mVBOVertices.bind();
size_t sizeVertices = mVertices.size() * sizeof(openglframework::Vector3);
mVBOVertices.copyDataIntoVBO(sizeVertices, getVerticesPointer(), GL_STATIC_DRAW);
mVBOVertices.unbind();
// Compute the transform used for rendering the cylinder
rp3d::decimal matrix[16];
transform.getOpenGLMatrix(matrix);
openglframework::Matrix4 newMatrix(matrix[0], matrix[4], matrix[8], matrix[12],
matrix[1], matrix[5], matrix[9], matrix[13],
matrix[2], matrix[6], matrix[10], matrix[14],
matrix[3], matrix[7], matrix[11], matrix[15]);
// Create the VBO for the normals data
mVBONormals.create();
mVBONormals.bind();
size_t sizeNormals = mNormals.size() * sizeof(openglframework::Vector3);
mVBONormals.copyDataIntoVBO(sizeNormals, getNormalsPointer(), GL_STATIC_DRAW);
mVBONormals.unbind();
// Apply the scaling matrix to have the correct cylinder dimensions
mTransformMatrix = newMatrix * mScalingMatrix;
if (hasTexture()) {
// Create the VBO for the texture co data
mVBOTextureCoords.create();
mVBOTextureCoords.bind();
size_t sizeTextureCoords = mUVs.size() * sizeof(openglframework::Vector2);
mVBOTextureCoords.copyDataIntoVBO(sizeTextureCoords, getUVTextureCoordinatesPointer(), GL_STATIC_DRAW);
mVBOTextureCoords.unbind();
}
// Create th VBO for the indices data
mVBOIndices.create();
mVBOIndices.bind();
size_t sizeIndices = mIndices[0].size() * sizeof(uint);
mVBOIndices.copyDataIntoVBO(sizeIndices, getIndicesPointer(), GL_STATIC_DRAW);
mVBOIndices.unbind();
// Create the VAO for both VBOs
mVAO.create();
mVAO.bind();
// Bind the VBO of vertices
mVBOVertices.bind();
// Bind the VBO of normals
mVBONormals.bind();
if (hasTexture()) {
// Bind the VBO of texture coords
mVBOTextureCoords.bind();
}
// Bind the VBO of indices
mVBOIndices.bind();
// Unbind the VAO
mVAO.unbind();
}
// Reset the transform
void Cylinder::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<rp3d::RigidBody*>(mBody);
if (rigidBody != NULL) {
rigidBody->setLinearVelocity(rp3d::Vector3(0, 0, 0));
rigidBody->setAngularVelocity(rp3d::Vector3(0, 0, 0));
}
updateTransform(1.0f);
}

View File

@ -29,9 +29,10 @@
// Libraries
#include "openglframework.h"
#include "reactphysics3d.h"
#include "PhysicsObject.h"
// Class Cylinder
class Cylinder : public openglframework::Mesh {
class Cylinder : public openglframework::Mesh, public PhysicsObject {
private :
@ -43,14 +44,35 @@ class Cylinder : public openglframework::Mesh {
/// Height of the cylinder
float mHeight;
/// Rigid body used to simulate the dynamics of the cylinder
rp3d::CollisionBody* mRigidBody;
/// Scaling matrix (applied to a sphere to obtain the correct cylinder dimensions)
openglframework::Matrix4 mScalingMatrix;
/// Previous transform (for interpolation)
rp3d::Transform mPreviousTransform;
/// Vertex Buffer Object for the vertices data
static openglframework::VertexBufferObject mVBOVertices;
/// Vertex Buffer Object for the normals data
static openglframework::VertexBufferObject mVBONormals;
/// Vertex Buffer Object for the texture coords
static openglframework::VertexBufferObject mVBOTextureCoords;
/// Vertex Buffer Object for the indices
static openglframework::VertexBufferObject mVBOIndices;
/// Vertex Array Object for the vertex data
static openglframework::VertexArrayObject mVAO;
// Total number of capsules created
static int totalNbCylinders;
// -------------------- Methods -------------------- //
// Create the Vertex Buffer Objects used to render with OpenGL.
void createVBOAndVAO();
public :
// -------------------- Methods -------------------- //
@ -66,28 +88,20 @@ class Cylinder : public openglframework::Mesh {
/// Destructor
~Cylinder();
/// Return a pointer to the collision body of the box
reactphysics3d::CollisionBody* getCollisionBody();
/// Return a pointer to the rigid body of the box
reactphysics3d::RigidBody* getRigidBody();
/// Update the transform matrix of the cylinder
void updateTransform();
/// 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);
/// Update the transform matrix of the object
virtual void updateTransform(float interpolationFactor);
};
// Return a pointer to the collision body of the box
inline rp3d::CollisionBody* Cylinder::getCollisionBody() {
return mRigidBody;
}
// Return a pointer to the rigid body of the box
inline rp3d::RigidBody* Cylinder::getRigidBody() {
return dynamic_cast<rp3d::RigidBody*>(mRigidBody);
// Update the transform matrix of the object
inline void Cylinder::updateTransform(float interpolationFactor) {
mTransformMatrix = computeTransform(interpolationFactor, mScalingMatrix);
}
#endif

View File

@ -26,6 +26,13 @@
// 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)
@ -64,6 +71,8 @@ Dumbbell::Dumbbell(const openglframework::Vector3 &position,
rp3d::Quaternion initOrientation(angleAroundX, 0, 0);
rp3d::Transform transformBody(initPosition, initOrientation);
mPreviousTransform = transformBody;
// Initial transform of the first sphere collision shape of the dumbbell (in local-space)
rp3d::Transform transformSphereShape1(rp3d::Vector3(0, 4.0, 0), rp3d::Quaternion::identity());
@ -84,6 +93,13 @@ Dumbbell::Dumbbell(const openglframework::Vector3 &position,
mBody = body;
mTransformMatrix = mTransformMatrix * mScalingMatrix;
// Create the VBOs and VAO
if (totalNbDumbbells == 0) {
createVBOAndVAO();
}
totalNbDumbbells++;
}
// Constructor
@ -142,13 +158,32 @@ Dumbbell::Dumbbell(const openglframework::Vector3 &position,
mBody->addCollisionShape(cylinderCollisionShape, transformCylinderShape);
mTransformMatrix = mTransformMatrix * mScalingMatrix;
// Create the VBOs and VAO
if (totalNbDumbbells == 0) {
createVBOAndVAO();
}
totalNbDumbbells++;
}
// Destructor
Dumbbell::~Dumbbell() {
if (totalNbDumbbells == 1) {
// 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
@ -159,58 +194,125 @@ void Dumbbell::render(openglframework::Shader& shader,
shader.bind();
// Set the model to camera matrix
const openglframework::Matrix4 localToCameraMatrix = worldToCameraMatrix * mTransformMatrix;
shader.setMatrix4x4Uniform("localToCameraMatrix", localToCameraMatrix);
shader.setMatrix4x4Uniform("localToWorldMatrix", mTransformMatrix);
shader.setMatrix4x4Uniform("worldToCameraMatrix", worldToCameraMatrix);
// Set the normal matrix (inverse transpose of the 3x3 upper-left sub matrix of the
// model-view matrix)
const openglframework::Matrix4 localToCameraMatrix = worldToCameraMatrix * mTransformMatrix;
const openglframework::Matrix3 normalMatrix =
localToCameraMatrix.getUpperLeft3x3Matrix().getInverse().getTranspose();
shader.setMatrix3x3Uniform("normalMatrix", normalMatrix);
shader.setMatrix3x3Uniform("normalMatrix", normalMatrix, false);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
if (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, false);
glVertexPointer(3, GL_FLOAT, 0, getVerticesPointer());
glNormalPointer(GL_FLOAT, 0, getNormalsPointer());
if(hasTexture()) {
glTexCoordPointer(2, GL_FLOAT, 0, getUVTextureCoordinatesPointer());
}
// 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, (char*)NULL);
mVBONormals.bind();
if (vertexNormalLoc != -1) glEnableVertexAttribArray(vertexNormalLoc);
if (vertexNormalLoc != -1) glVertexAttribPointer(vertexNormalLoc, 3, GL_FLOAT, GL_FALSE, 0, (char*)NULL);
// For each part of the mesh
for (unsigned int i=0; i<getNbParts(); i++) {
glDrawElements(GL_TRIANGLES, getNbFaces(i) * 3,
GL_UNSIGNED_INT, getIndicesPointer());
glDrawElements(GL_TRIANGLES, getNbFaces(i) * 3, GL_UNSIGNED_INT, (char*)NULL);
}
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
if (hasTexture()) {
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
glDisableVertexAttribArray(vertexPositionLoc);
if (vertexNormalLoc != -1) glDisableVertexAttribArray(vertexNormalLoc);
mVBONormals.unbind();
mVBOVertices.unbind();
// Unbind the VAO
mVAO.unbind();
// Unbind the shader
shader.unbind();
}
// Update the transform matrix of the sphere
void Dumbbell::updateTransform() {
// Create the Vertex Buffer Objects used to render with OpenGL.
/// We create two VBOs (one for vertices and one for indices)
void Dumbbell::createVBOAndVAO() {
// Get the interpolated transform of the rigid body
rp3d::Transform transform = mBody->getInterpolatedTransform();
// Create the VBO for the vertices data
mVBOVertices.create();
mVBOVertices.bind();
size_t sizeVertices = mVertices.size() * sizeof(openglframework::Vector3);
mVBOVertices.copyDataIntoVBO(sizeVertices, getVerticesPointer(), GL_STATIC_DRAW);
mVBOVertices.unbind();
// Compute the transform used for rendering the sphere
rp3d::decimal matrix[16];
transform.getOpenGLMatrix(matrix);
openglframework::Matrix4 newMatrix(matrix[0], matrix[4], matrix[8], matrix[12],
matrix[1], matrix[5], matrix[9], matrix[13],
matrix[2], matrix[6], matrix[10], matrix[14],
matrix[3], matrix[7], matrix[11], matrix[15]);
// Create the VBO for the normals data
mVBONormals.create();
mVBONormals.bind();
size_t sizeNormals = mNormals.size() * sizeof(openglframework::Vector3);
mVBONormals.copyDataIntoVBO(sizeNormals, getNormalsPointer(), GL_STATIC_DRAW);
mVBONormals.unbind();
// Apply the scaling matrix to have the correct sphere dimensions
mTransformMatrix = newMatrix * mScalingMatrix;
if (hasTexture()) {
// Create the VBO for the texture co data
mVBOTextureCoords.create();
mVBOTextureCoords.bind();
size_t sizeTextureCoords = mUVs.size() * sizeof(openglframework::Vector2);
mVBOTextureCoords.copyDataIntoVBO(sizeTextureCoords, getUVTextureCoordinatesPointer(), GL_STATIC_DRAW);
mVBOTextureCoords.unbind();
}
// Create th VBO for the indices data
mVBOIndices.create();
mVBOIndices.bind();
size_t sizeIndices = mIndices[0].size() * sizeof(uint);
mVBOIndices.copyDataIntoVBO(sizeIndices, getIndicesPointer(), GL_STATIC_DRAW);
mVBOIndices.unbind();
// Create the VAO for both VBOs
mVAO.create();
mVAO.bind();
// Bind the VBO of vertices
mVBOVertices.bind();
// Bind the VBO of normals
mVBONormals.bind();
if (hasTexture()) {
// Bind the VBO of texture coords
mVBOTextureCoords.bind();
}
// Bind the VBO of indices
mVBOIndices.bind();
// Unbind the VAO
mVAO.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<rp3d::RigidBody*>(mBody);
if (rigidBody != NULL) {
rigidBody->setLinearVelocity(rp3d::Vector3(0, 0, 0));
rigidBody->setAngularVelocity(rp3d::Vector3(0, 0, 0));
}
updateTransform(1.0f);
}

View File

@ -29,9 +29,10 @@
// Libraries
#include "openglframework.h"
#include "reactphysics3d.h"
#include "PhysicsObject.h"
// Class Sphere
class Dumbbell : public openglframework::Mesh {
class Dumbbell : public openglframework::Mesh, public PhysicsObject {
private :
@ -40,14 +41,35 @@ class Dumbbell : public openglframework::Mesh {
/// Radius of the spheres
float mRadius;
/// Rigid body used to simulate the dynamics of the sphere
rp3d::CollisionBody* mBody;
/// Scaling matrix (applied to a sphere to obtain the correct sphere dimensions)
openglframework::Matrix4 mScalingMatrix;
/// Previous transform (for interpolation)
rp3d::Transform mPreviousTransform;
/// Vertex Buffer Object for the vertices data
static openglframework::VertexBufferObject mVBOVertices;
/// Vertex Buffer Object for the normals data
static openglframework::VertexBufferObject mVBONormals;
/// Vertex Buffer Object for the texture coords
static openglframework::VertexBufferObject mVBOTextureCoords;
/// Vertex Buffer Object for the indices
static openglframework::VertexBufferObject mVBOIndices;
/// Vertex Array Object for the vertex data
static openglframework::VertexArrayObject mVAO;
// Total number of capsules created
static int totalNbDumbbells;
// -------------------- Methods -------------------- //
// Create the Vertex Buffer Objects used to render with OpenGL.
void createVBOAndVAO();
public :
// -------------------- Methods -------------------- //
@ -64,28 +86,20 @@ class Dumbbell : public openglframework::Mesh {
/// Destructor
~Dumbbell();
/// Return a pointer to the rigid body
rp3d::RigidBody* getRigidBody();
/// Return a pointer to the body
rp3d::CollisionBody* getCollisionBody();
/// Update the transform matrix of the sphere
void updateTransform();
/// 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);
/// Update the transform matrix of the object
virtual void updateTransform(float interpolationFactor);
};
// Return a pointer to the rigid body of the sphere
inline rp3d::RigidBody* Dumbbell::getRigidBody() {
return dynamic_cast<rp3d::RigidBody*>(mBody);
}
// Return a pointer to the body
inline rp3d::CollisionBody* Dumbbell::getCollisionBody() {
return mBody;
// Update the transform matrix of the object
inline void Dumbbell::updateTransform(float interpolationFactor) {
mTransformMatrix = computeTransform(interpolationFactor, mScalingMatrix);
}
#endif

View File

@ -47,7 +47,12 @@ void Line::render(openglframework::Shader& shader,
shader.bind();
// Set the model to camera matrix
shader.setMatrix4x4Uniform("localToCameraMatrix", worldToCameraMatrix);
shader.setMatrix4x4Uniform("localToWorldMatrix", openglframework::Matrix4::identity());
shader.setMatrix4x4Uniform("worldToCameraMatrix", worldToCameraMatrix);
// Set the vertex color
openglframework::Vector4 color(1, 0, 0, 1);
shader.setVector4Uniform("vertexColor", color, false);
glBegin(GL_LINES);
glVertex3f(mWorldPoint1.x, mWorldPoint1.y, mWorldPoint1.z);

View File

@ -58,9 +58,6 @@ class Line : public openglframework::Object3D {
/// Return the second point of the line
openglframework::Vector3 getPoint2() const;
/// Update the transform matrix of the sphere
void updateTransform();
/// Render the line at the correct position and with the correct orientation
void render(openglframework::Shader& shader,
const openglframework::Matrix4& worldToCameraMatrix);

View File

@ -0,0 +1,59 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2015 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 "PhysicsObject.h"
/// Constructor
PhysicsObject::PhysicsObject() {
mColor = openglframework::Color(1, 1, 1, 1);
mSleepingColor = openglframework::Color(1, 0, 0, 1);
}
// Compute the new transform matrix
openglframework::Matrix4 PhysicsObject::computeTransform(float interpolationFactor,
const openglframework::Matrix4& scalingMatrix) {
// Get the transform of the rigid body
rp3d::Transform transform = mBody->getTransform();
// Interpolate the transform between the previous one and the new one
rp3d::Transform interpolatedTransform = rp3d::Transform::interpolateTransforms(mPreviousTransform,
transform,
interpolationFactor);
mPreviousTransform = transform;
// Compute the transform used for rendering the box
rp3d::decimal matrix[16];
interpolatedTransform.getOpenGLMatrix(matrix);
openglframework::Matrix4 newMatrix(matrix[0], matrix[4], matrix[8], matrix[12],
matrix[1], matrix[5], matrix[9], matrix[13],
matrix[2], matrix[6], matrix[10], matrix[14],
matrix[3], matrix[7], matrix[11], matrix[15]);
// Apply the scaling matrix to have the correct box dimensions
return newMatrix * scalingMatrix;
}

View File

@ -0,0 +1,96 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2015 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 PHYSICSOBJECT_H
#define PHYSICSOBJECT_H
// Libraries
#include "openglframework.h"
#include "reactphysics3d.h"
// Class PhysicsObject
class PhysicsObject {
protected:
/// Body used to simulate the dynamics of the box
rp3d::CollisionBody* mBody;
/// Previous transform of the body (for interpolation)
rp3d::Transform mPreviousTransform;
/// Main color of the box
openglframework::Color mColor;
/// Sleeping color
openglframework::Color mSleepingColor;
// Compute the new transform matrix
openglframework::Matrix4 computeTransform(float interpolationFactor,
const openglframework::Matrix4 &scalingMatrix);
public:
/// Constructor
PhysicsObject();
/// Update the transform matrix of the object
virtual void updateTransform(float interpolationFactor)=0;
/// Set the color of the box
void setColor(const openglframework::Color& color);
/// Set the sleeping color of the box
void setSleepingColor(const openglframework::Color& color);
/// Return a pointer to the collision body of the box
reactphysics3d::CollisionBody* getCollisionBody();
/// Return a pointer to the rigid body of the box
reactphysics3d::RigidBody* getRigidBody();
};
// Set the color of the box
inline void PhysicsObject::setColor(const openglframework::Color& color) {
mColor = color;
}
// Set the sleeping color of the box
inline void PhysicsObject::setSleepingColor(const openglframework::Color& color) {
mSleepingColor = color;
}
// Return a pointer to the collision body of the box
inline rp3d::CollisionBody* PhysicsObject::getCollisionBody() {
return mBody;
}
// Return a pointer to the rigid body of the box (NULL if it's not a rigid body)
inline rp3d::RigidBody* PhysicsObject::getRigidBody() {
return dynamic_cast<rp3d::RigidBody*>(mBody);
}
#endif

View File

@ -26,6 +26,13 @@
// 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,
@ -57,13 +64,22 @@ Sphere::Sphere(float radius, const openglframework::Vector3 &position,
rp3d::Quaternion initOrientation = rp3d::Quaternion::identity();
rp3d::Transform transform(initPosition, initOrientation);
mPreviousTransform = transform;
// Create a rigid body corresponding to the sphere in the dynamics world
mRigidBody = world->createCollisionBody(transform);
mBody = world->createCollisionBody(transform);
// Add a collision shape to the body and specify the mass of the shape
mRigidBody->addCollisionShape(collisionShape, rp3d::Transform::identity());
mBody->addCollisionShape(collisionShape, rp3d::Transform::identity());
mTransformMatrix = mTransformMatrix * mScalingMatrix;
// Create the VBOs and VAO
if (totalNbSpheres == 0) {
createVBOAndVAO();
}
totalNbSpheres++;
}
// Constructor
@ -103,16 +119,34 @@ Sphere::Sphere(float radius, const openglframework::Vector3 &position,
// Add a collision shape to the body and specify the mass of the shape
body->addCollisionShape(collisionShape, rp3d::Transform::identity(), mass);
mRigidBody = body;
mBody = body;
mTransformMatrix = mTransformMatrix * mScalingMatrix;
// Create the VBOs and VAO
if (totalNbSpheres == 0) {
createVBOAndVAO();
}
totalNbSpheres++;
}
// Destructor
Sphere::~Sphere() {
if (totalNbSpheres == 1) {
// Destroy the mesh
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
@ -123,57 +157,125 @@ void Sphere::render(openglframework::Shader& shader,
shader.bind();
// Set the model to camera matrix
const openglframework::Matrix4 localToCameraMatrix = worldToCameraMatrix * mTransformMatrix;
shader.setMatrix4x4Uniform("localToCameraMatrix", localToCameraMatrix);
shader.setMatrix4x4Uniform("localToWorldMatrix", mTransformMatrix);
shader.setMatrix4x4Uniform("worldToCameraMatrix", worldToCameraMatrix);
// Set the normal matrix (inverse transpose of the 3x3 upper-left sub matrix of the
// model-view matrix)
const openglframework::Matrix4 localToCameraMatrix = worldToCameraMatrix * mTransformMatrix;
const openglframework::Matrix3 normalMatrix =
localToCameraMatrix.getUpperLeft3x3Matrix().getInverse().getTranspose();
shader.setMatrix3x3Uniform("normalMatrix", normalMatrix);
shader.setMatrix3x3Uniform("normalMatrix", normalMatrix, false);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
if (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, false);
glVertexPointer(3, GL_FLOAT, 0, getVerticesPointer());
glNormalPointer(GL_FLOAT, 0, getNormalsPointer());
if(hasTexture()) {
glTexCoordPointer(2, GL_FLOAT, 0, getUVTextureCoordinatesPointer());
}
// 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, (char*)NULL);
mVBONormals.bind();
if (vertexNormalLoc != -1) glVertexAttribPointer(vertexNormalLoc, 3, GL_FLOAT, GL_FALSE, 0, (char*)NULL);
if (vertexNormalLoc != -1) glEnableVertexAttribArray(vertexNormalLoc);
// For each part of the mesh
for (unsigned int i=0; i<getNbParts(); i++) {
glDrawElements(GL_TRIANGLES, getNbFaces(i) * 3,
GL_UNSIGNED_INT, getIndicesPointer());
glDrawElements(GL_TRIANGLES, getNbFaces(i) * 3, GL_UNSIGNED_INT, (char*)NULL);
}
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
if (hasTexture()) {
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
glDisableVertexAttribArray(vertexPositionLoc);
if (vertexNormalLoc != -1) glDisableVertexAttribArray(vertexNormalLoc);
mVBONormals.unbind();
mVBOVertices.unbind();
// Unbind the VAO
mVAO.unbind();
// Unbind the shader
shader.unbind();
}
// Update the transform matrix of the sphere
void Sphere::updateTransform() {
// Create the Vertex Buffer Objects used to render with OpenGL.
/// We create two VBOs (one for vertices and one for indices)
void Sphere::createVBOAndVAO() {
// Get the interpolated transform of the rigid body
rp3d::Transform transform = mRigidBody->getInterpolatedTransform();
// Create the VBO for the vertices data
mVBOVertices.create();
mVBOVertices.bind();
size_t sizeVertices = mVertices.size() * sizeof(openglframework::Vector3);
mVBOVertices.copyDataIntoVBO(sizeVertices, getVerticesPointer(), GL_STATIC_DRAW);
mVBOVertices.unbind();
// Compute the transform used for rendering the sphere
rp3d::decimal matrix[16];
transform.getOpenGLMatrix(matrix);
openglframework::Matrix4 newMatrix(matrix[0], matrix[4], matrix[8], matrix[12],
matrix[1], matrix[5], matrix[9], matrix[13],
matrix[2], matrix[6], matrix[10], matrix[14],
matrix[3], matrix[7], matrix[11], matrix[15]);
// Create the VBO for the normals data
mVBONormals.create();
mVBONormals.bind();
size_t sizeNormals = mNormals.size() * sizeof(openglframework::Vector3);
mVBONormals.copyDataIntoVBO(sizeNormals, getNormalsPointer(), GL_STATIC_DRAW);
mVBONormals.unbind();
// Apply the scaling matrix to have the correct sphere dimensions
mTransformMatrix = newMatrix * mScalingMatrix;
if (hasTexture()) {
// Create the VBO for the texture co data
mVBOTextureCoords.create();
mVBOTextureCoords.bind();
size_t sizeTextureCoords = mUVs.size() * sizeof(openglframework::Vector2);
mVBOTextureCoords.copyDataIntoVBO(sizeTextureCoords, getUVTextureCoordinatesPointer(), GL_STATIC_DRAW);
mVBOTextureCoords.unbind();
}
// Create th VBO for the indices data
mVBOIndices.create();
mVBOIndices.bind();
size_t sizeIndices = mIndices[0].size() * sizeof(uint);
mVBOIndices.copyDataIntoVBO(sizeIndices, getIndicesPointer(), GL_STATIC_DRAW);
mVBOIndices.unbind();
// Create the VAO for both VBOs
mVAO.create();
mVAO.bind();
// Bind the VBO of vertices
mVBOVertices.bind();
// Bind the VBO of normals
mVBONormals.bind();
if (hasTexture()) {
// Bind the VBO of texture coords
mVBOTextureCoords.bind();
}
// Bind the VBO of indices
mVBOIndices.bind();
// Unbind the VAO
mVAO.unbind();
}
// Reset the transform
void Sphere::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<rp3d::RigidBody*>(mBody);
if (rigidBody != NULL) {
rigidBody->setLinearVelocity(rp3d::Vector3(0, 0, 0));
rigidBody->setAngularVelocity(rp3d::Vector3(0, 0, 0));
}
updateTransform(1.0f);
}

View File

@ -29,9 +29,10 @@
// Libraries
#include "openglframework.h"
#include "reactphysics3d.h"
#include "PhysicsObject.h"
// Class Sphere
class Sphere : public openglframework::Mesh {
class Sphere : public openglframework::Mesh, public PhysicsObject {
private :
@ -40,14 +41,35 @@ class Sphere : public openglframework::Mesh {
/// Radius of the sphere
float mRadius;
/// Rigid body used to simulate the dynamics of the sphere
rp3d::CollisionBody* mRigidBody;
/// Scaling matrix (applied to a sphere to obtain the correct sphere dimensions)
openglframework::Matrix4 mScalingMatrix;
/// Previous transform (for interpolation)
rp3d::Transform mPreviousTransform;
/// Vertex Buffer Object for the vertices data
static openglframework::VertexBufferObject mVBOVertices;
/// Vertex Buffer Object for the normals data
static openglframework::VertexBufferObject mVBONormals;
/// Vertex Buffer Object for the texture coords
static openglframework::VertexBufferObject mVBOTextureCoords;
/// Vertex Buffer Object for the indices
static openglframework::VertexBufferObject mVBOIndices;
/// Vertex Array Object for the vertex data
static openglframework::VertexArrayObject mVAO;
// Total number of capsules created
static int totalNbSpheres;
// -------------------- Methods -------------------- //
// Create the Vertex Buffer Objects used to render with OpenGL.
void createVBOAndVAO();
public :
// -------------------- Methods -------------------- //
@ -63,28 +85,20 @@ class Sphere : public openglframework::Mesh {
/// Destructor
~Sphere();
/// Return a pointer to the collision body of the box
reactphysics3d::CollisionBody* getCollisionBody();
/// Return a pointer to the rigid body of the box
reactphysics3d::RigidBody* getRigidBody();
/// Update the transform matrix of the sphere
void updateTransform();
/// 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);
/// Update the transform matrix of the object
virtual void updateTransform(float interpolationFactor);
};
// Return a pointer to the collision body of the box
inline rp3d::CollisionBody* Sphere::getCollisionBody() {
return mRigidBody;
}
// Return a pointer to the rigid body of the box
inline rp3d::RigidBody* Sphere::getRigidBody() {
return dynamic_cast<rp3d::RigidBody*>(mRigidBody);
// Update the transform matrix of the object
inline void Sphere::updateTransform(float interpolationFactor) {
mTransformMatrix = computeTransform(interpolationFactor, mScalingMatrix);
}
#endif

View File

@ -0,0 +1,183 @@
/********************************************************************************
* ReactPhysics3D physics library, http://www.reactphysics3d.com *
* Copyright (c) 2010-2015 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 "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;
openglframework::Mesh VisualContactPoint::mMesh;
bool VisualContactPoint::mStaticDataCreated = false;
// Constructor
VisualContactPoint::VisualContactPoint(const openglframework::Vector3& position,
const std::string& meshFolderPath)
: mColor(1.0f, 0.0f, 0.0f, 1.0f) {
// Initialize the position where the mesh will be rendered
translateWorld(position);
}
// Destructor
VisualContactPoint::~VisualContactPoint() {
}
// Load and initialize the mesh for all the contact points
void VisualContactPoint::createStaticData(const std::string& meshFolderPath) {
if (mStaticDataCreated) return;
// Load the mesh from a file
openglframework::MeshReaderWriter::loadMeshFromFile(meshFolderPath + "sphere.obj", mMesh);
// Calculate the normals of the mesh
mMesh.calculateNormals();
mMesh.scaleVertices(VISUAL_CONTACT_POINT_RADIUS);
createVBOAndVAO();
mStaticDataCreated = true;
}
// Destroy the mesh for the contact points
void VisualContactPoint::destroyStaticData() {
if (!mStaticDataCreated) return;
// Destroy the VBOs and VAO
mVBOIndices.destroy();
mVBOVertices.destroy();
mVBONormals.destroy();
mVAO.destroy();
mMesh.destroy();
mStaticDataCreated = false;
}
// Render the sphere at the correct position and with the correct orientation
void VisualContactPoint::render(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
shader.setMatrix4x4Uniform("localToWorldMatrix", mTransformMatrix);
shader.setMatrix4x4Uniform("worldToCameraMatrix", worldToCameraMatrix);
// Set the normal matrix (inverse transpose of the 3x3 upper-left sub matrix of the
// model-view matrix)
const openglframework::Matrix4 localToCameraMatrix = worldToCameraMatrix * mTransformMatrix;
const openglframework::Matrix3 normalMatrix =
localToCameraMatrix.getUpperLeft3x3Matrix().getInverse().getTranspose();
shader.setMatrix3x3Uniform("normalMatrix", normalMatrix, false);
// Set the vertex color
openglframework::Vector4 color(mColor.r, mColor.g, mColor.b, mColor.a);
shader.setVector4Uniform("vertexColor", color, false);
// 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, (char*)NULL);
mVBONormals.bind();
if (vertexNormalLoc != -1) glVertexAttribPointer(vertexNormalLoc, 3, GL_FLOAT, GL_FALSE, 0, (char*)NULL);
if (vertexNormalLoc != -1) glEnableVertexAttribArray(vertexNormalLoc);
// For each part of the mesh
for (unsigned int i=0; i<mMesh.getNbParts(); i++) {
glDrawElements(GL_TRIANGLES, mMesh.getNbFaces(i) * 3, GL_UNSIGNED_INT, (char*)NULL);
}
glDisableVertexAttribArray(vertexPositionLoc);
if (vertexNormalLoc != -1) glDisableVertexAttribArray(vertexNormalLoc);
mVBONormals.unbind();
mVBOVertices.unbind();
// Unbind the VAO
mVAO.unbind();
// Unbind the shader
shader.unbind();
}
// Create the Vertex Buffer Objects used to render with OpenGL.
/// We create two VBOs (one for vertices and one for indices)
void VisualContactPoint::createVBOAndVAO() {
// Create the VBO for the vertices data
mVBOVertices.create();
mVBOVertices.bind();
size_t sizeVertices = mMesh.getVertices().size() * sizeof(openglframework::Vector3);
mVBOVertices.copyDataIntoVBO(sizeVertices, mMesh.getVerticesPointer(), GL_STATIC_DRAW);
mVBOVertices.unbind();
// Create the VBO for the normals data
mVBONormals.create();
mVBONormals.bind();
size_t sizeNormals = mMesh.getNormals().size() * sizeof(openglframework::Vector3);
mVBONormals.copyDataIntoVBO(sizeNormals, mMesh.getNormalsPointer(), GL_STATIC_DRAW);
mVBONormals.unbind();
// Create th VBO for the indices data
mVBOIndices.create();
mVBOIndices.bind();
size_t sizeIndices = mMesh.getIndices(0).size() * sizeof(uint);
mVBOIndices.copyDataIntoVBO(sizeIndices, mMesh.getIndicesPointer(), GL_STATIC_DRAW);
mVBOIndices.unbind();
// Create the VAO for both VBOs
mVAO.create();
mVAO.bind();
// Bind the VBO of vertices
mVBOVertices.bind();
// Bind the VBO of normals
mVBONormals.bind();
// Bind the VBO of indices
mVBOIndices.bind();
// Unbind the VAO
mVAO.unbind();
}

View File

@ -29,7 +29,7 @@
// Libraries
#include "openglframework.h"
const float VISUAL_CONTACT_POINT_RADIUS = 0.1f;
const float VISUAL_CONTACT_POINT_RADIUS = 0.2f;
// Class VisualContactPoint
class VisualContactPoint : public openglframework::Object3D {
@ -44,8 +44,26 @@ class VisualContactPoint : public openglframework::Object3D {
/// Sphere mesh for the visual contact point
static openglframework::Mesh mMesh;
/// True if the mesh has been initialized
static bool mIsMeshInitialized;
/// Vertex Buffer Object for the vertices data
static openglframework::VertexBufferObject mVBOVertices;
/// Vertex Buffer Object for the normals data
static openglframework::VertexBufferObject mVBONormals;
/// Vertex Buffer Object for the indices
static openglframework::VertexBufferObject mVBOIndices;
/// Vertex Array Object for the vertex data
static openglframework::VertexArrayObject mVAO;
/// True if static data (VBO, VAO) has been created already
static bool mStaticDataCreated;
/// Color
openglframework::Color mColor;
// Create the Vertex Buffer Objects used to render with OpenGL.
static void createVBOAndVAO();
// -------------------- Methods -------------------- //
@ -54,7 +72,8 @@ class VisualContactPoint : public openglframework::Object3D {
// -------------------- Methods -------------------- //
/// Constructor
VisualContactPoint(const openglframework::Vector3& position);
VisualContactPoint(const openglframework::Vector3& position,
const std::string &meshFolderPath);
/// Destructor
~VisualContactPoint();

View File

Before

Width:  |  Height:  |  Size: 109 KiB

After

Width:  |  Height:  |  Size: 109 KiB

Some files were not shown because too many files have changed in this diff Show More