Merge branch 'develop' of https://www.github.com/DanielChappuis/reactphysics3d into develop
This commit is contained in:
commit
87b88fc953
|
@ -18,7 +18,7 @@ SET(OUR_EXECUTABLE_OUTPUT_PATH "${PROJECT_BINARY_DIR}/bin")
|
|||
ENABLE_TESTING()
|
||||
|
||||
# Options
|
||||
OPTION(COMPILE_EXAMPLES "Select this if you want to build the examples" OFF)
|
||||
OPTION(COMPILE_TESTBED "Select this if you want to build the testbed application" OFF)
|
||||
OPTION(COMPILE_TESTS "Select this if you want to build the tests" OFF)
|
||||
OPTION(PROFILING_ENABLED "Select this if you want to compile with enabled profiling" OFF)
|
||||
OPTION(DOUBLE_PRECISION_ENABLED "Select this if you want to compile using double precision floating
|
||||
|
@ -119,8 +119,6 @@ SET (REACTPHYSICS3D_SOURCES
|
|||
"src/engine/OverlappingPair.cpp"
|
||||
"src/engine/Profiler.h"
|
||||
"src/engine/Profiler.cpp"
|
||||
"src/engine/Timer.h"
|
||||
"src/engine/Timer.cpp"
|
||||
"src/mathematics/mathematics.h"
|
||||
"src/mathematics/mathematics_functions.h"
|
||||
"src/mathematics/Matrix2x2.h"
|
||||
|
@ -144,10 +142,10 @@ SET (REACTPHYSICS3D_SOURCES
|
|||
# Create the library
|
||||
ADD_LIBRARY (reactphysics3d STATIC ${REACTPHYSICS3D_SOURCES})
|
||||
|
||||
# If we need to compile the examples
|
||||
IF(COMPILE_EXAMPLES)
|
||||
add_subdirectory(examples/)
|
||||
ENDIF(COMPILE_EXAMPLES)
|
||||
# If we need to compile the testbed application
|
||||
IF(COMPILE_TESTBED)
|
||||
add_subdirectory(testbed/)
|
||||
ENDIF(COMPILE_TESTBED)
|
||||
|
||||
# If we need to compile the tests
|
||||
IF(COMPILE_TESTS)
|
||||
|
|
Binary file not shown.
|
@ -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
|
||||
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}
|
||||
|
||||
|
@ -311,12 +314,8 @@ world.destroyCollisionBody(body);
|
|||
\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
|
||||
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
|
||||
world and
|
||||
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. \\
|
||||
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
|
||||
activated by default when you create the world. \\
|
||||
|
||||
Here is how to create the Dynamics World: \\
|
||||
|
||||
|
@ -324,11 +323,8 @@ world.destroyCollisionBody(body);
|
|||
// Gravity vector
|
||||
rp3d::Vector3 gravity(0.0, -9.81, 0.0);
|
||||
|
||||
// Time step (in seconds)
|
||||
rp3d::decimal timeStep = 1.0 / 60.0;
|
||||
|
||||
// Create the dynamics world
|
||||
rp3d::DynamicsWorld world(gravity, timeStep);
|
||||
rp3d::DynamicsWorld world(gravity);
|
||||
\end{lstlisting}
|
||||
|
||||
\subsection{Customizing the Dynamics World}
|
||||
|
@ -384,39 +380,67 @@ world.enableSleeping(false);
|
|||
|
||||
\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}
|
||||
// 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}
|
||||
|
||||
\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}
|
||||
|
||||
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
|
||||
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
|
||||
it with the \texttt{delete} operator.
|
||||
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 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 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}
|
||||
\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.
|
||||
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
|
||||
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: \\
|
||||
|
|
|
@ -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/)
|
|
@ -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})
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
# Minimum cmake version required
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
|
||||
|
||||
ADD_SUBDIRECTORY(opengl-framework/)
|
||||
ADD_SUBDIRECTORY(glfw/)
|
|
@ -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();
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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})
|
|
@ -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();
|
||||
}
|
|
@ -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})
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
@ -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})
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
@ -83,9 +83,6 @@ class Body {
|
|||
/// Private assignment operator
|
||||
Body& operator=(const Body& body);
|
||||
|
||||
/// Set the variable to know whether or not the body is sleeping
|
||||
virtual void setIsSleeping(bool isSleeping);
|
||||
|
||||
public :
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
@ -105,6 +102,9 @@ class Body {
|
|||
/// Set whether or not the body is allowed to go to sleep
|
||||
void setIsAllowedToSleep(bool isAllowedToSleep);
|
||||
|
||||
/// Set the variable to know whether or not the body is sleeping
|
||||
virtual void setIsSleeping(bool isSleeping);
|
||||
|
||||
/// Return whether or not the body is sleeping
|
||||
bool isSleeping() const;
|
||||
|
||||
|
|
|
@ -41,10 +41,6 @@ CollisionBody::CollisionBody(const Transform& transform, CollisionWorld& world,
|
|||
: Body(id), mType(DYNAMIC), mTransform(transform), mProxyCollisionShapes(NULL),
|
||||
mNbCollisionShapes(0), mContactManifoldsList(NULL), mWorld(world) {
|
||||
|
||||
mInterpolationFactor = 0.0;
|
||||
|
||||
// Initialize the old transform
|
||||
mOldTransform = transform;
|
||||
}
|
||||
|
||||
// Destructor
|
||||
|
|
|
@ -73,12 +73,6 @@ class CollisionBody : public Body {
|
|||
/// Position and orientation of the body
|
||||
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
|
||||
ProxyShape* mProxyCollisionShapes;
|
||||
|
||||
|
@ -105,9 +99,6 @@ class CollisionBody : public Body {
|
|||
/// Remove all the collision shapes
|
||||
void removeAllCollisionShapes();
|
||||
|
||||
/// Update the old transform with the current one.
|
||||
void updateOldTransform();
|
||||
|
||||
/// Update the broad-phase state for this body (because it has moved for instance)
|
||||
virtual void updateBroadPhaseState() const;
|
||||
|
||||
|
@ -118,9 +109,6 @@ class CollisionBody : public Body {
|
|||
/// Reset the mIsAlreadyInIsland variable of the body and contact manifolds
|
||||
int resetIsAlreadyInIslandAndCountManifolds();
|
||||
|
||||
/// Set the interpolation factor of the body
|
||||
void setInterpolationFactor(decimal factor);
|
||||
|
||||
public :
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
@ -144,7 +132,7 @@ class CollisionBody : public Body {
|
|||
const Transform& getTransform() const;
|
||||
|
||||
/// Set the current position and orientation
|
||||
void setTransform(const Transform& transform);
|
||||
virtual void setTransform(const Transform& transform);
|
||||
|
||||
/// Add a collision shape to the body.
|
||||
virtual ProxyShape* addCollisionShape(const CollisionShape& collisionShape,
|
||||
|
@ -153,9 +141,6 @@ class CollisionBody : public Body {
|
|||
/// Remove a collision shape from the body
|
||||
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
|
||||
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 transformation of the body that transforms the local-space
|
||||
|
@ -264,12 +235,6 @@ inline void CollisionBody::setTransform(const Transform& transform) {
|
|||
updateBroadPhaseState();
|
||||
}
|
||||
|
||||
// Update the old transform with the current one.
|
||||
/// This is used to compute the interpolated position and orientation of the body
|
||||
inline void CollisionBody::updateOldTransform() {
|
||||
mOldTransform = mTransform;
|
||||
}
|
||||
|
||||
// Return the first element of the linked list of contact manifolds involving this body
|
||||
/**
|
||||
* @return A pointer to the first element of the linked-list with the contact
|
||||
|
|
|
@ -265,6 +265,64 @@ void RigidBody::removeCollisionShape(const ProxyShape* proxyShape) {
|
|||
recomputeMassInformation();
|
||||
}
|
||||
|
||||
// Set the linear velocity of the rigid body.
|
||||
/**
|
||||
* @param linearVelocity Linear velocity vector of the body
|
||||
*/
|
||||
void RigidBody::setLinearVelocity(const Vector3& linearVelocity) {
|
||||
|
||||
// If it is a static body, we do nothing
|
||||
if (mType == STATIC) return;
|
||||
|
||||
// Update the linear velocity of the current body state
|
||||
mLinearVelocity = linearVelocity;
|
||||
|
||||
// If the linear velocity is not zero, awake the body
|
||||
if (mLinearVelocity.lengthSquare() > decimal(0.0)) {
|
||||
setIsSleeping(false);
|
||||
}
|
||||
}
|
||||
|
||||
// Set the angular velocity.
|
||||
/**
|
||||
* @param angularVelocity The angular velocity vector of the body
|
||||
*/
|
||||
void RigidBody::setAngularVelocity(const Vector3& angularVelocity) {
|
||||
|
||||
// If it is a static body, we do nothing
|
||||
if (mType == STATIC) return;
|
||||
|
||||
// Set the angular velocity
|
||||
mAngularVelocity = angularVelocity;
|
||||
|
||||
// If the velocity is not zero, awake the body
|
||||
if (mAngularVelocity.lengthSquare() > decimal(0.0)) {
|
||||
setIsSleeping(false);
|
||||
}
|
||||
}
|
||||
|
||||
// Set the current position and orientation
|
||||
/**
|
||||
* @param transform The transformation of the body that transforms the local-space
|
||||
* of the body into world-space
|
||||
*/
|
||||
void RigidBody::setTransform(const Transform& transform) {
|
||||
|
||||
// Update the transform of the body
|
||||
mTransform = transform;
|
||||
|
||||
const Vector3 oldCenterOfMass = mCenterOfMassWorld;
|
||||
|
||||
// Compute the new center of mass in world-space coordinates
|
||||
mCenterOfMassWorld = mTransform * mCenterOfMassLocal;
|
||||
|
||||
// Update the linear velocity of the center of mass
|
||||
mLinearVelocity += mAngularVelocity.cross(mCenterOfMassWorld - oldCenterOfMass);
|
||||
|
||||
// Update the broad-phase state of the body
|
||||
updateBroadPhaseState();
|
||||
}
|
||||
|
||||
// Recompute the center of mass, total mass and inertia tensor of the body using all
|
||||
// the collision shapes attached to the body.
|
||||
void RigidBody::recomputeMassInformation() {
|
||||
|
@ -342,8 +400,13 @@ void RigidBody::updateBroadPhaseState() const {
|
|||
|
||||
PROFILE("RigidBody::updateBroadPhaseState()");
|
||||
|
||||
<<<<<<< HEAD
|
||||
DynamicsWorld& world = static_cast<DynamicsWorld&>(mWorld);
|
||||
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 (ProxyShape* shape = mProxyCollisionShapes; shape != NULL; shape = shape->mNext) {
|
||||
|
|
|
@ -118,9 +118,6 @@ class RigidBody : public CollisionBody {
|
|||
/// Update the broad-phase state for this body (because it has moved for instance)
|
||||
virtual void updateBroadPhaseState() const;
|
||||
|
||||
/// Set the variable to know whether or not the body is sleeping
|
||||
virtual void setIsSleeping(bool isSleeping);
|
||||
|
||||
public :
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
@ -134,6 +131,9 @@ class RigidBody : public CollisionBody {
|
|||
/// Set the type of the body (static, kinematic or dynamic)
|
||||
void setType(BodyType type);
|
||||
|
||||
/// Set the current position and orientation
|
||||
virtual void setTransform(const Transform& transform);
|
||||
|
||||
/// Return the mass of the body
|
||||
decimal getMass() const;
|
||||
|
||||
|
@ -149,6 +149,9 @@ class RigidBody : public CollisionBody {
|
|||
/// Set the angular velocity.
|
||||
void setAngularVelocity(const Vector3& angularVelocity);
|
||||
|
||||
/// Set the variable to know whether or not the body is sleeping
|
||||
virtual void setIsSleeping(bool isSleeping);
|
||||
|
||||
/// Return the local inertia tensor of the body (in body coordinates)
|
||||
const Matrix3x3& getInertiaTensorLocal() const;
|
||||
|
||||
|
@ -252,20 +255,6 @@ inline Vector3 RigidBody::getAngularVelocity() const {
|
|||
return mAngularVelocity;
|
||||
}
|
||||
|
||||
// Set the angular velocity.
|
||||
/// You should only call this method for a kinematic body. Otherwise, it
|
||||
/// will do nothing.
|
||||
/**
|
||||
* @param angularVelocity The angular velocity vector of the body
|
||||
*/
|
||||
inline void RigidBody::setAngularVelocity(const Vector3& angularVelocity) {
|
||||
|
||||
// If it is a kinematic body
|
||||
if (mType == KINEMATIC) {
|
||||
mAngularVelocity = angularVelocity;
|
||||
}
|
||||
}
|
||||
|
||||
// Return the local inertia tensor of the body (in local-space coordinates)
|
||||
/**
|
||||
* @return The 3x3 inertia tensor matrix of the body (in local-space coordinates)
|
||||
|
@ -310,22 +299,6 @@ inline Matrix3x3 RigidBody::getInertiaTensorInverseWorld() const {
|
|||
mTransform.getOrientation().getMatrix().getTranspose();
|
||||
}
|
||||
|
||||
// Set the linear velocity of the rigid body.
|
||||
/// You should only call this method for a kinematic body. Otherwise, it
|
||||
/// will do nothing.
|
||||
/**
|
||||
* @param linearVelocity Linear velocity vector of the body
|
||||
*/
|
||||
inline void RigidBody::setLinearVelocity(const Vector3& linearVelocity) {
|
||||
|
||||
// If it is a kinematic body
|
||||
if (mType == KINEMATIC) {
|
||||
|
||||
// Update the linear velocity of the current body state
|
||||
mLinearVelocity = linearVelocity;
|
||||
}
|
||||
}
|
||||
|
||||
// Return true if the gravity needs to be applied to this rigid body
|
||||
/**
|
||||
* @return True if the gravity is applied to the body
|
||||
|
|
|
@ -83,9 +83,6 @@ const decimal PI = decimal(3.14159265);
|
|||
/// 2*Pi constant
|
||||
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
|
||||
const decimal DEFAULT_FRICTION_COEFFICIENT = decimal(0.3);
|
||||
|
||||
|
|
|
@ -40,6 +40,15 @@ CollisionWorld::CollisionWorld()
|
|||
|
||||
// Destructor
|
||||
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(mBodies.empty());
|
||||
}
|
||||
|
|
|
@ -37,10 +37,9 @@ using namespace std;
|
|||
// Constructor
|
||||
/**
|
||||
* @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)
|
||||
: CollisionWorld(), mTimer(timeStep),
|
||||
DynamicsWorld::DynamicsWorld(const Vector3 &gravity)
|
||||
: CollisionWorld(),
|
||||
mContactSolver(mMapBodyToConstrainedVelocityIndex),
|
||||
mConstraintSolver(mMapBodyToConstrainedVelocityIndex),
|
||||
mNbVelocitySolverIterations(DEFAULT_VELOCITY_SOLVER_NB_ITERATIONS),
|
||||
|
@ -60,6 +59,22 @@ DynamicsWorld::DynamicsWorld(const Vector3 &gravity, decimal timeStep = DEFAULT_
|
|||
// Destructor
|
||||
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
|
||||
for (uint i=0; i<mNbIslands; i++) {
|
||||
|
||||
|
@ -83,6 +98,9 @@ DynamicsWorld::~DynamicsWorld() {
|
|||
delete[] mConstrainedOrientations;
|
||||
}
|
||||
|
||||
assert(mJoints.size() == 0);
|
||||
assert(mRigidBodies.size() == 0);
|
||||
|
||||
#ifdef IS_PROFILING_ACTIVE
|
||||
|
||||
// Print the profiling report
|
||||
|
@ -95,7 +113,10 @@ DynamicsWorld::~DynamicsWorld() {
|
|||
}
|
||||
|
||||
// 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
|
||||
// Increment the frame counter of the profiler
|
||||
|
@ -104,13 +125,7 @@ void DynamicsWorld::update() {
|
|||
|
||||
PROFILE("DynamicsWorld::update()");
|
||||
|
||||
assert(mTimer.getIsRunning());
|
||||
|
||||
// Compute the time since the last update() call and update the timer
|
||||
mTimer.update();
|
||||
|
||||
// While the time accumulator is not empty
|
||||
while(mTimer.isPossibleToTakeStep()) {
|
||||
mTimeStep = timeStep;
|
||||
|
||||
// Notify the event listener about the beginning of an internal tick
|
||||
if (mEventListener != NULL) mEventListener->beginInternalTick();
|
||||
|
@ -127,9 +142,6 @@ void DynamicsWorld::update() {
|
|||
// Integrate the velocities
|
||||
integrateRigidBodiesVelocities();
|
||||
|
||||
// Update the timer
|
||||
mTimer.nextStep();
|
||||
|
||||
// Solve the contacts and constraints
|
||||
solveContactsAndConstraints();
|
||||
|
||||
|
@ -146,13 +158,9 @@ void DynamicsWorld::update() {
|
|||
|
||||
// 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
|
||||
resetBodiesForceAndTorque();
|
||||
|
||||
// Compute and set the interpolation factor to all the bodies
|
||||
setInterpolationFactorToAllBodies();
|
||||
}
|
||||
|
||||
// Integrate position and orientation of the rigid bodies.
|
||||
|
@ -162,8 +170,6 @@ void DynamicsWorld::integrateRigidBodiesPositions() {
|
|||
|
||||
PROFILE("DynamicsWorld::integrateRigidBodiesPositions()");
|
||||
|
||||
decimal dt = static_cast<decimal>(mTimer.getTimeStep());
|
||||
|
||||
// For each island of the world
|
||||
for (uint i=0; i < mNbIslands; i++) {
|
||||
|
||||
|
@ -190,10 +196,10 @@ void DynamicsWorld::integrateRigidBodiesPositions() {
|
|||
const Quaternion& currentOrientation = bodies[b]->getTransform().getOrientation();
|
||||
|
||||
// Update the new constrained position and orientation of the body
|
||||
mConstrainedPositions[indexArray] = currentPosition + newLinVelocity * dt;
|
||||
mConstrainedPositions[indexArray] = currentPosition + newLinVelocity * mTimeStep;
|
||||
mConstrainedOrientations[indexArray] = currentOrientation +
|
||||
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.
|
||||
void DynamicsWorld::initVelocityArrays() {
|
||||
|
||||
|
@ -305,8 +294,6 @@ void DynamicsWorld::integrateRigidBodiesVelocities() {
|
|||
// Initialize the bodies velocity arrays
|
||||
initVelocityArrays();
|
||||
|
||||
decimal dt = static_cast<decimal>(mTimer.getTimeStep());
|
||||
|
||||
// For each island of the world
|
||||
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
|
||||
mConstrainedLinearVelocities[indexBody] = bodies[b]->getLinearVelocity() +
|
||||
dt * bodies[b]->mMassInverse * bodies[b]->mExternalForce;
|
||||
mTimeStep * bodies[b]->mMassInverse * bodies[b]->mExternalForce;
|
||||
mConstrainedAngularVelocities[indexBody] = bodies[b]->getAngularVelocity() +
|
||||
dt * bodies[b]->getInertiaTensorInverseWorld() *
|
||||
mTimeStep * bodies[b]->getInertiaTensorInverseWorld() *
|
||||
bodies[b]->mExternalTorque;
|
||||
|
||||
// If the gravity has to be applied to this rigid body
|
||||
if (bodies[b]->isGravityEnabled() && mIsGravityEnabled) {
|
||||
|
||||
// Integrate the gravity force
|
||||
mConstrainedLinearVelocities[indexBody] += dt * bodies[b]->mMassInverse *
|
||||
mConstrainedLinearVelocities[indexBody] += mTimeStep * bodies[b]->mMassInverse *
|
||||
bodies[b]->getMass() * mGravity;
|
||||
}
|
||||
|
||||
|
@ -351,18 +338,15 @@ void DynamicsWorld::integrateRigidBodiesVelocities() {
|
|||
// => v2 = v1 * (1 - c * dt)
|
||||
decimal linDampingFactor = bodies[b]->getLinearDamping();
|
||||
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 angularDamping = clamp(decimal(1.0) - dt * angDampingFactor,
|
||||
decimal angularDamping = clamp(decimal(1.0) - mTimeStep * angDampingFactor,
|
||||
decimal(0.0), decimal(1.0));
|
||||
mConstrainedLinearVelocities[indexBody] *= clamp(linearDamping, decimal(0.0),
|
||||
decimal(1.0));
|
||||
mConstrainedAngularVelocities[indexBody] *= clamp(angularDamping, decimal(0.0),
|
||||
decimal(1.0));
|
||||
|
||||
// Update the old Transform of the body
|
||||
bodies[b]->updateOldTransform();
|
||||
|
||||
indexBody++;
|
||||
}
|
||||
}
|
||||
|
@ -373,9 +357,6 @@ void DynamicsWorld::solveContactsAndConstraints() {
|
|||
|
||||
PROFILE("DynamicsWorld::solveContactsAndConstraints()");
|
||||
|
||||
// Get the current time step
|
||||
decimal dt = static_cast<decimal>(mTimer.getTimeStep());
|
||||
|
||||
// Set the velocities arrays
|
||||
mContactSolver.setSplitVelocitiesArrays(mSplitLinearVelocities, mSplitAngularVelocities);
|
||||
mContactSolver.setConstrainedVelocitiesArrays(mConstrainedLinearVelocities,
|
||||
|
@ -399,7 +380,7 @@ void DynamicsWorld::solveContactsAndConstraints() {
|
|||
if (isContactsToSolve) {
|
||||
|
||||
// Initialize the solver
|
||||
mContactSolver.initializeForIsland(dt, mIslands[islandIndex]);
|
||||
mContactSolver.initializeForIsland(mTimeStep, mIslands[islandIndex]);
|
||||
|
||||
// Warm start the contact solver
|
||||
mContactSolver.warmStart();
|
||||
|
@ -409,7 +390,7 @@ void DynamicsWorld::solveContactsAndConstraints() {
|
|||
if (isConstraintsToSolve) {
|
||||
|
||||
// Initialize the constraint solver
|
||||
mConstraintSolver.initializeForIsland(dt, mIslands[islandIndex]);
|
||||
mConstraintSolver.initializeForIsland(mTimeStep, mIslands[islandIndex]);
|
||||
}
|
||||
|
||||
// For each iteration of the velocity solver
|
||||
|
@ -811,7 +792,6 @@ void DynamicsWorld::updateSleepingBodies() {
|
|||
|
||||
PROFILE("DynamicsWorld::updateSleepingBodies()");
|
||||
|
||||
const decimal dt = static_cast<decimal>(mTimer.getTimeStep());
|
||||
const decimal sleepLinearVelocitySquare = mSleepLinearVelocity * mSleepLinearVelocity;
|
||||
const decimal sleepAngularVelocitySquare = mSleepAngularVelocity * mSleepAngularVelocity;
|
||||
|
||||
|
@ -839,7 +819,7 @@ void DynamicsWorld::updateSleepingBodies() {
|
|||
else { // If the body velocity is bellow the sleeping velocity threshold
|
||||
|
||||
// Increase the sleep time
|
||||
bodies[b]->mSleepTime += dt;
|
||||
bodies[b]->mSleepTime += mTimeStep;
|
||||
if (bodies[b]->mSleepTime < minSleepTime) {
|
||||
minSleepTime = bodies[b]->mSleepTime;
|
||||
}
|
||||
|
@ -991,3 +971,23 @@ void DynamicsWorld::testCollision(CollisionCallback* callback) {
|
|||
// Perform the collision detection and report contacts
|
||||
mCollisionDetection.reportCollisionBetweenShapes(callback, emptySet, emptySet);
|
||||
}
|
||||
|
||||
/// Return the list of all contacts of the world
|
||||
std::vector<const ContactManifold*> DynamicsWorld::getContactsList() const {
|
||||
|
||||
std::vector<const ContactManifold*> contactManifolds;
|
||||
|
||||
// For each currently overlapping pair of bodies
|
||||
std::map<overlappingpairid, OverlappingPair*>::const_iterator it;
|
||||
for (it = mCollisionDetection.mOverlappingPairs.begin();
|
||||
it != mCollisionDetection.mOverlappingPairs.end(); ++it) {
|
||||
|
||||
OverlappingPair* pair = it->second;
|
||||
|
||||
// Get the contact manifold
|
||||
contactManifolds.push_back(pair->getContactManifold());
|
||||
}
|
||||
|
||||
// Return all the contact manifold
|
||||
return contactManifolds;
|
||||
}
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
#include "ContactSolver.h"
|
||||
#include "ConstraintSolver.h"
|
||||
#include "body/RigidBody.h"
|
||||
#include "Timer.h"
|
||||
#include "Island.h"
|
||||
#include "configuration.h"
|
||||
|
||||
|
@ -51,9 +50,6 @@ class DynamicsWorld : public CollisionWorld {
|
|||
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// Timer of the physics engine
|
||||
Timer mTimer;
|
||||
|
||||
/// Contact solver
|
||||
ContactSolver mContactSolver;
|
||||
|
||||
|
@ -78,6 +74,9 @@ class DynamicsWorld : public CollisionWorld {
|
|||
/// Gravity vector of the world
|
||||
Vector3 mGravity;
|
||||
|
||||
/// Current frame time step (in seconds)
|
||||
decimal mTimeStep;
|
||||
|
||||
/// True if the gravity force is on
|
||||
bool mIsGravityEnabled;
|
||||
|
||||
|
@ -182,23 +181,23 @@ class DynamicsWorld : public CollisionWorld {
|
|||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Constructor
|
||||
DynamicsWorld(const Vector3& mGravity, decimal timeStep);
|
||||
DynamicsWorld(const Vector3& mGravity);
|
||||
|
||||
/// Destructor
|
||||
virtual ~DynamicsWorld();
|
||||
|
||||
/// Start the physics simulation
|
||||
void start();
|
||||
|
||||
/// Stop the physics simulation
|
||||
void stop();
|
||||
|
||||
/// 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
|
||||
void setNbIterationsVelocitySolver(uint nbIterations);
|
||||
|
||||
/// Get the number of iterations for the position constraint solver
|
||||
uint getNbIterationsPositionSolver() const;
|
||||
|
||||
/// Set the number of iterations for the position constraint solver
|
||||
void setNbIterationsPositionSolver(uint nbIterations);
|
||||
|
||||
|
@ -227,6 +226,9 @@ class DynamicsWorld : public CollisionWorld {
|
|||
/// Return the gravity vector of the world
|
||||
Vector3 getGravity() const;
|
||||
|
||||
/// Set the gravity vector of the world
|
||||
void setGravity(Vector3& gravity);
|
||||
|
||||
/// Return if the gravity is on
|
||||
bool isGravityEnabled() const;
|
||||
|
||||
|
@ -239,9 +241,6 @@ class DynamicsWorld : public CollisionWorld {
|
|||
/// Return the number of joints in the world
|
||||
uint getNbJoints() const;
|
||||
|
||||
/// Return the current physics time (in seconds)
|
||||
long double getPhysicsTime() const;
|
||||
|
||||
/// Return an iterator to the beginning of the rigid bodies of the physics world
|
||||
std::set<RigidBody*>::iterator getRigidBodiesBeginIterator();
|
||||
|
||||
|
@ -298,6 +297,9 @@ class DynamicsWorld : public CollisionWorld {
|
|||
/// Test and report collisions between all shapes of the world
|
||||
virtual void testCollision(CollisionCallback* callback);
|
||||
|
||||
/// Return the list of all contacts of the world
|
||||
std::vector<const ContactManifold*> getContactsList() const;
|
||||
|
||||
// -------------------- Friendship -------------------- //
|
||||
|
||||
friend class RigidBody;
|
||||
|
@ -314,13 +316,9 @@ inline void DynamicsWorld::resetBodiesForceAndTorque() {
|
|||
}
|
||||
}
|
||||
|
||||
// Start the physics simulation
|
||||
inline void DynamicsWorld::start() {
|
||||
mTimer.start();
|
||||
}
|
||||
|
||||
inline void DynamicsWorld::stop() {
|
||||
mTimer.stop();
|
||||
// Get the number of iterations for the velocity constraint solver
|
||||
inline uint DynamicsWorld::getNbIterationsVelocitySolver() const {
|
||||
return mNbVelocitySolverIterations;
|
||||
}
|
||||
|
||||
// Set the number of iterations for the velocity constraint solver
|
||||
|
@ -331,6 +329,11 @@ inline void DynamicsWorld::setNbIterationsVelocitySolver(uint nbIterations) {
|
|||
mNbVelocitySolverIterations = nbIterations;
|
||||
}
|
||||
|
||||
// Get the number of iterations for the position constraint solver
|
||||
inline uint DynamicsWorld::getNbIterationsPositionSolver() const {
|
||||
return mNbPositionSolverIterations;
|
||||
}
|
||||
|
||||
// Set the number of iterations for the position constraint solver
|
||||
/**
|
||||
* @param nbIterations Number of iterations for the position solver
|
||||
|
@ -385,6 +388,14 @@ inline Vector3 DynamicsWorld::getGravity() const {
|
|||
return mGravity;
|
||||
}
|
||||
|
||||
// Set the gravity vector of the world
|
||||
/**
|
||||
* @param gravity The gravity vector (in meter per seconds squared)
|
||||
*/
|
||||
inline void DynamicsWorld::setGravity(Vector3& gravity) {
|
||||
mGravity = gravity;
|
||||
}
|
||||
|
||||
// Return if the gravity is enaled
|
||||
/**
|
||||
* @return True if the gravity is enabled in the world
|
||||
|
@ -434,14 +445,6 @@ inline std::set<RigidBody*>::iterator DynamicsWorld::getRigidBodiesEndIterator()
|
|||
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 and false otherwise
|
||||
|
|
|
@ -54,7 +54,9 @@ Vector2::~Vector2() {
|
|||
Vector2 Vector2::getUnit() const {
|
||||
decimal lengthVector = length();
|
||||
|
||||
assert(lengthVector > MACHINE_EPSILON);
|
||||
if (lengthVector < MACHINE_EPSILON) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Compute and return the unit vector
|
||||
decimal lengthInv = decimal(1.0) / lengthVector;
|
||||
|
|
|
@ -178,7 +178,9 @@ inline decimal Vector2::dot(const Vector2& vector) const {
|
|||
// Normalize the vector
|
||||
inline void Vector2::normalize() {
|
||||
decimal l = length();
|
||||
assert(l > std::numeric_limits<decimal>::epsilon());
|
||||
if (l < MACHINE_EPSILON) {
|
||||
return;
|
||||
}
|
||||
x /= l;
|
||||
y /= l;
|
||||
}
|
||||
|
|
|
@ -55,7 +55,9 @@ Vector3::~Vector3() {
|
|||
Vector3 Vector3::getUnit() const {
|
||||
decimal lengthVector = length();
|
||||
|
||||
assert(lengthVector > MACHINE_EPSILON);
|
||||
if (lengthVector < MACHINE_EPSILON) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Compute and return the unit vector
|
||||
decimal lengthInv = decimal(1.0) / lengthVector;
|
||||
|
|
|
@ -193,7 +193,9 @@ inline Vector3 Vector3::cross(const Vector3& vector) const {
|
|||
// Normalize the vector
|
||||
inline void Vector3::normalize() {
|
||||
decimal l = length();
|
||||
assert(l > std::numeric_limits<decimal>::epsilon());
|
||||
if (l < MACHINE_EPSILON) {
|
||||
return;
|
||||
}
|
||||
x /= l;
|
||||
y /= l;
|
||||
z /= l;
|
||||
|
|
97
testbed/CMakeLists.txt
Normal file
97
testbed/CMakeLists.txt
Normal 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})
|
|
@ -31,35 +31,89 @@
|
|||
|
||||
// Initialize static variables
|
||||
openglframework::VertexBufferObject Box::mVBOVertices(GL_ARRAY_BUFFER);
|
||||
openglframework::VertexBufferObject Box::mVBOIndices(GL_ELEMENT_ARRAY_BUFFER);
|
||||
bool Box::areVBOsCreated = false;
|
||||
VertexData Box::mCubeVertices[8] = {
|
||||
{openglframework::Vector3(1,1,1),openglframework::Vector3(1,1,1),openglframework::Color(1,0,0,1)},
|
||||
{openglframework::Vector3(-1,1,1),openglframework::Vector3(-1,1,1),openglframework::Color(1,0,0,1)},
|
||||
{openglframework::Vector3(-1,-1,1),openglframework::Vector3(-1,-1,1),openglframework::Color(1,0,0,1)},
|
||||
{openglframework::Vector3(1,-1,1),openglframework::Vector3(1,-1,1),openglframework::Color(1,0,0,1)},
|
||||
{openglframework::Vector3(1,-1,-1),openglframework::Vector3(1,-1,-1),openglframework::Color(1,0,0,1)},
|
||||
{openglframework::Vector3(-1,-1,-1),openglframework::Vector3(-1,-1,-1),openglframework::Color(1,0,0,1)},
|
||||
{openglframework::Vector3(-1,1,-1),openglframework::Vector3(-1,1,-1),openglframework::Color(1,0,0,1)},
|
||||
{openglframework::Vector3(1,1,-1),openglframework::Vector3(1,1,-1),openglframework::Color(1,0,0,1)}
|
||||
openglframework::VertexBufferObject Box::mVBONormals(GL_ARRAY_BUFFER);
|
||||
openglframework::VertexArrayObject Box::mVAO;
|
||||
int Box::totalNbBoxes = 0;
|
||||
GLfloat Box::mCubeVertices[108] = {
|
||||
-1.0f,-1.0f,-1.0f, // triangle 1 : begin
|
||||
-1.0f,-1.0f, 1.0f,
|
||||
-1.0f, 1.0f, 1.0f, // triangle 1 : end
|
||||
1.0f, 1.0f,-1.0f, // triangle 2 : begin
|
||||
-1.0f,-1.0f,-1.0f,
|
||||
-1.0f, 1.0f,-1.0f, // triangle 2 : end
|
||||
1.0f,-1.0f, 1.0f,
|
||||
-1.0f,-1.0f,-1.0f,
|
||||
1.0f,-1.0f,-1.0f,
|
||||
1.0f, 1.0f,-1.0f,
|
||||
1.0f,-1.0f,-1.0f,
|
||||
-1.0f,-1.0f,-1.0f,
|
||||
-1.0f,-1.0f,-1.0f,
|
||||
-1.0f, 1.0f, 1.0f,
|
||||
-1.0f, 1.0f,-1.0f,
|
||||
1.0f,-1.0f, 1.0f,
|
||||
-1.0f,-1.0f, 1.0f,
|
||||
-1.0f,-1.0f,-1.0f,
|
||||
-1.0f, 1.0f, 1.0f,
|
||||
-1.0f,-1.0f, 1.0f,
|
||||
1.0f,-1.0f, 1.0f,
|
||||
1.0f, 1.0f, 1.0f,
|
||||
1.0f,-1.0f,-1.0f,
|
||||
1.0f, 1.0f,-1.0f,
|
||||
1.0f,-1.0f,-1.0f,
|
||||
1.0f, 1.0f, 1.0f,
|
||||
1.0f,-1.0f, 1.0f,
|
||||
1.0f, 1.0f, 1.0f,
|
||||
1.0f, 1.0f,-1.0f,
|
||||
-1.0f, 1.0f,-1.0f,
|
||||
1.0f, 1.0f, 1.0f,
|
||||
-1.0f, 1.0f,-1.0f,
|
||||
-1.0f, 1.0f, 1.0f,
|
||||
1.0f, 1.0f, 1.0f,
|
||||
-1.0f, 1.0f, 1.0f,
|
||||
1.0f,-1.0f, 1.0f
|
||||
};
|
||||
GLfloat Box::mCubeNormals[108] = {
|
||||
-1.0f, 0.0f, 0.0f, // triangle 1 : begin
|
||||
-1.0f, 0.0f, 0.0f,
|
||||
-1.0f, 0.0f, 0.0f, // triangle 1 : end
|
||||
0.0f, 0.0f,-1.0f, // triangle 2 : begin
|
||||
0.0f, 0.0f,-1.0f,
|
||||
0.0f, 0.0f,-1.0f, // triangle 2 : end
|
||||
0.0f,-1.0f, 0.0f,
|
||||
0.0f,-1.0f, 0.0f,
|
||||
0.0f,-1.0f, 0.0f,//
|
||||
0.0f, 0.0f,-1.0f,
|
||||
0.0f, 0.0f,-1.0f,
|
||||
0.0f, 0.0f,-1.0f,//
|
||||
-1.0f, 0.0f, 0.0f,
|
||||
-1.0f, 0.0f, 0.0f,
|
||||
-1.0f, 0.0f,0.0f,//
|
||||
0.0f,-1.0f, 0.0f,
|
||||
0.0f,-1.0f, 0.0f,
|
||||
0.0f,-1.0f, 0.0f,//
|
||||
0.0f, 0.0f, 1.0f,
|
||||
0.0f, 0.0f, 1.0f,
|
||||
0.0f, 0.0f, 1.0f,//
|
||||
1.0f, 0.0f, 0.0f,
|
||||
1.0f, 0.0f, 0.0f,
|
||||
1.0f, 0.0f, 0.0f,//
|
||||
1.0f, 0.0f, 0.0f,
|
||||
1.0f, 0.0f, 0.0f,
|
||||
1.0f, 0.0f, 0.0f,//
|
||||
0.0f, 1.0f, 0.0f,
|
||||
0.0f, 1.0f, 0.0f,
|
||||
0.0f, 1.0f, 0.0f,//
|
||||
0.0f, 1.0f, 0.0f,
|
||||
0.0f, 1.0f, 0.0f,
|
||||
0.0f, 1.0f, 0.0f,//
|
||||
0.0f, 0.0f, 1.0f,
|
||||
0.0f, 0.0f, 1.0f,
|
||||
0.0f, 0.0f, 1.0f//
|
||||
};
|
||||
GLuint Box::mCubeIndices[36] = { 0, 1, 2,
|
||||
2, 3, 0,
|
||||
7, 4, 5,
|
||||
5, 6, 7,
|
||||
6, 5, 2,
|
||||
2, 1, 6,
|
||||
7, 0, 3,
|
||||
3, 4, 7,
|
||||
7, 6, 1,
|
||||
1, 0, 7,
|
||||
3, 2, 5,
|
||||
5, 4, 3};
|
||||
|
||||
// Constructor
|
||||
Box::Box(const openglframework::Vector3& size, const openglframework::Vector3 &position,
|
||||
reactphysics3d::CollisionWorld* world)
|
||||
: openglframework::Object3D(), mColor(0.5f, 0.5f, 0.5f, 1.0f) {
|
||||
: openglframework::Object3D() {
|
||||
|
||||
// Initialize the size of the box
|
||||
mSize[0] = size.x * 0.5f;
|
||||
|
@ -85,25 +139,30 @@ Box::Box(const openglframework::Vector3& size, const openglframework::Vector3 &p
|
|||
rp3d::Quaternion initOrientation = rp3d::Quaternion::identity();
|
||||
rp3d::Transform transform(initPosition, initOrientation);
|
||||
|
||||
mPreviousTransform = transform;
|
||||
|
||||
// Create a rigid body in the dynamics world
|
||||
mRigidBody = world->createCollisionBody(transform);
|
||||
mBody = world->createCollisionBody(transform);
|
||||
|
||||
// Add the collision shape to the body
|
||||
mRigidBody->addCollisionShape(collisionShape, rp3d::Transform::identity());
|
||||
mBody->addCollisionShape(collisionShape, rp3d::Transform::identity());
|
||||
|
||||
// If the Vertex Buffer object has not been created yet
|
||||
if (!areVBOsCreated) {
|
||||
if (totalNbBoxes == 0) {
|
||||
|
||||
// Create the Vertex Buffer
|
||||
createVBO();
|
||||
createVBOAndVAO();
|
||||
}
|
||||
|
||||
totalNbBoxes++;
|
||||
|
||||
mTransformMatrix = mTransformMatrix * mScalingMatrix;
|
||||
}
|
||||
|
||||
// Constructor
|
||||
Box::Box(const openglframework::Vector3& size, const openglframework::Vector3& position,
|
||||
float mass, reactphysics3d::DynamicsWorld* world)
|
||||
: openglframework::Object3D(), mColor(0.5f, 0.5f, 0.5f, 1.0f) {
|
||||
: openglframework::Object3D() {
|
||||
|
||||
// Initialize the size of the box
|
||||
mSize[0] = size.x * 0.5f;
|
||||
|
@ -129,111 +188,145 @@ Box::Box(const openglframework::Vector3& size, const openglframework::Vector3 &p
|
|||
rp3d::Quaternion initOrientation = rp3d::Quaternion::identity();
|
||||
rp3d::Transform transform(initPosition, initOrientation);
|
||||
|
||||
mPreviousTransform = transform;
|
||||
|
||||
// Create a rigid body in the dynamics world
|
||||
rp3d::RigidBody* body = world->createRigidBody(transform);
|
||||
|
||||
// Add the collision shape to the body
|
||||
body->addCollisionShape(collisionShape, rp3d::Transform::identity(), mass);
|
||||
|
||||
mRigidBody = body;
|
||||
mBody = body;
|
||||
|
||||
// If the Vertex Buffer object has not been created yet
|
||||
if (!areVBOsCreated) {
|
||||
if (totalNbBoxes == 0) {
|
||||
|
||||
// Create the Vertex Buffer
|
||||
createVBO();
|
||||
createVBOAndVAO();
|
||||
}
|
||||
|
||||
totalNbBoxes++;
|
||||
|
||||
mTransformMatrix = mTransformMatrix * mScalingMatrix;
|
||||
}
|
||||
|
||||
// Destructor
|
||||
Box::~Box() {
|
||||
|
||||
if (totalNbBoxes == 1) {
|
||||
|
||||
// Destroy the VBOs and VAO
|
||||
mVBOVertices.destroy();
|
||||
mVBONormals.destroy();
|
||||
mVAO.destroy();
|
||||
}
|
||||
|
||||
totalNbBoxes--;
|
||||
}
|
||||
|
||||
// Render the cube at the correct position and with the correct orientation
|
||||
void Box::render(openglframework::Shader& shader,
|
||||
const openglframework::Matrix4& worldToCameraMatrix) {
|
||||
|
||||
// Bind the VAO
|
||||
mVAO.bind();
|
||||
|
||||
// Bind the shader
|
||||
shader.bind();
|
||||
|
||||
mVBOVertices.bind();
|
||||
|
||||
// Set the model to camera matrix
|
||||
const openglframework::Matrix4 localToCameraMatrix = worldToCameraMatrix * mTransformMatrix;
|
||||
shader.setMatrix4x4Uniform("localToCameraMatrix", localToCameraMatrix);
|
||||
shader.setMatrix4x4Uniform("localToWorldMatrix", mTransformMatrix);
|
||||
shader.setMatrix4x4Uniform("worldToCameraMatrix", worldToCameraMatrix);
|
||||
|
||||
// Set the normal matrix (inverse transpose of the 3x3 upper-left sub matrix of the
|
||||
// model-view matrix)
|
||||
const openglframework::Matrix4 localToCameraMatrix = worldToCameraMatrix * mTransformMatrix;
|
||||
const openglframework::Matrix3 normalMatrix =
|
||||
localToCameraMatrix.getUpperLeft3x3Matrix().getInverse().getTranspose();
|
||||
shader.setMatrix3x3Uniform("normalMatrix", normalMatrix);
|
||||
shader.setMatrix3x3Uniform("normalMatrix", normalMatrix, false);
|
||||
|
||||
// Set the vertex color
|
||||
openglframework::Vector4 color(mColor.r, mColor.g, mColor.b, mColor.a);
|
||||
shader.setVector4Uniform("vertexColor", color);
|
||||
openglframework::Color currentColor = mBody->isSleeping() ? mSleepingColor : mColor;
|
||||
openglframework::Vector4 color(currentColor.r, currentColor.g, currentColor.b, currentColor.a);
|
||||
shader.setVector4Uniform("vertexColor", color, false);
|
||||
|
||||
// Bind the vertices VBO
|
||||
mVBOVertices.bind();
|
||||
// Get the location of shader attribute variables
|
||||
GLint vertexPositionLoc = shader.getAttribLocation("vertexPosition");
|
||||
GLint vertexNormalLoc = shader.getAttribLocation("vertexNormal", false);
|
||||
|
||||
// Enable the vertex, normal and color arrays
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
glEnableVertexAttribArray(vertexPositionLoc);
|
||||
glVertexAttribPointer(vertexPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, NULL);
|
||||
|
||||
// Set the arrays pointers
|
||||
glVertexPointer(3, GL_FLOAT, sizeof(VertexData), MEMBER_OFFSET(VertexData, position));
|
||||
glNormalPointer(GL_FLOAT, sizeof(VertexData), MEMBER_OFFSET(VertexData, normal));
|
||||
glColorPointer(3, GL_FLOAT, sizeof(VertexData), MEMBER_OFFSET(VertexData, color));
|
||||
mVBONormals.bind();
|
||||
|
||||
// Bind the indices VBO
|
||||
mVBOIndices.bind();
|
||||
if (vertexNormalLoc != -1) glEnableVertexAttribArray(vertexNormalLoc);
|
||||
if (vertexNormalLoc != -1) glVertexAttribPointer(vertexNormalLoc, 3, GL_FLOAT, GL_FALSE, 0, NULL);
|
||||
|
||||
// Draw the geometry of the box
|
||||
glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, (char*)NULL);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 36);
|
||||
|
||||
// Unbind the VBOs
|
||||
glDisableVertexAttribArray(vertexPositionLoc);
|
||||
if (vertexNormalLoc != -1) glDisableVertexAttribArray(vertexNormalLoc);
|
||||
|
||||
mVBONormals.unbind();
|
||||
mVBOVertices.unbind();
|
||||
mVBOIndices.unbind();
|
||||
|
||||
// Disable the arrays
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
glDisableClientState(GL_COLOR_ARRAY);
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
// Unbind the VAO
|
||||
mVAO.unbind();
|
||||
|
||||
// Unbind the shader
|
||||
shader.unbind();
|
||||
}
|
||||
|
||||
// Update the transform matrix of the box
|
||||
void Box::updateTransform() {
|
||||
|
||||
// Get the interpolated transform of the rigid body
|
||||
rp3d::Transform transform = mRigidBody->getInterpolatedTransform();
|
||||
|
||||
// Compute the transform used for rendering the box
|
||||
rp3d::decimal matrix[16];
|
||||
transform.getOpenGLMatrix(matrix);
|
||||
openglframework::Matrix4 newMatrix(matrix[0], matrix[4], matrix[8], matrix[12],
|
||||
matrix[1], matrix[5], matrix[9], matrix[13],
|
||||
matrix[2], matrix[6], matrix[10], matrix[14],
|
||||
matrix[3], matrix[7], matrix[11], matrix[15]);
|
||||
|
||||
// Apply the scaling matrix to have the correct box dimensions
|
||||
mTransformMatrix = newMatrix * mScalingMatrix;
|
||||
}
|
||||
|
||||
// Create the Vertex Buffer Objects used to render to box with OpenGL.
|
||||
/// We create two VBOs (one for vertices and one for indices) to render all the boxes
|
||||
/// in the simulation.
|
||||
void Box::createVBO() {
|
||||
void Box::createVBOAndVAO() {
|
||||
|
||||
// Create the VBOs
|
||||
// Create the VBO for the vertices data
|
||||
mVBOVertices.create();
|
||||
mVBOIndices.create();
|
||||
|
||||
// Copy the data into the VBOs
|
||||
mVBOVertices.bind();
|
||||
mVBOVertices.copyDataIntoVBO(sizeof(mCubeVertices), mCubeVertices, GL_STATIC_DRAW);
|
||||
mVBOIndices.copyDataIntoVBO(sizeof(mCubeIndices), mCubeIndices, GL_STATIC_DRAW);
|
||||
mVBOVertices.unbind();
|
||||
|
||||
areVBOsCreated = true;
|
||||
// Create th VBO for the normals data
|
||||
mVBONormals.create();
|
||||
mVBONormals.bind();
|
||||
mVBONormals.copyDataIntoVBO(sizeof(mCubeNormals), mCubeNormals, GL_STATIC_DRAW);
|
||||
mVBONormals.unbind();
|
||||
|
||||
// Create the VAO for both VBOs
|
||||
mVAO.create();
|
||||
mVAO.bind();
|
||||
|
||||
// Bind the VBO of vertices
|
||||
mVBOVertices.bind();
|
||||
|
||||
// Bind the VBO of indices
|
||||
mVBONormals.bind();
|
||||
|
||||
// Unbind the VAO
|
||||
mVAO.unbind();
|
||||
}
|
||||
|
||||
// Reset the transform
|
||||
void Box::resetTransform(const rp3d::Transform& transform) {
|
||||
|
||||
// Reset the transform
|
||||
mBody->setTransform(transform);
|
||||
|
||||
mBody->setIsSleeping(false);
|
||||
|
||||
// Reset the velocity of the rigid body
|
||||
rp3d::RigidBody* rigidBody = dynamic_cast<rp3d::RigidBody*>(mBody);
|
||||
if (rigidBody != NULL) {
|
||||
rigidBody->setLinearVelocity(rp3d::Vector3(0, 0, 0));
|
||||
rigidBody->setAngularVelocity(rp3d::Vector3(0, 0, 0));
|
||||
}
|
||||
|
||||
updateTransform(1.0f);
|
||||
}
|
|
@ -29,22 +29,10 @@
|
|||
// Libraries
|
||||
#include "openglframework.h"
|
||||
#include "reactphysics3d.h"
|
||||
|
||||
// Structure VertexData
|
||||
struct VertexData {
|
||||
|
||||
/// Vertex position
|
||||
openglframework::Vector3 position;
|
||||
|
||||
/// Vertex normal
|
||||
openglframework::Vector3 normal;
|
||||
|
||||
// Vertex color
|
||||
openglframework::Color color;
|
||||
};
|
||||
#include "PhysicsObject.h"
|
||||
|
||||
// Class Box
|
||||
class Box : public openglframework::Object3D {
|
||||
class Box : public openglframework::Object3D, public PhysicsObject {
|
||||
|
||||
private :
|
||||
|
||||
|
@ -53,34 +41,31 @@ class Box : public openglframework::Object3D {
|
|||
/// Size of each side of the box
|
||||
float mSize[3];
|
||||
|
||||
/// Rigid body used to simulate the dynamics of the box
|
||||
rp3d::CollisionBody* mRigidBody;
|
||||
|
||||
/// Scaling matrix (applied to a cube to obtain the correct box dimensions)
|
||||
openglframework::Matrix4 mScalingMatrix;
|
||||
|
||||
/// Vertex Buffer Object for the vertices data used to render the box with OpenGL
|
||||
static openglframework::VertexBufferObject mVBOVertices;
|
||||
|
||||
/// Vertex Buffer Object for the indices used to render the box with OpenGL
|
||||
static openglframework::VertexBufferObject mVBOIndices;
|
||||
/// Vertex Buffer Object for the normales used to render the box with OpenGL
|
||||
static openglframework::VertexBufferObject mVBONormals;
|
||||
|
||||
/// Vertex data for each vertex of the cube (used to render the box)
|
||||
static VertexData mCubeVertices[8];
|
||||
/// Vertex Array Object for the vertex data
|
||||
static openglframework::VertexArrayObject mVAO;
|
||||
|
||||
/// Indices of the cube (used to render the box)
|
||||
static GLuint mCubeIndices[36];
|
||||
/// Vertices coordinates of the triangles of the box
|
||||
static GLfloat mCubeVertices[108];
|
||||
|
||||
/// True if the VBOs have already been created
|
||||
static bool areVBOsCreated;
|
||||
/// Vertices normals of the triangles of the box
|
||||
static GLfloat mCubeNormals[108];
|
||||
|
||||
/// Main color of the box
|
||||
openglframework::Color mColor;
|
||||
/// Total number of boxes created
|
||||
static int totalNbBoxes;
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Create a Vertex Buffer Object to render to box with OpenGL
|
||||
static void createVBO();
|
||||
/// Create a the VAO and VBOs to render to box with OpenGL
|
||||
static void createVBOAndVAO();
|
||||
|
||||
public :
|
||||
|
||||
|
@ -97,35 +82,26 @@ class Box : public openglframework::Object3D {
|
|||
/// Destructor
|
||||
~Box();
|
||||
|
||||
/// Return a pointer to the collision body of the box
|
||||
reactphysics3d::CollisionBody* getCollisionBody();
|
||||
|
||||
/// Return a pointer to the rigid body of the box
|
||||
reactphysics3d::RigidBody* getRigidBody();
|
||||
|
||||
/// Update the transform matrix of the box
|
||||
void updateTransform();
|
||||
|
||||
/// Render the cube at the correct position and with the correct orientation
|
||||
void render(openglframework::Shader& shader, const openglframework::Matrix4& worldToCameraMatrix);
|
||||
|
||||
/// Set the color of the box
|
||||
void setColor(const openglframework::Color& color);
|
||||
/// Set the position of the box
|
||||
void resetTransform(const rp3d::Transform& transform);
|
||||
|
||||
/// Update the transform matrix of the object
|
||||
virtual void updateTransform(float interpolationFactor);
|
||||
};
|
||||
|
||||
// Return a pointer to the collision body of the box
|
||||
inline rp3d::CollisionBody* Box::getCollisionBody() {
|
||||
return mRigidBody;
|
||||
}
|
||||
|
||||
<<<<<<< HEAD:examples/common/Box.h
|
||||
// Return a pointer to the rigid body of the box
|
||||
inline rp3d::RigidBody* Box::getRigidBody() {
|
||||
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
|
|
@ -26,6 +26,13 @@
|
|||
// Libraries
|
||||
#include "Capsule.h"
|
||||
|
||||
openglframework::VertexBufferObject Capsule::mVBOVertices(GL_ARRAY_BUFFER);
|
||||
openglframework::VertexBufferObject Capsule::mVBONormals(GL_ARRAY_BUFFER);
|
||||
openglframework::VertexBufferObject Capsule::mVBOTextureCoords(GL_ARRAY_BUFFER);
|
||||
openglframework::VertexBufferObject Capsule::mVBOIndices(GL_ELEMENT_ARRAY_BUFFER);
|
||||
openglframework::VertexArrayObject Capsule::mVAO;
|
||||
int Capsule::totalNbCapsules = 0;
|
||||
|
||||
// Constructor
|
||||
Capsule::Capsule(float radius, float height, const openglframework::Vector3& position,
|
||||
reactphysics3d::CollisionWorld* world,
|
||||
|
@ -57,13 +64,22 @@ Capsule::Capsule(float radius, float height, const openglframework::Vector3& pos
|
|||
rp3d::Quaternion initOrientation = rp3d::Quaternion::identity();
|
||||
rp3d::Transform transform(initPosition, initOrientation);
|
||||
|
||||
mPreviousTransform = transform;
|
||||
|
||||
// Create a rigid body corresponding in the dynamics world
|
||||
mRigidBody = world->createCollisionBody(transform);
|
||||
mBody = world->createCollisionBody(transform);
|
||||
|
||||
// Add a collision shape to the body and specify the mass of the shape
|
||||
mRigidBody->addCollisionShape(collisionShape, rp3d::Transform::identity());
|
||||
mBody->addCollisionShape(collisionShape, rp3d::Transform::identity());
|
||||
|
||||
mTransformMatrix = mTransformMatrix * mScalingMatrix;
|
||||
|
||||
// Create the VBOs and VAO
|
||||
if (totalNbCapsules == 0) {
|
||||
createVBOAndVAO();
|
||||
}
|
||||
|
||||
totalNbCapsules++;
|
||||
}
|
||||
|
||||
// Constructor
|
||||
|
@ -103,16 +119,35 @@ Capsule::Capsule(float radius, float height, const openglframework::Vector3& pos
|
|||
// Add a collision shape to the body and specify the mass of the shape
|
||||
body->addCollisionShape(collisionShape, rp3d::Transform::identity(), mass);
|
||||
|
||||
mRigidBody = body;
|
||||
mBody = body;
|
||||
|
||||
mTransformMatrix = mTransformMatrix * mScalingMatrix;
|
||||
|
||||
// Create the VBOs and VAO
|
||||
if (totalNbCapsules == 0) {
|
||||
createVBOAndVAO();
|
||||
}
|
||||
|
||||
totalNbCapsules++;
|
||||
}
|
||||
|
||||
// Destructor
|
||||
Capsule::~Capsule() {
|
||||
|
||||
if (totalNbCapsules == 1) {
|
||||
|
||||
// Destroy the mesh
|
||||
destroy();
|
||||
|
||||
// Destroy the VBOs and VAO
|
||||
mVBOIndices.destroy();
|
||||
mVBOVertices.destroy();
|
||||
mVBONormals.destroy();
|
||||
mVBOTextureCoords.destroy();
|
||||
mVAO.destroy();
|
||||
}
|
||||
|
||||
totalNbCapsules--;
|
||||
}
|
||||
|
||||
// Render the sphere at the correct position and with the correct orientation
|
||||
|
@ -123,57 +158,126 @@ void Capsule::render(openglframework::Shader& shader,
|
|||
shader.bind();
|
||||
|
||||
// Set the model to camera matrix
|
||||
const openglframework::Matrix4 localToCameraMatrix = worldToCameraMatrix * mTransformMatrix;
|
||||
shader.setMatrix4x4Uniform("localToCameraMatrix", localToCameraMatrix);
|
||||
shader.setMatrix4x4Uniform("localToWorldMatrix", mTransformMatrix);
|
||||
shader.setMatrix4x4Uniform("worldToCameraMatrix", worldToCameraMatrix);
|
||||
|
||||
// Set the normal matrix (inverse transpose of the 3x3 upper-left sub matrix of the
|
||||
// model-view matrix)
|
||||
const openglframework::Matrix4 localToCameraMatrix = worldToCameraMatrix * mTransformMatrix;
|
||||
const openglframework::Matrix3 normalMatrix =
|
||||
localToCameraMatrix.getUpperLeft3x3Matrix().getInverse().getTranspose();
|
||||
shader.setMatrix3x3Uniform("normalMatrix", normalMatrix);
|
||||
shader.setMatrix3x3Uniform("normalMatrix", normalMatrix, false);
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
if (hasTexture()) {
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
// Set the vertex color
|
||||
openglframework::Color currentColor = mBody->isSleeping() ? mSleepingColor : mColor;
|
||||
openglframework::Vector4 color(currentColor.r, currentColor.g, currentColor.b, currentColor.a);
|
||||
shader.setVector4Uniform("vertexColor", color, false);
|
||||
|
||||
glVertexPointer(3, GL_FLOAT, 0, getVerticesPointer());
|
||||
glNormalPointer(GL_FLOAT, 0, getNormalsPointer());
|
||||
if(hasTexture()) {
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, getUVTextureCoordinatesPointer());
|
||||
}
|
||||
// Bind the VAO
|
||||
mVAO.bind();
|
||||
|
||||
mVBOVertices.bind();
|
||||
|
||||
// Get the location of shader attribute variables
|
||||
GLint vertexPositionLoc = shader.getAttribLocation("vertexPosition");
|
||||
GLint vertexNormalLoc = shader.getAttribLocation("vertexNormal", false);
|
||||
|
||||
glEnableVertexAttribArray(vertexPositionLoc);
|
||||
glVertexAttribPointer(vertexPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, (char*)NULL);
|
||||
|
||||
mVBONormals.bind();
|
||||
|
||||
if (vertexNormalLoc != -1) glVertexAttribPointer(vertexNormalLoc, 3, GL_FLOAT, GL_FALSE, 0, (char*)NULL);
|
||||
if (vertexNormalLoc != -1) glEnableVertexAttribArray(vertexNormalLoc);
|
||||
|
||||
// For each part of the mesh
|
||||
for (unsigned int i=0; i<getNbParts(); i++) {
|
||||
glDrawElements(GL_TRIANGLES, getNbFaces(i) * 3,
|
||||
GL_UNSIGNED_INT, getIndicesPointer());
|
||||
glDrawElements(GL_TRIANGLES, getNbFaces(i) * 3, GL_UNSIGNED_INT, (char*)NULL);
|
||||
}
|
||||
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
if (hasTexture()) {
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
glDisableVertexAttribArray(vertexPositionLoc);
|
||||
if (vertexNormalLoc != -1) glDisableVertexAttribArray(vertexNormalLoc);
|
||||
|
||||
mVBONormals.unbind();
|
||||
mVBOVertices.unbind();
|
||||
|
||||
// Unbind the VAO
|
||||
mVAO.unbind();
|
||||
|
||||
// Unbind the shader
|
||||
shader.unbind();
|
||||
}
|
||||
|
||||
// Update the transform matrix of the sphere
|
||||
void Capsule::updateTransform() {
|
||||
// Create the Vertex Buffer Objects used to render with OpenGL.
|
||||
/// We create two VBOs (one for vertices and one for indices)
|
||||
void Capsule::createVBOAndVAO() {
|
||||
|
||||
// Get the interpolated transform of the rigid body
|
||||
rp3d::Transform transform = mRigidBody->getInterpolatedTransform();
|
||||
// Create the VBO for the vertices data
|
||||
mVBOVertices.create();
|
||||
mVBOVertices.bind();
|
||||
size_t sizeVertices = mVertices.size() * sizeof(openglframework::Vector3);
|
||||
mVBOVertices.copyDataIntoVBO(sizeVertices, getVerticesPointer(), GL_STATIC_DRAW);
|
||||
mVBOVertices.unbind();
|
||||
|
||||
// Compute the transform used for rendering the sphere
|
||||
rp3d::decimal matrix[16];
|
||||
transform.getOpenGLMatrix(matrix);
|
||||
openglframework::Matrix4 newMatrix(matrix[0], matrix[4], matrix[8], matrix[12],
|
||||
matrix[1], matrix[5], matrix[9], matrix[13],
|
||||
matrix[2], matrix[6], matrix[10], matrix[14],
|
||||
matrix[3], matrix[7], matrix[11], matrix[15]);
|
||||
// Create the VBO for the normals data
|
||||
mVBONormals.create();
|
||||
mVBONormals.bind();
|
||||
size_t sizeNormals = mNormals.size() * sizeof(openglframework::Vector3);
|
||||
mVBONormals.copyDataIntoVBO(sizeNormals, getNormalsPointer(), GL_STATIC_DRAW);
|
||||
mVBONormals.unbind();
|
||||
|
||||
// Apply the scaling matrix to have the correct sphere dimensions
|
||||
mTransformMatrix = newMatrix * mScalingMatrix;
|
||||
if (hasTexture()) {
|
||||
// Create the VBO for the texture co data
|
||||
mVBOTextureCoords.create();
|
||||
mVBOTextureCoords.bind();
|
||||
size_t sizeTextureCoords = mUVs.size() * sizeof(openglframework::Vector2);
|
||||
mVBOTextureCoords.copyDataIntoVBO(sizeTextureCoords, getUVTextureCoordinatesPointer(), GL_STATIC_DRAW);
|
||||
mVBOTextureCoords.unbind();
|
||||
}
|
||||
|
||||
// Create th VBO for the indices data
|
||||
mVBOIndices.create();
|
||||
mVBOIndices.bind();
|
||||
size_t sizeIndices = mIndices[0].size() * sizeof(uint);
|
||||
mVBOIndices.copyDataIntoVBO(sizeIndices, getIndicesPointer(), GL_STATIC_DRAW);
|
||||
mVBOIndices.unbind();
|
||||
|
||||
// Create the VAO for both VBOs
|
||||
mVAO.create();
|
||||
mVAO.bind();
|
||||
|
||||
// Bind the VBO of vertices
|
||||
mVBOVertices.bind();
|
||||
|
||||
// Bind the VBO of normals
|
||||
mVBONormals.bind();
|
||||
|
||||
if (hasTexture()) {
|
||||
// Bind the VBO of texture coords
|
||||
mVBOTextureCoords.bind();
|
||||
}
|
||||
|
||||
// Bind the VBO of indices
|
||||
mVBOIndices.bind();
|
||||
|
||||
// Unbind the VAO
|
||||
mVAO.unbind();
|
||||
}
|
||||
|
||||
// Reset the transform
|
||||
void Capsule::resetTransform(const rp3d::Transform& transform) {
|
||||
|
||||
// Reset the transform
|
||||
mBody->setTransform(transform);
|
||||
|
||||
mBody->setIsSleeping(false);
|
||||
|
||||
// Reset the velocity of the rigid body
|
||||
rp3d::RigidBody* rigidBody = dynamic_cast<rp3d::RigidBody*>(mBody);
|
||||
if (rigidBody != NULL) {
|
||||
rigidBody->setLinearVelocity(rp3d::Vector3(0, 0, 0));
|
||||
rigidBody->setAngularVelocity(rp3d::Vector3(0, 0, 0));
|
||||
}
|
||||
|
||||
updateTransform(1.0f);
|
||||
}
|
|
@ -29,9 +29,10 @@
|
|||
// Libraries
|
||||
#include "openglframework.h"
|
||||
#include "reactphysics3d.h"
|
||||
#include "PhysicsObject.h"
|
||||
|
||||
// Class Sphere
|
||||
class Capsule : public openglframework::Mesh {
|
||||
class Capsule : public openglframework::Mesh, public PhysicsObject {
|
||||
|
||||
private :
|
||||
|
||||
|
@ -43,14 +44,35 @@ class Capsule : public openglframework::Mesh {
|
|||
/// Height of the capsule
|
||||
float mHeight;
|
||||
|
||||
/// Rigid body used to simulate the dynamics of the sphere
|
||||
rp3d::CollisionBody* mRigidBody;
|
||||
|
||||
/// Scaling matrix (applied to a sphere to obtain the correct sphere dimensions)
|
||||
openglframework::Matrix4 mScalingMatrix;
|
||||
|
||||
/// Previous transform (for interpolation)
|
||||
rp3d::Transform mPreviousTransform;
|
||||
|
||||
/// Vertex Buffer Object for the vertices data
|
||||
static openglframework::VertexBufferObject mVBOVertices;
|
||||
|
||||
/// Vertex Buffer Object for the normals data
|
||||
static openglframework::VertexBufferObject mVBONormals;
|
||||
|
||||
/// Vertex Buffer Object for the texture coords
|
||||
static openglframework::VertexBufferObject mVBOTextureCoords;
|
||||
|
||||
/// Vertex Buffer Object for the indices
|
||||
static openglframework::VertexBufferObject mVBOIndices;
|
||||
|
||||
/// Vertex Array Object for the vertex data
|
||||
static openglframework::VertexArrayObject mVAO;
|
||||
|
||||
// Total number of capsules created
|
||||
static int totalNbCapsules;
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
// Create the Vertex Buffer Objects used to render with OpenGL.
|
||||
void createVBOAndVAO();
|
||||
|
||||
public :
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
@ -67,28 +89,26 @@ class Capsule : public openglframework::Mesh {
|
|||
/// Destructor
|
||||
~Capsule();
|
||||
|
||||
/// Return a pointer to the collision body of the box
|
||||
reactphysics3d::CollisionBody* getCollisionBody();
|
||||
|
||||
/// Return a pointer to the rigid body of the box
|
||||
reactphysics3d::RigidBody* getRigidBody();
|
||||
|
||||
/// Update the transform matrix of the sphere
|
||||
void updateTransform();
|
||||
|
||||
/// Render the sphere at the correct position and with the correct orientation
|
||||
void render(openglframework::Shader& shader,
|
||||
const openglframework::Matrix4& worldToCameraMatrix);
|
||||
|
||||
/// Set the position of the box
|
||||
void resetTransform(const rp3d::Transform& transform);
|
||||
|
||||
/// Update the transform matrix of the object
|
||||
virtual void updateTransform(float interpolationFactor);
|
||||
};
|
||||
|
||||
// Return a pointer to the collision body of the box
|
||||
inline rp3d::CollisionBody* Capsule::getCollisionBody() {
|
||||
return mRigidBody;
|
||||
}
|
||||
|
||||
<<<<<<< HEAD:examples/common/Capsule.h
|
||||
// Return a pointer to the rigid body of the box
|
||||
inline rp3d::RigidBody* Capsule::getRigidBody() {
|
||||
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
|
|
@ -26,6 +26,13 @@
|
|||
// Libraries
|
||||
#include "Cone.h"
|
||||
|
||||
openglframework::VertexBufferObject Cone::mVBOVertices(GL_ARRAY_BUFFER);
|
||||
openglframework::VertexBufferObject Cone::mVBONormals(GL_ARRAY_BUFFER);
|
||||
openglframework::VertexBufferObject Cone::mVBOTextureCoords(GL_ARRAY_BUFFER);
|
||||
openglframework::VertexBufferObject Cone::mVBOIndices(GL_ELEMENT_ARRAY_BUFFER);
|
||||
openglframework::VertexArrayObject Cone::mVAO;
|
||||
int Cone::totalNbCones = 0;
|
||||
|
||||
// Constructor
|
||||
Cone::Cone(float radius, float height, const openglframework::Vector3 &position,
|
||||
reactphysics3d::CollisionWorld* world,
|
||||
|
@ -57,13 +64,22 @@ Cone::Cone(float radius, float height, const openglframework::Vector3 &position,
|
|||
rp3d::Quaternion initOrientation = rp3d::Quaternion::identity();
|
||||
rp3d::Transform transform(initPosition, initOrientation);
|
||||
|
||||
mPreviousTransform = transform;
|
||||
|
||||
// Create a rigid body corresponding to the cone in the dynamics world
|
||||
mRigidBody = world->createCollisionBody(transform);
|
||||
mBody = world->createCollisionBody(transform);
|
||||
|
||||
// Add a collision shape to the body and specify the mass of the shape
|
||||
mRigidBody->addCollisionShape(collisionShape, rp3d::Transform::identity());
|
||||
mBody->addCollisionShape(collisionShape, rp3d::Transform::identity());
|
||||
|
||||
mTransformMatrix = mTransformMatrix * mScalingMatrix;
|
||||
|
||||
// Create the VBOs and VAO
|
||||
if (totalNbCones == 0) {
|
||||
createVBOAndVAO();
|
||||
}
|
||||
|
||||
totalNbCones++;
|
||||
}
|
||||
|
||||
// Constructor
|
||||
|
@ -103,16 +119,34 @@ Cone::Cone(float radius, float height, const openglframework::Vector3 &position,
|
|||
// Add a collision shape to the body and specify the mass of the shape
|
||||
body->addCollisionShape(collisionShape, rp3d::Transform::identity(), mass);
|
||||
|
||||
mRigidBody = body;
|
||||
mBody = body;
|
||||
|
||||
mTransformMatrix = mTransformMatrix * mScalingMatrix;
|
||||
|
||||
// Create the VBOs and VAO
|
||||
if (totalNbCones == 0) {
|
||||
createVBOAndVAO();
|
||||
}
|
||||
|
||||
totalNbCones++;
|
||||
}
|
||||
|
||||
// Destructor
|
||||
Cone::~Cone() {
|
||||
|
||||
if (totalNbCones == 1) {
|
||||
// Destroy the mesh
|
||||
destroy();
|
||||
|
||||
// Destroy the VBOs and VAO
|
||||
mVBOIndices.destroy();
|
||||
mVBOVertices.destroy();
|
||||
mVBONormals.destroy();
|
||||
mVBOTextureCoords.destroy();
|
||||
mVAO.destroy();
|
||||
}
|
||||
|
||||
totalNbCones--;
|
||||
}
|
||||
|
||||
// Render the cone at the correct position and with the correct orientation
|
||||
|
@ -123,57 +157,126 @@ void Cone::render(openglframework::Shader& shader,
|
|||
shader.bind();
|
||||
|
||||
// Set the model to camera matrix
|
||||
const openglframework::Matrix4 localToCameraMatrix = worldToCameraMatrix * mTransformMatrix;
|
||||
shader.setMatrix4x4Uniform("localToCameraMatrix", localToCameraMatrix);
|
||||
shader.setMatrix4x4Uniform("localToWorldMatrix", mTransformMatrix);
|
||||
shader.setMatrix4x4Uniform("worldToCameraMatrix", worldToCameraMatrix);
|
||||
|
||||
// Set the normal matrix (inverse transpose of the 3x3 upper-left sub matrix of the
|
||||
// model-view matrix)
|
||||
const openglframework::Matrix4 localToCameraMatrix = worldToCameraMatrix * mTransformMatrix;
|
||||
const openglframework::Matrix3 normalMatrix =
|
||||
localToCameraMatrix.getUpperLeft3x3Matrix().getInverse().getTranspose();
|
||||
shader.setMatrix3x3Uniform("normalMatrix", normalMatrix);
|
||||
shader.setMatrix3x3Uniform("normalMatrix", normalMatrix, false);
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
if (hasTexture()) {
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
// Set the vertex color
|
||||
openglframework::Vector4 color(mColor.r, mColor.g, mColor.b, mColor.a);
|
||||
shader.setVector4Uniform("vertexColor", color, false);
|
||||
|
||||
glVertexPointer(3, GL_FLOAT, 0, getVerticesPointer());
|
||||
glNormalPointer(GL_FLOAT, 0, getNormalsPointer());
|
||||
if(hasTexture()) {
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, getUVTextureCoordinatesPointer());
|
||||
}
|
||||
// Bind the VAO
|
||||
mVAO.bind();
|
||||
|
||||
mVBOVertices.bind();
|
||||
|
||||
// Get the location of shader attribute variables
|
||||
GLint vertexPositionLoc = shader.getAttribLocation("vertexPosition");
|
||||
GLint vertexNormalLoc = shader.getAttribLocation("vertexNormal", false);
|
||||
|
||||
glEnableVertexAttribArray(vertexPositionLoc);
|
||||
glVertexAttribPointer(vertexPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, (char*)NULL);
|
||||
|
||||
mVBONormals.bind();
|
||||
|
||||
if (vertexNormalLoc != -1) glVertexAttribPointer(vertexNormalLoc, 3, GL_FLOAT, GL_FALSE, 0, (char*)NULL);
|
||||
if (vertexNormalLoc != -1) glEnableVertexAttribArray(vertexNormalLoc);
|
||||
|
||||
// For each part of the mesh
|
||||
for (unsigned int i=0; i<getNbParts(); i++) {
|
||||
glDrawElements(GL_TRIANGLES, getNbFaces(i) * 3,
|
||||
GL_UNSIGNED_INT, getIndicesPointer());
|
||||
glDrawElements(GL_TRIANGLES, getNbFaces(i) * 3, GL_UNSIGNED_INT, (char*)NULL);
|
||||
}
|
||||
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
if (hasTexture()) {
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
glDisableVertexAttribArray(vertexPositionLoc);
|
||||
if (vertexNormalLoc != -1) glDisableVertexAttribArray(vertexNormalLoc);
|
||||
|
||||
mVBONormals.unbind();
|
||||
mVBOVertices.unbind();
|
||||
|
||||
// Unbind the VAO
|
||||
mVAO.unbind();
|
||||
|
||||
// Unbind the shader
|
||||
shader.unbind();
|
||||
}
|
||||
|
||||
// Update the transform matrix of the cone
|
||||
void Cone::updateTransform() {
|
||||
// Create the Vertex Buffer Objects used to render with OpenGL.
|
||||
/// We create two VBOs (one for vertices and one for indices)
|
||||
void Cone::createVBOAndVAO() {
|
||||
|
||||
// Get the interpolated transform of the rigid body
|
||||
rp3d::Transform transform = mRigidBody->getInterpolatedTransform();
|
||||
// Create the VBO for the vertices data
|
||||
mVBOVertices.create();
|
||||
mVBOVertices.bind();
|
||||
size_t sizeVertices = mVertices.size() * sizeof(openglframework::Vector3);
|
||||
mVBOVertices.copyDataIntoVBO(sizeVertices, getVerticesPointer(), GL_STATIC_DRAW);
|
||||
mVBOVertices.unbind();
|
||||
|
||||
// Compute the transform used for rendering the cone
|
||||
rp3d::decimal matrix[16];
|
||||
transform.getOpenGLMatrix(matrix);
|
||||
openglframework::Matrix4 newMatrix(matrix[0], matrix[4], matrix[8], matrix[12],
|
||||
matrix[1], matrix[5], matrix[9], matrix[13],
|
||||
matrix[2], matrix[6], matrix[10], matrix[14],
|
||||
matrix[3], matrix[7], matrix[11], matrix[15]);
|
||||
// Create the VBO for the normals data
|
||||
mVBONormals.create();
|
||||
mVBONormals.bind();
|
||||
size_t sizeNormals = mNormals.size() * sizeof(openglframework::Vector3);
|
||||
mVBONormals.copyDataIntoVBO(sizeNormals, getNormalsPointer(), GL_STATIC_DRAW);
|
||||
mVBONormals.unbind();
|
||||
|
||||
// Apply the scaling matrix to have the correct cone dimensions
|
||||
mTransformMatrix = newMatrix * mScalingMatrix;
|
||||
if (hasTexture()) {
|
||||
// Create the VBO for the texture co data
|
||||
mVBOTextureCoords.create();
|
||||
mVBOTextureCoords.bind();
|
||||
size_t sizeTextureCoords = mUVs.size() * sizeof(openglframework::Vector2);
|
||||
mVBOTextureCoords.copyDataIntoVBO(sizeTextureCoords, getUVTextureCoordinatesPointer(), GL_STATIC_DRAW);
|
||||
mVBOTextureCoords.unbind();
|
||||
}
|
||||
|
||||
// Create th VBO for the indices data
|
||||
mVBOIndices.create();
|
||||
mVBOIndices.bind();
|
||||
size_t sizeIndices = mIndices[0].size() * sizeof(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);
|
||||
}
|
||||
|
|
@ -29,9 +29,10 @@
|
|||
// Libraries
|
||||
#include "openglframework.h"
|
||||
#include "reactphysics3d.h"
|
||||
#include "PhysicsObject.h"
|
||||
|
||||
// Class Cone
|
||||
class Cone : public openglframework::Mesh {
|
||||
class Cone : public openglframework::Mesh, public PhysicsObject {
|
||||
|
||||
private :
|
||||
|
||||
|
@ -43,14 +44,35 @@ class Cone : public openglframework::Mesh {
|
|||
/// Height of the cone
|
||||
float mHeight;
|
||||
|
||||
/// Rigid body used to simulate the dynamics of the cone
|
||||
rp3d::CollisionBody* mRigidBody;
|
||||
|
||||
/// Scaling matrix (applied to a sphere to obtain the correct cone dimensions)
|
||||
openglframework::Matrix4 mScalingMatrix;
|
||||
|
||||
/// Previous transform (for interpolation)
|
||||
rp3d::Transform mPreviousTransform;
|
||||
|
||||
/// Vertex Buffer Object for the vertices data
|
||||
static openglframework::VertexBufferObject mVBOVertices;
|
||||
|
||||
/// Vertex Buffer Object for the normals data
|
||||
static openglframework::VertexBufferObject mVBONormals;
|
||||
|
||||
/// Vertex Buffer Object for the texture coords
|
||||
static openglframework::VertexBufferObject mVBOTextureCoords;
|
||||
|
||||
/// Vertex Buffer Object for the indices
|
||||
static openglframework::VertexBufferObject mVBOIndices;
|
||||
|
||||
/// Vertex Array Object for the vertex data
|
||||
static openglframework::VertexArrayObject mVAO;
|
||||
|
||||
// Total number of cones created
|
||||
static int totalNbCones;
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
// Create the Vertex Buffer Objects used to render with OpenGL.
|
||||
void createVBOAndVAO();
|
||||
|
||||
public :
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
@ -66,28 +88,26 @@ class Cone : public openglframework::Mesh {
|
|||
/// Destructor
|
||||
~Cone();
|
||||
|
||||
/// Return a pointer to the collision body of the box
|
||||
reactphysics3d::CollisionBody* getCollisionBody();
|
||||
|
||||
/// Return a pointer to the rigid body of the box
|
||||
reactphysics3d::RigidBody* getRigidBody();
|
||||
|
||||
/// Update the transform matrix of the cone
|
||||
void updateTransform();
|
||||
|
||||
/// Render the cone at the correct position and with the correct orientation
|
||||
void render(openglframework::Shader& shader,
|
||||
const openglframework::Matrix4& worldToCameraMatrix);
|
||||
|
||||
/// Set the position of the box
|
||||
void resetTransform(const rp3d::Transform& transform);
|
||||
|
||||
/// Update the transform matrix of the object
|
||||
virtual void updateTransform(float interpolationFactor);
|
||||
};
|
||||
|
||||
// Return a pointer to the collision body of the box
|
||||
inline rp3d::CollisionBody* Cone::getCollisionBody() {
|
||||
return mRigidBody;
|
||||
}
|
||||
|
||||
<<<<<<< HEAD:examples/common/Cone.h
|
||||
// Return a pointer to the rigid body of the box
|
||||
inline rp3d::RigidBody* Cone::getRigidBody() {
|
||||
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
|
|
@ -30,7 +30,9 @@
|
|||
ConvexMesh::ConvexMesh(const openglframework::Vector3 &position,
|
||||
reactphysics3d::CollisionWorld* world,
|
||||
const std::string& meshFolderPath)
|
||||
: openglframework::Mesh() {
|
||||
: openglframework::Mesh(), mVBOVertices(GL_ARRAY_BUFFER),
|
||||
mVBONormals(GL_ARRAY_BUFFER), mVBOTextureCoords(GL_ARRAY_BUFFER),
|
||||
mVBOIndices(GL_ELEMENT_ARRAY_BUFFER) {
|
||||
|
||||
// Load the mesh from a file
|
||||
openglframework::MeshReaderWriter::loadMeshFromFile(meshFolderPath + "convexmesh.obj", *this);
|
||||
|
@ -79,18 +81,25 @@ ConvexMesh::ConvexMesh(const openglframework::Vector3 &position,
|
|||
rp3d::Quaternion initOrientation = rp3d::Quaternion::identity();
|
||||
rp3d::Transform transform(initPosition, initOrientation);
|
||||
|
||||
mPreviousTransform = transform;
|
||||
|
||||
// Create a rigid body corresponding to the sphere in the dynamics world
|
||||
mRigidBody = world->createCollisionBody(transform);
|
||||
mBody = world->createCollisionBody(transform);
|
||||
|
||||
// Add a collision shape to the body and specify the mass of the collision shape
|
||||
mRigidBody->addCollisionShape(collisionShape, rp3d::Transform::identity());
|
||||
mBody->addCollisionShape(collisionShape, rp3d::Transform::identity());
|
||||
|
||||
// Create the VBOs and VAO
|
||||
createVBOAndVAO();
|
||||
}
|
||||
|
||||
// Constructor
|
||||
ConvexMesh::ConvexMesh(const openglframework::Vector3 &position, float mass,
|
||||
reactphysics3d::DynamicsWorld* dynamicsWorld,
|
||||
const std::string& meshFolderPath)
|
||||
: openglframework::Mesh() {
|
||||
: openglframework::Mesh(), mVBOVertices(GL_ARRAY_BUFFER),
|
||||
mVBONormals(GL_ARRAY_BUFFER), mVBOTextureCoords(GL_ARRAY_BUFFER),
|
||||
mVBOIndices(GL_ELEMENT_ARRAY_BUFFER) {
|
||||
|
||||
// Load the mesh from a file
|
||||
openglframework::MeshReaderWriter::loadMeshFromFile(meshFolderPath + "convexmesh.obj", *this);
|
||||
|
@ -144,7 +153,10 @@ ConvexMesh::ConvexMesh(const openglframework::Vector3 &position, float mass,
|
|||
// Add a collision shape to the body and specify the mass of the collision shape
|
||||
body->addCollisionShape(collisionShape, rp3d::Transform::identity(), mass);
|
||||
|
||||
mRigidBody = body;
|
||||
mBody = body;
|
||||
|
||||
// Create the VBOs and VAO
|
||||
createVBOAndVAO();
|
||||
}
|
||||
|
||||
// Destructor
|
||||
|
@ -152,6 +164,13 @@ ConvexMesh::~ConvexMesh() {
|
|||
|
||||
// Destroy the mesh
|
||||
destroy();
|
||||
|
||||
// Destroy the VBOs and VAO
|
||||
mVBOIndices.destroy();
|
||||
mVBOVertices.destroy();
|
||||
mVBONormals.destroy();
|
||||
mVBOTextureCoords.destroy();
|
||||
mVAO.destroy();
|
||||
}
|
||||
|
||||
// Render the sphere at the correct position and with the correct orientation
|
||||
|
@ -162,57 +181,125 @@ void ConvexMesh::render(openglframework::Shader& shader,
|
|||
shader.bind();
|
||||
|
||||
// Set the model to camera matrix
|
||||
const openglframework::Matrix4 localToCameraMatrix = worldToCameraMatrix * mTransformMatrix;
|
||||
shader.setMatrix4x4Uniform("localToCameraMatrix", localToCameraMatrix);
|
||||
shader.setMatrix4x4Uniform("localToWorldMatrix", mTransformMatrix);
|
||||
shader.setMatrix4x4Uniform("worldToCameraMatrix", worldToCameraMatrix);
|
||||
|
||||
// Set the normal matrix (inverse transpose of the 3x3 upper-left sub matrix of the
|
||||
// model-view matrix)
|
||||
const openglframework::Matrix4 localToCameraMatrix = worldToCameraMatrix * mTransformMatrix;
|
||||
const openglframework::Matrix3 normalMatrix =
|
||||
localToCameraMatrix.getUpperLeft3x3Matrix().getInverse().getTranspose();
|
||||
shader.setMatrix3x3Uniform("normalMatrix", normalMatrix);
|
||||
shader.setMatrix3x3Uniform("normalMatrix", normalMatrix, false);
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
if (hasTexture()) {
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
// Set the vertex color
|
||||
openglframework::Vector4 color(mColor.r, mColor.g, mColor.b, mColor.a);
|
||||
shader.setVector4Uniform("vertexColor", color, false);
|
||||
|
||||
glVertexPointer(3, GL_FLOAT, 0, getVerticesPointer());
|
||||
glNormalPointer(GL_FLOAT, 0, getNormalsPointer());
|
||||
if(hasTexture()) {
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, getUVTextureCoordinatesPointer());
|
||||
}
|
||||
// Bind the VAO
|
||||
mVAO.bind();
|
||||
|
||||
mVBOVertices.bind();
|
||||
|
||||
// Get the location of shader attribute variables
|
||||
GLint vertexPositionLoc = shader.getAttribLocation("vertexPosition");
|
||||
GLint vertexNormalLoc = shader.getAttribLocation("vertexNormal", false);
|
||||
|
||||
glEnableVertexAttribArray(vertexPositionLoc);
|
||||
glVertexAttribPointer(vertexPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, (char*)NULL);
|
||||
|
||||
mVBONormals.bind();
|
||||
|
||||
if (vertexNormalLoc != -1) glVertexAttribPointer(vertexNormalLoc, 3, GL_FLOAT, GL_FALSE, 0, (char*)NULL);
|
||||
if (vertexNormalLoc != -1) glEnableVertexAttribArray(vertexNormalLoc);
|
||||
|
||||
// For each part of the mesh
|
||||
for (unsigned int i=0; i<getNbParts(); i++) {
|
||||
glDrawElements(GL_TRIANGLES, getNbFaces(i) * 3,
|
||||
GL_UNSIGNED_INT, getIndicesPointer());
|
||||
glDrawElements(GL_TRIANGLES, getNbFaces(i) * 3, GL_UNSIGNED_INT, (char*)NULL);
|
||||
}
|
||||
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
if (hasTexture()) {
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
glDisableVertexAttribArray(vertexPositionLoc);
|
||||
if (vertexNormalLoc != -1) glDisableVertexAttribArray(vertexNormalLoc);
|
||||
|
||||
mVBONormals.unbind();
|
||||
mVBOVertices.unbind();
|
||||
|
||||
// Unbind the VAO
|
||||
mVAO.unbind();
|
||||
|
||||
// Unbind the shader
|
||||
shader.unbind();
|
||||
}
|
||||
|
||||
// Update the transform matrix of the sphere
|
||||
void ConvexMesh::updateTransform() {
|
||||
// Create the Vertex Buffer Objects used to render with OpenGL.
|
||||
/// We create two VBOs (one for vertices and one for indices)
|
||||
void ConvexMesh::createVBOAndVAO() {
|
||||
|
||||
// Get the interpolated transform of the rigid body
|
||||
rp3d::Transform transform = mRigidBody->getInterpolatedTransform();
|
||||
// Create the VBO for the vertices data
|
||||
mVBOVertices.create();
|
||||
mVBOVertices.bind();
|
||||
size_t sizeVertices = mVertices.size() * sizeof(openglframework::Vector3);
|
||||
mVBOVertices.copyDataIntoVBO(sizeVertices, getVerticesPointer(), GL_STATIC_DRAW);
|
||||
mVBOVertices.unbind();
|
||||
|
||||
// Compute the transform used for rendering the sphere
|
||||
rp3d::decimal matrix[16];
|
||||
transform.getOpenGLMatrix(matrix);
|
||||
openglframework::Matrix4 newMatrix(matrix[0], matrix[4], matrix[8], matrix[12],
|
||||
matrix[1], matrix[5], matrix[9], matrix[13],
|
||||
matrix[2], matrix[6], matrix[10], matrix[14],
|
||||
matrix[3], matrix[7], matrix[11], matrix[15]);
|
||||
// Create the VBO for the normals data
|
||||
mVBONormals.create();
|
||||
mVBONormals.bind();
|
||||
size_t sizeNormals = mNormals.size() * sizeof(openglframework::Vector3);
|
||||
mVBONormals.copyDataIntoVBO(sizeNormals, getNormalsPointer(), GL_STATIC_DRAW);
|
||||
mVBONormals.unbind();
|
||||
|
||||
// Apply the scaling matrix to have the correct sphere dimensions
|
||||
mTransformMatrix = newMatrix;
|
||||
if (hasTexture()) {
|
||||
// Create the VBO for the texture co data
|
||||
mVBOTextureCoords.create();
|
||||
mVBOTextureCoords.bind();
|
||||
size_t sizeTextureCoords = mUVs.size() * sizeof(openglframework::Vector2);
|
||||
mVBOTextureCoords.copyDataIntoVBO(sizeTextureCoords, getUVTextureCoordinatesPointer(), GL_STATIC_DRAW);
|
||||
mVBOTextureCoords.unbind();
|
||||
}
|
||||
|
||||
// Create th VBO for the indices data
|
||||
mVBOIndices.create();
|
||||
mVBOIndices.bind();
|
||||
size_t sizeIndices = mIndices[0].size() * sizeof(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);
|
||||
}
|
|
@ -29,19 +29,38 @@
|
|||
// Libraries
|
||||
#include "openglframework.h"
|
||||
#include "reactphysics3d.h"
|
||||
#include "PhysicsObject.h"
|
||||
|
||||
// Class ConvexMesh
|
||||
class ConvexMesh : public openglframework::Mesh {
|
||||
class ConvexMesh : public openglframework::Mesh, public PhysicsObject {
|
||||
|
||||
private :
|
||||
|
||||
// -------------------- Attributes -------------------- //
|
||||
|
||||
/// Rigid body used to simulate the dynamics of the mesh
|
||||
rp3d::CollisionBody* mRigidBody;
|
||||
/// Previous transform (for interpolation)
|
||||
rp3d::Transform mPreviousTransform;
|
||||
|
||||
/// Vertex Buffer Object for the vertices data
|
||||
openglframework::VertexBufferObject mVBOVertices;
|
||||
|
||||
/// Vertex Buffer Object for the normals data
|
||||
openglframework::VertexBufferObject mVBONormals;
|
||||
|
||||
/// Vertex Buffer Object for the texture coords
|
||||
openglframework::VertexBufferObject mVBOTextureCoords;
|
||||
|
||||
/// Vertex Buffer Object for the indices
|
||||
openglframework::VertexBufferObject mVBOIndices;
|
||||
|
||||
/// Vertex Array Object for the vertex data
|
||||
openglframework::VertexArrayObject mVAO;
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
// Create the Vertex Buffer Objects used to render with OpenGL.
|
||||
void createVBOAndVAO();
|
||||
|
||||
public :
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
@ -57,28 +76,20 @@ class ConvexMesh : public openglframework::Mesh {
|
|||
/// Destructor
|
||||
~ConvexMesh();
|
||||
|
||||
/// Return a pointer to the collision body of the box
|
||||
reactphysics3d::CollisionBody* getCollisionBody();
|
||||
|
||||
/// Return a pointer to the rigid body of the box
|
||||
reactphysics3d::RigidBody* getRigidBody();
|
||||
|
||||
/// Update the transform matrix of the mesh
|
||||
void updateTransform();
|
||||
|
||||
/// Render the mesh at the correct position and with the correct orientation
|
||||
void render(openglframework::Shader& shader,
|
||||
const openglframework::Matrix4& worldToCameraMatrix);
|
||||
|
||||
/// Set the position of the box
|
||||
void resetTransform(const rp3d::Transform& transform);
|
||||
|
||||
/// Update the transform matrix of the object
|
||||
virtual void updateTransform(float interpolationFactor);
|
||||
};
|
||||
|
||||
// Return a pointer to the collision body of the box
|
||||
inline rp3d::CollisionBody* ConvexMesh::getCollisionBody() {
|
||||
return mRigidBody;
|
||||
}
|
||||
|
||||
// Return a pointer to the rigid body of the box
|
||||
inline rp3d::RigidBody* ConvexMesh::getRigidBody() {
|
||||
return dynamic_cast<rp3d::RigidBody*>(mRigidBody);
|
||||
// Update the transform matrix of the object
|
||||
inline void ConvexMesh::updateTransform(float interpolationFactor) {
|
||||
mTransformMatrix = computeTransform(interpolationFactor, openglframework::Matrix4::identity());
|
||||
}
|
||||
|
||||
#endif
|
|
@ -26,6 +26,13 @@
|
|||
// Libraries
|
||||
#include "Cylinder.h"
|
||||
|
||||
openglframework::VertexBufferObject Cylinder::mVBOVertices(GL_ARRAY_BUFFER);
|
||||
openglframework::VertexBufferObject Cylinder::mVBONormals(GL_ARRAY_BUFFER);
|
||||
openglframework::VertexBufferObject Cylinder::mVBOTextureCoords(GL_ARRAY_BUFFER);
|
||||
openglframework::VertexBufferObject Cylinder::mVBOIndices(GL_ELEMENT_ARRAY_BUFFER);
|
||||
openglframework::VertexArrayObject Cylinder::mVAO;
|
||||
int Cylinder::totalNbCylinders = 0;
|
||||
|
||||
// Constructor
|
||||
Cylinder::Cylinder(float radius, float height, const openglframework::Vector3& position,
|
||||
reactphysics3d::CollisionWorld* world,
|
||||
|
@ -57,13 +64,22 @@ Cylinder::Cylinder(float radius, float height, const openglframework::Vector3& p
|
|||
rp3d::Quaternion initOrientation = rp3d::Quaternion::identity();
|
||||
rp3d::Transform transform(initPosition, initOrientation);
|
||||
|
||||
mPreviousTransform = transform;
|
||||
|
||||
// Create a rigid body corresponding to the cylinder in the dynamics world
|
||||
mRigidBody = world->createCollisionBody(transform);
|
||||
mBody = world->createCollisionBody(transform);
|
||||
|
||||
// Add a collision shape to the body and specify the mass of the shape
|
||||
mRigidBody->addCollisionShape(collisionShape, rp3d::Transform::identity());
|
||||
mBody->addCollisionShape(collisionShape, rp3d::Transform::identity());
|
||||
|
||||
mTransformMatrix = mTransformMatrix * mScalingMatrix;
|
||||
|
||||
// Create the VBOs and VAO
|
||||
if (totalNbCylinders == 0) {
|
||||
createVBOAndVAO();
|
||||
}
|
||||
|
||||
totalNbCylinders++;
|
||||
}
|
||||
|
||||
// Constructor
|
||||
|
@ -105,14 +121,33 @@ Cylinder::Cylinder(float radius, float height, const openglframework::Vector3& p
|
|||
|
||||
mTransformMatrix = mTransformMatrix * mScalingMatrix;
|
||||
|
||||
mRigidBody = body;
|
||||
mBody = body;
|
||||
|
||||
// Create the VBOs and VAO
|
||||
if (totalNbCylinders == 0) {
|
||||
createVBOAndVAO();
|
||||
}
|
||||
|
||||
totalNbCylinders++;
|
||||
}
|
||||
|
||||
// Destructor
|
||||
Cylinder::~Cylinder() {
|
||||
|
||||
if (totalNbCylinders == 1) {
|
||||
|
||||
// Destroy the mesh
|
||||
destroy();
|
||||
|
||||
// Destroy the VBOs and VAO
|
||||
mVBOIndices.destroy();
|
||||
mVBOVertices.destroy();
|
||||
mVBONormals.destroy();
|
||||
mVBOTextureCoords.destroy();
|
||||
mVAO.destroy();
|
||||
}
|
||||
|
||||
totalNbCylinders--;
|
||||
}
|
||||
|
||||
// Render the cylinder at the correct position and with the correct orientation
|
||||
|
@ -123,57 +158,125 @@ void Cylinder::render(openglframework::Shader& shader,
|
|||
shader.bind();
|
||||
|
||||
// Set the model to camera matrix
|
||||
const openglframework::Matrix4 localToCameraMatrix = worldToCameraMatrix * mTransformMatrix;
|
||||
shader.setMatrix4x4Uniform("localToCameraMatrix", localToCameraMatrix);
|
||||
shader.setMatrix4x4Uniform("localToWorldMatrix", mTransformMatrix);
|
||||
shader.setMatrix4x4Uniform("worldToCameraMatrix", worldToCameraMatrix);
|
||||
|
||||
// Set the normal matrix (inverse transpose of the 3x3 upper-left sub matrix of the
|
||||
// model-view matrix)
|
||||
const openglframework::Matrix4 localToCameraMatrix = worldToCameraMatrix * mTransformMatrix;
|
||||
const openglframework::Matrix3 normalMatrix =
|
||||
localToCameraMatrix.getUpperLeft3x3Matrix().getInverse().getTranspose();
|
||||
shader.setMatrix3x3Uniform("normalMatrix", normalMatrix);
|
||||
shader.setMatrix3x3Uniform("normalMatrix", normalMatrix, false);
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
if (hasTexture()) {
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
// Set the vertex color
|
||||
openglframework::Vector4 color(mColor.r, mColor.g, mColor.b, mColor.a);
|
||||
shader.setVector4Uniform("vertexColor", color, false);
|
||||
|
||||
glVertexPointer(3, GL_FLOAT, 0, getVerticesPointer());
|
||||
glNormalPointer(GL_FLOAT, 0, getNormalsPointer());
|
||||
if(hasTexture()) {
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, getUVTextureCoordinatesPointer());
|
||||
}
|
||||
// Bind the VAO
|
||||
mVAO.bind();
|
||||
|
||||
mVBOVertices.bind();
|
||||
|
||||
// Get the location of shader attribute variables
|
||||
GLint vertexPositionLoc = shader.getAttribLocation("vertexPosition");
|
||||
GLint vertexNormalLoc = shader.getAttribLocation("vertexNormal", false);
|
||||
|
||||
glEnableVertexAttribArray(vertexPositionLoc);
|
||||
glVertexAttribPointer(vertexPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, (char*)NULL);
|
||||
|
||||
mVBONormals.bind();
|
||||
|
||||
if (vertexNormalLoc != -1) glVertexAttribPointer(vertexNormalLoc, 3, GL_FLOAT, GL_FALSE, 0, (char*)NULL);
|
||||
if (vertexNormalLoc != -1) glEnableVertexAttribArray(vertexNormalLoc);
|
||||
|
||||
// For each part of the mesh
|
||||
for (unsigned int i=0; i<getNbParts(); i++) {
|
||||
glDrawElements(GL_TRIANGLES, getNbFaces(i) * 3,
|
||||
GL_UNSIGNED_INT, getIndicesPointer());
|
||||
glDrawElements(GL_TRIANGLES, getNbFaces(i) * 3, GL_UNSIGNED_INT, (char*)NULL);
|
||||
}
|
||||
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
if (hasTexture()) {
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
glDisableVertexAttribArray(vertexPositionLoc);
|
||||
if (vertexNormalLoc != -1) glDisableVertexAttribArray(vertexNormalLoc);
|
||||
|
||||
mVBONormals.unbind();
|
||||
mVBOVertices.unbind();
|
||||
|
||||
// Unbind the VAO
|
||||
mVAO.unbind();
|
||||
|
||||
// Unbind the shader
|
||||
shader.unbind();
|
||||
}
|
||||
|
||||
// Update the transform matrix of the cylinder
|
||||
void Cylinder::updateTransform() {
|
||||
// Create the Vertex Buffer Objects used to render with OpenGL.
|
||||
/// We create two VBOs (one for vertices and one for indices)
|
||||
void Cylinder::createVBOAndVAO() {
|
||||
|
||||
// Get the interpolated transform of the rigid body
|
||||
rp3d::Transform transform = mRigidBody->getInterpolatedTransform();
|
||||
// Create the VBO for the vertices data
|
||||
mVBOVertices.create();
|
||||
mVBOVertices.bind();
|
||||
size_t sizeVertices = mVertices.size() * sizeof(openglframework::Vector3);
|
||||
mVBOVertices.copyDataIntoVBO(sizeVertices, getVerticesPointer(), GL_STATIC_DRAW);
|
||||
mVBOVertices.unbind();
|
||||
|
||||
// Compute the transform used for rendering the cylinder
|
||||
rp3d::decimal matrix[16];
|
||||
transform.getOpenGLMatrix(matrix);
|
||||
openglframework::Matrix4 newMatrix(matrix[0], matrix[4], matrix[8], matrix[12],
|
||||
matrix[1], matrix[5], matrix[9], matrix[13],
|
||||
matrix[2], matrix[6], matrix[10], matrix[14],
|
||||
matrix[3], matrix[7], matrix[11], matrix[15]);
|
||||
// Create the VBO for the normals data
|
||||
mVBONormals.create();
|
||||
mVBONormals.bind();
|
||||
size_t sizeNormals = mNormals.size() * sizeof(openglframework::Vector3);
|
||||
mVBONormals.copyDataIntoVBO(sizeNormals, getNormalsPointer(), GL_STATIC_DRAW);
|
||||
mVBONormals.unbind();
|
||||
|
||||
// Apply the scaling matrix to have the correct cylinder dimensions
|
||||
mTransformMatrix = newMatrix * mScalingMatrix;
|
||||
if (hasTexture()) {
|
||||
// Create the VBO for the texture co data
|
||||
mVBOTextureCoords.create();
|
||||
mVBOTextureCoords.bind();
|
||||
size_t sizeTextureCoords = mUVs.size() * sizeof(openglframework::Vector2);
|
||||
mVBOTextureCoords.copyDataIntoVBO(sizeTextureCoords, getUVTextureCoordinatesPointer(), GL_STATIC_DRAW);
|
||||
mVBOTextureCoords.unbind();
|
||||
}
|
||||
|
||||
// Create th VBO for the indices data
|
||||
mVBOIndices.create();
|
||||
mVBOIndices.bind();
|
||||
size_t sizeIndices = mIndices[0].size() * sizeof(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);
|
||||
}
|
|
@ -29,9 +29,10 @@
|
|||
// Libraries
|
||||
#include "openglframework.h"
|
||||
#include "reactphysics3d.h"
|
||||
#include "PhysicsObject.h"
|
||||
|
||||
// Class Cylinder
|
||||
class Cylinder : public openglframework::Mesh {
|
||||
class Cylinder : public openglframework::Mesh, public PhysicsObject {
|
||||
|
||||
private :
|
||||
|
||||
|
@ -43,14 +44,35 @@ class Cylinder : public openglframework::Mesh {
|
|||
/// Height of the cylinder
|
||||
float mHeight;
|
||||
|
||||
/// Rigid body used to simulate the dynamics of the cylinder
|
||||
rp3d::CollisionBody* mRigidBody;
|
||||
|
||||
/// Scaling matrix (applied to a sphere to obtain the correct cylinder dimensions)
|
||||
openglframework::Matrix4 mScalingMatrix;
|
||||
|
||||
/// Previous transform (for interpolation)
|
||||
rp3d::Transform mPreviousTransform;
|
||||
|
||||
/// Vertex Buffer Object for the vertices data
|
||||
static openglframework::VertexBufferObject mVBOVertices;
|
||||
|
||||
/// Vertex Buffer Object for the normals data
|
||||
static openglframework::VertexBufferObject mVBONormals;
|
||||
|
||||
/// Vertex Buffer Object for the texture coords
|
||||
static openglframework::VertexBufferObject mVBOTextureCoords;
|
||||
|
||||
/// Vertex Buffer Object for the indices
|
||||
static openglframework::VertexBufferObject mVBOIndices;
|
||||
|
||||
/// Vertex Array Object for the vertex data
|
||||
static openglframework::VertexArrayObject mVAO;
|
||||
|
||||
// Total number of capsules created
|
||||
static int totalNbCylinders;
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
// Create the Vertex Buffer Objects used to render with OpenGL.
|
||||
void createVBOAndVAO();
|
||||
|
||||
public :
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
@ -66,28 +88,20 @@ class Cylinder : public openglframework::Mesh {
|
|||
/// Destructor
|
||||
~Cylinder();
|
||||
|
||||
/// Return a pointer to the collision body of the box
|
||||
reactphysics3d::CollisionBody* getCollisionBody();
|
||||
|
||||
/// Return a pointer to the rigid body of the box
|
||||
reactphysics3d::RigidBody* getRigidBody();
|
||||
|
||||
/// Update the transform matrix of the cylinder
|
||||
void updateTransform();
|
||||
|
||||
/// Render the cylinder at the correct position and with the correct orientation
|
||||
void render(openglframework::Shader& shader,
|
||||
const openglframework::Matrix4& worldToCameraMatrix);
|
||||
|
||||
/// Set the position of the box
|
||||
void resetTransform(const rp3d::Transform& transform);
|
||||
|
||||
/// Update the transform matrix of the object
|
||||
virtual void updateTransform(float interpolationFactor);
|
||||
};
|
||||
|
||||
// Return a pointer to the collision body of the box
|
||||
inline rp3d::CollisionBody* Cylinder::getCollisionBody() {
|
||||
return mRigidBody;
|
||||
}
|
||||
|
||||
// Return a pointer to the rigid body of the box
|
||||
inline rp3d::RigidBody* Cylinder::getRigidBody() {
|
||||
return dynamic_cast<rp3d::RigidBody*>(mRigidBody);
|
||||
// Update the transform matrix of the object
|
||||
inline void Cylinder::updateTransform(float interpolationFactor) {
|
||||
mTransformMatrix = computeTransform(interpolationFactor, mScalingMatrix);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -26,6 +26,13 @@
|
|||
// Libraries
|
||||
#include "Dumbbell.h"
|
||||
|
||||
openglframework::VertexBufferObject Dumbbell::mVBOVertices(GL_ARRAY_BUFFER);
|
||||
openglframework::VertexBufferObject Dumbbell::mVBONormals(GL_ARRAY_BUFFER);
|
||||
openglframework::VertexBufferObject Dumbbell::mVBOTextureCoords(GL_ARRAY_BUFFER);
|
||||
openglframework::VertexBufferObject Dumbbell::mVBOIndices(GL_ELEMENT_ARRAY_BUFFER);
|
||||
openglframework::VertexArrayObject Dumbbell::mVAO;
|
||||
int Dumbbell::totalNbDumbbells = 0;
|
||||
|
||||
// Constructor
|
||||
Dumbbell::Dumbbell(const openglframework::Vector3 &position,
|
||||
reactphysics3d::DynamicsWorld* dynamicsWorld, const std::string& meshFolderPath)
|
||||
|
@ -64,6 +71,8 @@ Dumbbell::Dumbbell(const openglframework::Vector3 &position,
|
|||
rp3d::Quaternion initOrientation(angleAroundX, 0, 0);
|
||||
rp3d::Transform transformBody(initPosition, initOrientation);
|
||||
|
||||
mPreviousTransform = transformBody;
|
||||
|
||||
// Initial transform of the first sphere collision shape of the dumbbell (in local-space)
|
||||
rp3d::Transform transformSphereShape1(rp3d::Vector3(0, 4.0, 0), rp3d::Quaternion::identity());
|
||||
|
||||
|
@ -84,6 +93,13 @@ Dumbbell::Dumbbell(const openglframework::Vector3 &position,
|
|||
mBody = body;
|
||||
|
||||
mTransformMatrix = mTransformMatrix * mScalingMatrix;
|
||||
|
||||
// Create the VBOs and VAO
|
||||
if (totalNbDumbbells == 0) {
|
||||
createVBOAndVAO();
|
||||
}
|
||||
|
||||
totalNbDumbbells++;
|
||||
}
|
||||
|
||||
// Constructor
|
||||
|
@ -142,13 +158,32 @@ Dumbbell::Dumbbell(const openglframework::Vector3 &position,
|
|||
mBody->addCollisionShape(cylinderCollisionShape, transformCylinderShape);
|
||||
|
||||
mTransformMatrix = mTransformMatrix * mScalingMatrix;
|
||||
|
||||
// Create the VBOs and VAO
|
||||
if (totalNbDumbbells == 0) {
|
||||
createVBOAndVAO();
|
||||
}
|
||||
|
||||
totalNbDumbbells++;
|
||||
}
|
||||
|
||||
// Destructor
|
||||
Dumbbell::~Dumbbell() {
|
||||
|
||||
if (totalNbDumbbells == 1) {
|
||||
|
||||
// Destroy the mesh
|
||||
destroy();
|
||||
|
||||
// Destroy the VBOs and VAO
|
||||
mVBOIndices.destroy();
|
||||
mVBOVertices.destroy();
|
||||
mVBONormals.destroy();
|
||||
mVBOTextureCoords.destroy();
|
||||
mVAO.destroy();
|
||||
}
|
||||
|
||||
totalNbDumbbells--;
|
||||
}
|
||||
|
||||
// Render the sphere at the correct position and with the correct orientation
|
||||
|
@ -159,58 +194,125 @@ void Dumbbell::render(openglframework::Shader& shader,
|
|||
shader.bind();
|
||||
|
||||
// Set the model to camera matrix
|
||||
const openglframework::Matrix4 localToCameraMatrix = worldToCameraMatrix * mTransformMatrix;
|
||||
shader.setMatrix4x4Uniform("localToCameraMatrix", localToCameraMatrix);
|
||||
shader.setMatrix4x4Uniform("localToWorldMatrix", mTransformMatrix);
|
||||
shader.setMatrix4x4Uniform("worldToCameraMatrix", worldToCameraMatrix);
|
||||
|
||||
// Set the normal matrix (inverse transpose of the 3x3 upper-left sub matrix of the
|
||||
// model-view matrix)
|
||||
const openglframework::Matrix4 localToCameraMatrix = worldToCameraMatrix * mTransformMatrix;
|
||||
const openglframework::Matrix3 normalMatrix =
|
||||
localToCameraMatrix.getUpperLeft3x3Matrix().getInverse().getTranspose();
|
||||
shader.setMatrix3x3Uniform("normalMatrix", normalMatrix);
|
||||
shader.setMatrix3x3Uniform("normalMatrix", normalMatrix, false);
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
if (hasTexture()) {
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
// Set the vertex color
|
||||
openglframework::Vector4 color(mColor.r, mColor.g, mColor.b, mColor.a);
|
||||
shader.setVector4Uniform("vertexColor", color, false);
|
||||
|
||||
glVertexPointer(3, GL_FLOAT, 0, getVerticesPointer());
|
||||
glNormalPointer(GL_FLOAT, 0, getNormalsPointer());
|
||||
if(hasTexture()) {
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, getUVTextureCoordinatesPointer());
|
||||
}
|
||||
// Bind the VAO
|
||||
mVAO.bind();
|
||||
|
||||
mVBOVertices.bind();
|
||||
|
||||
// Get the location of shader attribute variables
|
||||
GLint vertexPositionLoc = shader.getAttribLocation("vertexPosition");
|
||||
GLint vertexNormalLoc = shader.getAttribLocation("vertexNormal", false);
|
||||
|
||||
glEnableVertexAttribArray(vertexPositionLoc);
|
||||
glVertexAttribPointer(vertexPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, (char*)NULL);
|
||||
|
||||
mVBONormals.bind();
|
||||
|
||||
if (vertexNormalLoc != -1) glEnableVertexAttribArray(vertexNormalLoc);
|
||||
if (vertexNormalLoc != -1) glVertexAttribPointer(vertexNormalLoc, 3, GL_FLOAT, GL_FALSE, 0, (char*)NULL);
|
||||
|
||||
// For each part of the mesh
|
||||
for (unsigned int i=0; i<getNbParts(); i++) {
|
||||
glDrawElements(GL_TRIANGLES, getNbFaces(i) * 3,
|
||||
GL_UNSIGNED_INT, getIndicesPointer());
|
||||
glDrawElements(GL_TRIANGLES, getNbFaces(i) * 3, GL_UNSIGNED_INT, (char*)NULL);
|
||||
}
|
||||
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
if (hasTexture()) {
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
glDisableVertexAttribArray(vertexPositionLoc);
|
||||
if (vertexNormalLoc != -1) glDisableVertexAttribArray(vertexNormalLoc);
|
||||
|
||||
mVBONormals.unbind();
|
||||
mVBOVertices.unbind();
|
||||
|
||||
// Unbind the VAO
|
||||
mVAO.unbind();
|
||||
|
||||
// Unbind the shader
|
||||
shader.unbind();
|
||||
}
|
||||
|
||||
// Update the transform matrix of the sphere
|
||||
void Dumbbell::updateTransform() {
|
||||
// Create the Vertex Buffer Objects used to render with OpenGL.
|
||||
/// We create two VBOs (one for vertices and one for indices)
|
||||
void Dumbbell::createVBOAndVAO() {
|
||||
|
||||
// Get the interpolated transform of the rigid body
|
||||
rp3d::Transform transform = mBody->getInterpolatedTransform();
|
||||
// Create the VBO for the vertices data
|
||||
mVBOVertices.create();
|
||||
mVBOVertices.bind();
|
||||
size_t sizeVertices = mVertices.size() * sizeof(openglframework::Vector3);
|
||||
mVBOVertices.copyDataIntoVBO(sizeVertices, getVerticesPointer(), GL_STATIC_DRAW);
|
||||
mVBOVertices.unbind();
|
||||
|
||||
// Compute the transform used for rendering the sphere
|
||||
rp3d::decimal matrix[16];
|
||||
transform.getOpenGLMatrix(matrix);
|
||||
openglframework::Matrix4 newMatrix(matrix[0], matrix[4], matrix[8], matrix[12],
|
||||
matrix[1], matrix[5], matrix[9], matrix[13],
|
||||
matrix[2], matrix[6], matrix[10], matrix[14],
|
||||
matrix[3], matrix[7], matrix[11], matrix[15]);
|
||||
// Create the VBO for the normals data
|
||||
mVBONormals.create();
|
||||
mVBONormals.bind();
|
||||
size_t sizeNormals = mNormals.size() * sizeof(openglframework::Vector3);
|
||||
mVBONormals.copyDataIntoVBO(sizeNormals, getNormalsPointer(), GL_STATIC_DRAW);
|
||||
mVBONormals.unbind();
|
||||
|
||||
// Apply the scaling matrix to have the correct sphere dimensions
|
||||
mTransformMatrix = newMatrix * mScalingMatrix;
|
||||
if (hasTexture()) {
|
||||
// Create the VBO for the texture co data
|
||||
mVBOTextureCoords.create();
|
||||
mVBOTextureCoords.bind();
|
||||
size_t sizeTextureCoords = mUVs.size() * sizeof(openglframework::Vector2);
|
||||
mVBOTextureCoords.copyDataIntoVBO(sizeTextureCoords, getUVTextureCoordinatesPointer(), GL_STATIC_DRAW);
|
||||
mVBOTextureCoords.unbind();
|
||||
}
|
||||
|
||||
// Create th VBO for the indices data
|
||||
mVBOIndices.create();
|
||||
mVBOIndices.bind();
|
||||
size_t sizeIndices = mIndices[0].size() * sizeof(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);
|
||||
}
|
|
@ -29,9 +29,10 @@
|
|||
// Libraries
|
||||
#include "openglframework.h"
|
||||
#include "reactphysics3d.h"
|
||||
#include "PhysicsObject.h"
|
||||
|
||||
// Class Sphere
|
||||
class Dumbbell : public openglframework::Mesh {
|
||||
class Dumbbell : public openglframework::Mesh, public PhysicsObject {
|
||||
|
||||
private :
|
||||
|
||||
|
@ -40,14 +41,35 @@ class Dumbbell : public openglframework::Mesh {
|
|||
/// Radius of the spheres
|
||||
float mRadius;
|
||||
|
||||
/// Rigid body used to simulate the dynamics of the sphere
|
||||
rp3d::CollisionBody* mBody;
|
||||
|
||||
/// Scaling matrix (applied to a sphere to obtain the correct sphere dimensions)
|
||||
openglframework::Matrix4 mScalingMatrix;
|
||||
|
||||
/// Previous transform (for interpolation)
|
||||
rp3d::Transform mPreviousTransform;
|
||||
|
||||
/// Vertex Buffer Object for the vertices data
|
||||
static openglframework::VertexBufferObject mVBOVertices;
|
||||
|
||||
/// Vertex Buffer Object for the normals data
|
||||
static openglframework::VertexBufferObject mVBONormals;
|
||||
|
||||
/// Vertex Buffer Object for the texture coords
|
||||
static openglframework::VertexBufferObject mVBOTextureCoords;
|
||||
|
||||
/// Vertex Buffer Object for the indices
|
||||
static openglframework::VertexBufferObject mVBOIndices;
|
||||
|
||||
/// Vertex Array Object for the vertex data
|
||||
static openglframework::VertexArrayObject mVAO;
|
||||
|
||||
// Total number of capsules created
|
||||
static int totalNbDumbbells;
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
// Create the Vertex Buffer Objects used to render with OpenGL.
|
||||
void createVBOAndVAO();
|
||||
|
||||
public :
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
@ -64,28 +86,20 @@ class Dumbbell : public openglframework::Mesh {
|
|||
/// Destructor
|
||||
~Dumbbell();
|
||||
|
||||
/// Return a pointer to the rigid body
|
||||
rp3d::RigidBody* getRigidBody();
|
||||
|
||||
/// Return a pointer to the body
|
||||
rp3d::CollisionBody* getCollisionBody();
|
||||
|
||||
/// Update the transform matrix of the sphere
|
||||
void updateTransform();
|
||||
|
||||
/// Render the sphere at the correct position and with the correct orientation
|
||||
void render(openglframework::Shader& shader,
|
||||
const openglframework::Matrix4& worldToCameraMatrix);
|
||||
|
||||
/// Set the position of the box
|
||||
void resetTransform(const rp3d::Transform& transform);
|
||||
|
||||
/// Update the transform matrix of the object
|
||||
virtual void updateTransform(float interpolationFactor);
|
||||
};
|
||||
|
||||
// Return a pointer to the rigid body of the sphere
|
||||
inline rp3d::RigidBody* Dumbbell::getRigidBody() {
|
||||
return dynamic_cast<rp3d::RigidBody*>(mBody);
|
||||
}
|
||||
|
||||
// Return a pointer to the body
|
||||
inline rp3d::CollisionBody* Dumbbell::getCollisionBody() {
|
||||
return mBody;
|
||||
// Update the transform matrix of the object
|
||||
inline void Dumbbell::updateTransform(float interpolationFactor) {
|
||||
mTransformMatrix = computeTransform(interpolationFactor, mScalingMatrix);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -47,7 +47,12 @@ void Line::render(openglframework::Shader& shader,
|
|||
shader.bind();
|
||||
|
||||
// Set the model to camera matrix
|
||||
shader.setMatrix4x4Uniform("localToCameraMatrix", worldToCameraMatrix);
|
||||
shader.setMatrix4x4Uniform("localToWorldMatrix", openglframework::Matrix4::identity());
|
||||
shader.setMatrix4x4Uniform("worldToCameraMatrix", worldToCameraMatrix);
|
||||
|
||||
// Set the vertex color
|
||||
openglframework::Vector4 color(1, 0, 0, 1);
|
||||
shader.setVector4Uniform("vertexColor", color, false);
|
||||
|
||||
glBegin(GL_LINES);
|
||||
glVertex3f(mWorldPoint1.x, mWorldPoint1.y, mWorldPoint1.z);
|
|
@ -58,9 +58,6 @@ class Line : public openglframework::Object3D {
|
|||
/// Return the second point of the line
|
||||
openglframework::Vector3 getPoint2() const;
|
||||
|
||||
/// Update the transform matrix of the sphere
|
||||
void updateTransform();
|
||||
|
||||
/// Render the line at the correct position and with the correct orientation
|
||||
void render(openglframework::Shader& shader,
|
||||
const openglframework::Matrix4& worldToCameraMatrix);
|
59
testbed/common/PhysicsObject.cpp
Normal file
59
testbed/common/PhysicsObject.cpp
Normal 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;
|
||||
}
|
96
testbed/common/PhysicsObject.h
Normal file
96
testbed/common/PhysicsObject.h
Normal 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
|
||||
|
|
@ -26,6 +26,13 @@
|
|||
// Libraries
|
||||
#include "Sphere.h"
|
||||
|
||||
openglframework::VertexBufferObject Sphere::mVBOVertices(GL_ARRAY_BUFFER);
|
||||
openglframework::VertexBufferObject Sphere::mVBONormals(GL_ARRAY_BUFFER);
|
||||
openglframework::VertexBufferObject Sphere::mVBOTextureCoords(GL_ARRAY_BUFFER);
|
||||
openglframework::VertexBufferObject Sphere::mVBOIndices(GL_ELEMENT_ARRAY_BUFFER);
|
||||
openglframework::VertexArrayObject Sphere::mVAO;
|
||||
int Sphere::totalNbSpheres = 0;
|
||||
|
||||
// Constructor
|
||||
Sphere::Sphere(float radius, const openglframework::Vector3 &position,
|
||||
reactphysics3d::CollisionWorld* world,
|
||||
|
@ -57,13 +64,22 @@ Sphere::Sphere(float radius, const openglframework::Vector3 &position,
|
|||
rp3d::Quaternion initOrientation = rp3d::Quaternion::identity();
|
||||
rp3d::Transform transform(initPosition, initOrientation);
|
||||
|
||||
mPreviousTransform = transform;
|
||||
|
||||
// Create a rigid body corresponding to the sphere in the dynamics world
|
||||
mRigidBody = world->createCollisionBody(transform);
|
||||
mBody = world->createCollisionBody(transform);
|
||||
|
||||
// Add a collision shape to the body and specify the mass of the shape
|
||||
mRigidBody->addCollisionShape(collisionShape, rp3d::Transform::identity());
|
||||
mBody->addCollisionShape(collisionShape, rp3d::Transform::identity());
|
||||
|
||||
mTransformMatrix = mTransformMatrix * mScalingMatrix;
|
||||
|
||||
// Create the VBOs and VAO
|
||||
if (totalNbSpheres == 0) {
|
||||
createVBOAndVAO();
|
||||
}
|
||||
|
||||
totalNbSpheres++;
|
||||
}
|
||||
|
||||
// Constructor
|
||||
|
@ -103,16 +119,34 @@ Sphere::Sphere(float radius, const openglframework::Vector3 &position,
|
|||
// Add a collision shape to the body and specify the mass of the shape
|
||||
body->addCollisionShape(collisionShape, rp3d::Transform::identity(), mass);
|
||||
|
||||
mRigidBody = body;
|
||||
mBody = body;
|
||||
|
||||
mTransformMatrix = mTransformMatrix * mScalingMatrix;
|
||||
|
||||
// Create the VBOs and VAO
|
||||
if (totalNbSpheres == 0) {
|
||||
createVBOAndVAO();
|
||||
}
|
||||
|
||||
totalNbSpheres++;
|
||||
}
|
||||
|
||||
// Destructor
|
||||
Sphere::~Sphere() {
|
||||
|
||||
if (totalNbSpheres == 1) {
|
||||
// Destroy the mesh
|
||||
destroy();
|
||||
|
||||
// Destroy the VBOs and VAO
|
||||
mVBOIndices.destroy();
|
||||
mVBOVertices.destroy();
|
||||
mVBONormals.destroy();
|
||||
mVBOTextureCoords.destroy();
|
||||
mVAO.destroy();
|
||||
}
|
||||
|
||||
totalNbSpheres--;
|
||||
}
|
||||
|
||||
// Render the sphere at the correct position and with the correct orientation
|
||||
|
@ -123,57 +157,125 @@ void Sphere::render(openglframework::Shader& shader,
|
|||
shader.bind();
|
||||
|
||||
// Set the model to camera matrix
|
||||
const openglframework::Matrix4 localToCameraMatrix = worldToCameraMatrix * mTransformMatrix;
|
||||
shader.setMatrix4x4Uniform("localToCameraMatrix", localToCameraMatrix);
|
||||
shader.setMatrix4x4Uniform("localToWorldMatrix", mTransformMatrix);
|
||||
shader.setMatrix4x4Uniform("worldToCameraMatrix", worldToCameraMatrix);
|
||||
|
||||
// Set the normal matrix (inverse transpose of the 3x3 upper-left sub matrix of the
|
||||
// model-view matrix)
|
||||
const openglframework::Matrix4 localToCameraMatrix = worldToCameraMatrix * mTransformMatrix;
|
||||
const openglframework::Matrix3 normalMatrix =
|
||||
localToCameraMatrix.getUpperLeft3x3Matrix().getInverse().getTranspose();
|
||||
shader.setMatrix3x3Uniform("normalMatrix", normalMatrix);
|
||||
shader.setMatrix3x3Uniform("normalMatrix", normalMatrix, false);
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
if (hasTexture()) {
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
// Set the vertex color
|
||||
openglframework::Vector4 color(mColor.r, mColor.g, mColor.b, mColor.a);
|
||||
shader.setVector4Uniform("vertexColor", color, false);
|
||||
|
||||
glVertexPointer(3, GL_FLOAT, 0, getVerticesPointer());
|
||||
glNormalPointer(GL_FLOAT, 0, getNormalsPointer());
|
||||
if(hasTexture()) {
|
||||
glTexCoordPointer(2, GL_FLOAT, 0, getUVTextureCoordinatesPointer());
|
||||
}
|
||||
// Bind the VAO
|
||||
mVAO.bind();
|
||||
|
||||
mVBOVertices.bind();
|
||||
|
||||
// Get the location of shader attribute variables
|
||||
GLint vertexPositionLoc = shader.getAttribLocation("vertexPosition");
|
||||
GLint vertexNormalLoc = shader.getAttribLocation("vertexNormal", false);
|
||||
|
||||
glEnableVertexAttribArray(vertexPositionLoc);
|
||||
glVertexAttribPointer(vertexPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, (char*)NULL);
|
||||
|
||||
mVBONormals.bind();
|
||||
|
||||
if (vertexNormalLoc != -1) glVertexAttribPointer(vertexNormalLoc, 3, GL_FLOAT, GL_FALSE, 0, (char*)NULL);
|
||||
if (vertexNormalLoc != -1) glEnableVertexAttribArray(vertexNormalLoc);
|
||||
|
||||
// For each part of the mesh
|
||||
for (unsigned int i=0; i<getNbParts(); i++) {
|
||||
glDrawElements(GL_TRIANGLES, getNbFaces(i) * 3,
|
||||
GL_UNSIGNED_INT, getIndicesPointer());
|
||||
glDrawElements(GL_TRIANGLES, getNbFaces(i) * 3, GL_UNSIGNED_INT, (char*)NULL);
|
||||
}
|
||||
|
||||
glDisableClientState(GL_NORMAL_ARRAY);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
if (hasTexture()) {
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
}
|
||||
glDisableVertexAttribArray(vertexPositionLoc);
|
||||
if (vertexNormalLoc != -1) glDisableVertexAttribArray(vertexNormalLoc);
|
||||
|
||||
mVBONormals.unbind();
|
||||
mVBOVertices.unbind();
|
||||
|
||||
// Unbind the VAO
|
||||
mVAO.unbind();
|
||||
|
||||
// Unbind the shader
|
||||
shader.unbind();
|
||||
}
|
||||
|
||||
// Update the transform matrix of the sphere
|
||||
void Sphere::updateTransform() {
|
||||
// Create the Vertex Buffer Objects used to render with OpenGL.
|
||||
/// We create two VBOs (one for vertices and one for indices)
|
||||
void Sphere::createVBOAndVAO() {
|
||||
|
||||
// Get the interpolated transform of the rigid body
|
||||
rp3d::Transform transform = mRigidBody->getInterpolatedTransform();
|
||||
// Create the VBO for the vertices data
|
||||
mVBOVertices.create();
|
||||
mVBOVertices.bind();
|
||||
size_t sizeVertices = mVertices.size() * sizeof(openglframework::Vector3);
|
||||
mVBOVertices.copyDataIntoVBO(sizeVertices, getVerticesPointer(), GL_STATIC_DRAW);
|
||||
mVBOVertices.unbind();
|
||||
|
||||
// Compute the transform used for rendering the sphere
|
||||
rp3d::decimal matrix[16];
|
||||
transform.getOpenGLMatrix(matrix);
|
||||
openglframework::Matrix4 newMatrix(matrix[0], matrix[4], matrix[8], matrix[12],
|
||||
matrix[1], matrix[5], matrix[9], matrix[13],
|
||||
matrix[2], matrix[6], matrix[10], matrix[14],
|
||||
matrix[3], matrix[7], matrix[11], matrix[15]);
|
||||
// Create the VBO for the normals data
|
||||
mVBONormals.create();
|
||||
mVBONormals.bind();
|
||||
size_t sizeNormals = mNormals.size() * sizeof(openglframework::Vector3);
|
||||
mVBONormals.copyDataIntoVBO(sizeNormals, getNormalsPointer(), GL_STATIC_DRAW);
|
||||
mVBONormals.unbind();
|
||||
|
||||
// Apply the scaling matrix to have the correct sphere dimensions
|
||||
mTransformMatrix = newMatrix * mScalingMatrix;
|
||||
if (hasTexture()) {
|
||||
// Create the VBO for the texture co data
|
||||
mVBOTextureCoords.create();
|
||||
mVBOTextureCoords.bind();
|
||||
size_t sizeTextureCoords = mUVs.size() * sizeof(openglframework::Vector2);
|
||||
mVBOTextureCoords.copyDataIntoVBO(sizeTextureCoords, getUVTextureCoordinatesPointer(), GL_STATIC_DRAW);
|
||||
mVBOTextureCoords.unbind();
|
||||
}
|
||||
|
||||
// Create th VBO for the indices data
|
||||
mVBOIndices.create();
|
||||
mVBOIndices.bind();
|
||||
size_t sizeIndices = mIndices[0].size() * sizeof(uint);
|
||||
mVBOIndices.copyDataIntoVBO(sizeIndices, getIndicesPointer(), GL_STATIC_DRAW);
|
||||
mVBOIndices.unbind();
|
||||
|
||||
// Create the VAO for both VBOs
|
||||
mVAO.create();
|
||||
mVAO.bind();
|
||||
|
||||
// Bind the VBO of vertices
|
||||
mVBOVertices.bind();
|
||||
|
||||
// Bind the VBO of normals
|
||||
mVBONormals.bind();
|
||||
|
||||
if (hasTexture()) {
|
||||
// Bind the VBO of texture coords
|
||||
mVBOTextureCoords.bind();
|
||||
}
|
||||
|
||||
// Bind the VBO of indices
|
||||
mVBOIndices.bind();
|
||||
|
||||
// Unbind the VAO
|
||||
mVAO.unbind();
|
||||
}
|
||||
|
||||
// Reset the transform
|
||||
void Sphere::resetTransform(const rp3d::Transform& transform) {
|
||||
|
||||
// Reset the transform
|
||||
mBody->setTransform(transform);
|
||||
|
||||
mBody->setIsSleeping(false);
|
||||
|
||||
// Reset the velocity of the rigid body
|
||||
rp3d::RigidBody* rigidBody = dynamic_cast<rp3d::RigidBody*>(mBody);
|
||||
if (rigidBody != NULL) {
|
||||
rigidBody->setLinearVelocity(rp3d::Vector3(0, 0, 0));
|
||||
rigidBody->setAngularVelocity(rp3d::Vector3(0, 0, 0));
|
||||
}
|
||||
|
||||
updateTransform(1.0f);
|
||||
}
|
|
@ -29,9 +29,10 @@
|
|||
// Libraries
|
||||
#include "openglframework.h"
|
||||
#include "reactphysics3d.h"
|
||||
#include "PhysicsObject.h"
|
||||
|
||||
// Class Sphere
|
||||
class Sphere : public openglframework::Mesh {
|
||||
class Sphere : public openglframework::Mesh, public PhysicsObject {
|
||||
|
||||
private :
|
||||
|
||||
|
@ -40,14 +41,35 @@ class Sphere : public openglframework::Mesh {
|
|||
/// Radius of the sphere
|
||||
float mRadius;
|
||||
|
||||
/// Rigid body used to simulate the dynamics of the sphere
|
||||
rp3d::CollisionBody* mRigidBody;
|
||||
|
||||
/// Scaling matrix (applied to a sphere to obtain the correct sphere dimensions)
|
||||
openglframework::Matrix4 mScalingMatrix;
|
||||
|
||||
/// Previous transform (for interpolation)
|
||||
rp3d::Transform mPreviousTransform;
|
||||
|
||||
/// Vertex Buffer Object for the vertices data
|
||||
static openglframework::VertexBufferObject mVBOVertices;
|
||||
|
||||
/// Vertex Buffer Object for the normals data
|
||||
static openglframework::VertexBufferObject mVBONormals;
|
||||
|
||||
/// Vertex Buffer Object for the texture coords
|
||||
static openglframework::VertexBufferObject mVBOTextureCoords;
|
||||
|
||||
/// Vertex Buffer Object for the indices
|
||||
static openglframework::VertexBufferObject mVBOIndices;
|
||||
|
||||
/// Vertex Array Object for the vertex data
|
||||
static openglframework::VertexArrayObject mVAO;
|
||||
|
||||
// Total number of capsules created
|
||||
static int totalNbSpheres;
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
// Create the Vertex Buffer Objects used to render with OpenGL.
|
||||
void createVBOAndVAO();
|
||||
|
||||
public :
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
@ -63,28 +85,26 @@ class Sphere : public openglframework::Mesh {
|
|||
/// Destructor
|
||||
~Sphere();
|
||||
|
||||
/// Return a pointer to the collision body of the box
|
||||
reactphysics3d::CollisionBody* getCollisionBody();
|
||||
|
||||
/// Return a pointer to the rigid body of the box
|
||||
reactphysics3d::RigidBody* getRigidBody();
|
||||
|
||||
/// Update the transform matrix of the sphere
|
||||
void updateTransform();
|
||||
|
||||
/// Render the sphere at the correct position and with the correct orientation
|
||||
void render(openglframework::Shader& shader,
|
||||
const openglframework::Matrix4& worldToCameraMatrix);
|
||||
|
||||
/// Set the position of the box
|
||||
void resetTransform(const rp3d::Transform& transform);
|
||||
|
||||
/// Update the transform matrix of the object
|
||||
virtual void updateTransform(float interpolationFactor);
|
||||
};
|
||||
|
||||
// Return a pointer to the collision body of the box
|
||||
inline rp3d::CollisionBody* Sphere::getCollisionBody() {
|
||||
return mRigidBody;
|
||||
}
|
||||
|
||||
<<<<<<< HEAD:examples/common/Sphere.h
|
||||
// Return a pointer to the rigid body of the box
|
||||
inline rp3d::RigidBody* Sphere::getRigidBody() {
|
||||
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
|
183
testbed/common/VisualContactPoint.cpp
Normal file
183
testbed/common/VisualContactPoint.cpp
Normal 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();
|
||||
}
|
|
@ -29,7 +29,7 @@
|
|||
// Libraries
|
||||
#include "openglframework.h"
|
||||
|
||||
const float VISUAL_CONTACT_POINT_RADIUS = 0.1f;
|
||||
const float VISUAL_CONTACT_POINT_RADIUS = 0.2f;
|
||||
|
||||
// Class VisualContactPoint
|
||||
class VisualContactPoint : public openglframework::Object3D {
|
||||
|
@ -44,8 +44,26 @@ class VisualContactPoint : public openglframework::Object3D {
|
|||
/// Sphere mesh for the visual contact point
|
||||
static openglframework::Mesh mMesh;
|
||||
|
||||
/// True if the mesh has been initialized
|
||||
static bool mIsMeshInitialized;
|
||||
/// Vertex Buffer Object for the vertices data
|
||||
static openglframework::VertexBufferObject mVBOVertices;
|
||||
|
||||
/// Vertex Buffer Object for the normals data
|
||||
static openglframework::VertexBufferObject mVBONormals;
|
||||
|
||||
/// Vertex Buffer Object for the indices
|
||||
static openglframework::VertexBufferObject mVBOIndices;
|
||||
|
||||
/// Vertex Array Object for the vertex data
|
||||
static openglframework::VertexArrayObject mVAO;
|
||||
|
||||
/// True if static data (VBO, VAO) has been created already
|
||||
static bool mStaticDataCreated;
|
||||
|
||||
/// Color
|
||||
openglframework::Color mColor;
|
||||
|
||||
// Create the Vertex Buffer Objects used to render with OpenGL.
|
||||
static void createVBOAndVAO();
|
||||
|
||||
// -------------------- Methods -------------------- //
|
||||
|
||||
|
@ -54,7 +72,8 @@ class VisualContactPoint : public openglframework::Object3D {
|
|||
// -------------------- Methods -------------------- //
|
||||
|
||||
/// Constructor
|
||||
VisualContactPoint(const openglframework::Vector3& position);
|
||||
VisualContactPoint(const openglframework::Vector3& position,
|
||||
const std::string &meshFolderPath);
|
||||
|
||||
/// Destructor
|
||||
~VisualContactPoint();
|
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
Loading…
Reference in New Issue
Block a user