This commit is contained in:
Colin 2015-08-26 04:01:18 -06:00
commit 87b88fc953
257 changed files with 9934 additions and 2445 deletions

View File

@ -18,7 +18,7 @@ SET(OUR_EXECUTABLE_OUTPUT_PATH "${PROJECT_BINARY_DIR}/bin")
ENABLE_TESTING() ENABLE_TESTING()
# Options # 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(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(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 OPTION(DOUBLE_PRECISION_ENABLED "Select this if you want to compile using double precision floating
@ -119,8 +119,6 @@ SET (REACTPHYSICS3D_SOURCES
"src/engine/OverlappingPair.cpp" "src/engine/OverlappingPair.cpp"
"src/engine/Profiler.h" "src/engine/Profiler.h"
"src/engine/Profiler.cpp" "src/engine/Profiler.cpp"
"src/engine/Timer.h"
"src/engine/Timer.cpp"
"src/mathematics/mathematics.h" "src/mathematics/mathematics.h"
"src/mathematics/mathematics_functions.h" "src/mathematics/mathematics_functions.h"
"src/mathematics/Matrix2x2.h" "src/mathematics/Matrix2x2.h"
@ -144,10 +142,10 @@ SET (REACTPHYSICS3D_SOURCES
# Create the library # Create the library
ADD_LIBRARY (reactphysics3d STATIC ${REACTPHYSICS3D_SOURCES}) ADD_LIBRARY (reactphysics3d STATIC ${REACTPHYSICS3D_SOURCES})
# If we need to compile the examples # If we need to compile the testbed application
IF(COMPILE_EXAMPLES) IF(COMPILE_TESTBED)
add_subdirectory(examples/) add_subdirectory(testbed/)
ENDIF(COMPILE_EXAMPLES) ENDIF(COMPILE_TESTBED)
# If we need to compile the tests # If we need to compile the tests
IF(COMPILE_TESTS) IF(COMPILE_TESTS)

View File

@ -228,7 +228,10 @@ rp3d::CollisionWorld world;
Do not forget to destroy the \texttt{CollisionWorld} instance at the end of your program in order to release the allocated memory. If the object has been created Do not forget to destroy the \texttt{CollisionWorld} instance at the end of your program in order to release the allocated memory. If the object has been created
statically, it will be destroyed automatically at the end of the scope in which it has been created. If the object has been created dynamically (using the \texttt{new} statically, it will be destroyed automatically at the end of the scope in which it has been created. If the object has been created dynamically (using the \texttt{new}
operator), you need to destroy it with the \texttt{delete} operator. operator), you need to destroy it with the \texttt{delete} operator. \\
When the \texttt{CollisionWorld} is destroyed, all the bodies that have been added into it and that have not been destroyed already will be destroyed.
Therefore, the pointers to the bodies of the world will become invalid after the existence of their \texttt{CollisionWorld}.
\section{Collision Bodies} \section{Collision Bodies}
@ -311,12 +314,8 @@ world.destroyCollisionBody(body);
\subsection{Creating the Dynamics World} \subsection{Creating the Dynamics World}
The first thing you have to do when you want to simulate the dynamics of rigid bodies in time is to create an instance The first thing you have to do when you want to simulate the dynamics of rigid bodies in time is to create an instance
of the \texttt{DynamicsWorld}. You need to specify two parameters when constructing the world. The first one is the gravity acceleration vector (in $m / s^2$) in the of the \texttt{DynamicsWorld}. You need to specify the gravity acceleration vector (in $m / s^2$) in the world as parameter. Note that gravity is
world and activated by default when you create the world. \\
the second one is the simulation time step (in seconds). Note that gravity is activated by default when you create the world. The time step is the fixed amount of time
used at each internal
physics tick. Note that multiple internal physics ticks can be taken at each frame. For real-time applications, a time step of $\frac{1}{60}$ seconds (60 Hz) is usually
used. Using a smaller time step makes the simulation more precise but also more expensive to compute. \\
Here is how to create the Dynamics World: \\ Here is how to create the Dynamics World: \\
@ -324,11 +323,8 @@ world.destroyCollisionBody(body);
// Gravity vector // Gravity vector
rp3d::Vector3 gravity(0.0, -9.81, 0.0); rp3d::Vector3 gravity(0.0, -9.81, 0.0);
// Time step (in seconds)
rp3d::decimal timeStep = 1.0 / 60.0;
// Create the dynamics world // Create the dynamics world
rp3d::DynamicsWorld world(gravity, timeStep); rp3d::DynamicsWorld world(gravity);
\end{lstlisting} \end{lstlisting}
\subsection{Customizing the Dynamics World} \subsection{Customizing the Dynamics World}
@ -384,39 +380,67 @@ world.enableSleeping(false);
\subsection{Updating the Dynamics World} \subsection{Updating the Dynamics World}
The first thing you have to do to simulate the dynamics of your world is to start the simulation using the following method: \\ The \texttt{DynamicsWorld} is used to simulate physics through time. It has to be updated each time you want to simulate a step forward in time. Most of the time,
you want to update the world right before rendering a new frame in a real-time application. \\
To update the physics world, you need to use the \texttt{DynamicsWorld::update()} method. This method will perform collision detection and update the
position and orientation of the bodies and joints. After updating the world, you will be able to get the new position and orientation of your bodies for the next
frame to render. This method requires a \emph{timeStep} parameter. This is the amount of time you want to advance the physics simulation (in seconds). \\
The smaller the time step you pick, the more precise the simulation will be but it can also be more expensive to compute. For a real-time application, you
probably want a time step of at most $\frac{1}{60}$ seconds to
have at least a 60 Hz framerate. Most of the time, physics engines prefer to work with a constant time step. It means that you should always call
the \texttt{DynamicsWorld::update()} method with the same time step parameter. You do not want to use the time between two frames as your time step because it will
not be constant. \\
You can use the following technique. First, you choose a constant time step for the physics. Let say the time step is $\frac{1}{60}$ seconds. Then, at each frame,
you compute the time difference between the current frame and the previous one and you accumulate this difference in a variable called \emph{accumulator}. The accumulator
is initialized to zero at the beginning of your application and is updated at each frame. The idea is to divide the time in the accumulator in several constant time steps.
For instance, if your accumulator contains $0.145$ seconds, it means that we can take $8$ physics steps of $\frac{1}{60}$ seconds during the current frame. Note that
$0.012$ seconds will remain in the accumulator and will probably be used in the next frame. As you can see, multiple physics steps can be taken at each frame. It is
important to understand that each call to the \texttt{DynamicsWorld::update()} method is done using a constant time step that is not varying with the framerate. \\
Here is what the code looks like at each frame: \\
\begin{lstlisting} \begin{lstlisting}
// Start the simulation
world.start(); // Constant physics time step
const float timeStep = 1.0 / 60.0;
// Get the current system time
long double currentFrameTime = getCurrentSystemTime();
// Compute the time difference between the two frames
long double deltaTime = currentFrameTime - previousFrameTime;
// Update the previous time
previousFrameTime = currentFrameTime;
// Add the time difference in the accumulator
accumulator += mDeltaTime;
// While there is enough accumulated time to take
// one or several physics steps
while (accumulator >= timeStep) {
// Update the Dynamics world with a constant time step
dynamicsWorld->update(timeStep);
// Decrease the accumulated time
accumulator -= timeStep;
}
\end{lstlisting} \end{lstlisting}
\vspace{0.6cm}
Then, each time you have to compute the next frame to render in your application, you need to update the state of the world. To do that, you simply need to call this method: \\
\begin{lstlisting}
// Update the world by taking a simulation step
world.update();
\end{lstlisting}
\vspace{0.6cm}
When the \texttt{DynamicsWorld::update()} method is called, collision detection is performed and the position and orientation of the bodies are updated accordingly.
After updating the world, you will be able to get the updated position and orientation of the bodies for the next frame. Make sure that you call
the \texttt{DynamicsWorld::start()} method before calling the \texttt{DynamicsWorld::update()} method. \\
You can also use the \texttt{DynamicsWorld::stop()} method to stop the simulation. You will then be able to start it again and continue updating it. \\
Note that you can get the elapsed time (in seconds) from the beginning of the physics simulation using the \texttt{DynamicsWorld::getPhysicsTime()} method.
This can be useful to
create some animations.
\subsection{Destroying the Dynamics World} \subsection{Destroying the Dynamics World}
Do not forget to destroy the \texttt{DynamicsWorld} instance at the end of your program in order to release the allocated memory. If the object has been created statically, it will Do not forget to destroy the \texttt{DynamicsWorld} instance at the end of your program in order to release the allocated memory. If the object has been created
automatically be destroyed at the end of the scope in which it has been created. If the object has been created dynamically (using the \texttt{new} operator), you need to destroy statically, it will automatically be destroyed at the end of the scope in which it has been created. If the object has been created dynamically (using the
it with the \texttt{delete} operator. \texttt{new} operator), you need to destroy it with the \texttt{delete} operator. \\
When the \texttt{DynamicsWorld} is destroyed, all the bodies and joints that have been added into it and that have not been destroyed already will be destroyed.
Therefore, the pointers to the bodies and joints of the world will become invalid after the existence of their \texttt{DynamicsWorld}.
\section{Rigid Bodies} \section{Rigid Bodies}
\label{sec:rigidbody} \label{sec:rigidbody}
@ -1472,8 +1496,91 @@ bool isHit = proxyShape->raycast(ray, raycastInfo);
In this example, you will see how to use the ray casting methods of the library. Several rays are thrown against the different collision shapes. In this example, you will see how to use the ray casting methods of the library. Several rays are thrown against the different collision shapes.
It is possible to switch from a collision shape to another using the space key. It is possible to switch from a collision shape to another using the space key.
\section{Receiving Feedback} \section{Retrieving contacts}
There are several ways to get the contacts information (contact point, normal, penetration depth, \dots) from the \texttt{DynamicsWorld}. \\
\subsection{Contacts of a given rigid body}
If you are interested to retrieve all the contacts of a single rigid body, you can use the \texttt{RigidBody::getContactManifoldsList()} method. This method will
return a linked list with all the current contact manifolds of the body. A contact manifold can contains several contact points. \\
Here is an example showing how to get the contact points of a given rigid body: \\
\begin{lstlisting}
const ContactManifoldListElement* listElem;
// Get the head of the linked list of contact manifolds of the body
listElem = rigidbody->getContactManifoldsList();
// For each contact manifold of the body
for (; listElem != NULL; listElem = listElem->next) {
ContactManifold* manifold = listElem->contactManifold;
// For each contact point of the manifold
for (int i=0; i<manifold->getNbContactPoints(); i++) {
// Get the contact point
ContactPoint* point = manifold->getContactPoint(i);
// Get the world-space contact point on body 1
Vector3 pos = point->getWorldPointOnBody1();
// Get the world-space contact normal
Vector3 normal = point->getNormal();
}
}
\end{lstlisting}
\vspace{0.6cm}
Note that this technique to retrieve the contacts, if you use it between the \texttt{DynamicsWorld::update()} calls, will only give you the contacts are the end of
each frame. You will probably miss several contacts that have occured in the physics internal sub-steps. In section \ref{sec:receiving_feedback}, you will
see how to get all the contact occuring in the physis sub-steps of the engine. Also note that a contact manifold contains some persistent contact points that
have may have been there for several frames.
\subsection{All the contacts of the world}
If you want to retrieve all the contacts of any rigid body in the world, you can use the \texttt{DynamicsWorld::getContactsList()} method. This method will
a \texttt{std::vector} with the list of all the current contact manifolds of the world. A contact manifold may contain several contact points. \\
The following example shows how to get all the contacts of the world using this method: \\
\begin{lstlisting}
std::vector<ContactManifold*> manifolds;
// Get all the contacts of the world
manifolds = dynamicsWorld->getContactsList();
std::vector<ContactManifold*>::iterator it;
// For each contact manifold of the body
for (it = manifolds.begin(); it != manifolds.end(); ++it) {
ContactManifold* manifold = *it;
// For each contact point of the manifold
for (int i=0; i<manifold->getNbContactPoints(); i++) {
// Get the contact point
ContactPoint* point = manifold->getContactPoint(i);
// Get the world-space contact point on body 1
Vector3 pos = point->getWorldPointOnBody1();
// Get the world-space contact normal
Vector3 normal = point->getNormal();
}
}
\end{lstlisting}
\vspace{0.6cm}
Note that this technique to retrieve the contacts, if you use it between the \texttt{DynamicsWorld::update()} calls, will only give you the contacts are the end of
each frame. You will probably miss several contacts that have occured in the physics internal sub-steps. In section \ref{sec:receiving_feedback}, you will
see how to get all the contact occuring in the physis sub-steps of the engine. Also note that a contact manifold contains some persistent contact points that
have may have been there for several frames.
\section{Receiving Feedback}
\label{sec:receiving_feedback}
Sometimes, you want to receive notifications from the physics engine when a given event happens. The \texttt{EventListener} class can be used for that purpose. In order to use Sometimes, you want to receive notifications from the physics engine when a given event happens. The \texttt{EventListener} class can be used for that purpose. In order to use
it, you need to create a new class that inherits from the \texttt{EventListener} class and overrides some methods that will be called by the ReactPhysics3D library when some events it, you need to create a new class that inherits from the \texttt{EventListener} class and overrides some methods that will be called by the ReactPhysics3D library when some events
occur. You also need to register your class in the physics world using the \texttt{DynamicsWorld::setEventListener()} as in the following code: \\ occur. You also need to register your class in the physics world using the \texttt{DynamicsWorld::setEventListener()} as in the following code: \\

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

View File

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

View File

@ -73,12 +73,6 @@ class CollisionBody : public Body {
/// Position and orientation of the body /// Position and orientation of the body
Transform mTransform; Transform mTransform;
/// Last position and orientation of the body
Transform mOldTransform;
/// Interpolation factor used for the state interpolation
decimal mInterpolationFactor;
/// First element of the linked list of proxy collision shapes of this body /// First element of the linked list of proxy collision shapes of this body
ProxyShape* mProxyCollisionShapes; ProxyShape* mProxyCollisionShapes;
@ -105,9 +99,6 @@ class CollisionBody : public Body {
/// Remove all the collision shapes /// Remove all the collision shapes
void removeAllCollisionShapes(); 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) /// Update the broad-phase state for this body (because it has moved for instance)
virtual void updateBroadPhaseState() const; virtual void updateBroadPhaseState() const;
@ -118,9 +109,6 @@ class CollisionBody : public Body {
/// Reset the mIsAlreadyInIsland variable of the body and contact manifolds /// Reset the mIsAlreadyInIsland variable of the body and contact manifolds
int resetIsAlreadyInIslandAndCountManifolds(); int resetIsAlreadyInIslandAndCountManifolds();
/// Set the interpolation factor of the body
void setInterpolationFactor(decimal factor);
public : public :
// -------------------- Methods -------------------- // // -------------------- Methods -------------------- //
@ -144,7 +132,7 @@ class CollisionBody : public Body {
const Transform& getTransform() const; const Transform& getTransform() const;
/// Set the current position and orientation /// Set the current position and orientation
void setTransform(const Transform& transform); virtual void setTransform(const Transform& transform);
/// Add a collision shape to the body. /// Add a collision shape to the body.
virtual ProxyShape* addCollisionShape(const CollisionShape& collisionShape, virtual ProxyShape* addCollisionShape(const CollisionShape& collisionShape,
@ -153,9 +141,6 @@ class CollisionBody : public Body {
/// Remove a collision shape from the body /// Remove a collision shape from the body
virtual void removeCollisionShape(const ProxyShape* proxyShape); virtual void removeCollisionShape(const ProxyShape* proxyShape);
/// Return the interpolated transform for rendering
Transform getInterpolatedTransform() const;
/// Return the first element of the linked list of contact manifolds involving this body /// Return the first element of the linked list of contact manifolds involving this body
const ContactManifoldListElement* getContactManifoldsList() const; const ContactManifoldListElement* getContactManifoldsList() const;
@ -227,20 +212,6 @@ inline void CollisionBody::setType(BodyType type) {
} }
} }
// Return the interpolated transform for rendering
/**
* @return The current interpolated transformation (between previous and current frame)
*/
inline Transform CollisionBody::getInterpolatedTransform() const {
return Transform::interpolateTransforms(mOldTransform, mTransform, mInterpolationFactor);
}
// Set the interpolation factor of the body
inline void CollisionBody::setInterpolationFactor(decimal factor) {
// Set the factor
mInterpolationFactor = factor;
}
// Return the current position and orientation // Return the current position and orientation
/** /**
* @return The current transformation of the body that transforms the local-space * @return The current transformation of the body that transforms the local-space
@ -264,12 +235,6 @@ inline void CollisionBody::setTransform(const Transform& transform) {
updateBroadPhaseState(); 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 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 * @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(); 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 // Recompute the center of mass, total mass and inertia tensor of the body using all
// the collision shapes attached to the body. // the collision shapes attached to the body.
void RigidBody::recomputeMassInformation() { void RigidBody::recomputeMassInformation() {
@ -342,8 +400,13 @@ void RigidBody::updateBroadPhaseState() const {
PROFILE("RigidBody::updateBroadPhaseState()"); PROFILE("RigidBody::updateBroadPhaseState()");
<<<<<<< HEAD
DynamicsWorld& world = static_cast<DynamicsWorld&>(mWorld); DynamicsWorld& world = static_cast<DynamicsWorld&>(mWorld);
const Vector3 displacement = world.mTimer.getTimeStep() * mLinearVelocity; const Vector3 displacement = world.mTimer.getTimeStep() * mLinearVelocity;
=======
DynamicsWorld& world = dynamic_cast<DynamicsWorld&>(mWorld);
const Vector3 displacement = world.mTimeStep* mLinearVelocity;
>>>>>>> 1bde11f245806de07a12b1cf6c33cdb83046b882
// For all the proxy collision shapes of the body // For all the proxy collision shapes of the body
for (ProxyShape* shape = mProxyCollisionShapes; shape != NULL; shape = shape->mNext) { for (ProxyShape* shape = mProxyCollisionShapes; shape != NULL; shape = shape->mNext) {

View File

@ -118,9 +118,6 @@ class RigidBody : public CollisionBody {
/// Update the broad-phase state for this body (because it has moved for instance) /// Update the broad-phase state for this body (because it has moved for instance)
virtual void updateBroadPhaseState() const; virtual void updateBroadPhaseState() const;
/// Set the variable to know whether or not the body is sleeping
virtual void setIsSleeping(bool isSleeping);
public : public :
// -------------------- Methods -------------------- // // -------------------- Methods -------------------- //
@ -134,6 +131,9 @@ class RigidBody : public CollisionBody {
/// Set the type of the body (static, kinematic or dynamic) /// Set the type of the body (static, kinematic or dynamic)
void setType(BodyType type); void setType(BodyType type);
/// Set the current position and orientation
virtual void setTransform(const Transform& transform);
/// Return the mass of the body /// Return the mass of the body
decimal getMass() const; decimal getMass() const;
@ -149,6 +149,9 @@ class RigidBody : public CollisionBody {
/// Set the angular velocity. /// Set the angular velocity.
void setAngularVelocity(const Vector3& angularVelocity); 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) /// Return the local inertia tensor of the body (in body coordinates)
const Matrix3x3& getInertiaTensorLocal() const; const Matrix3x3& getInertiaTensorLocal() const;
@ -252,20 +255,6 @@ inline Vector3 RigidBody::getAngularVelocity() const {
return mAngularVelocity; 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 local inertia tensor of the body (in local-space coordinates)
/** /**
* @return The 3x3 inertia tensor matrix 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(); 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 needs to be applied to this rigid body
/** /**
* @return True if the gravity is applied to the body * @return True if the gravity is applied to the body

View File

@ -83,9 +83,6 @@ const decimal PI = decimal(3.14159265);
/// 2*Pi constant /// 2*Pi constant
const decimal PI_TIMES_2 = decimal(6.28318530); const decimal PI_TIMES_2 = decimal(6.28318530);
/// Default internal constant timestep in seconds
const decimal DEFAULT_TIMESTEP = decimal(1.0 / 60.0);
/// Default friction coefficient for a rigid body /// Default friction coefficient for a rigid body
const decimal DEFAULT_FRICTION_COEFFICIENT = decimal(0.3); const decimal DEFAULT_FRICTION_COEFFICIENT = decimal(0.3);

View File

@ -40,6 +40,15 @@ CollisionWorld::CollisionWorld()
// Destructor // Destructor
CollisionWorld::~CollisionWorld() { CollisionWorld::~CollisionWorld() {
// Destroy all the collision bodies that have not been removed
std::set<CollisionBody*>::iterator itBodies;
for (itBodies = mBodies.begin(); itBodies != mBodies.end(); ) {
std::set<CollisionBody*>::iterator itToRemove = itBodies;
++itBodies;
destroyCollisionBody(*itToRemove);
}
assert(mCollisionShapes.empty()); assert(mCollisionShapes.empty());
assert(mBodies.empty()); assert(mBodies.empty());
} }

View File

@ -37,10 +37,9 @@ using namespace std;
// Constructor // Constructor
/** /**
* @param gravity Gravity vector in the world (in meters per second squared) * @param gravity Gravity vector in the world (in meters per second squared)
* @param timeStep Time step for an internal physics tick (in seconds)
*/ */
DynamicsWorld::DynamicsWorld(const Vector3 &gravity, decimal timeStep = DEFAULT_TIMESTEP) DynamicsWorld::DynamicsWorld(const Vector3 &gravity)
: CollisionWorld(), mTimer(timeStep), : CollisionWorld(),
mContactSolver(mMapBodyToConstrainedVelocityIndex), mContactSolver(mMapBodyToConstrainedVelocityIndex),
mConstraintSolver(mMapBodyToConstrainedVelocityIndex), mConstraintSolver(mMapBodyToConstrainedVelocityIndex),
mNbVelocitySolverIterations(DEFAULT_VELOCITY_SOLVER_NB_ITERATIONS), mNbVelocitySolverIterations(DEFAULT_VELOCITY_SOLVER_NB_ITERATIONS),
@ -60,6 +59,22 @@ DynamicsWorld::DynamicsWorld(const Vector3 &gravity, decimal timeStep = DEFAULT_
// Destructor // Destructor
DynamicsWorld::~DynamicsWorld() { DynamicsWorld::~DynamicsWorld() {
// Destroy all the joints that have not been removed
std::set<Joint*>::iterator itJoints;
for (itJoints = mJoints.begin(); itJoints != mJoints.end();) {
std::set<Joint*>::iterator itToRemove = itJoints;
++itJoints;
destroyJoint(*itToRemove);
}
// Destroy all the rigid bodies that have not been removed
std::set<RigidBody*>::iterator itRigidBodies;
for (itRigidBodies = mRigidBodies.begin(); itRigidBodies != mRigidBodies.end();) {
std::set<RigidBody*>::iterator itToRemove = itRigidBodies;
++itRigidBodies;
destroyRigidBody(*itToRemove);
}
// Release the memory allocated for the islands // Release the memory allocated for the islands
for (uint i=0; i<mNbIslands; i++) { for (uint i=0; i<mNbIslands; i++) {
@ -83,6 +98,9 @@ DynamicsWorld::~DynamicsWorld() {
delete[] mConstrainedOrientations; delete[] mConstrainedOrientations;
} }
assert(mJoints.size() == 0);
assert(mRigidBodies.size() == 0);
#ifdef IS_PROFILING_ACTIVE #ifdef IS_PROFILING_ACTIVE
// Print the profiling report // Print the profiling report
@ -95,7 +113,10 @@ DynamicsWorld::~DynamicsWorld() {
} }
// Update the physics simulation // Update the physics simulation
void DynamicsWorld::update() { /**
* @param timeStep The amount of time to step the simulation by (in seconds)
*/
void DynamicsWorld::update(decimal timeStep) {
#ifdef IS_PROFILING_ACTIVE #ifdef IS_PROFILING_ACTIVE
// Increment the frame counter of the profiler // Increment the frame counter of the profiler
@ -104,55 +125,42 @@ void DynamicsWorld::update() {
PROFILE("DynamicsWorld::update()"); PROFILE("DynamicsWorld::update()");
assert(mTimer.getIsRunning()); mTimeStep = timeStep;
// Compute the time since the last update() call and update the timer
mTimer.update();
// While the time accumulator is not empty // Notify the event listener about the beginning of an internal tick
while(mTimer.isPossibleToTakeStep()) { if (mEventListener != NULL) mEventListener->beginInternalTick();
// Notify the event listener about the beginning of an internal tick // Reset all the contact manifolds lists of each body
if (mEventListener != NULL) mEventListener->beginInternalTick(); resetContactManifoldListsOfBodies();
// Reset all the contact manifolds lists of each body // Compute the collision detection
resetContactManifoldListsOfBodies(); mCollisionDetection.computeCollisionDetection();
// Compute the collision detection
mCollisionDetection.computeCollisionDetection();
// Compute the islands (separate groups of bodies with constraints between each others) // Compute the islands (separate groups of bodies with constraints between each others)
computeIslands(); computeIslands();
// Integrate the velocities // Integrate the velocities
integrateRigidBodiesVelocities(); integrateRigidBodiesVelocities();
// Update the timer // Solve the contacts and constraints
mTimer.nextStep(); solveContactsAndConstraints();
// Solve the contacts and constraints // Integrate the position and orientation of each body
solveContactsAndConstraints(); integrateRigidBodiesPositions();
// Integrate the position and orientation of each body // Solve the position correction for constraints
integrateRigidBodiesPositions(); solvePositionCorrection();
// Solve the position correction for constraints // Update the state (positions and velocities) of the bodies
solvePositionCorrection(); updateBodiesState();
// Update the state (positions and velocities) of the bodies if (mIsSleepingEnabled) updateSleepingBodies();
updateBodiesState();
if (mIsSleepingEnabled) updateSleepingBodies(); // Notify the event listener about the end of an internal tick
if (mEventListener != NULL) mEventListener->endInternalTick();
// Notify the event listener about the end of an internal tick
if (mEventListener != NULL) mEventListener->endInternalTick();
}
// Reset the external force and torque applied to the bodies // Reset the external force and torque applied to the bodies
resetBodiesForceAndTorque(); resetBodiesForceAndTorque();
// Compute and set the interpolation factor to all the bodies
setInterpolationFactorToAllBodies();
} }
// Integrate position and orientation of the rigid bodies. // Integrate position and orientation of the rigid bodies.
@ -161,8 +169,6 @@ void DynamicsWorld::update() {
void DynamicsWorld::integrateRigidBodiesPositions() { void DynamicsWorld::integrateRigidBodiesPositions() {
PROFILE("DynamicsWorld::integrateRigidBodiesPositions()"); PROFILE("DynamicsWorld::integrateRigidBodiesPositions()");
decimal dt = static_cast<decimal>(mTimer.getTimeStep());
// For each island of the world // For each island of the world
for (uint i=0; i < mNbIslands; i++) { for (uint i=0; i < mNbIslands; i++) {
@ -190,10 +196,10 @@ void DynamicsWorld::integrateRigidBodiesPositions() {
const Quaternion& currentOrientation = bodies[b]->getTransform().getOrientation(); const Quaternion& currentOrientation = bodies[b]->getTransform().getOrientation();
// Update the new constrained position and orientation of the body // Update the new constrained position and orientation of the body
mConstrainedPositions[indexArray] = currentPosition + newLinVelocity * dt; mConstrainedPositions[indexArray] = currentPosition + newLinVelocity * mTimeStep;
mConstrainedOrientations[indexArray] = currentOrientation + mConstrainedOrientations[indexArray] = currentOrientation +
Quaternion(0, newAngVelocity) * Quaternion(0, newAngVelocity) *
currentOrientation * decimal(0.5) * dt; currentOrientation * decimal(0.5) * mTimeStep;
} }
} }
} }
@ -232,23 +238,6 @@ void DynamicsWorld::updateBodiesState() {
} }
} }
// Compute and set the interpolation factor to all bodies
void DynamicsWorld::setInterpolationFactorToAllBodies() {
PROFILE("DynamicsWorld::setInterpolationFactorToAllBodies()");
// Compute the interpolation factor
decimal factor = mTimer.computeInterpolationFactor();
assert(factor >= 0.0 && factor <= 1.0);
// Set the factor to all bodies
set<RigidBody*>::iterator it;
for (it = mRigidBodies.begin(); it != mRigidBodies.end(); ++it) {
(*it)->setInterpolationFactor(factor);
}
}
// Initialize the bodies velocities arrays for the next simulation step. // Initialize the bodies velocities arrays for the next simulation step.
void DynamicsWorld::initVelocityArrays() { void DynamicsWorld::initVelocityArrays() {
@ -305,8 +294,6 @@ void DynamicsWorld::integrateRigidBodiesVelocities() {
// Initialize the bodies velocity arrays // Initialize the bodies velocity arrays
initVelocityArrays(); initVelocityArrays();
decimal dt = static_cast<decimal>(mTimer.getTimeStep());
// For each island of the world // For each island of the world
for (uint i=0; i < mNbIslands; i++) { for (uint i=0; i < mNbIslands; i++) {
@ -323,16 +310,16 @@ void DynamicsWorld::integrateRigidBodiesVelocities() {
// Integrate the external force to get the new velocity of the body // Integrate the external force to get the new velocity of the body
mConstrainedLinearVelocities[indexBody] = bodies[b]->getLinearVelocity() + mConstrainedLinearVelocities[indexBody] = bodies[b]->getLinearVelocity() +
dt * bodies[b]->mMassInverse * bodies[b]->mExternalForce; mTimeStep * bodies[b]->mMassInverse * bodies[b]->mExternalForce;
mConstrainedAngularVelocities[indexBody] = bodies[b]->getAngularVelocity() + mConstrainedAngularVelocities[indexBody] = bodies[b]->getAngularVelocity() +
dt * bodies[b]->getInertiaTensorInverseWorld() * mTimeStep * bodies[b]->getInertiaTensorInverseWorld() *
bodies[b]->mExternalTorque; bodies[b]->mExternalTorque;
// If the gravity has to be applied to this rigid body // If the gravity has to be applied to this rigid body
if (bodies[b]->isGravityEnabled() && mIsGravityEnabled) { if (bodies[b]->isGravityEnabled() && mIsGravityEnabled) {
// Integrate the gravity force // Integrate the gravity force
mConstrainedLinearVelocities[indexBody] += dt * bodies[b]->mMassInverse * mConstrainedLinearVelocities[indexBody] += mTimeStep * bodies[b]->mMassInverse *
bodies[b]->getMass() * mGravity; bodies[b]->getMass() * mGravity;
} }
@ -351,18 +338,15 @@ void DynamicsWorld::integrateRigidBodiesVelocities() {
// => v2 = v1 * (1 - c * dt) // => v2 = v1 * (1 - c * dt)
decimal linDampingFactor = bodies[b]->getLinearDamping(); decimal linDampingFactor = bodies[b]->getLinearDamping();
decimal angDampingFactor = bodies[b]->getAngularDamping(); decimal angDampingFactor = bodies[b]->getAngularDamping();
decimal linearDamping = clamp(decimal(1.0) - dt * linDampingFactor, decimal linearDamping = clamp(decimal(1.0) - mTimeStep * linDampingFactor,
decimal(0.0), decimal(1.0)); decimal(0.0), decimal(1.0));
decimal angularDamping = clamp(decimal(1.0) - dt * angDampingFactor, decimal angularDamping = clamp(decimal(1.0) - mTimeStep * angDampingFactor,
decimal(0.0), decimal(1.0)); decimal(0.0), decimal(1.0));
mConstrainedLinearVelocities[indexBody] *= clamp(linearDamping, decimal(0.0), mConstrainedLinearVelocities[indexBody] *= clamp(linearDamping, decimal(0.0),
decimal(1.0)); decimal(1.0));
mConstrainedAngularVelocities[indexBody] *= clamp(angularDamping, decimal(0.0), mConstrainedAngularVelocities[indexBody] *= clamp(angularDamping, decimal(0.0),
decimal(1.0)); decimal(1.0));
// Update the old Transform of the body
bodies[b]->updateOldTransform();
indexBody++; indexBody++;
} }
} }
@ -373,9 +357,6 @@ void DynamicsWorld::solveContactsAndConstraints() {
PROFILE("DynamicsWorld::solveContactsAndConstraints()"); PROFILE("DynamicsWorld::solveContactsAndConstraints()");
// Get the current time step
decimal dt = static_cast<decimal>(mTimer.getTimeStep());
// Set the velocities arrays // Set the velocities arrays
mContactSolver.setSplitVelocitiesArrays(mSplitLinearVelocities, mSplitAngularVelocities); mContactSolver.setSplitVelocitiesArrays(mSplitLinearVelocities, mSplitAngularVelocities);
mContactSolver.setConstrainedVelocitiesArrays(mConstrainedLinearVelocities, mContactSolver.setConstrainedVelocitiesArrays(mConstrainedLinearVelocities,
@ -399,7 +380,7 @@ void DynamicsWorld::solveContactsAndConstraints() {
if (isContactsToSolve) { if (isContactsToSolve) {
// Initialize the solver // Initialize the solver
mContactSolver.initializeForIsland(dt, mIslands[islandIndex]); mContactSolver.initializeForIsland(mTimeStep, mIslands[islandIndex]);
// Warm start the contact solver // Warm start the contact solver
mContactSolver.warmStart(); mContactSolver.warmStart();
@ -409,7 +390,7 @@ void DynamicsWorld::solveContactsAndConstraints() {
if (isConstraintsToSolve) { if (isConstraintsToSolve) {
// Initialize the constraint solver // Initialize the constraint solver
mConstraintSolver.initializeForIsland(dt, mIslands[islandIndex]); mConstraintSolver.initializeForIsland(mTimeStep, mIslands[islandIndex]);
} }
// For each iteration of the velocity solver // For each iteration of the velocity solver
@ -811,7 +792,6 @@ void DynamicsWorld::updateSleepingBodies() {
PROFILE("DynamicsWorld::updateSleepingBodies()"); PROFILE("DynamicsWorld::updateSleepingBodies()");
const decimal dt = static_cast<decimal>(mTimer.getTimeStep());
const decimal sleepLinearVelocitySquare = mSleepLinearVelocity * mSleepLinearVelocity; const decimal sleepLinearVelocitySquare = mSleepLinearVelocity * mSleepLinearVelocity;
const decimal sleepAngularVelocitySquare = mSleepAngularVelocity * mSleepAngularVelocity; const decimal sleepAngularVelocitySquare = mSleepAngularVelocity * mSleepAngularVelocity;
@ -839,7 +819,7 @@ void DynamicsWorld::updateSleepingBodies() {
else { // If the body velocity is bellow the sleeping velocity threshold else { // If the body velocity is bellow the sleeping velocity threshold
// Increase the sleep time // Increase the sleep time
bodies[b]->mSleepTime += dt; bodies[b]->mSleepTime += mTimeStep;
if (bodies[b]->mSleepTime < minSleepTime) { if (bodies[b]->mSleepTime < minSleepTime) {
minSleepTime = bodies[b]->mSleepTime; minSleepTime = bodies[b]->mSleepTime;
} }
@ -991,3 +971,23 @@ void DynamicsWorld::testCollision(CollisionCallback* callback) {
// Perform the collision detection and report contacts // Perform the collision detection and report contacts
mCollisionDetection.reportCollisionBetweenShapes(callback, emptySet, emptySet); 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

@ -32,7 +32,6 @@
#include "ContactSolver.h" #include "ContactSolver.h"
#include "ConstraintSolver.h" #include "ConstraintSolver.h"
#include "body/RigidBody.h" #include "body/RigidBody.h"
#include "Timer.h"
#include "Island.h" #include "Island.h"
#include "configuration.h" #include "configuration.h"
@ -51,9 +50,6 @@ class DynamicsWorld : public CollisionWorld {
// -------------------- Attributes -------------------- // // -------------------- Attributes -------------------- //
/// Timer of the physics engine
Timer mTimer;
/// Contact solver /// Contact solver
ContactSolver mContactSolver; ContactSolver mContactSolver;
@ -78,6 +74,9 @@ class DynamicsWorld : public CollisionWorld {
/// Gravity vector of the world /// Gravity vector of the world
Vector3 mGravity; Vector3 mGravity;
/// Current frame time step (in seconds)
decimal mTimeStep;
/// True if the gravity force is on /// True if the gravity force is on
bool mIsGravityEnabled; bool mIsGravityEnabled;
@ -182,23 +181,23 @@ class DynamicsWorld : public CollisionWorld {
// -------------------- Methods -------------------- // // -------------------- Methods -------------------- //
/// Constructor /// Constructor
DynamicsWorld(const Vector3& mGravity, decimal timeStep); DynamicsWorld(const Vector3& mGravity);
/// Destructor /// Destructor
virtual ~DynamicsWorld(); virtual ~DynamicsWorld();
/// Start the physics simulation
void start();
/// Stop the physics simulation
void stop();
/// Update the physics simulation /// Update the physics simulation
void update(); 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 /// Set the number of iterations for the velocity constraint solver
void setNbIterationsVelocitySolver(uint nbIterations); 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 /// Set the number of iterations for the position constraint solver
void setNbIterationsPositionSolver(uint nbIterations); void setNbIterationsPositionSolver(uint nbIterations);
@ -227,6 +226,9 @@ class DynamicsWorld : public CollisionWorld {
/// Return the gravity vector of the world /// Return the gravity vector of the world
Vector3 getGravity() const; Vector3 getGravity() const;
/// Set the gravity vector of the world
void setGravity(Vector3& gravity);
/// Return if the gravity is on /// Return if the gravity is on
bool isGravityEnabled() const; bool isGravityEnabled() const;
@ -239,9 +241,6 @@ class DynamicsWorld : public CollisionWorld {
/// Return the number of joints in the world /// Return the number of joints in the world
uint getNbJoints() const; 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 /// Return an iterator to the beginning of the rigid bodies of the physics world
std::set<RigidBody*>::iterator getRigidBodiesBeginIterator(); std::set<RigidBody*>::iterator getRigidBodiesBeginIterator();
@ -298,6 +297,9 @@ class DynamicsWorld : public CollisionWorld {
/// Test and report collisions between all shapes of the world /// Test and report collisions between all shapes of the world
virtual void testCollision(CollisionCallback* callback); virtual void testCollision(CollisionCallback* callback);
/// Return the list of all contacts of the world
std::vector<const ContactManifold*> getContactsList() const;
// -------------------- Friendship -------------------- // // -------------------- Friendship -------------------- //
friend class RigidBody; friend class RigidBody;
@ -314,15 +316,11 @@ inline void DynamicsWorld::resetBodiesForceAndTorque() {
} }
} }
// Start the physics simulation // Get the number of iterations for the velocity constraint solver
inline void DynamicsWorld::start() { inline uint DynamicsWorld::getNbIterationsVelocitySolver() const {
mTimer.start(); return mNbVelocitySolverIterations;
} }
inline void DynamicsWorld::stop() {
mTimer.stop();
}
// Set the number of iterations for the velocity constraint solver // Set the number of iterations for the velocity constraint solver
/** /**
* @param nbIterations Number of iterations for the velocity solver * @param nbIterations Number of iterations for the velocity solver
@ -331,6 +329,11 @@ inline void DynamicsWorld::setNbIterationsVelocitySolver(uint nbIterations) {
mNbVelocitySolverIterations = 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 // Set the number of iterations for the position constraint solver
/** /**
* @param nbIterations Number of iterations for the position solver * @param nbIterations Number of iterations for the position solver
@ -385,6 +388,14 @@ inline Vector3 DynamicsWorld::getGravity() const {
return mGravity; 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 if the gravity is enaled
/** /**
* @return True if the gravity is enabled in the world * @return True if the gravity is enabled in the world
@ -434,14 +445,6 @@ inline std::set<RigidBody*>::iterator DynamicsWorld::getRigidBodiesEndIterator()
return mRigidBodies.end(); return mRigidBodies.end();
} }
// Return the current physics time (in seconds)
/**
* @return The current physics time (in seconds)
*/
inline long double DynamicsWorld::getPhysicsTime() const {
return mTimer.getPhysicsTime();
}
// Return true if the sleeping technique is enabled // Return true if the sleeping technique is enabled
/** /**
* @return True if the sleeping technique is enabled and false otherwise * @return True if the sleeping technique is enabled and false otherwise

View File

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

View File

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

View File

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

View File

@ -193,7 +193,9 @@ inline Vector3 Vector3::cross(const Vector3& vector) const {
// Normalize the vector // Normalize the vector
inline void Vector3::normalize() { inline void Vector3::normalize() {
decimal l = length(); decimal l = length();
assert(l > std::numeric_limits<decimal>::epsilon()); if (l < MACHINE_EPSILON) {
return;
}
x /= l; x /= l;
y /= l; y /= l;
z /= 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(${GLEW_INCLUDE_PATH} "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 // Initialize static variables
openglframework::VertexBufferObject Box::mVBOVertices(GL_ARRAY_BUFFER); openglframework::VertexBufferObject Box::mVBOVertices(GL_ARRAY_BUFFER);
openglframework::VertexBufferObject Box::mVBOIndices(GL_ELEMENT_ARRAY_BUFFER); openglframework::VertexBufferObject Box::mVBONormals(GL_ARRAY_BUFFER);
bool Box::areVBOsCreated = false; openglframework::VertexArrayObject Box::mVAO;
VertexData Box::mCubeVertices[8] = { int Box::totalNbBoxes = 0;
{openglframework::Vector3(1,1,1),openglframework::Vector3(1,1,1),openglframework::Color(1,0,0,1)}, GLfloat Box::mCubeVertices[108] = {
{openglframework::Vector3(-1,1,1),openglframework::Vector3(-1,1,1),openglframework::Color(1,0,0,1)}, -1.0f,-1.0f,-1.0f, // triangle 1 : begin
{openglframework::Vector3(-1,-1,1),openglframework::Vector3(-1,-1,1),openglframework::Color(1,0,0,1)}, -1.0f,-1.0f, 1.0f,
{openglframework::Vector3(1,-1,1),openglframework::Vector3(1,-1,1),openglframework::Color(1,0,0,1)}, -1.0f, 1.0f, 1.0f, // triangle 1 : end
{openglframework::Vector3(1,-1,-1),openglframework::Vector3(1,-1,-1),openglframework::Color(1,0,0,1)}, 1.0f, 1.0f,-1.0f, // triangle 2 : begin
{openglframework::Vector3(-1,-1,-1),openglframework::Vector3(-1,-1,-1),openglframework::Color(1,0,0,1)}, -1.0f,-1.0f,-1.0f,
{openglframework::Vector3(-1,1,-1),openglframework::Vector3(-1,1,-1),openglframework::Color(1,0,0,1)}, -1.0f, 1.0f,-1.0f, // triangle 2 : end
{openglframework::Vector3(1,1,-1),openglframework::Vector3(1,1,-1),openglframework::Color(1,0,0,1)} 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 // Constructor
Box::Box(const openglframework::Vector3& size, const openglframework::Vector3 &position, Box::Box(const openglframework::Vector3& size, const openglframework::Vector3 &position,
reactphysics3d::CollisionWorld* world) reactphysics3d::CollisionWorld* world)
: openglframework::Object3D(), mColor(0.5f, 0.5f, 0.5f, 1.0f) { : openglframework::Object3D() {
// Initialize the size of the box // Initialize the size of the box
mSize[0] = size.x * 0.5f; 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::Quaternion initOrientation = rp3d::Quaternion::identity();
rp3d::Transform transform(initPosition, initOrientation); rp3d::Transform transform(initPosition, initOrientation);
mPreviousTransform = transform;
// Create a rigid body in the dynamics world // Create a rigid body in the dynamics world
mRigidBody = world->createCollisionBody(transform); mBody = world->createCollisionBody(transform);
// Add the collision shape to the body // 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 the Vertex Buffer object has not been created yet
if (!areVBOsCreated) { if (totalNbBoxes == 0) {
// Create the Vertex Buffer // Create the Vertex Buffer
createVBO(); createVBOAndVAO();
} }
totalNbBoxes++;
mTransformMatrix = mTransformMatrix * mScalingMatrix; mTransformMatrix = mTransformMatrix * mScalingMatrix;
} }
// Constructor // 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) float mass, reactphysics3d::DynamicsWorld* world)
: openglframework::Object3D(), mColor(0.5f, 0.5f, 0.5f, 1.0f) { : openglframework::Object3D() {
// Initialize the size of the box // Initialize the size of the box
mSize[0] = size.x * 0.5f; 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::Quaternion initOrientation = rp3d::Quaternion::identity();
rp3d::Transform transform(initPosition, initOrientation); rp3d::Transform transform(initPosition, initOrientation);
mPreviousTransform = transform;
// Create a rigid body in the dynamics world // Create a rigid body in the dynamics world
rp3d::RigidBody* body = world->createRigidBody(transform); rp3d::RigidBody* body = world->createRigidBody(transform);
// Add the collision shape to the body // Add the collision shape to the body
body->addCollisionShape(collisionShape, rp3d::Transform::identity(), mass); body->addCollisionShape(collisionShape, rp3d::Transform::identity(), mass);
mRigidBody = body; mBody = body;
// If the Vertex Buffer object has not been created yet // If the Vertex Buffer object has not been created yet
if (!areVBOsCreated) { if (totalNbBoxes == 0) {
// Create the Vertex Buffer // Create the Vertex Buffer
createVBO(); createVBOAndVAO();
} }
totalNbBoxes++;
mTransformMatrix = mTransformMatrix * mScalingMatrix; mTransformMatrix = mTransformMatrix * mScalingMatrix;
} }
// Destructor // Destructor
Box::~Box() { 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 // Render the cube at the correct position and with the correct orientation
void Box::render(openglframework::Shader& shader, void Box::render(openglframework::Shader& shader,
const openglframework::Matrix4& worldToCameraMatrix) { const openglframework::Matrix4& worldToCameraMatrix) {
// Bind the VAO
mVAO.bind();
// Bind the shader // Bind the shader
shader.bind(); shader.bind();
mVBOVertices.bind();
// Set the model to camera matrix // Set the model to camera matrix
const openglframework::Matrix4 localToCameraMatrix = worldToCameraMatrix * mTransformMatrix; shader.setMatrix4x4Uniform("localToWorldMatrix", mTransformMatrix);
shader.setMatrix4x4Uniform("localToCameraMatrix", localToCameraMatrix); shader.setMatrix4x4Uniform("worldToCameraMatrix", worldToCameraMatrix);
// Set the normal matrix (inverse transpose of the 3x3 upper-left sub matrix of the // Set the normal matrix (inverse transpose of the 3x3 upper-left sub matrix of the
// model-view matrix) // model-view matrix)
const openglframework::Matrix4 localToCameraMatrix = worldToCameraMatrix * mTransformMatrix;
const openglframework::Matrix3 normalMatrix = const openglframework::Matrix3 normalMatrix =
localToCameraMatrix.getUpperLeft3x3Matrix().getInverse().getTranspose(); localToCameraMatrix.getUpperLeft3x3Matrix().getInverse().getTranspose();
shader.setMatrix3x3Uniform("normalMatrix", normalMatrix); shader.setMatrix3x3Uniform("normalMatrix", normalMatrix, false);
// Set the vertex color // Set the vertex color
openglframework::Vector4 color(mColor.r, mColor.g, mColor.b, mColor.a); openglframework::Color currentColor = mBody->isSleeping() ? mSleepingColor : mColor;
shader.setVector4Uniform("vertexColor", color); openglframework::Vector4 color(currentColor.r, currentColor.g, currentColor.b, currentColor.a);
shader.setVector4Uniform("vertexColor", color, false);
// Bind the vertices VBO // Get the location of shader attribute variables
mVBOVertices.bind(); GLint vertexPositionLoc = shader.getAttribLocation("vertexPosition");
GLint vertexNormalLoc = shader.getAttribLocation("vertexNormal", false);
// Enable the vertex, normal and color arrays glEnableVertexAttribArray(vertexPositionLoc);
glEnableClientState(GL_VERTEX_ARRAY); glVertexAttribPointer(vertexPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, NULL);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
// Set the arrays pointers mVBONormals.bind();
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));
// Bind the indices VBO if (vertexNormalLoc != -1) glEnableVertexAttribArray(vertexNormalLoc);
mVBOIndices.bind(); if (vertexNormalLoc != -1) glVertexAttribPointer(vertexNormalLoc, 3, GL_FLOAT, GL_FALSE, 0, NULL);
// Draw the geometry of the box // 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(); mVBOVertices.unbind();
mVBOIndices.unbind();
// Disable the arrays // Unbind the VAO
glDisableClientState(GL_VERTEX_ARRAY); mVAO.unbind();
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
// Unbind the shader // Unbind the shader
shader.unbind(); 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. // Create the Vertex Buffer Objects used to render to box with OpenGL.
/// We create two VBOs (one for vertices and one for indices) to render all the boxes /// We create two VBOs (one for vertices and one for indices) to render all the boxes
/// in the simulation. /// in the simulation.
void Box::createVBO() { void Box::createVBOAndVAO() {
// Create the VBOs // Create the VBO for the vertices data
mVBOVertices.create(); mVBOVertices.create();
mVBOIndices.create(); mVBOVertices.bind();
// Copy the data into the VBOs
mVBOVertices.copyDataIntoVBO(sizeof(mCubeVertices), mCubeVertices, GL_STATIC_DRAW); 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 // Libraries
#include "openglframework.h" #include "openglframework.h"
#include "reactphysics3d.h" #include "reactphysics3d.h"
#include "PhysicsObject.h"
// Structure VertexData
struct VertexData {
/// Vertex position
openglframework::Vector3 position;
/// Vertex normal
openglframework::Vector3 normal;
// Vertex color
openglframework::Color color;
};
// Class Box // Class Box
class Box : public openglframework::Object3D { class Box : public openglframework::Object3D, public PhysicsObject {
private : private :
@ -53,34 +41,31 @@ class Box : public openglframework::Object3D {
/// Size of each side of the box /// Size of each side of the box
float mSize[3]; 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) /// Scaling matrix (applied to a cube to obtain the correct box dimensions)
openglframework::Matrix4 mScalingMatrix; openglframework::Matrix4 mScalingMatrix;
/// Vertex Buffer Object for the vertices data used to render the box with OpenGL /// Vertex Buffer Object for the vertices data used to render the box with OpenGL
static openglframework::VertexBufferObject mVBOVertices; static openglframework::VertexBufferObject mVBOVertices;
/// Vertex Buffer Object for the indices used to render the box with OpenGL /// Vertex Buffer Object for the normales used to render the box with OpenGL
static openglframework::VertexBufferObject mVBOIndices; static openglframework::VertexBufferObject mVBONormals;
/// Vertex data for each vertex of the cube (used to render the box) /// Vertex Array Object for the vertex data
static VertexData mCubeVertices[8]; static openglframework::VertexArrayObject mVAO;
/// Indices of the cube (used to render the box) /// Vertices coordinates of the triangles of the box
static GLuint mCubeIndices[36]; static GLfloat mCubeVertices[108];
/// True if the VBOs have already been created /// Vertices normals of the triangles of the box
static bool areVBOsCreated; static GLfloat mCubeNormals[108];
/// Main color of the box /// Total number of boxes created
openglframework::Color mColor; static int totalNbBoxes;
// -------------------- Methods -------------------- // // -------------------- Methods -------------------- //
/// Create a Vertex Buffer Object to render to box with OpenGL /// Create a the VAO and VBOs to render to box with OpenGL
static void createVBO(); static void createVBOAndVAO();
public : public :
@ -97,35 +82,26 @@ class Box : public openglframework::Object3D {
/// Destructor /// Destructor
~Box(); ~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 /// Render the cube at the correct position and with the correct orientation
void render(openglframework::Shader& shader, const openglframework::Matrix4& worldToCameraMatrix); void render(openglframework::Shader& shader, const openglframework::Matrix4& worldToCameraMatrix);
/// Set the color of the box /// Set the position of the box
void setColor(const openglframework::Color& color); 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 <<<<<<< HEAD:examples/common/Box.h
inline rp3d::CollisionBody* Box::getCollisionBody() {
return mRigidBody;
}
// Return a pointer to the rigid body of the box // Return a pointer to the rigid body of the box
inline rp3d::RigidBody* Box::getRigidBody() { inline rp3d::RigidBody* Box::getRigidBody() {
return static_cast<rp3d::RigidBody*>(mRigidBody); return static_cast<rp3d::RigidBody*>(mRigidBody);
=======
// Update the transform matrix of the object
inline void Box::updateTransform(float interpolationFactor) {
mTransformMatrix = computeTransform(interpolationFactor, mScalingMatrix);
>>>>>>> 1bde11f245806de07a12b1cf6c33cdb83046b882:testbed/common/Box.h
} }
// Set the color of the box
inline void Box::setColor(const openglframework::Color& color) {
mColor = color;
}
#endif #endif

View File

@ -26,6 +26,13 @@
// Libraries // Libraries
#include "Capsule.h" #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 // Constructor
Capsule::Capsule(float radius, float height, const openglframework::Vector3& position, Capsule::Capsule(float radius, float height, const openglframework::Vector3& position,
reactphysics3d::CollisionWorld* world, reactphysics3d::CollisionWorld* world,
@ -57,13 +64,22 @@ Capsule::Capsule(float radius, float height, const openglframework::Vector3& pos
rp3d::Quaternion initOrientation = rp3d::Quaternion::identity(); rp3d::Quaternion initOrientation = rp3d::Quaternion::identity();
rp3d::Transform transform(initPosition, initOrientation); rp3d::Transform transform(initPosition, initOrientation);
mPreviousTransform = transform;
// Create a rigid body corresponding in the dynamics world // 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 // 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; mTransformMatrix = mTransformMatrix * mScalingMatrix;
// Create the VBOs and VAO
if (totalNbCapsules == 0) {
createVBOAndVAO();
}
totalNbCapsules++;
} }
// Constructor // 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 // Add a collision shape to the body and specify the mass of the shape
body->addCollisionShape(collisionShape, rp3d::Transform::identity(), mass); body->addCollisionShape(collisionShape, rp3d::Transform::identity(), mass);
mRigidBody = body; mBody = body;
mTransformMatrix = mTransformMatrix * mScalingMatrix; mTransformMatrix = mTransformMatrix * mScalingMatrix;
// Create the VBOs and VAO
if (totalNbCapsules == 0) {
createVBOAndVAO();
}
totalNbCapsules++;
} }
// Destructor // Destructor
Capsule::~Capsule() { Capsule::~Capsule() {
// Destroy the mesh if (totalNbCapsules == 1) {
destroy();
// Destroy the mesh
destroy();
// Destroy the VBOs and VAO
mVBOIndices.destroy();
mVBOVertices.destroy();
mVBONormals.destroy();
mVBOTextureCoords.destroy();
mVAO.destroy();
}
totalNbCapsules--;
} }
// Render the sphere at the correct position and with the correct orientation // Render the sphere at the correct position and with the correct orientation
@ -123,57 +158,126 @@ void Capsule::render(openglframework::Shader& shader,
shader.bind(); shader.bind();
// Set the model to camera matrix // Set the model to camera matrix
const openglframework::Matrix4 localToCameraMatrix = worldToCameraMatrix * mTransformMatrix; shader.setMatrix4x4Uniform("localToWorldMatrix", mTransformMatrix);
shader.setMatrix4x4Uniform("localToCameraMatrix", localToCameraMatrix); shader.setMatrix4x4Uniform("worldToCameraMatrix", worldToCameraMatrix);
// Set the normal matrix (inverse transpose of the 3x3 upper-left sub matrix of the // Set the normal matrix (inverse transpose of the 3x3 upper-left sub matrix of the
// model-view matrix) // model-view matrix)
const openglframework::Matrix4 localToCameraMatrix = worldToCameraMatrix * mTransformMatrix;
const openglframework::Matrix3 normalMatrix = const openglframework::Matrix3 normalMatrix =
localToCameraMatrix.getUpperLeft3x3Matrix().getInverse().getTranspose(); localToCameraMatrix.getUpperLeft3x3Matrix().getInverse().getTranspose();
shader.setMatrix3x3Uniform("normalMatrix", normalMatrix); shader.setMatrix3x3Uniform("normalMatrix", normalMatrix, false);
glEnableClientState(GL_VERTEX_ARRAY); // Set the vertex color
glEnableClientState(GL_NORMAL_ARRAY); openglframework::Color currentColor = mBody->isSleeping() ? mSleepingColor : mColor;
if (hasTexture()) { openglframework::Vector4 color(currentColor.r, currentColor.g, currentColor.b, currentColor.a);
glEnableClientState(GL_TEXTURE_COORD_ARRAY); shader.setVector4Uniform("vertexColor", color, false);
}
glVertexPointer(3, GL_FLOAT, 0, getVerticesPointer()); // Bind the VAO
glNormalPointer(GL_FLOAT, 0, getNormalsPointer()); mVAO.bind();
if(hasTexture()) {
glTexCoordPointer(2, GL_FLOAT, 0, getUVTextureCoordinatesPointer()); 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 each part of the mesh
for (unsigned int i=0; i<getNbParts(); i++) { for (unsigned int i=0; i<getNbParts(); i++) {
glDrawElements(GL_TRIANGLES, getNbFaces(i) * 3, glDrawElements(GL_TRIANGLES, getNbFaces(i) * 3, GL_UNSIGNED_INT, (char*)NULL);
GL_UNSIGNED_INT, getIndicesPointer());
} }
glDisableClientState(GL_NORMAL_ARRAY); glDisableVertexAttribArray(vertexPositionLoc);
glDisableClientState(GL_VERTEX_ARRAY); if (vertexNormalLoc != -1) glDisableVertexAttribArray(vertexNormalLoc);
if (hasTexture()) {
glDisableClientState(GL_TEXTURE_COORD_ARRAY); mVBONormals.unbind();
} mVBOVertices.unbind();
// Unbind the VAO
mVAO.unbind();
// Unbind the shader // Unbind the shader
shader.unbind(); shader.unbind();
} }
// Update the transform matrix of the sphere // Create the Vertex Buffer Objects used to render with OpenGL.
void Capsule::updateTransform() { /// We create two VBOs (one for vertices and one for indices)
void Capsule::createVBOAndVAO() {
// Get the interpolated transform of the rigid body // Create the VBO for the vertices data
rp3d::Transform transform = mRigidBody->getInterpolatedTransform(); 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 // Create the VBO for the normals data
rp3d::decimal matrix[16]; mVBONormals.create();
transform.getOpenGLMatrix(matrix); mVBONormals.bind();
openglframework::Matrix4 newMatrix(matrix[0], matrix[4], matrix[8], matrix[12], size_t sizeNormals = mNormals.size() * sizeof(openglframework::Vector3);
matrix[1], matrix[5], matrix[9], matrix[13], mVBONormals.copyDataIntoVBO(sizeNormals, getNormalsPointer(), GL_STATIC_DRAW);
matrix[2], matrix[6], matrix[10], matrix[14], mVBONormals.unbind();
matrix[3], matrix[7], matrix[11], matrix[15]);
// Apply the scaling matrix to have the correct sphere dimensions if (hasTexture()) {
mTransformMatrix = newMatrix * mScalingMatrix; // 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 // Libraries
#include "openglframework.h" #include "openglframework.h"
#include "reactphysics3d.h" #include "reactphysics3d.h"
#include "PhysicsObject.h"
// Class Sphere // Class Sphere
class Capsule : public openglframework::Mesh { class Capsule : public openglframework::Mesh, public PhysicsObject {
private : private :
@ -43,14 +44,35 @@ class Capsule : public openglframework::Mesh {
/// Height of the capsule /// Height of the capsule
float mHeight; 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) /// Scaling matrix (applied to a sphere to obtain the correct sphere dimensions)
openglframework::Matrix4 mScalingMatrix; 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 -------------------- // // -------------------- Methods -------------------- //
// Create the Vertex Buffer Objects used to render with OpenGL.
void createVBOAndVAO();
public : public :
// -------------------- Methods -------------------- // // -------------------- Methods -------------------- //
@ -67,28 +89,26 @@ class Capsule : public openglframework::Mesh {
/// Destructor /// Destructor
~Capsule(); ~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 /// Render the sphere at the correct position and with the correct orientation
void render(openglframework::Shader& shader, void render(openglframework::Shader& shader,
const openglframework::Matrix4& worldToCameraMatrix); 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 <<<<<<< HEAD:examples/common/Capsule.h
inline rp3d::CollisionBody* Capsule::getCollisionBody() {
return mRigidBody;
}
// Return a pointer to the rigid body of the box // Return a pointer to the rigid body of the box
inline rp3d::RigidBody* Capsule::getRigidBody() { inline rp3d::RigidBody* Capsule::getRigidBody() {
return static_cast<rp3d::RigidBody*>(mRigidBody); return static_cast<rp3d::RigidBody*>(mRigidBody);
=======
// Update the transform matrix of the object
inline void Capsule::updateTransform(float interpolationFactor) {
mTransformMatrix = computeTransform(interpolationFactor, mScalingMatrix);
>>>>>>> 1bde11f245806de07a12b1cf6c33cdb83046b882:testbed/common/Capsule.h
} }
#endif #endif

View File

@ -26,6 +26,13 @@
// Libraries // Libraries
#include "Cone.h" #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 // Constructor
Cone::Cone(float radius, float height, const openglframework::Vector3 &position, Cone::Cone(float radius, float height, const openglframework::Vector3 &position,
reactphysics3d::CollisionWorld* world, reactphysics3d::CollisionWorld* world,
@ -57,13 +64,22 @@ Cone::Cone(float radius, float height, const openglframework::Vector3 &position,
rp3d::Quaternion initOrientation = rp3d::Quaternion::identity(); rp3d::Quaternion initOrientation = rp3d::Quaternion::identity();
rp3d::Transform transform(initPosition, initOrientation); rp3d::Transform transform(initPosition, initOrientation);
mPreviousTransform = transform;
// Create a rigid body corresponding to the cone in the dynamics world // 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 // 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; mTransformMatrix = mTransformMatrix * mScalingMatrix;
// Create the VBOs and VAO
if (totalNbCones == 0) {
createVBOAndVAO();
}
totalNbCones++;
} }
// Constructor // 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 // Add a collision shape to the body and specify the mass of the shape
body->addCollisionShape(collisionShape, rp3d::Transform::identity(), mass); body->addCollisionShape(collisionShape, rp3d::Transform::identity(), mass);
mRigidBody = body; mBody = body;
mTransformMatrix = mTransformMatrix * mScalingMatrix; mTransformMatrix = mTransformMatrix * mScalingMatrix;
// Create the VBOs and VAO
if (totalNbCones == 0) {
createVBOAndVAO();
}
totalNbCones++;
} }
// Destructor // Destructor
Cone::~Cone() { Cone::~Cone() {
// Destroy the mesh if (totalNbCones == 1) {
destroy(); // 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 // Render the cone at the correct position and with the correct orientation
@ -123,57 +157,126 @@ void Cone::render(openglframework::Shader& shader,
shader.bind(); shader.bind();
// Set the model to camera matrix // Set the model to camera matrix
const openglframework::Matrix4 localToCameraMatrix = worldToCameraMatrix * mTransformMatrix; shader.setMatrix4x4Uniform("localToWorldMatrix", mTransformMatrix);
shader.setMatrix4x4Uniform("localToCameraMatrix", localToCameraMatrix); shader.setMatrix4x4Uniform("worldToCameraMatrix", worldToCameraMatrix);
// Set the normal matrix (inverse transpose of the 3x3 upper-left sub matrix of the // Set the normal matrix (inverse transpose of the 3x3 upper-left sub matrix of the
// model-view matrix) // model-view matrix)
const openglframework::Matrix4 localToCameraMatrix = worldToCameraMatrix * mTransformMatrix;
const openglframework::Matrix3 normalMatrix = const openglframework::Matrix3 normalMatrix =
localToCameraMatrix.getUpperLeft3x3Matrix().getInverse().getTranspose(); localToCameraMatrix.getUpperLeft3x3Matrix().getInverse().getTranspose();
shader.setMatrix3x3Uniform("normalMatrix", normalMatrix); shader.setMatrix3x3Uniform("normalMatrix", normalMatrix, false);
glEnableClientState(GL_VERTEX_ARRAY); // Set the vertex color
glEnableClientState(GL_NORMAL_ARRAY); openglframework::Vector4 color(mColor.r, mColor.g, mColor.b, mColor.a);
if (hasTexture()) { shader.setVector4Uniform("vertexColor", color, false);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
}
glVertexPointer(3, GL_FLOAT, 0, getVerticesPointer()); // Bind the VAO
glNormalPointer(GL_FLOAT, 0, getNormalsPointer()); mVAO.bind();
if(hasTexture()) {
glTexCoordPointer(2, GL_FLOAT, 0, getUVTextureCoordinatesPointer()); 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 each part of the mesh
for (unsigned int i=0; i<getNbParts(); i++) { for (unsigned int i=0; i<getNbParts(); i++) {
glDrawElements(GL_TRIANGLES, getNbFaces(i) * 3, glDrawElements(GL_TRIANGLES, getNbFaces(i) * 3, GL_UNSIGNED_INT, (char*)NULL);
GL_UNSIGNED_INT, getIndicesPointer());
} }
glDisableClientState(GL_NORMAL_ARRAY); glDisableVertexAttribArray(vertexPositionLoc);
glDisableClientState(GL_VERTEX_ARRAY); if (vertexNormalLoc != -1) glDisableVertexAttribArray(vertexNormalLoc);
if (hasTexture()) {
glDisableClientState(GL_TEXTURE_COORD_ARRAY); mVBONormals.unbind();
} mVBOVertices.unbind();
// Unbind the VAO
mVAO.unbind();
// Unbind the shader // Unbind the shader
shader.unbind(); shader.unbind();
} }
// Update the transform matrix of the cone // Create the Vertex Buffer Objects used to render with OpenGL.
void Cone::updateTransform() { /// We create two VBOs (one for vertices and one for indices)
void Cone::createVBOAndVAO() {
// Get the interpolated transform of the rigid body // Create the VBO for the vertices data
rp3d::Transform transform = mRigidBody->getInterpolatedTransform(); 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 // Create the VBO for the normals data
rp3d::decimal matrix[16]; mVBONormals.create();
transform.getOpenGLMatrix(matrix); mVBONormals.bind();
openglframework::Matrix4 newMatrix(matrix[0], matrix[4], matrix[8], matrix[12], size_t sizeNormals = mNormals.size() * sizeof(openglframework::Vector3);
matrix[1], matrix[5], matrix[9], matrix[13], mVBONormals.copyDataIntoVBO(sizeNormals, getNormalsPointer(), GL_STATIC_DRAW);
matrix[2], matrix[6], matrix[10], matrix[14], mVBONormals.unbind();
matrix[3], matrix[7], matrix[11], matrix[15]);
// Apply the scaling matrix to have the correct cone dimensions if (hasTexture()) {
mTransformMatrix = newMatrix * mScalingMatrix; // 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(unsigned int);
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 // Libraries
#include "openglframework.h" #include "openglframework.h"
#include "reactphysics3d.h" #include "reactphysics3d.h"
#include "PhysicsObject.h"
// Class Cone // Class Cone
class Cone : public openglframework::Mesh { class Cone : public openglframework::Mesh, public PhysicsObject {
private : private :
@ -43,14 +44,35 @@ class Cone : public openglframework::Mesh {
/// Height of the cone /// Height of the cone
float mHeight; 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) /// Scaling matrix (applied to a sphere to obtain the correct cone dimensions)
openglframework::Matrix4 mScalingMatrix; 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 -------------------- // // -------------------- Methods -------------------- //
// Create the Vertex Buffer Objects used to render with OpenGL.
void createVBOAndVAO();
public : public :
// -------------------- Methods -------------------- // // -------------------- Methods -------------------- //
@ -66,28 +88,26 @@ class Cone : public openglframework::Mesh {
/// Destructor /// Destructor
~Cone(); ~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 /// Render the cone at the correct position and with the correct orientation
void render(openglframework::Shader& shader, void render(openglframework::Shader& shader,
const openglframework::Matrix4& worldToCameraMatrix); 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 <<<<<<< HEAD:examples/common/Cone.h
inline rp3d::CollisionBody* Cone::getCollisionBody() {
return mRigidBody;
}
// Return a pointer to the rigid body of the box // Return a pointer to the rigid body of the box
inline rp3d::RigidBody* Cone::getRigidBody() { inline rp3d::RigidBody* Cone::getRigidBody() {
return static_cast<rp3d::RigidBody*>(mRigidBody); return static_cast<rp3d::RigidBody*>(mRigidBody);
=======
// Update the transform matrix of the object
inline void Cone::updateTransform(float interpolationFactor) {
mTransformMatrix = computeTransform(interpolationFactor, mScalingMatrix);
>>>>>>> 1bde11f245806de07a12b1cf6c33cdb83046b882:testbed/common/Cone.h
} }
#endif #endif

View File

@ -30,7 +30,9 @@
ConvexMesh::ConvexMesh(const openglframework::Vector3 &position, ConvexMesh::ConvexMesh(const openglframework::Vector3 &position,
reactphysics3d::CollisionWorld* world, reactphysics3d::CollisionWorld* world,
const std::string& meshFolderPath) 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 // Load the mesh from a file
openglframework::MeshReaderWriter::loadMeshFromFile(meshFolderPath + "convexmesh.obj", *this); openglframework::MeshReaderWriter::loadMeshFromFile(meshFolderPath + "convexmesh.obj", *this);
@ -79,18 +81,25 @@ ConvexMesh::ConvexMesh(const openglframework::Vector3 &position,
rp3d::Quaternion initOrientation = rp3d::Quaternion::identity(); rp3d::Quaternion initOrientation = rp3d::Quaternion::identity();
rp3d::Transform transform(initPosition, initOrientation); rp3d::Transform transform(initPosition, initOrientation);
mPreviousTransform = transform;
// Create a rigid body corresponding to the sphere in the dynamics world // 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 // 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 // Constructor
ConvexMesh::ConvexMesh(const openglframework::Vector3 &position, float mass, ConvexMesh::ConvexMesh(const openglframework::Vector3 &position, float mass,
reactphysics3d::DynamicsWorld* dynamicsWorld, reactphysics3d::DynamicsWorld* dynamicsWorld,
const std::string& meshFolderPath) 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 // Load the mesh from a file
openglframework::MeshReaderWriter::loadMeshFromFile(meshFolderPath + "convexmesh.obj", *this); 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 // Add a collision shape to the body and specify the mass of the collision shape
body->addCollisionShape(collisionShape, rp3d::Transform::identity(), mass); body->addCollisionShape(collisionShape, rp3d::Transform::identity(), mass);
mRigidBody = body; mBody = body;
// Create the VBOs and VAO
createVBOAndVAO();
} }
// Destructor // Destructor
@ -152,6 +164,13 @@ ConvexMesh::~ConvexMesh() {
// Destroy the mesh // Destroy the mesh
destroy(); 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 // Render the sphere at the correct position and with the correct orientation
@ -162,57 +181,125 @@ void ConvexMesh::render(openglframework::Shader& shader,
shader.bind(); shader.bind();
// Set the model to camera matrix // Set the model to camera matrix
const openglframework::Matrix4 localToCameraMatrix = worldToCameraMatrix * mTransformMatrix; shader.setMatrix4x4Uniform("localToWorldMatrix", mTransformMatrix);
shader.setMatrix4x4Uniform("localToCameraMatrix", localToCameraMatrix); shader.setMatrix4x4Uniform("worldToCameraMatrix", worldToCameraMatrix);
// Set the normal matrix (inverse transpose of the 3x3 upper-left sub matrix of the // Set the normal matrix (inverse transpose of the 3x3 upper-left sub matrix of the
// model-view matrix) // model-view matrix)
const openglframework::Matrix4 localToCameraMatrix = worldToCameraMatrix * mTransformMatrix;
const openglframework::Matrix3 normalMatrix = const openglframework::Matrix3 normalMatrix =
localToCameraMatrix.getUpperLeft3x3Matrix().getInverse().getTranspose(); localToCameraMatrix.getUpperLeft3x3Matrix().getInverse().getTranspose();
shader.setMatrix3x3Uniform("normalMatrix", normalMatrix); shader.setMatrix3x3Uniform("normalMatrix", normalMatrix, false);
glEnableClientState(GL_VERTEX_ARRAY); // Set the vertex color
glEnableClientState(GL_NORMAL_ARRAY); openglframework::Vector4 color(mColor.r, mColor.g, mColor.b, mColor.a);
if (hasTexture()) { shader.setVector4Uniform("vertexColor", color, false);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
}
glVertexPointer(3, GL_FLOAT, 0, getVerticesPointer()); // Bind the VAO
glNormalPointer(GL_FLOAT, 0, getNormalsPointer()); mVAO.bind();
if(hasTexture()) {
glTexCoordPointer(2, GL_FLOAT, 0, getUVTextureCoordinatesPointer()); 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 each part of the mesh
for (unsigned int i=0; i<getNbParts(); i++) { for (unsigned int i=0; i<getNbParts(); i++) {
glDrawElements(GL_TRIANGLES, getNbFaces(i) * 3, glDrawElements(GL_TRIANGLES, getNbFaces(i) * 3, GL_UNSIGNED_INT, (char*)NULL);
GL_UNSIGNED_INT, getIndicesPointer());
} }
glDisableClientState(GL_NORMAL_ARRAY); glDisableVertexAttribArray(vertexPositionLoc);
glDisableClientState(GL_VERTEX_ARRAY); if (vertexNormalLoc != -1) glDisableVertexAttribArray(vertexNormalLoc);
if (hasTexture()) {
glDisableClientState(GL_TEXTURE_COORD_ARRAY); mVBONormals.unbind();
} mVBOVertices.unbind();
// Unbind the VAO
mVAO.unbind();
// Unbind the shader // Unbind the shader
shader.unbind(); shader.unbind();
} }
// Update the transform matrix of the sphere // Create the Vertex Buffer Objects used to render with OpenGL.
void ConvexMesh::updateTransform() { /// We create two VBOs (one for vertices and one for indices)
void ConvexMesh::createVBOAndVAO() {
// Get the interpolated transform of the rigid body // Create the VBO for the vertices data
rp3d::Transform transform = mRigidBody->getInterpolatedTransform(); 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 // Create the VBO for the normals data
rp3d::decimal matrix[16]; mVBONormals.create();
transform.getOpenGLMatrix(matrix); mVBONormals.bind();
openglframework::Matrix4 newMatrix(matrix[0], matrix[4], matrix[8], matrix[12], size_t sizeNormals = mNormals.size() * sizeof(openglframework::Vector3);
matrix[1], matrix[5], matrix[9], matrix[13], mVBONormals.copyDataIntoVBO(sizeNormals, getNormalsPointer(), GL_STATIC_DRAW);
matrix[2], matrix[6], matrix[10], matrix[14], mVBONormals.unbind();
matrix[3], matrix[7], matrix[11], matrix[15]);
// Apply the scaling matrix to have the correct sphere dimensions if (hasTexture()) {
mTransformMatrix = newMatrix; // 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(unsigned int);
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 // Libraries
#include "openglframework.h" #include "openglframework.h"
#include "reactphysics3d.h" #include "reactphysics3d.h"
#include "PhysicsObject.h"
// Class ConvexMesh // Class ConvexMesh
class ConvexMesh : public openglframework::Mesh { class ConvexMesh : public openglframework::Mesh, public PhysicsObject {
private : private :
// -------------------- Attributes -------------------- // // -------------------- Attributes -------------------- //
/// Rigid body used to simulate the dynamics of the mesh /// Previous transform (for interpolation)
rp3d::CollisionBody* mRigidBody; 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 -------------------- // // -------------------- Methods -------------------- //
// Create the Vertex Buffer Objects used to render with OpenGL.
void createVBOAndVAO();
public : public :
// -------------------- Methods -------------------- // // -------------------- Methods -------------------- //
@ -57,28 +76,20 @@ class ConvexMesh : public openglframework::Mesh {
/// Destructor /// Destructor
~ConvexMesh(); ~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 /// Render the mesh at the correct position and with the correct orientation
void render(openglframework::Shader& shader, void render(openglframework::Shader& shader,
const openglframework::Matrix4& worldToCameraMatrix); 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 // Update the transform matrix of the object
inline rp3d::CollisionBody* ConvexMesh::getCollisionBody() { inline void ConvexMesh::updateTransform(float interpolationFactor) {
return mRigidBody; mTransformMatrix = computeTransform(interpolationFactor, openglframework::Matrix4::identity());
}
// Return a pointer to the rigid body of the box
inline rp3d::RigidBody* ConvexMesh::getRigidBody() {
return dynamic_cast<rp3d::RigidBody*>(mRigidBody);
} }
#endif #endif

View File

@ -26,6 +26,13 @@
// Libraries // Libraries
#include "Cylinder.h" #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 // Constructor
Cylinder::Cylinder(float radius, float height, const openglframework::Vector3& position, Cylinder::Cylinder(float radius, float height, const openglframework::Vector3& position,
reactphysics3d::CollisionWorld* world, reactphysics3d::CollisionWorld* world,
@ -57,13 +64,22 @@ Cylinder::Cylinder(float radius, float height, const openglframework::Vector3& p
rp3d::Quaternion initOrientation = rp3d::Quaternion::identity(); rp3d::Quaternion initOrientation = rp3d::Quaternion::identity();
rp3d::Transform transform(initPosition, initOrientation); rp3d::Transform transform(initPosition, initOrientation);
mPreviousTransform = transform;
// Create a rigid body corresponding to the cylinder in the dynamics world // 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 // 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; mTransformMatrix = mTransformMatrix * mScalingMatrix;
// Create the VBOs and VAO
if (totalNbCylinders == 0) {
createVBOAndVAO();
}
totalNbCylinders++;
} }
// Constructor // Constructor
@ -105,14 +121,33 @@ Cylinder::Cylinder(float radius, float height, const openglframework::Vector3& p
mTransformMatrix = mTransformMatrix * mScalingMatrix; mTransformMatrix = mTransformMatrix * mScalingMatrix;
mRigidBody = body; mBody = body;
// Create the VBOs and VAO
if (totalNbCylinders == 0) {
createVBOAndVAO();
}
totalNbCylinders++;
} }
// Destructor // Destructor
Cylinder::~Cylinder() { Cylinder::~Cylinder() {
// Destroy the mesh if (totalNbCylinders == 1) {
destroy();
// Destroy the mesh
destroy();
// Destroy the VBOs and VAO
mVBOIndices.destroy();
mVBOVertices.destroy();
mVBONormals.destroy();
mVBOTextureCoords.destroy();
mVAO.destroy();
}
totalNbCylinders--;
} }
// Render the cylinder at the correct position and with the correct orientation // Render the cylinder at the correct position and with the correct orientation
@ -123,57 +158,125 @@ void Cylinder::render(openglframework::Shader& shader,
shader.bind(); shader.bind();
// Set the model to camera matrix // Set the model to camera matrix
const openglframework::Matrix4 localToCameraMatrix = worldToCameraMatrix * mTransformMatrix; shader.setMatrix4x4Uniform("localToWorldMatrix", mTransformMatrix);
shader.setMatrix4x4Uniform("localToCameraMatrix", localToCameraMatrix); shader.setMatrix4x4Uniform("worldToCameraMatrix", worldToCameraMatrix);
// Set the normal matrix (inverse transpose of the 3x3 upper-left sub matrix of the // Set the normal matrix (inverse transpose of the 3x3 upper-left sub matrix of the
// model-view matrix) // model-view matrix)
const openglframework::Matrix4 localToCameraMatrix = worldToCameraMatrix * mTransformMatrix;
const openglframework::Matrix3 normalMatrix = const openglframework::Matrix3 normalMatrix =
localToCameraMatrix.getUpperLeft3x3Matrix().getInverse().getTranspose(); localToCameraMatrix.getUpperLeft3x3Matrix().getInverse().getTranspose();
shader.setMatrix3x3Uniform("normalMatrix", normalMatrix); shader.setMatrix3x3Uniform("normalMatrix", normalMatrix, false);
glEnableClientState(GL_VERTEX_ARRAY); // Set the vertex color
glEnableClientState(GL_NORMAL_ARRAY); openglframework::Vector4 color(mColor.r, mColor.g, mColor.b, mColor.a);
if (hasTexture()) { shader.setVector4Uniform("vertexColor", color, false);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
}
glVertexPointer(3, GL_FLOAT, 0, getVerticesPointer()); // Bind the VAO
glNormalPointer(GL_FLOAT, 0, getNormalsPointer()); mVAO.bind();
if(hasTexture()) {
glTexCoordPointer(2, GL_FLOAT, 0, getUVTextureCoordinatesPointer()); 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 each part of the mesh
for (unsigned int i=0; i<getNbParts(); i++) { for (unsigned int i=0; i<getNbParts(); i++) {
glDrawElements(GL_TRIANGLES, getNbFaces(i) * 3, glDrawElements(GL_TRIANGLES, getNbFaces(i) * 3, GL_UNSIGNED_INT, (char*)NULL);
GL_UNSIGNED_INT, getIndicesPointer());
} }
glDisableClientState(GL_NORMAL_ARRAY); glDisableVertexAttribArray(vertexPositionLoc);
glDisableClientState(GL_VERTEX_ARRAY); if (vertexNormalLoc != -1) glDisableVertexAttribArray(vertexNormalLoc);
if (hasTexture()) {
glDisableClientState(GL_TEXTURE_COORD_ARRAY); mVBONormals.unbind();
} mVBOVertices.unbind();
// Unbind the VAO
mVAO.unbind();
// Unbind the shader // Unbind the shader
shader.unbind(); shader.unbind();
} }
// Update the transform matrix of the cylinder // Create the Vertex Buffer Objects used to render with OpenGL.
void Cylinder::updateTransform() { /// We create two VBOs (one for vertices and one for indices)
void Cylinder::createVBOAndVAO() {
// Get the interpolated transform of the rigid body // Create the VBO for the vertices data
rp3d::Transform transform = mRigidBody->getInterpolatedTransform(); 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 // Create the VBO for the normals data
rp3d::decimal matrix[16]; mVBONormals.create();
transform.getOpenGLMatrix(matrix); mVBONormals.bind();
openglframework::Matrix4 newMatrix(matrix[0], matrix[4], matrix[8], matrix[12], size_t sizeNormals = mNormals.size() * sizeof(openglframework::Vector3);
matrix[1], matrix[5], matrix[9], matrix[13], mVBONormals.copyDataIntoVBO(sizeNormals, getNormalsPointer(), GL_STATIC_DRAW);
matrix[2], matrix[6], matrix[10], matrix[14], mVBONormals.unbind();
matrix[3], matrix[7], matrix[11], matrix[15]);
// Apply the scaling matrix to have the correct cylinder dimensions if (hasTexture()) {
mTransformMatrix = newMatrix * mScalingMatrix; // 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(unsigned int);
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 // Libraries
#include "openglframework.h" #include "openglframework.h"
#include "reactphysics3d.h" #include "reactphysics3d.h"
#include "PhysicsObject.h"
// Class Cylinder // Class Cylinder
class Cylinder : public openglframework::Mesh { class Cylinder : public openglframework::Mesh, public PhysicsObject {
private : private :
@ -43,14 +44,35 @@ class Cylinder : public openglframework::Mesh {
/// Height of the cylinder /// Height of the cylinder
float mHeight; 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) /// Scaling matrix (applied to a sphere to obtain the correct cylinder dimensions)
openglframework::Matrix4 mScalingMatrix; 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 -------------------- // // -------------------- Methods -------------------- //
// Create the Vertex Buffer Objects used to render with OpenGL.
void createVBOAndVAO();
public : public :
// -------------------- Methods -------------------- // // -------------------- Methods -------------------- //
@ -61,33 +83,25 @@ class Cylinder : public openglframework::Mesh {
/// Constructor /// Constructor
Cylinder(float radius, float height, const openglframework::Vector3& position, Cylinder(float radius, float height, const openglframework::Vector3& position,
float mass, rp3d::DynamicsWorld* dynamicsWorld, const std::string &meshFolderPath); float mass, rp3d::DynamicsWorld* dynamicsWorld, const std::string &meshFolderPath);
/// Destructor /// Destructor
~Cylinder(); ~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 /// Render the cylinder at the correct position and with the correct orientation
void render(openglframework::Shader& shader, void render(openglframework::Shader& shader,
const openglframework::Matrix4& worldToCameraMatrix); 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 // Update the transform matrix of the object
inline rp3d::CollisionBody* Cylinder::getCollisionBody() { inline void Cylinder::updateTransform(float interpolationFactor) {
return mRigidBody; mTransformMatrix = computeTransform(interpolationFactor, mScalingMatrix);
}
// Return a pointer to the rigid body of the box
inline rp3d::RigidBody* Cylinder::getRigidBody() {
return dynamic_cast<rp3d::RigidBody*>(mRigidBody);
} }
#endif #endif

View File

@ -26,6 +26,13 @@
// Libraries // Libraries
#include "Dumbbell.h" #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 // Constructor
Dumbbell::Dumbbell(const openglframework::Vector3 &position, Dumbbell::Dumbbell(const openglframework::Vector3 &position,
reactphysics3d::DynamicsWorld* dynamicsWorld, const std::string& meshFolderPath) reactphysics3d::DynamicsWorld* dynamicsWorld, const std::string& meshFolderPath)
@ -64,6 +71,8 @@ Dumbbell::Dumbbell(const openglframework::Vector3 &position,
rp3d::Quaternion initOrientation(angleAroundX, 0, 0); rp3d::Quaternion initOrientation(angleAroundX, 0, 0);
rp3d::Transform transformBody(initPosition, initOrientation); rp3d::Transform transformBody(initPosition, initOrientation);
mPreviousTransform = transformBody;
// Initial transform of the first sphere collision shape of the dumbbell (in local-space) // 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()); rp3d::Transform transformSphereShape1(rp3d::Vector3(0, 4.0, 0), rp3d::Quaternion::identity());
@ -84,6 +93,13 @@ Dumbbell::Dumbbell(const openglframework::Vector3 &position,
mBody = body; mBody = body;
mTransformMatrix = mTransformMatrix * mScalingMatrix; mTransformMatrix = mTransformMatrix * mScalingMatrix;
// Create the VBOs and VAO
if (totalNbDumbbells == 0) {
createVBOAndVAO();
}
totalNbDumbbells++;
} }
// Constructor // Constructor
@ -142,13 +158,32 @@ Dumbbell::Dumbbell(const openglframework::Vector3 &position,
mBody->addCollisionShape(cylinderCollisionShape, transformCylinderShape); mBody->addCollisionShape(cylinderCollisionShape, transformCylinderShape);
mTransformMatrix = mTransformMatrix * mScalingMatrix; mTransformMatrix = mTransformMatrix * mScalingMatrix;
// Create the VBOs and VAO
if (totalNbDumbbells == 0) {
createVBOAndVAO();
}
totalNbDumbbells++;
} }
// Destructor // Destructor
Dumbbell::~Dumbbell() { Dumbbell::~Dumbbell() {
// Destroy the mesh if (totalNbDumbbells == 1) {
destroy();
// Destroy the mesh
destroy();
// Destroy the VBOs and VAO
mVBOIndices.destroy();
mVBOVertices.destroy();
mVBONormals.destroy();
mVBOTextureCoords.destroy();
mVAO.destroy();
}
totalNbDumbbells--;
} }
// Render the sphere at the correct position and with the correct orientation // Render the sphere at the correct position and with the correct orientation
@ -159,58 +194,125 @@ void Dumbbell::render(openglframework::Shader& shader,
shader.bind(); shader.bind();
// Set the model to camera matrix // Set the model to camera matrix
const openglframework::Matrix4 localToCameraMatrix = worldToCameraMatrix * mTransformMatrix; shader.setMatrix4x4Uniform("localToWorldMatrix", mTransformMatrix);
shader.setMatrix4x4Uniform("localToCameraMatrix", localToCameraMatrix); shader.setMatrix4x4Uniform("worldToCameraMatrix", worldToCameraMatrix);
// Set the normal matrix (inverse transpose of the 3x3 upper-left sub matrix of the // Set the normal matrix (inverse transpose of the 3x3 upper-left sub matrix of the
// model-view matrix) // model-view matrix)
const openglframework::Matrix4 localToCameraMatrix = worldToCameraMatrix * mTransformMatrix;
const openglframework::Matrix3 normalMatrix = const openglframework::Matrix3 normalMatrix =
localToCameraMatrix.getUpperLeft3x3Matrix().getInverse().getTranspose(); localToCameraMatrix.getUpperLeft3x3Matrix().getInverse().getTranspose();
shader.setMatrix3x3Uniform("normalMatrix", normalMatrix); shader.setMatrix3x3Uniform("normalMatrix", normalMatrix, false);
glEnableClientState(GL_VERTEX_ARRAY); // Set the vertex color
glEnableClientState(GL_NORMAL_ARRAY); openglframework::Vector4 color(mColor.r, mColor.g, mColor.b, mColor.a);
if (hasTexture()) { shader.setVector4Uniform("vertexColor", color, false);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
}
glVertexPointer(3, GL_FLOAT, 0, getVerticesPointer()); // Bind the VAO
glNormalPointer(GL_FLOAT, 0, getNormalsPointer()); mVAO.bind();
if(hasTexture()) {
glTexCoordPointer(2, GL_FLOAT, 0, getUVTextureCoordinatesPointer()); 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 each part of the mesh
for (unsigned int i=0; i<getNbParts(); i++) { for (unsigned int i=0; i<getNbParts(); i++) {
glDrawElements(GL_TRIANGLES, getNbFaces(i) * 3, glDrawElements(GL_TRIANGLES, getNbFaces(i) * 3, GL_UNSIGNED_INT, (char*)NULL);
GL_UNSIGNED_INT, getIndicesPointer());
} }
glDisableClientState(GL_NORMAL_ARRAY); glDisableVertexAttribArray(vertexPositionLoc);
glDisableClientState(GL_VERTEX_ARRAY); if (vertexNormalLoc != -1) glDisableVertexAttribArray(vertexNormalLoc);
if (hasTexture()) {
glDisableClientState(GL_TEXTURE_COORD_ARRAY); mVBONormals.unbind();
} mVBOVertices.unbind();
// Unbind the VAO
mVAO.unbind();
// Unbind the shader // Unbind the shader
shader.unbind(); shader.unbind();
} }
// Update the transform matrix of the sphere // Create the Vertex Buffer Objects used to render with OpenGL.
void Dumbbell::updateTransform() { /// We create two VBOs (one for vertices and one for indices)
void Dumbbell::createVBOAndVAO() {
// Get the interpolated transform of the rigid body // Create the VBO for the vertices data
rp3d::Transform transform = mBody->getInterpolatedTransform(); 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 // Create the VBO for the normals data
rp3d::decimal matrix[16]; mVBONormals.create();
transform.getOpenGLMatrix(matrix); mVBONormals.bind();
openglframework::Matrix4 newMatrix(matrix[0], matrix[4], matrix[8], matrix[12], size_t sizeNormals = mNormals.size() * sizeof(openglframework::Vector3);
matrix[1], matrix[5], matrix[9], matrix[13], mVBONormals.copyDataIntoVBO(sizeNormals, getNormalsPointer(), GL_STATIC_DRAW);
matrix[2], matrix[6], matrix[10], matrix[14], mVBONormals.unbind();
matrix[3], matrix[7], matrix[11], matrix[15]);
// Apply the scaling matrix to have the correct sphere dimensions if (hasTexture()) {
mTransformMatrix = newMatrix * mScalingMatrix; // 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(unsigned int);
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 // Libraries
#include "openglframework.h" #include "openglframework.h"
#include "reactphysics3d.h" #include "reactphysics3d.h"
#include "PhysicsObject.h"
// Class Sphere // Class Sphere
class Dumbbell : public openglframework::Mesh { class Dumbbell : public openglframework::Mesh, public PhysicsObject {
private : private :
@ -40,14 +41,35 @@ class Dumbbell : public openglframework::Mesh {
/// Radius of the spheres /// Radius of the spheres
float mRadius; 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) /// Scaling matrix (applied to a sphere to obtain the correct sphere dimensions)
openglframework::Matrix4 mScalingMatrix; 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 -------------------- // // -------------------- Methods -------------------- //
// Create the Vertex Buffer Objects used to render with OpenGL.
void createVBOAndVAO();
public : public :
// -------------------- Methods -------------------- // // -------------------- Methods -------------------- //
@ -64,28 +86,20 @@ class Dumbbell : public openglframework::Mesh {
/// Destructor /// Destructor
~Dumbbell(); ~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 /// Render the sphere at the correct position and with the correct orientation
void render(openglframework::Shader& shader, void render(openglframework::Shader& shader,
const openglframework::Matrix4& worldToCameraMatrix); 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 // Update the transform matrix of the object
inline rp3d::RigidBody* Dumbbell::getRigidBody() { inline void Dumbbell::updateTransform(float interpolationFactor) {
return dynamic_cast<rp3d::RigidBody*>(mBody); mTransformMatrix = computeTransform(interpolationFactor, mScalingMatrix);
}
// Return a pointer to the body
inline rp3d::CollisionBody* Dumbbell::getCollisionBody() {
return mBody;
} }
#endif #endif

View File

@ -47,7 +47,12 @@ void Line::render(openglframework::Shader& shader,
shader.bind(); shader.bind();
// Set the model to camera matrix // 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); glBegin(GL_LINES);
glVertex3f(mWorldPoint1.x, mWorldPoint1.y, mWorldPoint1.z); 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 /// Return the second point of the line
openglframework::Vector3 getPoint2() const; 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 /// Render the line at the correct position and with the correct orientation
void render(openglframework::Shader& shader, void render(openglframework::Shader& shader,
const openglframework::Matrix4& worldToCameraMatrix); 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 // Libraries
#include "Sphere.h" #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 // Constructor
Sphere::Sphere(float radius, const openglframework::Vector3 &position, Sphere::Sphere(float radius, const openglframework::Vector3 &position,
reactphysics3d::CollisionWorld* world, reactphysics3d::CollisionWorld* world,
@ -57,13 +64,22 @@ Sphere::Sphere(float radius, const openglframework::Vector3 &position,
rp3d::Quaternion initOrientation = rp3d::Quaternion::identity(); rp3d::Quaternion initOrientation = rp3d::Quaternion::identity();
rp3d::Transform transform(initPosition, initOrientation); rp3d::Transform transform(initPosition, initOrientation);
mPreviousTransform = transform;
// Create a rigid body corresponding to the sphere in the dynamics world // 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 // 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; mTransformMatrix = mTransformMatrix * mScalingMatrix;
// Create the VBOs and VAO
if (totalNbSpheres == 0) {
createVBOAndVAO();
}
totalNbSpheres++;
} }
// Constructor // 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 // Add a collision shape to the body and specify the mass of the shape
body->addCollisionShape(collisionShape, rp3d::Transform::identity(), mass); body->addCollisionShape(collisionShape, rp3d::Transform::identity(), mass);
mRigidBody = body; mBody = body;
mTransformMatrix = mTransformMatrix * mScalingMatrix; mTransformMatrix = mTransformMatrix * mScalingMatrix;
// Create the VBOs and VAO
if (totalNbSpheres == 0) {
createVBOAndVAO();
}
totalNbSpheres++;
} }
// Destructor // Destructor
Sphere::~Sphere() { Sphere::~Sphere() {
// Destroy the mesh if (totalNbSpheres == 1) {
destroy(); // 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 // Render the sphere at the correct position and with the correct orientation
@ -123,57 +157,125 @@ void Sphere::render(openglframework::Shader& shader,
shader.bind(); shader.bind();
// Set the model to camera matrix // Set the model to camera matrix
const openglframework::Matrix4 localToCameraMatrix = worldToCameraMatrix * mTransformMatrix; shader.setMatrix4x4Uniform("localToWorldMatrix", mTransformMatrix);
shader.setMatrix4x4Uniform("localToCameraMatrix", localToCameraMatrix); shader.setMatrix4x4Uniform("worldToCameraMatrix", worldToCameraMatrix);
// Set the normal matrix (inverse transpose of the 3x3 upper-left sub matrix of the // Set the normal matrix (inverse transpose of the 3x3 upper-left sub matrix of the
// model-view matrix) // model-view matrix)
const openglframework::Matrix4 localToCameraMatrix = worldToCameraMatrix * mTransformMatrix;
const openglframework::Matrix3 normalMatrix = const openglframework::Matrix3 normalMatrix =
localToCameraMatrix.getUpperLeft3x3Matrix().getInverse().getTranspose(); localToCameraMatrix.getUpperLeft3x3Matrix().getInverse().getTranspose();
shader.setMatrix3x3Uniform("normalMatrix", normalMatrix); shader.setMatrix3x3Uniform("normalMatrix", normalMatrix, false);
glEnableClientState(GL_VERTEX_ARRAY); // Set the vertex color
glEnableClientState(GL_NORMAL_ARRAY); openglframework::Vector4 color(mColor.r, mColor.g, mColor.b, mColor.a);
if (hasTexture()) { shader.setVector4Uniform("vertexColor", color, false);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
}
glVertexPointer(3, GL_FLOAT, 0, getVerticesPointer()); // Bind the VAO
glNormalPointer(GL_FLOAT, 0, getNormalsPointer()); mVAO.bind();
if(hasTexture()) {
glTexCoordPointer(2, GL_FLOAT, 0, getUVTextureCoordinatesPointer()); 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 each part of the mesh
for (unsigned int i=0; i<getNbParts(); i++) { for (unsigned int i=0; i<getNbParts(); i++) {
glDrawElements(GL_TRIANGLES, getNbFaces(i) * 3, glDrawElements(GL_TRIANGLES, getNbFaces(i) * 3, GL_UNSIGNED_INT, (char*)NULL);
GL_UNSIGNED_INT, getIndicesPointer());
} }
glDisableClientState(GL_NORMAL_ARRAY); glDisableVertexAttribArray(vertexPositionLoc);
glDisableClientState(GL_VERTEX_ARRAY); if (vertexNormalLoc != -1) glDisableVertexAttribArray(vertexNormalLoc);
if (hasTexture()) {
glDisableClientState(GL_TEXTURE_COORD_ARRAY); mVBONormals.unbind();
} mVBOVertices.unbind();
// Unbind the VAO
mVAO.unbind();
// Unbind the shader // Unbind the shader
shader.unbind(); shader.unbind();
} }
// Update the transform matrix of the sphere // Create the Vertex Buffer Objects used to render with OpenGL.
void Sphere::updateTransform() { /// We create two VBOs (one for vertices and one for indices)
void Sphere::createVBOAndVAO() {
// Get the interpolated transform of the rigid body // Create the VBO for the vertices data
rp3d::Transform transform = mRigidBody->getInterpolatedTransform(); 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 // Create the VBO for the normals data
rp3d::decimal matrix[16]; mVBONormals.create();
transform.getOpenGLMatrix(matrix); mVBONormals.bind();
openglframework::Matrix4 newMatrix(matrix[0], matrix[4], matrix[8], matrix[12], size_t sizeNormals = mNormals.size() * sizeof(openglframework::Vector3);
matrix[1], matrix[5], matrix[9], matrix[13], mVBONormals.copyDataIntoVBO(sizeNormals, getNormalsPointer(), GL_STATIC_DRAW);
matrix[2], matrix[6], matrix[10], matrix[14], mVBONormals.unbind();
matrix[3], matrix[7], matrix[11], matrix[15]);
// Apply the scaling matrix to have the correct sphere dimensions if (hasTexture()) {
mTransformMatrix = newMatrix * mScalingMatrix; // 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 // Libraries
#include "openglframework.h" #include "openglframework.h"
#include "reactphysics3d.h" #include "reactphysics3d.h"
#include "PhysicsObject.h"
// Class Sphere // Class Sphere
class Sphere : public openglframework::Mesh { class Sphere : public openglframework::Mesh, public PhysicsObject {
private : private :
@ -40,14 +41,35 @@ class Sphere : public openglframework::Mesh {
/// Radius of the sphere /// Radius of the sphere
float mRadius; 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) /// Scaling matrix (applied to a sphere to obtain the correct sphere dimensions)
openglframework::Matrix4 mScalingMatrix; 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 -------------------- // // -------------------- Methods -------------------- //
// Create the Vertex Buffer Objects used to render with OpenGL.
void createVBOAndVAO();
public : public :
// -------------------- Methods -------------------- // // -------------------- Methods -------------------- //
@ -63,28 +85,26 @@ class Sphere : public openglframework::Mesh {
/// Destructor /// Destructor
~Sphere(); ~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 /// Render the sphere at the correct position and with the correct orientation
void render(openglframework::Shader& shader, void render(openglframework::Shader& shader,
const openglframework::Matrix4& worldToCameraMatrix); 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 <<<<<<< HEAD:examples/common/Sphere.h
inline rp3d::CollisionBody* Sphere::getCollisionBody() {
return mRigidBody;
}
// Return a pointer to the rigid body of the box // Return a pointer to the rigid body of the box
inline rp3d::RigidBody* Sphere::getRigidBody() { inline rp3d::RigidBody* Sphere::getRigidBody() {
return static_cast<rp3d::RigidBody*>(mRigidBody); return static_cast<rp3d::RigidBody*>(mRigidBody);
=======
// Update the transform matrix of the object
inline void Sphere::updateTransform(float interpolationFactor) {
mTransformMatrix = computeTransform(interpolationFactor, mScalingMatrix);
>>>>>>> 1bde11f245806de07a12b1cf6c33cdb83046b882:testbed/common/Sphere.h
} }
#endif #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(unsigned int);
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 // Libraries
#include "openglframework.h" #include "openglframework.h"
const float VISUAL_CONTACT_POINT_RADIUS = 0.1f; const float VISUAL_CONTACT_POINT_RADIUS = 0.2f;
// Class VisualContactPoint // Class VisualContactPoint
class VisualContactPoint : public openglframework::Object3D { class VisualContactPoint : public openglframework::Object3D {
@ -44,8 +44,26 @@ class VisualContactPoint : public openglframework::Object3D {
/// Sphere mesh for the visual contact point /// Sphere mesh for the visual contact point
static openglframework::Mesh mMesh; static openglframework::Mesh mMesh;
/// True if the mesh has been initialized /// Vertex Buffer Object for the vertices data
static bool mIsMeshInitialized; 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 -------------------- // // -------------------- Methods -------------------- //
@ -54,7 +72,8 @@ class VisualContactPoint : public openglframework::Object3D {
// -------------------- Methods -------------------- // // -------------------- Methods -------------------- //
/// Constructor /// Constructor
VisualContactPoint(const openglframework::Vector3& position); VisualContactPoint(const openglframework::Vector3& position,
const std::string &meshFolderPath);
/// Destructor /// Destructor
~VisualContactPoint(); ~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