Add raycasting example

This commit is contained in:
Daniel Chappuis 2014-11-29 13:08:11 +01:00
parent 4ae7e7997a
commit c1fa7b0f50
22 changed files with 1301 additions and 54 deletions

View File

@ -8,3 +8,4 @@ ADD_SUBDIRECTORY(common/)
ADD_SUBDIRECTORY(cubes/)
ADD_SUBDIRECTORY(joints/)
ADD_SUBDIRECTORY(collisionshapes/)
ADD_SUBDIRECTORY(raycast/)

View File

@ -58,7 +58,7 @@ GLuint Box::mCubeIndices[36] = { 0, 1, 2,
// Constructor
Box::Box(const openglframework::Vector3& size, const openglframework::Vector3 &position,
float mass, reactphysics3d::DynamicsWorld* dynamicsWorld)
reactphysics3d::CollisionWorld* world)
: openglframework::Object3D(), mColor(0.5f, 0.5f, 0.5f, 1.0f) {
// Initialize the size of the box
@ -86,16 +86,64 @@ Box::Box(const openglframework::Vector3& size, const openglframework::Vector3 &p
rp3d::Transform transform(initPosition, initOrientation);
// Create a rigid body in the dynamics world
mRigidBody = dynamicsWorld->createRigidBody(transform);
mRigidBody = world->createCollisionBody(transform);
// Add the collision shape to the body
mRigidBody->addCollisionShape(collisionShape, mass);
mRigidBody->addCollisionShape(collisionShape, rp3d::Transform::identity());
// If the Vertex Buffer object has not been created yet
if (!areVBOsCreated) {
// Create the Vertex Buffer
createVBO();
}
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) {
// Initialize the size of the box
mSize[0] = size.x * 0.5f;
mSize[1] = size.y * 0.5f;
mSize[2] = size.z * 0.5f;
// Compute the scaling matrix
mScalingMatrix = openglframework::Matrix4(mSize[0], 0, 0, 0,
0, mSize[1], 0, 0,
0, 0, mSize[2], 0,
0, 0, 0, 1);
// Initialize the position where the cube will be rendered
translateWorld(position);
// Create the collision shape for the rigid body (box shape)
// ReactPhysics3D will clone this object to create an internal one. Therefore,
// it is OK if this object is destroyed right after calling RigidBody::addCollisionShape()
const rp3d::BoxShape collisionShape(rp3d::Vector3(mSize[0], mSize[1], mSize[2]));
// Initial position and orientation of the rigid body
rp3d::Vector3 initPosition(position.x, position.y, position.z);
rp3d::Quaternion initOrientation = rp3d::Quaternion::identity();
rp3d::Transform transform(initPosition, initOrientation);
// 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;
// If the Vertex Buffer object has not been created yet
if (!areVBOsCreated) {
// Create the Vertex Buffer
createVBO();
}
mTransformMatrix = mTransformMatrix * mScalingMatrix;
}
// Destructor

View File

@ -54,7 +54,7 @@ class Box : public openglframework::Object3D {
float mSize[3];
/// Rigid body used to simulate the dynamics of the box
rp3d::RigidBody* mRigidBody;
rp3d::CollisionBody* mRigidBody;
/// Scaling matrix (applied to a cube to obtain the correct box dimensions)
openglframework::Matrix4 mScalingMatrix;
@ -88,13 +88,20 @@ class Box : public openglframework::Object3D {
/// Constructor
Box(const openglframework::Vector3& size, const openglframework::Vector3& position,
float mass, rp3d::DynamicsWorld* dynamicsWorld);
reactphysics3d::CollisionWorld* world);
/// Constructor
Box(const openglframework::Vector3& size, const openglframework::Vector3& position,
float mass, reactphysics3d::DynamicsWorld *world);
/// 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
rp3d::RigidBody* getRigidBody();
reactphysics3d::RigidBody* getRigidBody();
/// Update the transform matrix of the box
void updateTransform();
@ -106,9 +113,14 @@ class Box : public openglframework::Object3D {
void setColor(const openglframework::Color& color);
};
// Return a pointer to the collision body of the box
inline rp3d::CollisionBody* Box::getCollisionBody() {
return mRigidBody;
}
// Return a pointer to the rigid body of the box
inline rp3d::RigidBody* Box::getRigidBody() {
return mRigidBody;
return dynamic_cast<rp3d::RigidBody*>(mRigidBody);
}
// Set the color of the box

View File

@ -26,6 +26,45 @@
// Libraries
#include "Capsule.h"
// Constructor
Capsule::Capsule(float radius, float height, const openglframework::Vector3& position,
reactphysics3d::CollisionWorld* world,
const std::string& meshFolderPath)
: openglframework::Mesh(), mRadius(radius), mHeight(height) {
// Load the mesh from a file
openglframework::MeshReaderWriter::loadMeshFromFile(meshFolderPath + "capsule.obj", *this);
// Calculate the normals of the mesh
calculateNormals();
// Compute the scaling matrix
mScalingMatrix = openglframework::Matrix4(mRadius, 0, 0, 0,
0, (mHeight + 2.0f * mRadius) / 3.0f, 0,0,
0, 0, mRadius, 0,
0, 0, 0, 1.0f);
// Initialize the position where the sphere will be rendered
translateWorld(position);
// Create the collision shape for the rigid body (sphere shape)
// ReactPhysics3D will clone this object to create an internal one. Therefore,
// it is OK if this object is destroyed right after calling RigidBody::addCollisionShape()
const rp3d::CapsuleShape collisionShape(mRadius, mHeight);
// Initial position and orientation of the rigid body
rp3d::Vector3 initPosition(position.x, position.y, position.z);
rp3d::Quaternion initOrientation = rp3d::Quaternion::identity();
rp3d::Transform transform(initPosition, initOrientation);
// Create a rigid body corresponding in the dynamics world
mRigidBody = world->createCollisionBody(transform);
// Add a collision shape to the body and specify the mass of the shape
mRigidBody->addCollisionShape(collisionShape, rp3d::Transform::identity());
mTransformMatrix = mTransformMatrix * mScalingMatrix;
}
// Constructor
Capsule::Capsule(float radius, float height, const openglframework::Vector3& position,
@ -59,10 +98,14 @@ Capsule::Capsule(float radius, float height, const openglframework::Vector3& pos
rp3d::Transform transform(initPosition, initOrientation);
// Create a rigid body corresponding in the dynamics world
mRigidBody = dynamicsWorld->createRigidBody(transform);
rp3d::RigidBody* body = dynamicsWorld->createRigidBody(transform);
// Add a collision shape to the body and specify the mass of the shape
mRigidBody->addCollisionShape(collisionShape, mass);
body->addCollisionShape(collisionShape, rp3d::Transform::identity(), mass);
mRigidBody = body;
mTransformMatrix = mTransformMatrix * mScalingMatrix;
}
// Destructor

View File

@ -44,7 +44,7 @@ class Capsule : public openglframework::Mesh {
float mHeight;
/// Rigid body used to simulate the dynamics of the sphere
rp3d::RigidBody* mRigidBody;
rp3d::CollisionBody* mRigidBody;
/// Scaling matrix (applied to a sphere to obtain the correct sphere dimensions)
openglframework::Matrix4 mScalingMatrix;
@ -57,13 +57,21 @@ class Capsule : public openglframework::Mesh {
/// Constructor
Capsule(float radius, float height, const openglframework::Vector3& position,
float mass, rp3d::DynamicsWorld* dynamicsWorld, const std::string& meshFolderPath);
reactphysics3d::CollisionWorld* world, const std::string& meshFolderPath);
/// Constructor
Capsule(float radius, float height, const openglframework::Vector3& position,
float mass, reactphysics3d::DynamicsWorld* dynamicsWorld,
const std::string& meshFolderPath);
/// Destructor
~Capsule();
/// Return a pointer to the rigid body of the sphere
rp3d::RigidBody* getRigidBody();
/// 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();
@ -73,9 +81,14 @@ class Capsule : public openglframework::Mesh {
const openglframework::Matrix4& worldToCameraMatrix);
};
// Return a pointer to the rigid body of the sphere
inline rp3d::RigidBody* Capsule::getRigidBody() {
// Return a pointer to the collision body of the box
inline rp3d::CollisionBody* Capsule::getCollisionBody() {
return mRigidBody;
}
// Return a pointer to the rigid body of the box
inline rp3d::RigidBody* Capsule::getRigidBody() {
return dynamic_cast<rp3d::RigidBody*>(mRigidBody);
}
#endif

View File

@ -26,6 +26,45 @@
// Libraries
#include "Cone.h"
// Constructor
Cone::Cone(float radius, float height, const openglframework::Vector3 &position,
reactphysics3d::CollisionWorld* world,
const std::string& meshFolderPath)
: openglframework::Mesh(), mRadius(radius), mHeight(height) {
// Load the mesh from a file
openglframework::MeshReaderWriter::loadMeshFromFile(meshFolderPath + "cone.obj", *this);
// Calculate the normals of the mesh
calculateNormals();
// Compute the scaling matrix
mScalingMatrix = openglframework::Matrix4(mRadius, 0, 0, 0,
0, mHeight, 0, 0,
0, 0, mRadius, 0,
0, 0, 0, 1);
// Initialize the position where the cone will be rendered
translateWorld(position);
// Create the collision shape for the rigid body (cone shape)
// ReactPhysics3D will clone this object to create an internal one. Therefore,
// it is OK if this object is destroyed right after calling RigidBody::addCollisionShape()
const rp3d::ConeShape collisionShape(mRadius, mHeight);
// Initial position and orientation of the rigid body
rp3d::Vector3 initPosition(position.x, position.y, position.z);
rp3d::Quaternion initOrientation = rp3d::Quaternion::identity();
rp3d::Transform transform(initPosition, initOrientation);
// Create a rigid body corresponding to the cone in the dynamics world
mRigidBody = world->createCollisionBody(transform);
// Add a collision shape to the body and specify the mass of the shape
mRigidBody->addCollisionShape(collisionShape, rp3d::Transform::identity());
mTransformMatrix = mTransformMatrix * mScalingMatrix;
}
// Constructor
Cone::Cone(float radius, float height, const openglframework::Vector3 &position,
@ -59,10 +98,14 @@ Cone::Cone(float radius, float height, const openglframework::Vector3 &position,
rp3d::Transform transform(initPosition, initOrientation);
// Create a rigid body corresponding to the cone in the dynamics world
mRigidBody = dynamicsWorld->createRigidBody(transform);
rp3d::RigidBody* body = dynamicsWorld->createRigidBody(transform);
// Add a collision shape to the body and specify the mass of the shape
mRigidBody->addCollisionShape(collisionShape, mass);
body->addCollisionShape(collisionShape, rp3d::Transform::identity(), mass);
mRigidBody = body;
mTransformMatrix = mTransformMatrix * mScalingMatrix;
}
// Destructor

View File

@ -44,7 +44,7 @@ class Cone : public openglframework::Mesh {
float mHeight;
/// Rigid body used to simulate the dynamics of the cone
rp3d::RigidBody* mRigidBody;
rp3d::CollisionBody* mRigidBody;
/// Scaling matrix (applied to a sphere to obtain the correct cone dimensions)
openglframework::Matrix4 mScalingMatrix;
@ -55,6 +55,10 @@ class Cone : public openglframework::Mesh {
// -------------------- Methods -------------------- //
/// Constructor
Cone(float radius, float height, const openglframework::Vector3& position,
rp3d::CollisionWorld* world, const std::string& meshFolderPath);
/// Constructor
Cone(float radius, float height, const openglframework::Vector3& position,
float mass, rp3d::DynamicsWorld* dynamicsWorld, const std::string& meshFolderPath);
@ -62,8 +66,11 @@ class Cone : public openglframework::Mesh {
/// Destructor
~Cone();
/// Return a pointer to the rigid body of the cone
rp3d::RigidBody* getRigidBody();
/// 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();
@ -73,9 +80,14 @@ class Cone : public openglframework::Mesh {
const openglframework::Matrix4& worldToCameraMatrix);
};
// Return a pointer to the rigid body of the cone
inline rp3d::RigidBody* Cone::getRigidBody() {
// Return a pointer to the collision body of the box
inline rp3d::CollisionBody* Cone::getCollisionBody() {
return mRigidBody;
}
// Return a pointer to the rigid body of the box
inline rp3d::RigidBody* Cone::getRigidBody() {
return dynamic_cast<rp3d::RigidBody*>(mRigidBody);
}
#endif

View File

@ -26,6 +26,56 @@
// Libraries
#include "ConvexMesh.h"
// Constructor
ConvexMesh::ConvexMesh(const openglframework::Vector3 &position,
reactphysics3d::CollisionWorld* world,
const std::string& meshFolderPath)
: openglframework::Mesh() {
// Load the mesh from a file
openglframework::MeshReaderWriter::loadMeshFromFile(meshFolderPath + "convexmesh.obj", *this);
// Calculate the normals of the mesh
calculateNormals();
// Initialize the position where the sphere will be rendered
translateWorld(position);
// Create the collision shape for the rigid body (convex mesh shape)
// ReactPhysics3D will clone this object to create an internal one. Therefore,
// it is OK if this object is destroyed right after calling RigidBody::addCollisionShape()
rp3d::decimal* verticesArray = (rp3d::decimal*) getVerticesPointer();
rp3d::ConvexMeshShape collisionShape(verticesArray, mVertices.size(),
sizeof(openglframework::Vector3));
// Add the edges information of the mesh into the convex mesh collision shape.
// This is optional but it really speed up the convex mesh collision detection at the
// cost of some additional memory to store the edges inside the collision shape.
for (unsigned int i=0; i<getNbFaces(); i++) { // For each triangle face of the mesh
// Get the three vertex IDs of the vertices of the face
unsigned int v1 = getVertexIndexInFace(i, 0);
unsigned int v2 = getVertexIndexInFace(i, 1);
unsigned int v3 = getVertexIndexInFace(i, 2);
// Add the three edges into the collision shape
collisionShape.addEdge(v1, v2);
collisionShape.addEdge(v1, v3);
collisionShape.addEdge(v2, v3);
}
collisionShape.setIsEdgesInformationUsed(true);// Enable the fast collision detection with edges
// Initial position and orientation of the rigid body
rp3d::Vector3 initPosition(position.x, position.y, position.z);
rp3d::Quaternion initOrientation = rp3d::Quaternion::identity();
rp3d::Transform transform(initPosition, initOrientation);
// Create a rigid body corresponding to the sphere in the dynamics world
mRigidBody = world->createCollisionBody(transform);
// Add a collision shape to the body and specify the mass of the collision shape
mRigidBody->addCollisionShape(collisionShape, rp3d::Transform::identity());
}
// Constructor
ConvexMesh::ConvexMesh(const openglframework::Vector3 &position, float mass,
@ -72,10 +122,12 @@ ConvexMesh::ConvexMesh(const openglframework::Vector3 &position, float mass,
rp3d::Transform transform(initPosition, initOrientation);
// Create a rigid body corresponding to the sphere in the dynamics world
mRigidBody = dynamicsWorld->createRigidBody(transform);
rp3d::RigidBody* body = dynamicsWorld->createRigidBody(transform);
// Add a collision shape to the body and specify the mass of the collision shape
mRigidBody->addCollisionShape(collisionShape, mass);
body->addCollisionShape(collisionShape, rp3d::Transform::identity(), mass);
mRigidBody = body;
}
// Destructor

View File

@ -38,7 +38,7 @@ class ConvexMesh : public openglframework::Mesh {
// -------------------- Attributes -------------------- //
/// Rigid body used to simulate the dynamics of the mesh
rp3d::RigidBody* mRigidBody;
rp3d::CollisionBody* mRigidBody;
// -------------------- Methods -------------------- //
@ -46,6 +46,10 @@ class ConvexMesh : public openglframework::Mesh {
// -------------------- Methods -------------------- //
/// Constructor
ConvexMesh(const openglframework::Vector3& position,
rp3d::CollisionWorld* world, const std::string& meshFolderPath);
/// Constructor
ConvexMesh(const openglframework::Vector3& position, float mass,
rp3d::DynamicsWorld* dynamicsWorld, const std::string& meshFolderPath);
@ -53,8 +57,11 @@ class ConvexMesh : public openglframework::Mesh {
/// Destructor
~ConvexMesh();
/// Return a pointer to the rigid body of the mesh
rp3d::RigidBody* getRigidBody();
/// 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();
@ -64,9 +71,14 @@ class ConvexMesh : public openglframework::Mesh {
const openglframework::Matrix4& worldToCameraMatrix);
};
// Return a pointer to the rigid body of the mesh
inline rp3d::RigidBody* ConvexMesh::getRigidBody() {
// 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);
}
#endif

View File

@ -26,6 +26,45 @@
// Libraries
#include "Cylinder.h"
// Constructor
Cylinder::Cylinder(float radius, float height, const openglframework::Vector3& position,
reactphysics3d::CollisionWorld* world,
const std::string& meshFolderPath)
: openglframework::Mesh(), mRadius(radius), mHeight(height) {
// Load the mesh from a file
openglframework::MeshReaderWriter::loadMeshFromFile(meshFolderPath + "cylinder.obj", *this);
// Calculate the normals of the mesh
calculateNormals();
// Compute the scaling matrix
mScalingMatrix = openglframework::Matrix4(mRadius, 0, 0, 0,
0, mHeight, 0, 0,
0, 0, mRadius, 0,
0, 0, 0, 1);
// Initialize the position where the cylinder will be rendered
translateWorld(position);
// Create the collision shape for the rigid body (cylinder shape)
// ReactPhysics3D will clone this object to create an internal one. Therefore,
// it is OK if this object is destroyed right after calling RigidBody::addCollisionShape()
const rp3d::CylinderShape collisionShape(mRadius, mHeight);
// Initial position and orientation of the rigid body
rp3d::Vector3 initPosition(position.x, position.y, position.z);
rp3d::Quaternion initOrientation = rp3d::Quaternion::identity();
rp3d::Transform transform(initPosition, initOrientation);
// Create a rigid body corresponding to the cylinder in the dynamics world
mRigidBody = world->createCollisionBody(transform);
// Add a collision shape to the body and specify the mass of the shape
mRigidBody->addCollisionShape(collisionShape, rp3d::Transform::identity());
mTransformMatrix = mTransformMatrix * mScalingMatrix;
}
// Constructor
Cylinder::Cylinder(float radius, float height, const openglframework::Vector3& position,
@ -59,10 +98,14 @@ Cylinder::Cylinder(float radius, float height, const openglframework::Vector3& p
rp3d::Transform transform(initPosition, initOrientation);
// Create a rigid body corresponding to the cylinder in the dynamics world
mRigidBody = dynamicsWorld->createRigidBody(transform);
rp3d::RigidBody* body = dynamicsWorld->createRigidBody(transform);
// Add a collision shape to the body and specify the mass of the shape
mRigidBody->addCollisionShape(collisionShape, mass);
body->addCollisionShape(collisionShape, rp3d::Transform::identity(), mass);
mTransformMatrix = mTransformMatrix * mScalingMatrix;
mRigidBody = body;
}
// Destructor

View File

@ -44,7 +44,7 @@ class Cylinder : public openglframework::Mesh {
float mHeight;
/// Rigid body used to simulate the dynamics of the cylinder
rp3d::RigidBody* mRigidBody;
rp3d::CollisionBody* mRigidBody;
/// Scaling matrix (applied to a sphere to obtain the correct cylinder dimensions)
openglframework::Matrix4 mScalingMatrix;
@ -55,6 +55,10 @@ class Cylinder : public openglframework::Mesh {
// -------------------- Methods -------------------- //
/// Constructor
Cylinder(float radius, float height, const openglframework::Vector3& position,
rp3d::CollisionWorld* world, const std::string &meshFolderPath);
/// Constructor
Cylinder(float radius, float height, const openglframework::Vector3& position,
float mass, rp3d::DynamicsWorld* dynamicsWorld, const std::string &meshFolderPath);
@ -62,8 +66,11 @@ class Cylinder : public openglframework::Mesh {
/// Destructor
~Cylinder();
/// Return a pointer to the rigid body of the cylinder
rp3d::RigidBody* getRigidBody();
/// 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();
@ -73,9 +80,14 @@ class Cylinder : public openglframework::Mesh {
const openglframework::Matrix4& worldToCameraMatrix);
};
// Return a pointer to the rigid body of the cylinder
inline rp3d::RigidBody* Cylinder::getRigidBody() {
// 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);
}
#endif

View File

@ -26,7 +26,6 @@
// Libraries
#include "Dumbbell.h"
// Constructor
Dumbbell::Dumbbell(const openglframework::Vector3 &position,
reactphysics3d::DynamicsWorld* dynamicsWorld, const std::string& meshFolderPath)
@ -75,12 +74,74 @@ Dumbbell::Dumbbell(const openglframework::Vector3 &position,
rp3d::Transform transformCylinderShape(rp3d::Vector3(0, 0, 0), rp3d::Quaternion::identity());
// Create a rigid body corresponding to the dumbbell in the dynamics world
mRigidBody = dynamicsWorld->createRigidBody(transformBody);
rp3d::RigidBody* body = dynamicsWorld->createRigidBody(transformBody);
// Add the three collision shapes to the body and specify the mass and transform of the shapes
mRigidBody->addCollisionShape(sphereCollisionShape, massSphere, transformSphereShape1);
mRigidBody->addCollisionShape(sphereCollisionShape, massSphere, transformSphereShape2);
mRigidBody->addCollisionShape(cylinderCollisionShape, massCylinder, transformCylinderShape);
body->addCollisionShape(sphereCollisionShape, transformSphereShape1, massSphere);
body->addCollisionShape(sphereCollisionShape, transformSphereShape2, massSphere);
body->addCollisionShape(cylinderCollisionShape, transformCylinderShape, massCylinder);
mBody = body;
mTransformMatrix = mTransformMatrix * mScalingMatrix;
}
// Constructor
Dumbbell::Dumbbell(const openglframework::Vector3 &position,
reactphysics3d::CollisionWorld* world, const std::string& meshFolderPath)
: openglframework::Mesh() {
// Load the mesh from a file
openglframework::MeshReaderWriter::loadMeshFromFile(meshFolderPath + "dumbbell.obj", *this);
// Calculate the normals of the mesh
calculateNormals();
// Identity scaling matrix
mScalingMatrix.setToIdentity();
// Initialize the position where the sphere will be rendered
translateWorld(position);
// Create a sphere collision shape for the two ends of the dumbbell
// ReactPhysics3D will clone this object to create an internal one. Therefore,
// it is OK if this object is destroyed right after calling RigidBody::addCollisionShape()
const rp3d::decimal radiusSphere = rp3d::decimal(1.5);
const rp3d::decimal massSphere = rp3d::decimal(2.0);
const rp3d::SphereShape sphereCollisionShape(radiusSphere);
// Create a cylinder collision shape for the middle of the dumbbell
// ReactPhysics3D will clone this object to create an internal one. Therefore,
// it is OK if this object is destroyed right after calling RigidBody::addCollisionShape()
const rp3d::decimal radiusCylinder = rp3d::decimal(0.5);
const rp3d::decimal heightCylinder = rp3d::decimal(8.0);
const rp3d::decimal massCylinder = rp3d::decimal(1.0);
const rp3d::CylinderShape cylinderCollisionShape(radiusCylinder, heightCylinder);
// Initial position and orientation of the rigid body
rp3d::Vector3 initPosition(position.x, position.y, position.z);
rp3d::decimal angleAroundX = 0;//rp3d::PI / 2;
rp3d::Quaternion initOrientation(angleAroundX, 0, 0);
rp3d::Transform transformBody(initPosition, initOrientation);
// 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());
// Initial transform of the second sphere collision shape of the dumbell (in local-space)
rp3d::Transform transformSphereShape2(rp3d::Vector3(0, -4.0, 0), rp3d::Quaternion::identity());
// Initial transform of the cylinder collision shape of the dumbell (in local-space)
rp3d::Transform transformCylinderShape(rp3d::Vector3(0, 0, 0), rp3d::Quaternion::identity());
// Create a rigid body corresponding to the dumbbell in the dynamics world
mBody = world->createCollisionBody(transformBody);
// Add the three collision shapes to the body and specify the mass and transform of the shapes
mBody->addCollisionShape(sphereCollisionShape, transformSphereShape1);
mBody->addCollisionShape(sphereCollisionShape, transformSphereShape2);
mBody->addCollisionShape(cylinderCollisionShape, transformCylinderShape);
mTransformMatrix = mTransformMatrix * mScalingMatrix;
}
// Destructor
@ -139,7 +200,7 @@ void Dumbbell::render(openglframework::Shader& shader,
void Dumbbell::updateTransform() {
// Get the interpolated transform of the rigid body
rp3d::Transform transform = mRigidBody->getInterpolatedTransform();
rp3d::Transform transform = mBody->getInterpolatedTransform();
// Compute the transform used for rendering the sphere
rp3d::decimal matrix[16];

View File

@ -41,7 +41,7 @@ class Dumbbell : public openglframework::Mesh {
float mRadius;
/// Rigid body used to simulate the dynamics of the sphere
rp3d::RigidBody* mRigidBody;
rp3d::CollisionBody* mBody;
/// Scaling matrix (applied to a sphere to obtain the correct sphere dimensions)
openglframework::Matrix4 mScalingMatrix;
@ -56,12 +56,20 @@ class Dumbbell : public openglframework::Mesh {
Dumbbell(const openglframework::Vector3& position, rp3d::DynamicsWorld* dynamicsWorld,
const std::string& meshFolderPath);
/// Constructor
Dumbbell(const openglframework::Vector3& position, rp3d::CollisionWorld* world,
const std::string& meshFolderPath);
/// Destructor
~Dumbbell();
/// Return a pointer to the rigid body of the sphere
/// 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();
@ -72,7 +80,12 @@ class Dumbbell : public openglframework::Mesh {
// Return a pointer to the rigid body of the sphere
inline rp3d::RigidBody* Dumbbell::getRigidBody() {
return mRigidBody;
return dynamic_cast<rp3d::RigidBody*>(mBody);
}
// Return a pointer to the body
inline rp3d::CollisionBody* Dumbbell::getCollisionBody() {
return mBody;
}
#endif

59
examples/common/Line.cpp Normal file
View File

@ -0,0 +1,59 @@
/********************************************************************************
* ReactPhysics3D physics library, http://code.google.com/p/reactphysics3d/ *
* Copyright (c) 2010-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 "Line.h"
// Constructor
Line::Line(const openglframework::Vector3& worldPoint1,
const openglframework::Vector3& worldPoint2)
: mWorldPoint1(worldPoint1), mWorldPoint2(worldPoint2) {
}
// Destructor
Line::~Line() {
}
// Render the sphere at the correct position and with the correct orientation
void Line::render(openglframework::Shader& shader,
const openglframework::Matrix4& worldToCameraMatrix) {
// Bind the shader
shader.bind();
// Set the model to camera matrix
shader.setMatrix4x4Uniform("localToCameraMatrix", worldToCameraMatrix);
glBegin(GL_LINES);
glVertex3f(mWorldPoint1.x, mWorldPoint1.y, mWorldPoint1.z);
glVertex3f(mWorldPoint2.x, mWorldPoint2.y, mWorldPoint2.z);
glEnd();
// Unbind the shader
shader.unbind();
}

54
examples/common/Line.h Normal file
View File

@ -0,0 +1,54 @@
#ifndef LINE_H
#define LINE_H
// Libraries
#include "openglframework.h"
#include "reactphysics3d.h"
// Class Line
class Line : public openglframework::Object3D {
private :
// -------------------- Attributes -------------------- //
openglframework::Vector3 mWorldPoint1, mWorldPoint2;
// -------------------- Methods -------------------- //
public :
// -------------------- Methods -------------------- //
/// Constructor
Line(const openglframework::Vector3& worldPoint1,
const openglframework::Vector3& worldPoint2);
/// Destructor
~Line();
/// Return the first point of the line
openglframework::Vector3 getPoint1() const;
/// 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);
};
// Return the first point of the line
inline openglframework::Vector3 Line::getPoint1() const {
return mWorldPoint1;
}
// Return the second point of the line
inline openglframework::Vector3 Line::getPoint2() const {
return mWorldPoint2;
}
#endif

View File

@ -26,10 +26,9 @@
// Libraries
#include "Sphere.h"
// Constructor
Sphere::Sphere(float radius, const openglframework::Vector3 &position,
float mass, reactphysics3d::DynamicsWorld* dynamicsWorld,
reactphysics3d::CollisionWorld* world,
const std::string& meshFolderPath)
: openglframework::Mesh(), mRadius(radius) {
@ -59,10 +58,54 @@ Sphere::Sphere(float radius, const openglframework::Vector3 &position,
rp3d::Transform transform(initPosition, initOrientation);
// Create a rigid body corresponding to the sphere in the dynamics world
mRigidBody = dynamicsWorld->createRigidBody(transform);
mRigidBody = world->createCollisionBody(transform);
// Add a collision shape to the body and specify the mass of the shape
mRigidBody->addCollisionShape(collisionShape, mass);
mRigidBody->addCollisionShape(collisionShape, rp3d::Transform::identity());
mTransformMatrix = mTransformMatrix * mScalingMatrix;
}
// Constructor
Sphere::Sphere(float radius, const openglframework::Vector3 &position,
float mass, reactphysics3d::DynamicsWorld* world,
const std::string& meshFolderPath)
: openglframework::Mesh(), mRadius(radius) {
// Load the mesh from a file
openglframework::MeshReaderWriter::loadMeshFromFile(meshFolderPath + "sphere.obj", *this);
// Calculate the normals of the mesh
calculateNormals();
// Compute the scaling matrix
mScalingMatrix = openglframework::Matrix4(mRadius, 0, 0, 0,
0, mRadius, 0, 0,
0, 0, mRadius, 0,
0, 0, 0, 1);
// Initialize the position where the sphere will be rendered
translateWorld(position);
// Create the collision shape for the rigid body (sphere shape)
// ReactPhysics3D will clone this object to create an internal one. Therefore,
// it is OK if this object is destroyed right after calling RigidBody::addCollisionShape()
const rp3d::SphereShape collisionShape(mRadius);
// Initial position and orientation of the rigid body
rp3d::Vector3 initPosition(position.x, position.y, position.z);
rp3d::Quaternion initOrientation = rp3d::Quaternion::identity();
rp3d::Transform transform(initPosition, initOrientation);
// Create a rigid body corresponding to the sphere in the dynamics world
rp3d::RigidBody* body = world->createRigidBody(transform);
// Add a collision shape to the body and specify the mass of the shape
body->addCollisionShape(collisionShape, rp3d::Transform::identity(), mass);
mRigidBody = body;
mTransformMatrix = mTransformMatrix * mScalingMatrix;
}
// Destructor

View File

@ -41,7 +41,7 @@ class Sphere : public openglframework::Mesh {
float mRadius;
/// Rigid body used to simulate the dynamics of the sphere
rp3d::RigidBody* mRigidBody;
rp3d::CollisionBody* mRigidBody;
/// Scaling matrix (applied to a sphere to obtain the correct sphere dimensions)
openglframework::Matrix4 mScalingMatrix;
@ -52,6 +52,10 @@ class Sphere : public openglframework::Mesh {
// -------------------- Methods -------------------- //
/// Constructor
Sphere(float radius, const openglframework::Vector3& position,
rp3d::CollisionWorld* world, const std::string& meshFolderPath);
/// Constructor
Sphere(float radius, const openglframework::Vector3& position,
float mass, rp3d::DynamicsWorld* dynamicsWorld, const std::string& meshFolderPath);
@ -59,8 +63,11 @@ class Sphere : public openglframework::Mesh {
/// Destructor
~Sphere();
/// Return a pointer to the rigid body of the sphere
rp3d::RigidBody* getRigidBody();
/// 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();
@ -70,9 +77,14 @@ class Sphere : public openglframework::Mesh {
const openglframework::Matrix4& worldToCameraMatrix);
};
// Return a pointer to the rigid body of the sphere
inline rp3d::RigidBody* Sphere::getRigidBody() {
// Return a pointer to the collision body of the box
inline rp3d::CollisionBody* Sphere::getCollisionBody() {
return mRigidBody;
}
// Return a pointer to the rigid body of the box
inline rp3d::RigidBody* Sphere::getRigidBody() {
return dynamic_cast<rp3d::RigidBody*>(mRigidBody);
}
#endif

View File

@ -59,6 +59,15 @@ struct Color {
// Return the white color
static Color white() { return Color(1.0f, 1.0f, 1.0f, 1.0f);}
// Return the red color
static Color red() { return Color(1.0f, 0.0f, 0.0f, 1.0f);}
// Return the green color
static Color green() { return Color(0.0f, 1.0f, 0.0f, 1.0f);}
// Return the blue color
static Color blue() { return Color(0.0f, 0.0f, 1.0f, 1.0f);}
// = operator
Color& operator=(const Color& color) {
if (&color != this) {

View File

@ -0,0 +1,43 @@
# 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}/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(RAYCAST_SOURCES
Raycast.cpp
Scene.cpp
Scene.h
"../common/VisualContactPoint.cpp"
"../common/ConvexMesh.cpp"
"../common/Capsule.cpp"
"../common/Sphere.cpp"
"../common/Line.cpp"
"../common/Cylinder.cpp"
"../common/Cone.cpp"
"../common/Dumbbell.cpp"
"../common/Box.cpp"
"../common/Viewer.cpp"
)
# Create the executable
ADD_EXECUTABLE(raycast ${RAYCAST_SOURCES})
# Link with libraries
TARGET_LINK_LIBRARIES(raycast reactphysics3d openglframework glfw ${GLFW_LIBRARIES})

View File

@ -0,0 +1,155 @@
/********************************************************************************
* ReactPhysics3D physics library, http://code.google.com/p/reactphysics3d/ *
* Copyright (c) 2010-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 "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();
}

309
examples/raycast/Scene.cpp Normal file
View File

@ -0,0 +1,309 @@
/********************************************************************************
* ReactPhysics3D physics library, http://code.google.com/p/reactphysics3d/ *
* Copyright (c) 2010-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 "Scene.h"
// Namespaces
using namespace openglframework;
// Constructor
Scene::Scene(Viewer* viewer, const std::string& shaderFolderPath, const std::string& meshFolderPath)
: mViewer(viewer), mLight0(0), mCurrentBodyIndex(-1), mAreNormalsDisplayed(false),
mPhongShader(shaderFolderPath + "phong.vert",
shaderFolderPath +"phong.frag") {
// Move the light 0
mLight0.translateWorld(Vector3(50, 50, 50));
// Compute the radius and the center of the scene
float radiusScene = 30.0f;
openglframework::Vector3 center(0, 0, 0);
// Set the center of the scene
mViewer->setScenePosition(center, radiusScene);
// Create the dynamics world for the physics simulation
mCollisionWorld = new rp3d::CollisionWorld();
// Create the static data for the visual contact points
VisualContactPoint::createStaticData(meshFolderPath);
// ---------- Dumbbell ---------- //
openglframework::Vector3 position1(0, 0, 0);
// Create a convex mesh and a corresponding rigid in the dynamics world
mDumbbell = new Dumbbell(position1, mCollisionWorld, meshFolderPath);
// ---------- Box ---------- //
openglframework::Vector3 position2(0, 0, 0);
// Create a sphere and a corresponding rigid in the dynamics world
mBox = new Box(BOX_SIZE, position2, mCollisionWorld);
mBox->getCollisionBody()->setIsActive(false);
// ---------- Sphere ---------- //
openglframework::Vector3 position3(0, 0, 0);
// Create a sphere and a corresponding rigid in the dynamics world
mSphere = new Sphere(SPHERE_RADIUS, position3, mCollisionWorld,
meshFolderPath);
// ---------- Cone ---------- //
openglframework::Vector3 position4(0, 0, 0);
// Create a cone and a corresponding rigid in the dynamics world
mCone = new Cone(CONE_RADIUS, CONE_HEIGHT, position4, mCollisionWorld,
meshFolderPath);
mCone->getCollisionBody()->setIsActive(false);
// ---------- Cylinder ---------- //
openglframework::Vector3 position5(0, 0, 0);
// Create a cylinder and a corresponding rigid in the dynamics world
mCylinder = new Cylinder(CYLINDER_RADIUS, CYLINDER_HEIGHT, position5,
mCollisionWorld, meshFolderPath);
mCylinder->getCollisionBody()->setIsActive(false);
// ---------- Capsule ---------- //
openglframework::Vector3 position6(0, 0, 0);
// Create a cylinder and a corresponding rigid in the dynamics world
mCapsule = new Capsule(CAPSULE_RADIUS, CAPSULE_HEIGHT, position6 ,
mCollisionWorld, meshFolderPath);
// ---------- Convex Mesh ---------- //
openglframework::Vector3 position7(0, 0, 0);
// Create a convex mesh and a corresponding rigid in the dynamics world
mConvexMesh = new ConvexMesh(position7, mCollisionWorld, meshFolderPath);
// Create the lines that will be used for raycasting
createLines();
changeBody();
}
// Create the raycast lines
void Scene::createLines() {
int nbRaysOneDimension = sqrt(NB_RAYS);
for (int i=0; i<nbRaysOneDimension; i++) {
for (int j=0; j<nbRaysOneDimension; j++) {
float theta = i * 2.0f * M_PI / float(nbRaysOneDimension);
float phi = j * M_PI / float(nbRaysOneDimension);
// Generate a point on a sphere with spherical coordinates
float x = RAY_LENGTH * std::sin(phi) * std::cos(theta);
float y = RAY_LENGTH * std::sin(phi) * std::sin(theta);
float z = RAY_LENGTH * std::cos(phi);
// Create a line from the point on the sphere to the center of
// the scene
openglframework::Vector3 point1(x, y, z);
openglframework::Vector3 point2(0.0f, 0.0f, 0.0f);
Line* line = new Line(point1, point2);
mLines.push_back(line);
}
}
}
// Change the body to raycast and to display
void Scene::changeBody() {
mCurrentBodyIndex++;
if (mCurrentBodyIndex >= NB_BODIES) mCurrentBodyIndex = 0;
mSphere->getCollisionBody()->setIsActive(false);
mBox->getCollisionBody()->setIsActive(false);
mCone->getCollisionBody()->setIsActive(false);
mCylinder->getCollisionBody()->setIsActive(false);
mCapsule->getCollisionBody()->setIsActive(false);
mConvexMesh->getCollisionBody()->setIsActive(false);
mDumbbell->getCollisionBody()->setIsActive(false);
switch(mCurrentBodyIndex) {
case 0: mSphere->getCollisionBody()->setIsActive(true);
break;
case 1: mBox->getCollisionBody()->setIsActive(true);
break;
case 2: mCone->getCollisionBody()->setIsActive(true);
break;
case 3: mCylinder->getCollisionBody()->setIsActive(true);
break;
case 4: mCapsule->getCollisionBody()->setIsActive(true);
break;
case 5: mConvexMesh->getCollisionBody()->setIsActive(true);
break;
case 6: mDumbbell->getCollisionBody()->setIsActive(true);
break;
}
}
// Destructor
Scene::~Scene() {
// Destroy the shader
mPhongShader.destroy();
// Destroy the box rigid body from the dynamics world
mCollisionWorld->destroyCollisionBody(mBox->getCollisionBody());
delete mBox;
// Destroy the sphere
mCollisionWorld->destroyCollisionBody(mSphere->getCollisionBody());
delete mSphere;
// Destroy the corresponding rigid body from the dynamics world
mCollisionWorld->destroyCollisionBody(mCone->getCollisionBody());
delete mCone;
// Destroy the corresponding rigid body from the dynamics world
mCollisionWorld->destroyCollisionBody(mCylinder->getCollisionBody());
// Destroy the sphere
delete mCylinder;
// Destroy the corresponding rigid body from the dynamics world
mCollisionWorld->destroyCollisionBody(mCapsule->getCollisionBody());
// Destroy the sphere
delete mCapsule;
// Destroy the corresponding rigid body from the dynamics world
mCollisionWorld->destroyCollisionBody(mConvexMesh->getCollisionBody());
// Destroy the convex mesh
delete mConvexMesh;
// Destroy the corresponding rigid body from the dynamics world
mCollisionWorld->destroyCollisionBody(mDumbbell->getCollisionBody());
// Destroy the convex mesh
delete mDumbbell;
mRaycastManager.resetPoints();
// Destroy the static data for the visual contact points
VisualContactPoint::destroyStaticData();
// Destroy the collision world
delete mCollisionWorld;
// Destroy the lines
for (std::vector<Line*>::iterator it = mLines.begin(); it != mLines.end();
++it) {
delete (*it);
}
}
// Take a step for the simulation
void Scene::simulate() {
mRaycastManager.resetPoints();
// For each line of the scene
for (std::vector<Line*>::iterator it = mLines.begin(); it != mLines.end();
++it) {
Line* line = *it;
// Create a ray corresponding to the line
openglframework::Vector3 p1 = line->getPoint1();
openglframework::Vector3 p2 = line->getPoint2();
rp3d::Vector3 point1(p1.x, p1.y, p1.z);
rp3d::Vector3 point2(p2.x, p2.y, p2.z);
rp3d::Ray ray(point1, point2);
// Perform a raycast query on the physics world by passing a raycast
// callback class in argument.
mCollisionWorld->raycast(ray, &mRaycastManager);
}
}
// Render the scene
void Scene::render() {
glEnable(GL_DEPTH_TEST);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_CULL_FACE);
// Get the world-space to camera-space matrix
const Camera& camera = mViewer->getCamera();
const openglframework::Matrix4 worldToCameraMatrix = camera.getTransformMatrix().getInverse();
// Bind the shader
mPhongShader.bind();
openglframework::Vector4 grey(0.7, 0.7, 0.7, 1);
mPhongShader.setVector4Uniform("vertexColor", grey);
// Set the variables of the shader
mPhongShader.setMatrix4x4Uniform("projectionMatrix", camera.getProjectionMatrix());
mPhongShader.setVector3Uniform("light0PosCameraSpace", worldToCameraMatrix * mLight0.getOrigin());
mPhongShader.setVector3Uniform("lightAmbientColor", Vector3(0.3f, 0.3f, 0.3f));
const Color& diffColLight0 = mLight0.getDiffuseColor();
const Color& specColLight0 = mLight0.getSpecularColor();
mPhongShader.setVector3Uniform("light0DiffuseColor", Vector3(diffColLight0.r, diffColLight0.g, diffColLight0.b));
mPhongShader.setVector3Uniform("light0SpecularColor", Vector3(specColLight0.r, specColLight0.g, specColLight0.b));
mPhongShader.setFloatUniform("shininess", 200.0f);
if (mBox->getCollisionBody()->isActive()) mBox->render(mPhongShader, worldToCameraMatrix);
if (mSphere->getCollisionBody()->isActive()) mSphere->render(mPhongShader, worldToCameraMatrix);
if (mCone->getCollisionBody()->isActive()) mCone->render(mPhongShader, worldToCameraMatrix);
if (mCylinder->getCollisionBody()->isActive()) mCylinder->render(mPhongShader, worldToCameraMatrix);
if (mCapsule->getCollisionBody()->isActive()) mCapsule->render(mPhongShader, worldToCameraMatrix);
if (mConvexMesh->getCollisionBody()->isActive()) mConvexMesh->render(mPhongShader, worldToCameraMatrix);
if (mDumbbell->getCollisionBody()->isActive()) mDumbbell->render(mPhongShader, worldToCameraMatrix);
mPhongShader.unbind();
mPhongShader.bind();
mPhongShader.setVector3Uniform("light0SpecularColor", Vector3(0, 0, 0));
openglframework::Vector4 redColor(1, 0, 0, 1);
mPhongShader.setVector4Uniform("vertexColor", redColor);
// Render all the raycast hit points
mRaycastManager.render(mPhongShader, worldToCameraMatrix, mAreNormalsDisplayed);
mPhongShader.unbind();
mPhongShader.bind();
openglframework::Vector4 blueColor(0, 0.62, 0.92, 1);
mPhongShader.setVector4Uniform("vertexColor", blueColor);
// Render the lines
for (std::vector<Line*>::iterator it = mLines.begin(); it != mLines.end();
++it) {
(*it)->render(mPhongShader, worldToCameraMatrix);
}
// Unbind the shader
mPhongShader.unbind();
}

198
examples/raycast/Scene.h Normal file
View File

@ -0,0 +1,198 @@
/********************************************************************************
* ReactPhysics3D physics library, http://code.google.com/p/reactphysics3d/ *
* Copyright (c) 2010-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. *
* *
********************************************************************************/
#ifndef SCENE_H
#define SCENE_H
// Libraries
#include "openglframework.h"
#include "reactphysics3d.h"
#include "Sphere.h"
#include "Box.h"
#include "Cone.h"
#include "Cylinder.h"
#include "Capsule.h"
#include "Line.h"
#include "ConvexMesh.h"
#include "Dumbbell.h"
#include "VisualContactPoint.h"
#include "../common/Viewer.h"
// Constants
const openglframework::Vector3 BOX_SIZE(4, 2, 1);
const float SPHERE_RADIUS = 3.0f;
const float CONE_RADIUS = 3.0f;
const float CONE_HEIGHT = 5.0f;
const float CYLINDER_RADIUS = 3.0f;
const float CYLINDER_HEIGHT = 5.0f;
const float CAPSULE_RADIUS = 3.0f;
const float CAPSULE_HEIGHT = 5.0f;
const float DUMBBELL_HEIGHT = 5.0f;
const int NB_RAYS = 100;
const float RAY_LENGTH = 30.0f;
const int NB_BODIES = 7;
// Raycast manager
class RaycastManager : public rp3d::RaycastCallback {
private:
/// All the visual contact points
std::vector<VisualContactPoint*> mHitPoints;
/// All the normals at hit points
std::vector<Line*> mNormals;
public:
virtual rp3d::decimal notifyRaycastHit(const rp3d::RaycastInfo& raycastInfo) {
rp3d::Vector3 hitPos = raycastInfo.worldPoint;
openglframework::Vector3 position(hitPos.x, hitPos.y, hitPos.z);
VisualContactPoint* point = new VisualContactPoint(position);
mHitPoints.push_back(point);
// Create a line to display the normal at hit point
rp3d::Vector3 n = raycastInfo.worldNormal;
openglframework::Vector3 normal(n.x, n.y, n.z);
Line* normalLine = new Line(position, position + normal);
mNormals.push_back(normalLine);
return raycastInfo.hitFraction;
}
void render(openglframework::Shader& shader,
const openglframework::Matrix4& worldToCameraMatrix,
bool showNormals) {
// Render all the raycast hit points
for (std::vector<VisualContactPoint*>::iterator it = mHitPoints.begin();
it != mHitPoints.end(); ++it) {
(*it)->render(shader, worldToCameraMatrix);
}
if (showNormals) {
// Render all the normals at hit points
for (std::vector<Line*>::iterator it = mNormals.begin();
it != mNormals.end(); ++it) {
(*it)->render(shader, worldToCameraMatrix);
}
}
}
void resetPoints() {
// Destroy all the visual contact points
for (std::vector<VisualContactPoint*>::iterator it = mHitPoints.begin();
it != mHitPoints.end(); ++it) {
delete (*it);
}
mHitPoints.clear();
// Destroy all the normals
for (std::vector<Line*>::iterator it = mNormals.begin();
it != mNormals.end(); ++it) {
delete (*it);
}
mNormals.clear();
}
};
// Class Scene
class Scene {
private :
// -------------------- Attributes -------------------- //
/// Pointer to the viewer
Viewer* mViewer;
/// Raycast manager
RaycastManager mRaycastManager;
/// Light 0
openglframework::Light mLight0;
/// Phong shader
openglframework::Shader mPhongShader;
/// All the raycast lines
std::vector<Line*> mLines;
/// Current body index
int mCurrentBodyIndex;
/// True if the hit points normals are displayed
bool mAreNormalsDisplayed;
/// Raycast manager
/// All objects on the scene
Box* mBox;
Sphere* mSphere;
Cone* mCone;
Cylinder* mCylinder;
Capsule* mCapsule;
ConvexMesh* mConvexMesh;
Dumbbell* mDumbbell;
/// Collision world used for the physics simulation
rp3d::CollisionWorld* mCollisionWorld;
/// Create the raycast lines
void createLines();
public:
// -------------------- Methods -------------------- //
/// Constructor
Scene(Viewer* viewer, const std::string& shaderFolderPath,
const std::string& meshFolderPath);
/// Destructor
~Scene();
/// Take a step for the simulation
void simulate();
/// Render the scene
void render();
/// Change the body to raycast
void changeBody();
/// Display or not the surface normals at hit points
void showHideNormals();
};
// Display or not the surface normals at hit points
inline void Scene::showHideNormals() {
mAreNormalsDisplayed = !mAreNormalsDisplayed;
}
#endif