211 lines
6.2 KiB
C++

/*
* Copyright (c) 2016-2016 Irlan Robson http://www.irlan.net
*
* 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 B3_WORLD_H
#define B3_WORLD_H
#include <bounce/common/memory/stack_allocator.h>
#include <bounce/common/memory/block_pool.h>
#include <bounce/common/template/list.h>
#include <bounce/dynamics/time_step.h>
#include <bounce/dynamics/joint_manager.h>
#include <bounce/dynamics/contact_manager.h>
struct b3BodyDef;
class b3Body;
class b3QueryListener;
class b3RayCastListener;
class b3ContactListener;
class b3ContactFilter;
struct b3RayCastSingleOutput
{
b3Shape* shape; // shape
b3Vec3 point; // intersection point on surface
b3Vec3 normal; // surface normal of intersection
float32 fraction; // time of intersection on segment
};
// Use a physics world to create/destroy rigid bodies, execute ray cast and volume queries.
class b3World
{
public:
b3World();
~b3World();
// The filter passed can tell the world to disallow the contact creation between
// two shapes.
void SetContactFilter(b3ContactFilter* filter);
// The listener passed will be notified when two body shapes begin/stays/ends
// touching with each other.
void SetContactListener(b3ContactListener* listener);
// Enable body sleeping. This improves performance.
void SetSleeping(bool flag);
// Enable warm-starting for the constraint solvers. This improves stability significantly.
void SetWarmStart(bool flag);
// Set the world gravity force.
void SetGravity(const b3Vec3& gravity);
// Create a new rigid body.
b3Body* CreateBody(const b3BodyDef& def);
// Destroy an existing rigid body.
void DestroyBody(b3Body* body);
// Create a new joint.
b3Joint* CreateJoint(const b3JointDef& def);
// Remove a joint from the world and deallocate it from the memory.
void DestroyJoint(b3Joint* joint);
// Simulate a physics step.
// The function parameters are the ammount of time to simulate,
// and the number of constraint solver iterations.
void Step(float32 dt, u32 velocityIterations, u32 positionIterations);
// Perform a ray cast with the world.
// If the ray doesn't intersect with a shape in the world then return false.
// The ray cast output is the intercepted shape, the intersection
// point in world space, the face normal on the shape associated with the point,
// and the intersection fraction.
bool RayCastSingle(b3RayCastSingleOutput* output, const b3Vec3& p1, const b3Vec3& p2) const;
// Perform a ray cast with the world.
// The given ray cast listener will be notified when a ray intersects a shape
// in the world.
// The ray cast output is the intercepted shape, the intersection
// point in world space, the face normal on the shape associated with the point,
// and the intersection fraction.
void RayCast(b3RayCastListener* listener, const b3Vec3& p1, const b3Vec3& p2) const;
// Perform a AABB cast with the world.
// The query listener will be notified when two shape AABBs are overlapping.
// If the listener returns false then the query is stopped immediately.
// Otherwise, it continues searching for new overlapping shape AABBs.
void QueryAABB(b3QueryListener* listener, const b3AABB3& aabb) const;
// Get the list of bodies in this world.
const b3List2<b3Body>& GetBodyList() const;
b3List2<b3Body>& GetBodyList();
// Get the list of joints in this world.
const b3List2<b3Joint>& GetJointList() const;
b3List2<b3Joint>& GetJointList();
// Get the list of contacts in this world.
const b3List2<b3Contact>& GetContactList() const;
b3List2<b3Contact>& GetContactList();
// Debug draw the physics entities that belong to this world.
// The user must implement the debug draw interface b3Draw and b3_debugDraw must have been
// set to the user implementation.
void DebugDraw() const;
void DrawShape(const b3Transform& xf, const b3Shape* shape) const;
void DrawJoint(const b3Joint* joint) const;
void DrawContact(const b3Contact* contact) const;
private :
enum b3Flags
{
e_shapeAddedFlag = 0x0001,
e_clearForcesFlag = 0x0002,
};
friend class b3Body;
friend class b3Shape;
friend class b3Contact;
friend class b3ConvexContact;
friend class b3MeshContact;
friend class b3Joint;
void Solve(float32 dt, u32 velocityIterations, u32 positionIterations);
bool m_sleeping;
bool m_warmStarting;
u32 m_flags;
b3Vec3 m_gravity;
b3Draw* m_debugDraw;
b3StackAllocator m_stackAllocator;
b3BlockPool m_bodyBlocks;
// List of bodies
b3List2<b3Body> m_bodyList;
// List of joints
b3JointManager m_jointMan;
// List of contacts
b3ContactManager m_contactMan;
};
inline void b3World::SetContactListener(b3ContactListener* listener)
{
m_contactMan.m_contactListener = listener;
}
inline void b3World::SetContactFilter(b3ContactFilter* filter)
{
m_contactMan.m_contactFilter = filter;
}
inline void b3World::SetGravity(const b3Vec3& gravity)
{
m_gravity = gravity;
}
inline void b3World::SetWarmStart(bool flag)
{
m_warmStarting = flag;
}
inline const b3List2<b3Body>& b3World::GetBodyList() const
{
return m_bodyList;
}
inline b3List2<b3Body>& b3World::GetBodyList()
{
return m_bodyList;
}
inline const b3List2<b3Joint>& b3World::GetJointList() const
{
return m_jointMan.m_jointList;
}
inline b3List2<b3Joint>& b3World::GetJointList()
{
return m_jointMan.m_jointList;
}
inline const b3List2<b3Contact>& b3World::GetContactList() const
{
return m_contactMan.m_contactList;
}
inline b3List2<b3Contact>& b3World::GetContactList()
{
return m_contactMan.m_contactList;
}
#endif