Update the testbed application to perform the interpolation externally

This commit is contained in:
Daniel Chappuis 2015-04-20 23:23:46 +02:00
parent b8192db3ef
commit e35db3f150
30 changed files with 493 additions and 96 deletions

View File

@ -20,7 +20,7 @@ FILE(COPY "shaders/" DESTINATION "${EXECUTABLE_OUTPUT_PATH}/shaders/")
FILE(COPY "meshes/" DESTINATION "${EXECUTABLE_OUTPUT_PATH}/meshes/")
# Headers
INCLUDE_DIRECTORIES("src" "opengl-framework/src/" "glfw/include/" "common/" "scenes/")
INCLUDE_DIRECTORIES("src/" "opengl-framework/src/" "glfw/include/" "common/" "scenes/")
# Testbed source files
SET(TESTBED_SOURCES
@ -31,6 +31,8 @@ SET(TESTBED_SOURCES
src/Gui.cpp
src/Scene.h
src/Scene.cpp
src/Timer.h
src/Timer.cpp
)
# Common source files

View File

@ -85,6 +85,8 @@ 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);
@ -205,14 +207,19 @@ void Box::render(openglframework::Shader& shader,
}
// Update the transform matrix of the box
void Box::updateTransform() {
void Box::updateTransform(float interpolationFactor) {
// Get the interpolated transform of the rigid body
rp3d::Transform transform = mRigidBody->getInterpolatedTransform();
// Get the transform of the rigid body
rp3d::Transform transform = mRigidBody->getTransform();
// Interpolate the transform between the previous one and the new one
rp3d::Transform interpolatedTransform = rp3d::Transform::interpolateTransforms(mPreviousTransform,
transform,
interpolationFactor);
// Compute the transform used for rendering the box
rp3d::decimal matrix[16];
transform.getOpenGLMatrix(matrix);
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],

View File

@ -56,6 +56,9 @@ class Box : public openglframework::Object3D {
/// Rigid body used to simulate the dynamics of the box
rp3d::CollisionBody* mRigidBody;
/// Previous transform of the body (for interpolation)
rp3d::Transform mPreviousTransform;
/// Scaling matrix (applied to a cube to obtain the correct box dimensions)
openglframework::Matrix4 mScalingMatrix;
@ -104,7 +107,7 @@ class Box : public openglframework::Object3D {
reactphysics3d::RigidBody* getRigidBody();
/// Update the transform matrix of the box
void updateTransform();
void updateTransform(float interpolationFactor);
/// Render the cube at the correct position and with the correct orientation
void render(openglframework::Shader& shader, const openglframework::Matrix4& worldToCameraMatrix);

View File

@ -57,6 +57,8 @@ 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);
@ -161,14 +163,19 @@ void Capsule::render(openglframework::Shader& shader,
}
// Update the transform matrix of the sphere
void Capsule::updateTransform() {
void Capsule::updateTransform(float interpolationFactor) {
// Get the interpolated transform of the rigid body
rp3d::Transform transform = mRigidBody->getInterpolatedTransform();
// Get the transform of the rigid body
rp3d::Transform transform = mRigidBody->getTransform();
// Interpolate the transform between the previous one and the new one
rp3d::Transform interpolatedTransform = rp3d::Transform::interpolateTransforms(mPreviousTransform,
transform,
interpolationFactor);
// Compute the transform used for rendering the sphere
rp3d::decimal matrix[16];
transform.getOpenGLMatrix(matrix);
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],

View File

@ -49,6 +49,9 @@ class Capsule : public openglframework::Mesh {
/// Scaling matrix (applied to a sphere to obtain the correct sphere dimensions)
openglframework::Matrix4 mScalingMatrix;
/// Previous transform (for interpolation)
rp3d::Transform mPreviousTransform;
// -------------------- Methods -------------------- //
public :
@ -74,7 +77,7 @@ class Capsule : public openglframework::Mesh {
reactphysics3d::RigidBody* getRigidBody();
/// Update the transform matrix of the sphere
void updateTransform();
void updateTransform(float interpolationFactor);
/// Render the sphere at the correct position and with the correct orientation
void render(openglframework::Shader& shader,

View File

@ -57,6 +57,8 @@ 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);
@ -161,14 +163,19 @@ void Cone::render(openglframework::Shader& shader,
}
// Update the transform matrix of the cone
void Cone::updateTransform() {
void Cone::updateTransform(float interpolationFactor) {
// Get the interpolated transform of the rigid body
rp3d::Transform transform = mRigidBody->getInterpolatedTransform();
// Get the transform of the rigid body
rp3d::Transform transform = mRigidBody->getTransform();
// Interpolate the transform between the previous one and the new one
rp3d::Transform interpolatedTransform = rp3d::Transform::interpolateTransforms(mPreviousTransform,
transform,
interpolationFactor);
// Compute the transform used for rendering the cone
rp3d::decimal matrix[16];
transform.getOpenGLMatrix(matrix);
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],

View File

@ -49,6 +49,9 @@ class Cone : public openglframework::Mesh {
/// Scaling matrix (applied to a sphere to obtain the correct cone dimensions)
openglframework::Matrix4 mScalingMatrix;
/// Previous transform (for interpolation)
rp3d::Transform mPreviousTransform;
// -------------------- Methods -------------------- //
public :
@ -73,7 +76,7 @@ class Cone : public openglframework::Mesh {
reactphysics3d::RigidBody* getRigidBody();
/// Update the transform matrix of the cone
void updateTransform();
void updateTransform(float interpolationFactor);
/// Render the cone at the correct position and with the correct orientation
void render(openglframework::Shader& shader,

View File

@ -79,6 +79,8 @@ 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);
@ -200,14 +202,19 @@ void ConvexMesh::render(openglframework::Shader& shader,
}
// Update the transform matrix of the sphere
void ConvexMesh::updateTransform() {
void ConvexMesh::updateTransform(float interpolationFactor) {
// Get the interpolated transform of the rigid body
rp3d::Transform transform = mRigidBody->getInterpolatedTransform();
// Get the transform of the rigid body
rp3d::Transform transform = mRigidBody->getTransform();
// Interpolate the transform between the previous one and the new one
rp3d::Transform interpolatedTransform = rp3d::Transform::interpolateTransforms(mPreviousTransform,
transform,
interpolationFactor);
// Compute the transform used for rendering the sphere
rp3d::decimal matrix[16];
transform.getOpenGLMatrix(matrix);
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],

View File

@ -40,6 +40,9 @@ class ConvexMesh : public openglframework::Mesh {
/// Rigid body used to simulate the dynamics of the mesh
rp3d::CollisionBody* mRigidBody;
/// Previous transform (for interpolation)
rp3d::Transform mPreviousTransform;
// -------------------- Methods -------------------- //
public :
@ -64,7 +67,7 @@ class ConvexMesh : public openglframework::Mesh {
reactphysics3d::RigidBody* getRigidBody();
/// Update the transform matrix of the mesh
void updateTransform();
void updateTransform(float interpolationFactor);
/// Render the mesh at the correct position and with the correct orientation
void render(openglframework::Shader& shader,

View File

@ -57,6 +57,8 @@ 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);
@ -161,14 +163,19 @@ void Cylinder::render(openglframework::Shader& shader,
}
// Update the transform matrix of the cylinder
void Cylinder::updateTransform() {
void Cylinder::updateTransform(float interpolationFactor) {
// Get the interpolated transform of the rigid body
rp3d::Transform transform = mRigidBody->getInterpolatedTransform();
// Get the transform of the rigid body
rp3d::Transform transform = mRigidBody->getTransform();
// Interpolate the transform between the previous one and the new one
rp3d::Transform interpolatedTransform = rp3d::Transform::interpolateTransforms(mPreviousTransform,
transform,
interpolationFactor);
// Compute the transform used for rendering the cylinder
rp3d::decimal matrix[16];
transform.getOpenGLMatrix(matrix);
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],

View File

@ -49,6 +49,9 @@ class Cylinder : public openglframework::Mesh {
/// Scaling matrix (applied to a sphere to obtain the correct cylinder dimensions)
openglframework::Matrix4 mScalingMatrix;
/// Previous transform (for interpolation)
rp3d::Transform mPreviousTransform;
// -------------------- Methods -------------------- //
public :
@ -73,7 +76,7 @@ class Cylinder : public openglframework::Mesh {
reactphysics3d::RigidBody* getRigidBody();
/// Update the transform matrix of the cylinder
void updateTransform();
void updateTransform(float interpolationFactor);
/// Render the cylinder at the correct position and with the correct orientation
void render(openglframework::Shader& shader,

View File

@ -64,6 +64,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());
@ -197,14 +199,19 @@ void Dumbbell::render(openglframework::Shader& shader,
}
// Update the transform matrix of the sphere
void Dumbbell::updateTransform() {
void Dumbbell::updateTransform(float interpolationFactor) {
// Get the interpolated transform of the rigid body
rp3d::Transform transform = mBody->getInterpolatedTransform();
// 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);
// Compute the transform used for rendering the sphere
rp3d::decimal matrix[16];
transform.getOpenGLMatrix(matrix);
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],

View File

@ -46,6 +46,9 @@ class Dumbbell : public openglframework::Mesh {
/// Scaling matrix (applied to a sphere to obtain the correct sphere dimensions)
openglframework::Matrix4 mScalingMatrix;
/// Previous transform (for interpolation)
rp3d::Transform mPreviousTransform;
// -------------------- Methods -------------------- //
public :
@ -71,7 +74,7 @@ class Dumbbell : public openglframework::Mesh {
rp3d::CollisionBody* getCollisionBody();
/// Update the transform matrix of the sphere
void updateTransform();
void updateTransform(float interpolationFactor);
/// Render the sphere at the correct position and with the correct orientation
void render(openglframework::Shader& shader,

View File

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

View File

@ -57,6 +57,8 @@ 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);
@ -161,14 +163,19 @@ void Sphere::render(openglframework::Shader& shader,
}
// Update the transform matrix of the sphere
void Sphere::updateTransform() {
void Sphere::updateTransform(float interpolationFactor) {
// Get the interpolated transform of the rigid body
rp3d::Transform transform = mRigidBody->getInterpolatedTransform();
// Get the transform of the rigid body
rp3d::Transform transform = mRigidBody->getTransform();
// Interpolate the transform between the previous one and the new one
rp3d::Transform interpolatedTransform = rp3d::Transform::interpolateTransforms(mPreviousTransform,
transform,
interpolationFactor);
// Compute the transform used for rendering the sphere
rp3d::decimal matrix[16];
transform.getOpenGLMatrix(matrix);
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],

View File

@ -46,6 +46,9 @@ class Sphere : public openglframework::Mesh {
/// Scaling matrix (applied to a sphere to obtain the correct sphere dimensions)
openglframework::Matrix4 mScalingMatrix;
/// Previous transform (for interpolation)
rp3d::Transform mPreviousTransform;
// -------------------- Methods -------------------- //
public :
@ -70,7 +73,7 @@ class Sphere : public openglframework::Mesh {
reactphysics3d::RigidBody* getRigidBody();
/// Update the transform matrix of the sphere
void updateTransform();
void updateTransform(float interpolationFactor);
/// Render the sphere at the correct position and with the correct orientation
void render(openglframework::Shader& shader,

View File

@ -53,7 +53,7 @@ CollisionShapesScene::CollisionShapesScene(const std::string& name)
rp3d::decimal timeStep = 1.0f / 60.0f;
// Create the dynamics world for the physics simulation
mDynamicsWorld = new rp3d::DynamicsWorld(gravity, timeStep);
mDynamicsWorld = new rp3d::DynamicsWorld(gravity);
// Set the number of iterations of the constraint solver
mDynamicsWorld->setNbIterationsVelocitySolver(15);
@ -216,9 +216,6 @@ CollisionShapesScene::CollisionShapesScene(const std::string& name)
// Change the material properties of the rigid body
rp3d::Material& material = mFloor->getRigidBody()->getMaterial();
material.setBounciness(rp3d::decimal(0.2));
// Start the simulation
mDynamicsWorld->start();
}
// Destructor
@ -309,46 +306,49 @@ CollisionShapesScene::~CollisionShapesScene() {
delete mDynamicsWorld;
}
// Take a step for the simulation
void CollisionShapesScene::update() {
// Update the physics world (take a simulation step)
void CollisionShapesScene::updatePhysics() {
// Take a simulation step
mDynamicsWorld->update();
mDynamicsWorld->update(mEngineSettings.timeStep);
}
// Take a step for the simulation
void CollisionShapesScene::update() {
// Update the position and orientation of the boxes
for (std::vector<Box*>::iterator it = mBoxes.begin(); it != mBoxes.end(); ++it) {
// Update the transform used for the rendering
(*it)->updateTransform();
(*it)->updateTransform(mInterpolationFactor);
}
// Update the position and orientation of the sphere
for (std::vector<Sphere*>::iterator it = mSpheres.begin(); it != mSpheres.end(); ++it) {
// Update the transform used for the rendering
(*it)->updateTransform();
(*it)->updateTransform(mInterpolationFactor);
}
// Update the position and orientation of the cones
for (std::vector<Cone*>::iterator it = mCones.begin(); it != mCones.end(); ++it) {
// Update the transform used for the rendering
(*it)->updateTransform();
(*it)->updateTransform(mInterpolationFactor);
}
// Update the position and orientation of the cylinders
for (std::vector<Cylinder*>::iterator it = mCylinders.begin(); it != mCylinders.end(); ++it) {
// Update the transform used for the rendering
(*it)->updateTransform();
(*it)->updateTransform(mInterpolationFactor);
}
// Update the position and orientation of the capsules
for (std::vector<Capsule*>::iterator it = mCapsules.begin(); it != mCapsules.end(); ++it) {
// Update the transform used for the rendering
(*it)->updateTransform();
(*it)->updateTransform(mInterpolationFactor);
}
// Update the position and orientation of the convex meshes
@ -356,7 +356,7 @@ void CollisionShapesScene::update() {
it != mConvexMeshes.end(); ++it) {
// Update the transform used for the rendering
(*it)->updateTransform();
(*it)->updateTransform(mInterpolationFactor);
}
// Update the position and orientation of the dumbbells
@ -364,10 +364,10 @@ void CollisionShapesScene::update() {
it != mDumbbells.end(); ++it) {
// Update the transform used for the rendering
(*it)->updateTransform();
(*it)->updateTransform(mInterpolationFactor);
}
mFloor->updateTransform();
mFloor->updateTransform(mInterpolationFactor);
}
// Render the scene

View File

@ -114,6 +114,10 @@ class CollisionShapesScene : public Scene{
/// Destructor
virtual ~CollisionShapesScene();
/// Update the physics world (take a simulation step)
/// Can be called several times per frame
virtual void updatePhysics();
/// Take a step for the simulation
virtual void update();

View File

@ -52,7 +52,7 @@ CubesScene::CubesScene(const std::string& name)
rp3d::decimal timeStep = 1.0f / 60.0f;
// Create the dynamics world for the physics simulation
mDynamicsWorld = new rp3d::DynamicsWorld(gravity, timeStep);
mDynamicsWorld = new rp3d::DynamicsWorld(gravity);
// Set the number of iterations of the constraint solver
mDynamicsWorld->setNbIterationsVelocitySolver(15);
@ -89,18 +89,11 @@ CubesScene::CubesScene(const std::string& name)
// Change the material properties of the floor rigid body
rp3d::Material& material = mFloor->getRigidBody()->getMaterial();
material.setBounciness(rp3d::decimal(0.3));
// Start the simulation
mDynamicsWorld->start();
counter=0;
}
// Destructor
CubesScene::~CubesScene() {
mDynamicsWorld->stop();
// Destroy the shader
mPhongShader.destroy();
@ -124,25 +117,24 @@ CubesScene::~CubesScene() {
delete mDynamicsWorld;
}
// Take a step for the simulation
void CubesScene::update() {
counter++;
if (counter == 400) {
//mIsRunning = false;
}
// Update the physics world (take a simulation step)
void CubesScene::updatePhysics() {
// Take a simulation step
mDynamicsWorld->update();
mDynamicsWorld->update(mEngineSettings.timeStep);
}
// Update the scene
void CubesScene::update() {
// Update the position and orientation of the boxes
for (std::vector<Box*>::iterator it = mBoxes.begin(); it != mBoxes.end(); ++it) {
// Update the transform used for the rendering
(*it)->updateTransform();
(*it)->updateTransform(mInterpolationFactor);
}
mFloor->updateTransform();
mFloor->updateTransform(mInterpolationFactor);
// Set the color of the awake/sleeping bodies
for (uint i=0; i<mBoxes.size(); i++) {

View File

@ -48,8 +48,6 @@ class CubesScene : public Scene {
// -------------------- Attributes -------------------- //
int counter;
/// Light 0
openglframework::Light mLight0;
@ -75,6 +73,10 @@ class CubesScene : public Scene {
/// Destructor
virtual ~CubesScene();
/// Update the physics world (take a simulation step)
/// Can be called several times per frame
virtual void updatePhysics();
/// Update the scene (take a simulation step)
virtual void update();

View File

@ -53,7 +53,7 @@ JointsScene::JointsScene(const std::string& name)
rp3d::decimal timeStep = 1.0f / 60.0f;
// Create the dynamics world for the physics simulation
mDynamicsWorld = new rp3d::DynamicsWorld(gravity, timeStep);
mDynamicsWorld = new rp3d::DynamicsWorld(gravity);
// Set the number of iterations of the constraint solver
mDynamicsWorld->setNbIterationsVelocitySolver(15);
@ -72,17 +72,11 @@ JointsScene::JointsScene(const std::string& name)
// Create the floor
createFloor();
// Start the simulation
mDynamicsWorld->start();
}
// Destructor
JointsScene::~JointsScene() {
// Stop the physics simulation
mDynamicsWorld->stop();
// Destroy the shader
mPhongShader.destroy();
@ -122,28 +116,32 @@ JointsScene::~JointsScene() {
delete mDynamicsWorld;
}
// Take a step for the simulation
void JointsScene::update() {
// Update the physics world (take a simulation step)
void JointsScene::updatePhysics() {
// Update the motor speed of the Slider Joint (to move up and down)
long double motorSpeed = 2 * cos(mDynamicsWorld->getPhysicsTime() * 1.5);
long double motorSpeed = 2 * cos(mEngineSettings.elapsedTime * 1.5);
mSliderJoint->setMotorSpeed(rp3d::decimal(motorSpeed));
// Take a simulation step
mDynamicsWorld->update();
mDynamicsWorld->update(mEngineSettings.timeStep);
}
// Take a step for the simulation
void JointsScene::update() {
// Update the position and orientation of the boxes
mSliderJointBottomBox->updateTransform();
mSliderJointTopBox->updateTransform();
mPropellerBox->updateTransform();
mFixedJointBox1->updateTransform();
mFixedJointBox2->updateTransform();
mSliderJointBottomBox->updateTransform(mInterpolationFactor);
mSliderJointTopBox->updateTransform(mInterpolationFactor);
mPropellerBox->updateTransform(mInterpolationFactor);
mFixedJointBox1->updateTransform(mInterpolationFactor);
mFixedJointBox2->updateTransform(mInterpolationFactor);
for (int i=0; i<NB_BALLSOCKETJOINT_BOXES; i++) {
mBallAndSocketJointChainBoxes[i]->updateTransform();
mBallAndSocketJointChainBoxes[i]->updateTransform(mInterpolationFactor);
}
// Update the position and orientation of the floor
mFloor->updateTransform();
mFloor->updateTransform(mInterpolationFactor);
}
// Render the scene

View File

@ -127,6 +127,10 @@ class JointsScene : public Scene {
/// Destructor
virtual ~JointsScene();
/// Update the physics world (take a simulation step)
/// Can be called several times per frame
virtual void updatePhysics();
/// Take a step for the simulation
virtual void update();

View File

@ -227,6 +227,11 @@ RaycastScene::~RaycastScene() {
}
}
// Update the physics world (take a simulation step)
void RaycastScene::updatePhysics() {
}
// Take a step for the simulation
void RaycastScene::update() {

View File

@ -177,6 +177,10 @@ class RaycastScene : public Scene {
/// Destructor
virtual ~RaycastScene();
/// Update the physics world (take a simulation step)
/// Can be called several times per frame
virtual void updatePhysics();
/// Take a step for the simulation
virtual void update();

View File

@ -30,7 +30,7 @@
using namespace openglframework;
// Constructor
Scene::Scene(const std::string& name) : mName(name) {
Scene::Scene(const std::string& name) : mName(name), mInterpolationFactor(0.0f) {
}

View File

@ -29,6 +29,16 @@
// Libraries
#include "openglframework.h"
/// Structure EngineSettings
/// This structure contains several physics engine parameters
struct EngineSettings {
public:
float elapsedTime; // Elapsed time (in seconds)
float timeStep; // Current time step (in seconds)
};
// Class Scene
// Abstract class that represents a 3D scene.
class Scene {
@ -40,6 +50,9 @@ class Scene {
/// Scene name
std::string mName;
/// Physics engine settings
EngineSettings mEngineSettings;
/// Camera
openglframework::Camera mCamera;
@ -58,6 +71,9 @@ class Scene {
/// True if the last point computed on a sphere (for camera rotation) is valid
bool mIsLastPointOnSphereValid;
/// Interpolation factor for the bodies in the current frame
float mInterpolationFactor;
// -------------------- Methods -------------------- //
/// Set the scene position (where the camera needs to look at)
@ -93,7 +109,11 @@ class Scene {
/// Reshape the view
virtual void reshape(int width, int height);
/// Update the scene (take a simulation step)
/// Update the physics world (take a simulation step)
/// Can be called several times per frame
virtual void updatePhysics()=0;
/// Update the scene
virtual void update()=0;
/// Render the scene
@ -121,6 +141,12 @@ class Scene {
/// Return a reference to the camera
const openglframework::Camera& getCamera() const;
/// Set the engine settings
void setEngineSettings(const EngineSettings& settings);
/// Set the interpolation factor
void setInterpolationFactor(float interpolationFactor);
};
// Called when a keyboard event occurs
@ -144,5 +170,14 @@ inline void Scene::setWindowDimension(int width, int height) {
mWindowHeight = height;
}
// Set the engine settings
inline void Scene::setEngineSettings(const EngineSettings& settings) {
mEngineSettings = settings;
}
// Set the interpolation factor
inline void Scene::setInterpolationFactor(float interpolationFactor) {
mInterpolationFactor = interpolationFactor;
}
#endif

View File

@ -124,6 +124,8 @@ void TestbedApplication::init() {
// Create all the scenes
createScenes();
mTimer.start();
}
// Create all the scenes
@ -159,9 +161,40 @@ void TestbedApplication::destroyScenes() {
mCurrentScene = NULL;
}
// Update the physics of the current scene
void TestbedApplication::updatePhysics() {
// Set the engine settings
mEngineSettings.elapsedTime = mTimer.getPhysicsTime();
mCurrentScene->setEngineSettings(mEngineSettings);
if (mTimer.isRunning()) {
// Compute the time since the last update() call and update the timer
mTimer.update();
// While the time accumulator is not empty
while(mTimer.isPossibleToTakeStep()) {
// Take a physics simulation step
mCurrentScene->updatePhysics();
// Update the timer
mTimer.nextStep();
}
}
}
void TestbedApplication::update() {
// Physics simulation
// Compute the interpolation factor
float factor = mTimer.computeInterpolationFactor(mEngineSettings.timeStep);
assert(factor >= 0.0f && factor <= 1.0f);
// Notify the scene about the interpolation factor
mCurrentScene->setInterpolationFactor(factor);
// Update the scene
mCurrentScene->update();
// Compute the current framerate

View File

@ -30,6 +30,7 @@
#include "openglframework.h"
#include "GUI.h"
#include "Scene.h"
#include "Timer.h"
#include <GLFW/glfw3.h>
/// Class TestbedApplication
@ -50,12 +51,18 @@ class TestbedApplication {
/// Graphical User Interface
Gui mGUI;
/// Timer
Timer mTimer;
/// List of 3D scenes
std::vector<Scene*> mScenes;
/// Current 3D scene
Scene* mCurrentScene;
/// Physics engine settings
EngineSettings mEngineSettings;
/// Current number of frames per seconds
double mFPS;
@ -85,6 +92,9 @@ class TestbedApplication {
/// Private assignment operator (for the singleton class)
void operator=(TestbedApplication const&);
/// Update the physics of the current scene
void updatePhysics();
/// Update
void update();

64
testbed/src/Timer.cpp Normal file
View File

@ -0,0 +1,64 @@
/********************************************************************************
* 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 "Timer.h"
// Constructor
Timer::Timer() : mIsRunning(false) {
}
// Destructor
Timer::~Timer() {
}
// Return the current time of the system in seconds
long double Timer::getCurrentSystemTime() {
#if defined(WINDOWS_OS)
LARGE_INTEGER ticksPerSecond;
LARGE_INTEGER ticks;
QueryPerformanceFrequency(&ticksPerSecond);
QueryPerformanceCounter(&ticks);
return (long double(ticks.QuadPart) / long double(ticksPerSecond.QuadPart));
#else
// Initialize the lastUpdateTime with the current time in seconds
timeval timeValue;
gettimeofday(&timeValue, NULL);
return (timeValue.tv_sec + (timeValue.tv_usec / 1000000.0));
#endif
}

177
testbed/src/Timer.h Normal file
View File

@ -0,0 +1,177 @@
/********************************************************************************
* 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 TIMER_H
#define TIMER_H
// Libraries
#include <stdexcept>
#include <iostream>
#include <ctime>
#include <cassert>
#include "configuration.h"
#if defined(WINDOWS_OS) // For Windows platform
#define NOMINMAX // This is used to avoid definition of max() and min() macros
#include <windows.h>
#else // For Mac OS or Linux platform
#include <sys/time.h>
#endif
// Class Timer
/**
* This class will take care of the time in the physics engine. It
* uses functions that depend on the current platform to get the
* current time.
*/
class Timer {
private :
// -------------------- Attributes -------------------- //
/// Timestep dt of the physics engine (timestep > 0.0)
double mTimeStep;
/// Last time the timer has been updated
long double mLastUpdateTime;
/// Time difference between the two last timer update() calls
long double mDeltaTime;
/// Used to fix the time step and avoid strange time effects
double mAccumulator;
/// True if the timer is running
bool mIsRunning;
// -------------------- Methods -------------------- //
/// Private copy-constructor
Timer(const Timer& timer);
/// Private assignment operator
Timer& operator=(const Timer& timer);
public :
// -------------------- Methods -------------------- //
/// Constructor
Timer();
/// Destructor
virtual ~Timer();
/// Return the current time of the physics engine
long double getPhysicsTime() const;
/// Start the timer
void start();
/// Stop the timer
void stop();
/// Return true if the timer is running
bool isRunning() const;
/// True if it's possible to take a new step
bool isPossibleToTakeStep() const;
/// Compute the time since the last update() call and add it to the accumulator
void update();
/// Take a new step => update the timer by adding the timeStep value to the current time
void nextStep();
/// Compute the interpolation factor
float computeInterpolationFactor(float timeStep);
/// Return the current time of the system in seconds
static long double getCurrentSystemTime();
};
// Return the current time
inline long double Timer::getPhysicsTime() const {
return mLastUpdateTime;
}
// Return if the timer is running
inline bool Timer::isRunning() const {
return mIsRunning;
}
// Start the timer
inline void Timer::start() {
if (!mIsRunning) {
// Get the current system time
mLastUpdateTime = getCurrentSystemTime();
mAccumulator = 0.0;
mIsRunning = true;
}
}
// Stop the timer
inline void Timer::stop() {
mIsRunning = false;
}
// True if it's possible to take a new step
inline bool Timer::isPossibleToTakeStep() const {
return (mAccumulator >= mTimeStep);
}
// Take a new step => update the timer by adding the timeStep value to the current time
inline void Timer::nextStep() {
assert(mIsRunning);
// Update the accumulator value
mAccumulator -= mTimeStep;
}
// Compute the interpolation factor
inline float Timer::computeInterpolationFactor(float timeStep) {
return (float(mAccumulator) / timeStep);
}
// Compute the time since the last update() call and add it to the accumulator
inline void Timer::update() {
// Get the current system time
long double currentTime = getCurrentSystemTime();
// Compute the delta display time between two display frames
mDeltaTime = currentTime - mLastUpdateTime;
// Update the current display time
mLastUpdateTime = currentTime;
// Update the accumulator value
mAccumulator += mDeltaTime;
}
#endif