Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • Alexandre.Meyer/m1if37-animation
  • Alexandre.Meyer/m2-apprentissage-profond-image
  • Alexandre.Meyer/m2-animation
  • Alexandre.Meyer/hugo-web-minimal
  • Alexandre.Meyer/lifami
  • Alexandre.Meyer/lifapcd
  • Alexandre.Meyer/www
  • Alexandre.Meyer/lifstage
8 results
Show changes
Showing
with 0 additions and 3525 deletions
/*
* Copyright (c) 2006-2009 Erin Catto http://www.box2d.org
*
* 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.
*/
#include "Box2D/Dynamics/b2WorldCallbacks.h"
#include "Box2D/Dynamics/b2Fixture.h"
// Return true if contact calculations should be performed between these two shapes.
// If you implement your own collision filter you may want to build from this implementation.
bool b2ContactFilter::ShouldCollide(b2Fixture* fixtureA, b2Fixture* fixtureB)
{
const b2Filter& filterA = fixtureA->GetFilterData();
const b2Filter& filterB = fixtureB->GetFilterData();
if (filterA.groupIndex == filterB.groupIndex && filterA.groupIndex != 0)
{
return filterA.groupIndex > 0;
}
bool collide = (filterA.maskBits & filterB.categoryBits) != 0 && (filterA.categoryBits & filterB.maskBits) != 0;
return collide;
}
/*
* Copyright (c) 2006-2009 Erin Catto http://www.box2d.org
*
* 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 B2_WORLD_CALLBACKS_H
#define B2_WORLD_CALLBACKS_H
#include "Box2D/Common/b2Settings.h"
struct b2Vec2;
struct b2Transform;
class b2Fixture;
class b2Body;
class b2Joint;
class b2Contact;
struct b2ContactResult;
struct b2Manifold;
/// Joints and fixtures are destroyed when their associated
/// body is destroyed. Implement this listener so that you
/// may nullify references to these joints and shapes.
class b2DestructionListener
{
public:
virtual ~b2DestructionListener() {}
/// Called when any joint is about to be destroyed due
/// to the destruction of one of its attached bodies.
virtual void SayGoodbye(b2Joint* joint) = 0;
/// Called when any fixture is about to be destroyed due
/// to the destruction of its parent body.
virtual void SayGoodbye(b2Fixture* fixture) = 0;
};
/// Implement this class to provide collision filtering. In other words, you can implement
/// this class if you want finer control over contact creation.
class b2ContactFilter
{
public:
virtual ~b2ContactFilter() {}
/// Return true if contact calculations should be performed between these two shapes.
/// @warning for performance reasons this is only called when the AABBs begin to overlap.
virtual bool ShouldCollide(b2Fixture* fixtureA, b2Fixture* fixtureB);
};
/// Contact impulses for reporting. Impulses are used instead of forces because
/// sub-step forces may approach infinity for rigid body collisions. These
/// match up one-to-one with the contact points in b2Manifold.
struct b2ContactImpulse
{
float32 normalImpulses[b2_maxManifoldPoints];
float32 tangentImpulses[b2_maxManifoldPoints];
int32 count;
};
/// Implement this class to get contact information. You can use these results for
/// things like sounds and game logic. You can also get contact results by
/// traversing the contact lists after the time step. However, you might miss
/// some contacts because continuous physics leads to sub-stepping.
/// Additionally you may receive multiple callbacks for the same contact in a
/// single time step.
/// You should strive to make your callbacks efficient because there may be
/// many callbacks per time step.
/// @warning You cannot create/destroy Box2D entities inside these callbacks.
class b2ContactListener
{
public:
virtual ~b2ContactListener() {}
/// Called when two fixtures begin to touch.
virtual void BeginContact(b2Contact* contact) { B2_NOT_USED(contact); }
/// Called when two fixtures cease to touch.
virtual void EndContact(b2Contact* contact) { B2_NOT_USED(contact); }
/// This is called after a contact is updated. This allows you to inspect a
/// contact before it goes to the solver. If you are careful, you can modify the
/// contact manifold (e.g. disable contact).
/// A copy of the old manifold is provided so that you can detect changes.
/// Note: this is called only for awake bodies.
/// Note: this is called even when the number of contact points is zero.
/// Note: this is not called for sensors.
/// Note: if you set the number of contact points to zero, you will not
/// get an EndContact callback. However, you may get a BeginContact callback
/// the next step.
virtual void PreSolve(b2Contact* contact, const b2Manifold* oldManifold)
{
B2_NOT_USED(contact);
B2_NOT_USED(oldManifold);
}
/// This lets you inspect a contact after the solver is finished. This is useful
/// for inspecting impulses.
/// Note: the contact manifold does not include time of impact impulses, which can be
/// arbitrarily large if the sub-step is small. Hence the impulse is provided explicitly
/// in a separate data structure.
/// Note: this is only called for contacts that are touching, solid, and awake.
virtual void PostSolve(b2Contact* contact, const b2ContactImpulse* impulse)
{
B2_NOT_USED(contact);
B2_NOT_USED(impulse);
}
};
/// Callback class for AABB queries.
/// See b2World::Query
class b2QueryCallback
{
public:
virtual ~b2QueryCallback() {}
/// Called for each fixture found in the query AABB.
/// @return false to terminate the query.
virtual bool ReportFixture(b2Fixture* fixture) = 0;
};
/// Callback class for ray casts.
/// See b2World::RayCast
class b2RayCastCallback
{
public:
virtual ~b2RayCastCallback() {}
/// Called for each fixture found in the query. You control how the ray cast
/// proceeds by returning a float:
/// return -1: ignore this fixture and continue
/// return 0: terminate the ray cast
/// return fraction: clip the ray to this point
/// return 1: don't clip the ray and continue
/// @param fixture the fixture hit by the ray
/// @param point the point of initial intersection
/// @param normal the normal vector at the point of intersection
/// @return -1 to filter, 0 to terminate, fraction to clip the ray for
/// closest hit, 1 to continue
virtual float32 ReportFixture( b2Fixture* fixture, const b2Vec2& point,
const b2Vec2& normal, float32 fraction) = 0;
};
#endif
/*
* Copyright (c) 2011 Erin Catto http://box2d.org
*
* 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.
*/
#include "Box2D/Rope/b2Rope.h"
#include "Box2D/Common/b2Draw.h"
b2Rope::b2Rope()
{
m_count = 0;
m_ps = nullptr;
m_p0s = nullptr;
m_vs = nullptr;
m_ims = nullptr;
m_Ls = nullptr;
m_as = nullptr;
m_gravity.SetZero();
m_k2 = 1.0f;
m_k3 = 0.1f;
}
b2Rope::~b2Rope()
{
b2Free(m_ps);
b2Free(m_p0s);
b2Free(m_vs);
b2Free(m_ims);
b2Free(m_Ls);
b2Free(m_as);
}
void b2Rope::Initialize(const b2RopeDef* def)
{
b2Assert(def->count >= 3);
m_count = def->count;
m_ps = (b2Vec2*)b2Alloc(m_count * sizeof(b2Vec2));
m_p0s = (b2Vec2*)b2Alloc(m_count * sizeof(b2Vec2));
m_vs = (b2Vec2*)b2Alloc(m_count * sizeof(b2Vec2));
m_ims = (float32*)b2Alloc(m_count * sizeof(float32));
for (int32 i = 0; i < m_count; ++i)
{
m_ps[i] = def->vertices[i];
m_p0s[i] = def->vertices[i];
m_vs[i].SetZero();
float32 m = def->masses[i];
if (m > 0.0f)
{
m_ims[i] = 1.0f / m;
}
else
{
m_ims[i] = 0.0f;
}
}
int32 count2 = m_count - 1;
int32 count3 = m_count - 2;
m_Ls = (float32*)b2Alloc(count2 * sizeof(float32));
m_as = (float32*)b2Alloc(count3 * sizeof(float32));
for (int32 i = 0; i < count2; ++i)
{
b2Vec2 p1 = m_ps[i];
b2Vec2 p2 = m_ps[i+1];
m_Ls[i] = b2Distance(p1, p2);
}
for (int32 i = 0; i < count3; ++i)
{
b2Vec2 p1 = m_ps[i];
b2Vec2 p2 = m_ps[i + 1];
b2Vec2 p3 = m_ps[i + 2];
b2Vec2 d1 = p2 - p1;
b2Vec2 d2 = p3 - p2;
float32 a = b2Cross(d1, d2);
float32 b = b2Dot(d1, d2);
m_as[i] = b2Atan2(a, b);
}
m_gravity = def->gravity;
m_damping = def->damping;
m_k2 = def->k2;
m_k3 = def->k3;
}
void b2Rope::Step(float32 h, int32 iterations)
{
if (h == 0.0)
{
return;
}
float32 d = expf(- h * m_damping);
for (int32 i = 0; i < m_count; ++i)
{
m_p0s[i] = m_ps[i];
if (m_ims[i] > 0.0f)
{
m_vs[i] += h * m_gravity;
}
m_vs[i] *= d;
m_ps[i] += h * m_vs[i];
}
for (int32 i = 0; i < iterations; ++i)
{
SolveC2();
SolveC3();
SolveC2();
}
float32 inv_h = 1.0f / h;
for (int32 i = 0; i < m_count; ++i)
{
m_vs[i] = inv_h * (m_ps[i] - m_p0s[i]);
}
}
void b2Rope::SolveC2()
{
int32 count2 = m_count - 1;
for (int32 i = 0; i < count2; ++i)
{
b2Vec2 p1 = m_ps[i];
b2Vec2 p2 = m_ps[i + 1];
b2Vec2 d = p2 - p1;
float32 L = d.Normalize();
float32 im1 = m_ims[i];
float32 im2 = m_ims[i + 1];
if (im1 + im2 == 0.0f)
{
continue;
}
float32 s1 = im1 / (im1 + im2);
float32 s2 = im2 / (im1 + im2);
p1 -= m_k2 * s1 * (m_Ls[i] - L) * d;
p2 += m_k2 * s2 * (m_Ls[i] - L) * d;
m_ps[i] = p1;
m_ps[i + 1] = p2;
}
}
void b2Rope::SetAngle(float32 angle)
{
int32 count3 = m_count - 2;
for (int32 i = 0; i < count3; ++i)
{
m_as[i] = angle;
}
}
void b2Rope::SolveC3()
{
int32 count3 = m_count - 2;
for (int32 i = 0; i < count3; ++i)
{
b2Vec2 p1 = m_ps[i];
b2Vec2 p2 = m_ps[i + 1];
b2Vec2 p3 = m_ps[i + 2];
float32 m1 = m_ims[i];
float32 m2 = m_ims[i + 1];
float32 m3 = m_ims[i + 2];
b2Vec2 d1 = p2 - p1;
b2Vec2 d2 = p3 - p2;
float32 L1sqr = d1.LengthSquared();
float32 L2sqr = d2.LengthSquared();
if (L1sqr * L2sqr == 0.0f)
{
continue;
}
float32 a = b2Cross(d1, d2);
float32 b = b2Dot(d1, d2);
float32 angle = b2Atan2(a, b);
b2Vec2 Jd1 = (-1.0f / L1sqr) * d1.Skew();
b2Vec2 Jd2 = (1.0f / L2sqr) * d2.Skew();
b2Vec2 J1 = -Jd1;
b2Vec2 J2 = Jd1 - Jd2;
b2Vec2 J3 = Jd2;
float32 mass = m1 * b2Dot(J1, J1) + m2 * b2Dot(J2, J2) + m3 * b2Dot(J3, J3);
if (mass == 0.0f)
{
continue;
}
mass = 1.0f / mass;
float32 C = angle - m_as[i];
while (C > b2_pi)
{
angle -= 2 * b2_pi;
C = angle - m_as[i];
}
while (C < -b2_pi)
{
angle += 2.0f * b2_pi;
C = angle - m_as[i];
}
float32 impulse = - m_k3 * mass * C;
p1 += (m1 * impulse) * J1;
p2 += (m2 * impulse) * J2;
p3 += (m3 * impulse) * J3;
m_ps[i] = p1;
m_ps[i + 1] = p2;
m_ps[i + 2] = p3;
}
}
void b2Rope::Draw(b2Draw* draw) const
{
b2Color c(0.4f, 0.5f, 0.7f);
for (int32 i = 0; i < m_count - 1; ++i)
{
draw->DrawSegment(m_ps[i], m_ps[i+1], c);
}
}
/*
* Copyright (c) 2011 Erin Catto http://www.box2d.org
*
* 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 B2_ROPE_H
#define B2_ROPE_H
#include "Box2D/Common/b2Math.h"
class b2Draw;
///
struct b2RopeDef
{
b2RopeDef()
{
vertices = nullptr;
count = 0;
masses = nullptr;
gravity.SetZero();
damping = 0.1f;
k2 = 0.9f;
k3 = 0.1f;
}
///
b2Vec2* vertices;
///
int32 count;
///
float32* masses;
///
b2Vec2 gravity;
///
float32 damping;
/// Stretching stiffness
float32 k2;
/// Bending stiffness. Values above 0.5 can make the simulation blow up.
float32 k3;
};
///
class b2Rope
{
public:
b2Rope();
~b2Rope();
///
void Initialize(const b2RopeDef* def);
///
void Step(float32 timeStep, int32 iterations);
///
int32 GetVertexCount() const
{
return m_count;
}
///
const b2Vec2* GetVertices() const
{
return m_ps;
}
///
void Draw(b2Draw* draw) const;
///
void SetAngle(float32 angle);
private:
void SolveC2();
void SolveC3();
int32 m_count;
b2Vec2* m_ps;
b2Vec2* m_p0s;
b2Vec2* m_vs;
float32* m_ims;
float32* m_Ls;
float32* m_as;
b2Vec2 m_gravity;
float32 m_damping;
float32 m_k2;
float32 m_k3;
};
#endif
/*
* Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com
*
* 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.
*/
#include "b2BuoyancyController.h"
#include "../b2Fixture.h"
b2BuoyancyController::b2BuoyancyController(const b2BuoyancyControllerDef* def) : b2Controller(def)
{
normal = def->normal;
offset = def->offset;
density = def->density;
velocity = def->velocity;
linearDrag = def->linearDrag;
angularDrag = def->angularDrag;
useDensity = def->useDensity;
useWorldGravity = def->useWorldGravity;
gravity = def->gravity;
}
void b2BuoyancyController::Step(const b2TimeStep& step)
{
B2_NOT_USED(step);
if(!m_bodyList)
return;
if(useWorldGravity)
{
gravity = m_world->GetGravity();
}
for(b2ControllerEdge *i=m_bodyList;i;i=i->nextBody)
{
b2Body* body = i->body;
if(body->IsSleeping())
{
//Buoyancy force is just a function of position,
//so unlike most forces, it is safe to ignore sleeping bodes
continue;
}
b2Vec2 areac(0,0);
b2Vec2 massc(0,0);
float32 area = 0;
float32 mass = 0;
for(b2Fixture* shape=body->GetFixtureList();shape;shape=shape->GetNext())
{
b2Vec2 sc(0,0);
float32 sarea = shape->ComputeSubmergedArea(normal, offset, &sc);
area += sarea;
areac.x += sarea * sc.x;
areac.y += sarea * sc.y;
float shapeDensity = 0;
if(useDensity)
{
//TODO: Expose density publicly
shapeDensity=shape->GetDensity();
}
else
{
shapeDensity = 1;
}
mass += sarea*shapeDensity;
massc.x += sarea * sc.x * shapeDensity;
massc.y += sarea * sc.y * shapeDensity;
}
areac.x/=area;
areac.y/=area;
b2Vec2 localCentroid = b2MulT(body->GetXForm(),areac);
massc.x/=mass;
massc.y/=mass;
if(area<B2_FLT_EPSILON)
continue;
//Buoyancy
b2Vec2 buoyancyForce = -density*area*gravity;
body->ApplyForce(buoyancyForce,massc);
//Linear drag
b2Vec2 dragForce = body->GetLinearVelocityFromWorldPoint(areac) - velocity;
dragForce *= -linearDrag*area;
body->ApplyForce(dragForce,areac);
//Angular drag
//TODO: Something that makes more physical sense?
body->ApplyTorque(-body->GetInertia()/body->GetMass()*area*body->GetAngularVelocity()*angularDrag);
}
}
void b2BuoyancyController::Draw(b2DebugDraw *debugDraw)
{
float32 r = 1000;
b2Vec2 p1 = offset * normal + b2Cross(normal, r);
b2Vec2 p2 = offset * normal - b2Cross(normal, r);
b2Color color(0,0,0.8f);
debugDraw->DrawSegment(p1, p2, color);
}
void b2BuoyancyController::Destroy(b2BlockAllocator* allocator)
{
allocator->Free(this, sizeof(b2BuoyancyController));
}
b2BuoyancyController* b2BuoyancyControllerDef::Create(b2BlockAllocator* allocator) const
{
void* mem = allocator->Allocate(sizeof(b2BuoyancyController));
return new (mem) b2BuoyancyController(this);
}
/*
* Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com
*
* 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 B2_BUOYANCYCONTROLLER_H
#define B2_BUOYANCYCONTROLLER_H
#include "b2Controller.h"
class b2BuoyancyControllerDef;
/// Calculates buoyancy forces for fluids in the form of a half plane.
class b2BuoyancyController : public b2Controller{
public:
/// The outer surface normal
b2Vec2 normal;
/// The height of the fluid surface along the normal
float32 offset;
/// The fluid density
float32 density;
/// Fluid velocity, for drag calculations
b2Vec2 velocity;
/// Linear drag co-efficient
float32 linearDrag;
/// Linear drag co-efficient
float32 angularDrag;
/// If false, bodies are assumed to be uniformly dense, otherwise use the shapes densities
bool useDensity; //False by default to prevent a gotcha
/// If true, gravity is taken from the world instead of the gravity parameter.
bool useWorldGravity;
/// Gravity vector, if the world's gravity is not used
b2Vec2 gravity;
/// @see b2Controller::Step
void Step(const b2TimeStep& step);
/// @see b2Controller::Draw
void Draw(b2DebugDraw *debugDraw);
protected:
void Destroy(b2BlockAllocator* allocator);
private:
friend class b2BuoyancyControllerDef;
b2BuoyancyController(const b2BuoyancyControllerDef* def);
};
/// This class is used to build buoyancy controllers
class b2BuoyancyControllerDef : public b2ControllerDef
{
public:
/// The outer surface normal
b2Vec2 normal;
/// The height of the fluid surface along the normal
float32 offset;
/// The fluid density
float32 density;
/// Fluid velocity, for drag calculations
b2Vec2 velocity;
/// Linear drag co-efficient
float32 linearDrag;
/// Linear drag co-efficient
float32 angularDrag;
/// If false, bodies are assumed to be uniformly dense, otherwise use the shapes densities
bool useDensity; //False by default to prevent a gotcha
/// If true, gravity is taken from the world instead of the gravity parameter.
bool useWorldGravity;
/// Gravity vector, if the world's gravity is not used
b2Vec2 gravity;
b2BuoyancyControllerDef():
normal(0,1),
offset(0),
density(0),
velocity(0,0),
linearDrag(0),
angularDrag(0),
useDensity(false),
useWorldGravity(true),
gravity(0,0)
{
}
private:
b2BuoyancyController* Create(b2BlockAllocator* allocator) const;
};
#endif
/*
* Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
*
* 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.
*/
#include "b2ConstantAccelController.h"
b2ConstantAccelController::b2ConstantAccelController(const b2ConstantAccelControllerDef* def) : b2Controller(def)
{
A = def->A;
}
void b2ConstantAccelController::Step(const b2TimeStep& step)
{
for(b2ControllerEdge *i=m_bodyList;i;i=i->nextBody){
b2Body* body = i->body;
if(body->IsSleeping())
continue;
body->SetLinearVelocity(body->GetLinearVelocity()+step.dt*A);
}
}
void b2ConstantAccelController::Destroy(b2BlockAllocator* allocator)
{
allocator->Free(this, sizeof(b2ConstantAccelController));
}
b2ConstantAccelController* b2ConstantAccelControllerDef::Create(b2BlockAllocator* allocator) const
{
void* mem = allocator->Allocate(sizeof(b2ConstantAccelController));
return new (mem) b2ConstantAccelController(this);
}
/*
* Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
*
* 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 B2_CONSTANTACCELCONTROLLER_H
#define B2_CONSTANTACCELCONTROLLER_H
#include "b2Controller.h"
class b2ConstantAccelControllerDef;
/// Applies a force every frame
class b2ConstantAccelController : public b2Controller{
public:
/// The force to apply
b2Vec2 A;
/// @see b2Controller::Step
void Step(const b2TimeStep& step);
protected:
void Destroy(b2BlockAllocator* allocator);
private:
friend class b2ConstantAccelControllerDef;
b2ConstantAccelController(const b2ConstantAccelControllerDef* def);
};
/// This class is used to build constant acceleration controllers
class b2ConstantAccelControllerDef : public b2ControllerDef
{
public:
/// The force to apply
b2Vec2 A;
private:
b2ConstantAccelController* Create(b2BlockAllocator* allocator) const;
};
#endif
/*
* Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
*
* 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.
*/
#include "b2ConstantForceController.h"
b2ConstantForceController::b2ConstantForceController(const b2ConstantForceControllerDef* def) : b2Controller(def)
{
F = def->F;
}
void b2ConstantForceController::Step(const b2TimeStep& step)
{
B2_NOT_USED(step);
for(b2ControllerEdge *i=m_bodyList;i;i=i->nextBody){
b2Body* body = i->body;
if(body->IsSleeping())
continue;
body->ApplyForce(F,body->GetWorldCenter());
}
}
void b2ConstantForceController::Destroy(b2BlockAllocator* allocator)
{
allocator->Free(this, sizeof(b2ConstantForceController));
}
b2ConstantForceController* b2ConstantForceControllerDef::Create(b2BlockAllocator* allocator) const
{
void* mem = allocator->Allocate(sizeof(b2ConstantForceController));
return new (mem) b2ConstantForceController(this);
}
/*
* Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
*
* 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 B2_CONSTANTFORCECONTROLLER_H
#define B2_CONSTANTFORCECONTROLLER_H
#include "b2Controller.h"
class b2ConstantForceControllerDef;
/// Applies a force every frame
class b2ConstantForceController : public b2Controller
{
public:
/// The force to apply
b2Vec2 F;
/// @see b2Controller::Step
void Step(const b2TimeStep& step);
protected:
void Destroy(b2BlockAllocator* allocator);
private:
friend class b2ConstantForceControllerDef;
b2ConstantForceController(const b2ConstantForceControllerDef* def);
};
/// This class is used to build constant force controllers
class b2ConstantForceControllerDef : public b2ControllerDef
{
public:
/// The force to apply
b2Vec2 F;
private:
b2ConstantForceController* Create(b2BlockAllocator* allocator) const;
};
#endif
/*
* Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
*
* 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.
*/
#include "b2Controller.h"
#include "../../Common/b2BlockAllocator.h"
b2Controller::~b2Controller()
{
//Remove attached bodies
Clear();
}
void b2Controller::AddBody(b2Body* body)
{
void* mem = m_world->m_blockAllocator.Allocate(sizeof(b2ControllerEdge));
b2ControllerEdge* edge = new (mem) b2ControllerEdge;
edge->body = body;
edge->controller = this;
//Add edge to controller list
edge->nextBody = m_bodyList;
edge->prevBody = NULL;
if(m_bodyList)
m_bodyList->prevBody = edge;
m_bodyList = edge;
++m_bodyCount;
//Add edge to body list
edge->nextController = body->m_controllerList;
edge->prevController = NULL;
if(body->m_controllerList)
body->m_controllerList->prevController = edge;
body->m_controllerList = edge;
}
void b2Controller::RemoveBody(b2Body* body)
{
//Assert that the controller is not empty
b2Assert(m_bodyCount>0);
//Find the corresponding edge
b2ControllerEdge* edge = m_bodyList;
while(edge && edge->body!=body)
edge = edge->nextBody;
//Assert that we are removing a body that is currently attached to the controller
b2Assert(edge!=NULL);
//Remove edge from controller list
if(edge->prevBody)
edge->prevBody->nextBody = edge->nextBody;
if(edge->nextBody)
edge->nextBody->prevBody = edge->prevBody;
if(edge == m_bodyList)
m_bodyList = edge->nextBody;
--m_bodyCount;
//Remove edge from body list
if(edge->prevController)
edge->prevController->nextController = edge->nextController;
if(edge->nextController)
edge->nextController->prevController = edge->prevController;
if(edge == body->m_controllerList)
body->m_controllerList = edge->nextController;
//Free the edge
m_world->m_blockAllocator.Free(edge, sizeof(b2ControllerEdge));
}
void b2Controller::Clear(){
while(m_bodyList)
{
b2ControllerEdge* edge = m_bodyList;
//Remove edge from controller list
m_bodyList = edge->nextBody;
//Remove edge from body list
if(edge->prevController)
edge->prevController->nextController = edge->nextController;
if(edge->nextController)
edge->nextController->prevController = edge->prevController;
if(edge == edge->body->m_controllerList)
edge->body->m_controllerList = edge->nextController;
//Free the edge
m_world->m_blockAllocator.Free(edge, sizeof(b2ControllerEdge));
}
m_bodyCount = 0;
}
/*
* Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
*
* 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 B2_CONTROLLER_H
#define B2_CONTROLLER_H
#include "../../Dynamics/b2World.h"
#include "../../Dynamics/b2Body.h"
class b2Body;
class b2World;
class b2Controller;
/// A controller edge is used to connect bodies and controllers together
/// in a bipartite graph.
struct b2ControllerEdge
{
b2Controller* controller; ///< provides quick access to other end of this edge.
b2Body* body; ///< the body
b2ControllerEdge* prevBody; ///< the previous controller edge in the controllers's joint list
b2ControllerEdge* nextBody; ///< the next controller edge in the controllers's joint list
b2ControllerEdge* prevController; ///< the previous controller edge in the body's joint list
b2ControllerEdge* nextController; ///< the next controller edge in the body's joint list
};
class b2ControllerDef;
/// Base class for controllers. Controllers are a convience for encapsulating common
/// per-step functionality.
class b2Controller
{
public:
virtual ~b2Controller();
/// Controllers override this to implement per-step functionality.
virtual void Step(const b2TimeStep& step) = 0;
/// Controllers override this to provide debug drawing.
virtual void Draw(b2DebugDraw *debugDraw) {B2_NOT_USED(debugDraw);};
/// Adds a body to the controller list.
void AddBody(b2Body* body);
/// Removes a body from the controller list.
void RemoveBody(b2Body* body);
/// Removes all bodies from the controller list.
void Clear();
/// Get the next controller in the world's body list.
b2Controller* GetNext();
const b2Controller* GetNext() const;
/// Get the parent world of this body.
b2World* GetWorld();
const b2World* GetWorld() const;
/// Get the attached body list
b2ControllerEdge* GetBodyList();
const b2ControllerEdge* GetBodyList() const;
protected:
friend class b2World;
b2World* m_world;
b2ControllerEdge* m_bodyList;
int32 m_bodyCount;
b2Controller(const b2ControllerDef* def):
m_world(NULL),
m_bodyList(NULL),
m_bodyCount(0),
m_prev(NULL),
m_next(NULL)
{
B2_NOT_USED(def);
}
virtual void Destroy(b2BlockAllocator* allocator) = 0;
private:
b2Controller* m_prev;
b2Controller* m_next;
static void Destroy(b2Controller* controller, b2BlockAllocator* allocator);
};
class b2ControllerDef
{
public:
virtual ~b2ControllerDef() {};
private:
friend class b2World;
virtual b2Controller* Create(b2BlockAllocator* allocator) const = 0;
};
inline b2Controller* b2Controller::GetNext()
{
return m_next;
}
inline const b2Controller* b2Controller::GetNext() const
{
return m_next;
}
inline b2World* b2Controller::GetWorld()
{
return m_world;
}
inline const b2World* b2Controller::GetWorld() const
{
return m_world;
}
inline b2ControllerEdge* b2Controller::GetBodyList()
{
return m_bodyList;
}
inline const b2ControllerEdge* b2Controller::GetBodyList() const
{
return m_bodyList;
}
inline void b2Controller::Destroy(b2Controller* controller, b2BlockAllocator* allocator)
{
controller->Destroy(allocator);
}
#endif
/*
* Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
*
* 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.
*/
#include "b2GravityController.h"
b2GravityController::b2GravityController(const b2GravityControllerDef* def) : b2Controller(def)
{
G = def->G;
invSqr = def->invSqr;
}
void b2GravityController::Step(const b2TimeStep& step)
{
B2_NOT_USED(step);
if(invSqr){
for(b2ControllerEdge *i=m_bodyList;i;i=i->nextBody){
b2Body* body1 = i->body;
for(b2ControllerEdge *j=m_bodyList;j!=i;j=j->nextBody){
b2Body* body2 = j->body;
b2Vec2 d = body2->GetWorldCenter() - body1->GetWorldCenter();
float32 r2 = d.LengthSquared();
if(r2 < B2_FLT_EPSILON)
continue;
b2Vec2 f = G / r2 / sqrt(r2) * body1->GetMass() * body2->GetMass() * d;
body1->ApplyForce(f , body1->GetWorldCenter());
body2->ApplyForce(-1.0f*f, body2->GetWorldCenter());
}
}
}else{
for(b2ControllerEdge *i=m_bodyList;i;i=i->nextBody){
b2Body* body1 = i->body;
for(b2ControllerEdge *j=m_bodyList;j!=i;j=j->nextBody){
b2Body* body2 = j->body;
b2Vec2 d = body2->GetWorldCenter() - body1->GetWorldCenter();
float32 r2 = d.LengthSquared();
if(r2 < B2_FLT_EPSILON)
continue;
b2Vec2 f = G / r2 * body1->GetMass() * body2->GetMass() * d;
body1->ApplyForce(f , body1->GetWorldCenter());
body2->ApplyForce(-1.0f*f, body2->GetWorldCenter());
}
}
}
}
void b2GravityController::Destroy(b2BlockAllocator* allocator)
{
allocator->Free(this, sizeof(b2GravityController));
}
b2GravityController* b2GravityControllerDef::Create(b2BlockAllocator* allocator) const
{
void* mem = allocator->Allocate(sizeof(b2GravityController));
return new (mem) b2GravityController(this);
}
/*
* Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
*
* 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 B2_GRAVITYCONTROLLER_H
#define B2_GRAVITYCONTROLLER_H
#include "b2Controller.h"
class b2GravityControllerDef;
/// Applies simplified gravity between every pair of bodies
class b2GravityController : public b2Controller{
public:
/// Specifies the strength of the gravitiation force
float32 G;
/// If true, gravity is proportional to r^-2, otherwise r^-1
bool invSqr;
/// @see b2Controller::Step
void Step(const b2TimeStep& step);
protected:
void Destroy(b2BlockAllocator* allocator);
private:
friend class b2GravityControllerDef;
b2GravityController(const b2GravityControllerDef* def);
};
/// This class is used to build gravity controllers
class b2GravityControllerDef : public b2ControllerDef
{
public:
/// Specifies the strength of the gravitiation force
float32 G;
/// If true, gravity is proportional to r^-2, otherwise r^-1
bool invSqr;
private:
b2GravityController* Create(b2BlockAllocator* allocator) const;
};
#endif
/*
* Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
*
* 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.
*/
#include "b2TensorDampingController.h"
b2TensorDampingController::b2TensorDampingController(const b2TensorDampingControllerDef* def) : b2Controller(def)
{
T = def->T;
maxTimestep = def->maxTimestep;
}
void b2TensorDampingController::Step(const b2TimeStep& step)
{
float32 timestep = step.dt;
if(timestep<=B2_FLT_EPSILON)
return;
if(timestep>maxTimestep && maxTimestep>0)
timestep = maxTimestep;
for(b2ControllerEdge *i=m_bodyList;i;i=i->nextBody){
b2Body* body = i->body;
if(body->IsSleeping())
continue;
b2Vec2 damping = body->GetWorldVector(
b2Mul(T,
body->GetLocalVector(
body->GetLinearVelocity()
)
)
);
body->SetLinearVelocity(body->GetLinearVelocity() + timestep * damping);
}
}
void b2TensorDampingControllerDef::SetAxisAligned(float32 xDamping, float32 yDamping)
{
T.col1.x = -xDamping;
T.col1.y = 0;
T.col2.x = 0;
T.col2.y = -yDamping;
if(xDamping>0 || yDamping>0){
maxTimestep = 1/b2Max(xDamping,yDamping);
}else{
maxTimestep = 0;
}
}
void b2TensorDampingController::Destroy(b2BlockAllocator* allocator)
{
allocator->Free(this, sizeof(b2TensorDampingController));
}
b2TensorDampingController* b2TensorDampingControllerDef::Create(b2BlockAllocator* allocator) const
{
void* mem = allocator->Allocate(sizeof(b2TensorDampingController));
return new (mem) b2TensorDampingController(this);
}
/*
* Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
*
* 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 B2_TENSORDAMPINGCONTROLLER_H
#define B2_TENSORDAMPINGCONTROLLER_H
#include "b2Controller.h"
class b2TensorDampingControllerDef;
/// Applies top down linear damping to the controlled bodies
/// The damping is calculated by multiplying velocity by a matrix in local co-ordinates.
class b2TensorDampingController : public b2Controller{
public:
/// Tensor to use in damping model
b2Mat22 T;
/*Some examples (matrixes in format (row1; row2) )
(-a 0;0 -a) Standard isotropic damping with strength a
(0 a;-a 0) Electron in fixed field - a force at right angles to velocity with proportional magnitude
(-a 0;0 -b) Differing x and y damping. Useful e.g. for top-down wheels.
*/
//By the way, tensor in this case just means matrix, don't let the terminology get you down.
/// Set this to a positive number to clamp the maximum amount of damping done.
float32 maxTimestep;
// Typically one wants maxTimestep to be 1/(max eigenvalue of T), so that damping will never cause something to reverse direction
/// @see b2Controller::Step
void Step(const b2TimeStep& step);
protected:
void Destroy(b2BlockAllocator* allocator);
private:
friend class b2TensorDampingControllerDef;
b2TensorDampingController(const b2TensorDampingControllerDef* def);
};
/// This class is used to build tensor damping controllers
class b2TensorDampingControllerDef : public b2ControllerDef
{
public:
/// Tensor to use in damping model
b2Mat22 T;
/// Set this to a positive number to clamp the maximum amount of damping done.
float32 maxTimestep;
/// Sets damping independantly along the x and y axes
void SetAxisAligned(float32 xDamping,float32 yDamping);
private:
b2TensorDampingController* Create(b2BlockAllocator* allocator) const;
};
#endif
/*
Copyright (c) 2006 Henry Strickland & Ryan Seto
2007-2008 Tobias Weyand (modifications and extensions)
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
(* http://www.opensource.org/licenses/mit-license.php *)
*/
#ifndef _FIXED_H_
#define _FIXED_H_
#include <stdio.h>
#ifdef TARGET_IS_NDS
#include "nds.h"
#endif
#define FIXED_BP 16
#define FIXED_MAX ((1<<(32-FIXED_BP-1))-1)
#define FIXED_MIN (-(1<<(32-FIXED_BP-1)))
#define FIXED_EPSILON (Fixed(0.00007f))
#define G_1_DIV_PI 20861
class Fixed {
private:
int g; // the guts
const static int BP= FIXED_BP; // how many low bits are right of Binary Point
const static int BP2= BP*2; // how many low bits are right of Binary Point
const static int BPhalf= BP/2; // how many low bits are right of Binary Point
double STEP(); // smallest step we can represent
// for private construction via guts
enum FixedRaw { RAW };
Fixed(FixedRaw, int guts);
public:
Fixed();
Fixed(const Fixed &a);
Fixed(float a);
Fixed(double a);
Fixed(int a);
Fixed(long a);
Fixed& operator =(const Fixed a);
Fixed& operator =(float a);
Fixed& operator =(double a);
Fixed& operator =(int a);
Fixed& operator =(long a);
operator float();
operator double();
operator int();
operator long();
operator unsigned short();
operator float() const;
Fixed operator +() const;
Fixed operator -() const;
Fixed operator +(const Fixed a) const;
Fixed operator -(const Fixed a) const;
#if 1
// more acurate, using long long
Fixed operator *(const Fixed a) const;
#else
// faster, but with only half as many bits right of binary point
Fixed operator *(const Fixed a) const;
#endif
Fixed operator /(const Fixed a) const;
Fixed operator *(unsigned short a) const;
Fixed operator *(int a) const;
Fixed operator +(float a) const;
Fixed operator -(float a) const;
Fixed operator *(float a) const;
Fixed operator /(float a) const;
Fixed operator +(double a) const;
Fixed operator -(double a) const;
Fixed operator *(double a) const;
Fixed operator /(double a) const;
Fixed operator >>(int a) const;
Fixed operator <<(int a) const;
Fixed& operator +=(Fixed a);
Fixed& operator -=(Fixed a);
Fixed& operator *=(Fixed a);
Fixed& operator /=(Fixed a);
Fixed& operator +=(int a);
Fixed& operator -=(int a);
Fixed& operator *=(int a);
Fixed& operator /=(int a);
Fixed& operator +=(long a);
Fixed& operator -=(long a);
Fixed& operator *=(long a);
Fixed& operator /=(long a);
Fixed& operator +=(float a);
Fixed& operator -=(float a);
Fixed& operator *=(float a);
Fixed& operator /=(float a);
Fixed& operator +=(double a);
Fixed& operator -=(double a);
Fixed& operator *=(double a);
Fixed& operator /=(double a);
bool operator ==(const Fixed a) const;
bool operator !=(const Fixed a) const;
bool operator <=(const Fixed a) const;
bool operator >=(const Fixed a) const;
bool operator <(const Fixed a) const;
bool operator >(const Fixed a) const;
bool operator ==(float a) const;
bool operator !=(float a) const;
bool operator <=(float a) const;
bool operator >=(float a) const;
bool operator <(float a) const;
bool operator >(float a) const;
bool operator ==(double a) const;
bool operator !=(double a) const;
bool operator <=(double a) const;
bool operator >=(double a) const;
bool operator <(double a) const;
bool operator >(double a) const;
bool operator >(int a) const;
bool operator <(int a) const;
bool operator >=(int a) const;
bool operator <=(int a) const;
Fixed abs();
Fixed sqrt();
#ifdef TARGET_IS_NDS
Fixed cosf();
Fixed sinf();
Fixed tanf();
#endif
};
//
// Implementation
//
inline double Fixed::STEP() { return 1.0 / (1<<BP); } // smallest step we can represent
// for private construction via guts
inline Fixed::Fixed(FixedRaw, int guts) : g(guts) {}
inline Fixed::Fixed() : g(0) {}
inline Fixed::Fixed(const Fixed &a) : g( a.g ) {}
inline Fixed::Fixed(float a) : g( int(a * (float)(1<<BP)) ) {}
inline Fixed::Fixed(double a) : g( int(a * (double)(1<<BP) ) ) {}
inline Fixed::Fixed(int a) : g( a << BP ) {}
inline Fixed::Fixed(long a) : g( a << BP ) {}
inline Fixed& Fixed::operator =(const Fixed a) { g= a.g; return *this; }
inline Fixed& Fixed::operator =(float a) { g= Fixed(a).g; return *this; }
inline Fixed& Fixed::operator =(double a) { g= Fixed(a).g; return *this; }
inline Fixed& Fixed::operator =(int a) { g= Fixed(a).g; return *this; }
inline Fixed& Fixed::operator =(long a) { g= Fixed(a).g; return *this; }
inline Fixed::operator float() { return g * (float)STEP(); }
inline Fixed::operator double() { return g * (double)STEP(); }
inline Fixed::operator int() { return g>>BP; }
inline Fixed::operator long() { return g>>BP; }
#pragma warning(disable: 4244) //HARDWIRE added pragma to prevent VS2005 compilation error
inline Fixed::operator unsigned short() { return g>>BP; }
inline Fixed::operator float() const { return g / (float)(1<<BP); }
inline Fixed Fixed::operator +() const { return Fixed(RAW,g); }
inline Fixed Fixed::operator -() const { return Fixed(RAW,-g); }
inline Fixed Fixed::operator +(const Fixed a) const { return Fixed(RAW, g + a.g); }
inline Fixed Fixed::operator -(const Fixed a) const { return Fixed(RAW, g - a.g); }
#if 1
// more acurate, using long long
inline Fixed Fixed::operator *(const Fixed a) const { return Fixed(RAW, (int)( ((long long)g * (long long)a.g ) >> BP)); }
#elif 0
// check for overflow and figure out where. Must specify -rdynamic in linker
#include <execinfo.h>
#include <signal.h>
#include <exception>
inline Fixed Fixed::operator *(const Fixed a) const {
long long x = ((long long)g * (long long)a.g );
if(x > 0x7fffffffffffLL || x < -0x7fffffffffffLL) {
printf("overflow");
void *array[2];
int nSize = backtrace(array, 2);
char **symbols = backtrace_symbols(array, nSize);
for(int i=0; i<nSize; i++) {
printf(" %s", symbols[i]);
}
printf("\n");
}
return Fixed(RAW, (int)(x>>BP));
}
#else
// faster, but with only half as many bits right of binary point
inline Fixed Fixed::operator *(const Fixed a) const { return Fixed(RAW, (g>>BPhalf) * (a.g>>BPhalf) ); }
#endif
#ifdef TARGET_IS_NDS
// Division using the DS's maths coprocessor
inline Fixed Fixed::operator /(const Fixed a) const
{
//printf("%d %d\n", (long long)g << BP, a.g);
return Fixed(RAW, int( div64((long long)g << BP, a.g) ) );
}
#else
inline Fixed Fixed::operator /(const Fixed a) const
{
return Fixed(RAW, int( (((long long)g << BP2) / (long long)(a.g)) >> BP) );
//return Fixed(RAW, int( (((long long)g << BP) / (long long)(a.g)) ) );
}
#endif
inline Fixed Fixed::operator *(unsigned short a) const { return operator*(Fixed(a)); }
inline Fixed Fixed::operator *(int a) const { return operator*(Fixed(a)); }
inline Fixed Fixed::operator +(float a) const { return Fixed(RAW, g + Fixed(a).g); }
inline Fixed Fixed::operator -(float a) const { return Fixed(RAW, g - Fixed(a).g); }
inline Fixed Fixed::operator *(float a) const { return Fixed(RAW, (g>>BPhalf) * (Fixed(a).g>>BPhalf) ); }
//inline Fixed Fixed::operator /(float a) const { return Fixed(RAW, int( (((long long)g << BP2) / (long long)(Fixed(a).g)) >> BP) ); }
inline Fixed Fixed::operator /(float a) const { return operator/(Fixed(a)); }
inline Fixed Fixed::operator +(double a) const { return Fixed(RAW, g + Fixed(a).g); }
inline Fixed Fixed::operator -(double a) const { return Fixed(RAW, g - Fixed(a).g); }
inline Fixed Fixed::operator *(double a) const { return Fixed(RAW, (g>>BPhalf) * (Fixed(a).g>>BPhalf) ); }
//inline Fixed Fixed::operator /(double a) const { return Fixed(RAW, int( (((long long)g << BP2) / (long long)(Fixed(a).g)) >> BP) ); }
inline Fixed Fixed::operator /(double a) const { return operator/(Fixed(a)); }
inline Fixed Fixed::operator >>(int a) const { return Fixed(RAW, g >> a); }
inline Fixed Fixed::operator <<(int a) const { return Fixed(RAW, g << a); }
inline Fixed& Fixed::operator +=(Fixed a) { return *this = *this + a; }
inline Fixed& Fixed::operator -=(Fixed a) { return *this = *this - a; }
inline Fixed& Fixed::operator *=(Fixed a) { return *this = *this * a; }
//inline Fixed& Fixed::operator /=(Fixed a) { return *this = *this / a; }
inline Fixed& Fixed::operator /=(Fixed a) { return *this = operator/(a); }
inline Fixed& Fixed::operator +=(int a) { return *this = *this + (Fixed)a; }
inline Fixed& Fixed::operator -=(int a) { return *this = *this - (Fixed)a; }
inline Fixed& Fixed::operator *=(int a) { return *this = *this * (Fixed)a; }
//inline Fixed& Fixed::operator /=(int a) { return *this = *this / (Fixed)a; }
inline Fixed& Fixed::operator /=(int a) { return *this = operator/((Fixed)a); }
inline Fixed& Fixed::operator +=(long a) { return *this = *this + (Fixed)a; }
inline Fixed& Fixed::operator -=(long a) { return *this = *this - (Fixed)a; }
inline Fixed& Fixed::operator *=(long a) { return *this = *this * (Fixed)a; }
//inline Fixed& Fixed::operator /=(long a) { return *this = *this / (Fixed)a; }
inline Fixed& Fixed::operator /=(long a) { return *this = operator/((Fixed)a); }
inline Fixed& Fixed::operator +=(float a) { return *this = *this + a; }
inline Fixed& Fixed::operator -=(float a) { return *this = *this - a; }
inline Fixed& Fixed::operator *=(float a) { return *this = *this * a; }
//inline Fixed& Fixed::operator /=(float a) { return *this = *this / a; }
inline Fixed& Fixed::operator /=(float a) { return *this = operator/(a); }
inline Fixed& Fixed::operator +=(double a) { return *this = *this + a; }
inline Fixed& Fixed::operator -=(double a) { return *this = *this - a; }
inline Fixed& Fixed::operator *=(double a) { return *this = *this * a; }
//inline Fixed& Fixed::operator /=(double a) { return *this = *this / a; }
inline Fixed& Fixed::operator /=(double a) { return *this = operator/(a); }
inline Fixed operator +(int a, const Fixed b) { return Fixed(a)+b; }
inline Fixed operator -(int a, const Fixed b) { return Fixed(a)-b; }
inline Fixed operator *(int a, const Fixed b) { return Fixed(a)*b; }
inline Fixed operator /(int a, const Fixed b) { return Fixed(a)/b; };
inline Fixed operator +(float a, const Fixed b) { return Fixed(a)+b; }
inline Fixed operator -(float a, const Fixed b) { return Fixed(a)-b; }
inline Fixed operator *(float a, const Fixed b) { return Fixed(a)*b; }
inline Fixed operator /(float a, const Fixed b) { return Fixed(a)/b; }
inline bool Fixed::operator ==(const Fixed a) const { return g == a.g; }
inline bool Fixed::operator !=(const Fixed a) const { return g != a.g; }
inline bool Fixed::operator <=(const Fixed a) const { return g <= a.g; }
inline bool Fixed::operator >=(const Fixed a) const { return g >= a.g; }
inline bool Fixed::operator <(const Fixed a) const { return g < a.g; }
inline bool Fixed::operator >(const Fixed a) const { return g > a.g; }
inline bool Fixed::operator ==(float a) const { return g == Fixed(a).g; }
inline bool Fixed::operator !=(float a) const { return g != Fixed(a).g; }
inline bool Fixed::operator <=(float a) const { return g <= Fixed(a).g; }
inline bool Fixed::operator >=(float a) const { return g >= Fixed(a).g; }
inline bool Fixed::operator <(float a) const { return g < Fixed(a).g; }
inline bool Fixed::operator >(float a) const { return g > Fixed(a).g; }
inline bool Fixed::operator ==(double a) const { return g == Fixed(a).g; }
inline bool Fixed::operator !=(double a) const { return g != Fixed(a).g; }
inline bool Fixed::operator <=(double a) const { return g <= Fixed(a).g; }
inline bool Fixed::operator >=(double a) const { return g >= Fixed(a).g; }
inline bool Fixed::operator <(double a) const { return g < Fixed(a).g; }
inline bool Fixed::operator >(double a) const { return g > Fixed(a).g; }
inline bool Fixed::operator >(int a) const { return g > Fixed(a).g; }
inline bool Fixed::operator <(int a) const { return g < Fixed(a).g; }
inline bool Fixed::operator >=(int a) const{ return g >= Fixed(a).g; };
inline bool Fixed::operator <=(int a) const{ return g <= Fixed(a).g; };
inline bool operator ==(float a, const Fixed b) { return Fixed(a) == b; }
inline bool operator !=(float a, const Fixed b) { return Fixed(a) != b; }
inline bool operator <=(float a, const Fixed b) { return Fixed(a) <= b; }
inline bool operator >=(float a, const Fixed b) { return Fixed(a) >= b; }
inline bool operator <(float a, const Fixed b) { return Fixed(a) < b; }
inline bool operator >(float a, const Fixed b) { return Fixed(a) > b; }
inline Fixed operator +(double a, const Fixed b) { return Fixed(a)+b; }
inline Fixed operator -(double a, const Fixed b) { return Fixed(a)-b; }
inline Fixed operator *(double a, const Fixed b) { return Fixed(a)*b; }
inline Fixed operator /(double a, const Fixed b) { return Fixed(a)/b; }
inline bool operator ==(double a, const Fixed b) { return Fixed(a) == b; }
inline bool operator !=(double a, const Fixed b) { return Fixed(a) != b; }
inline bool operator <=(double a, const Fixed b) { return Fixed(a) <= b; }
inline bool operator >=(double a, const Fixed b) { return Fixed(a) >= b; }
inline bool operator <(double a, const Fixed b) { return Fixed(a) < b; }
inline bool operator >(double a, const Fixed b) { return Fixed(a) > b; }
inline bool operator ==(int a, const Fixed b) { return Fixed(a) == b; }
inline bool operator !=(int a, const Fixed b) { return Fixed(a) != b; }
inline bool operator <=(int a, const Fixed b) { return Fixed(a) <= b; }
inline bool operator >=(int a, const Fixed b) { return Fixed(a) >= b; }
inline bool operator <(int a, const Fixed b) { return Fixed(a) < b; }
inline bool operator >(int a, const Fixed b) { return Fixed(a) > b; }
inline int& operator +=(int& a, const Fixed b) { a = (Fixed)a + b; return a; }
inline int& operator -=(int& a, const Fixed b) { a = (Fixed)a - b; return a; }
inline int& operator *=(int& a, const Fixed b) { a = (Fixed)a * b; return a; }
inline int& operator /=(int& a, const Fixed b) { a = (Fixed)a / b; return a; }
inline long& operator +=(long& a, const Fixed b) { a = (Fixed)a + b; return a; }
inline long& operator -=(long& a, const Fixed b) { a = (Fixed)a - b; return a; }
inline long& operator *=(long& a, const Fixed b) { a = (Fixed)a * b; return a; }
inline long& operator /=(long& a, const Fixed b) { a = (Fixed)a / b; return a; }
inline float& operator +=(float& a, const Fixed b) { a = a + b; return a; }
inline float& operator -=(float& a, const Fixed b) { a = a - b; return a; }
inline float& operator *=(float& a, const Fixed b) { a = a * b; return a; }
inline float& operator /=(float& a, const Fixed b) { a = a / b; return a; }
inline double& operator +=(double& a, const Fixed b) { a = a + b; return a; }
inline double& operator -=(double& a, const Fixed b) { a = a - b; return a; }
inline double& operator *=(double& a, const Fixed b) { a = a * b; return a; }
inline double& operator /=(double& a, const Fixed b) { a = a / b; return a; }
inline Fixed Fixed::abs() { return (g>0) ? Fixed(RAW, g) : Fixed(RAW, -g); }
inline Fixed abs(Fixed f) { return f.abs(); }
//inline Fixed atan2(Fixed a, Fixed b) { return atan2f((float) a, (float) b); }
inline Fixed atan2(Fixed y, Fixed x)
{
Fixed abs_y = y.abs() + FIXED_EPSILON; // avoid 0/0
Fixed r, angle;
if(x >= 0.0f) {
r = (x - abs_y) / (x + abs_y);
angle = 3.1415926/4.0;
} else {
r = (x + abs_y) / (abs_y - x);
angle = 3.0*3.1415926/4.0;
}
angle += Fixed(0.1963) * (r * r * r) - Fixed(0.9817) * r;
return (y < 0) ? -angle : angle;
}
#if TARGET_IS_NDS
static inline long nds_sqrt64(long long a)
{
SQRT_CR = SQRT_64;
while(SQRT_CR & SQRT_BUSY);
SQRT_PARAM64 = a;
while(SQRT_CR & SQRT_BUSY);
return SQRT_RESULT32;
}
static inline int32 div6464(int64 num, int64 den)
{
DIV_CR = DIV_64_64;
while(DIV_CR & DIV_BUSY);
DIV_NUMERATOR64 = num;
DIV_DENOMINATOR64 = den;
while(DIV_CR & DIV_BUSY);
return (DIV_RESULT32);
}
inline Fixed Fixed::sqrt()
{
return Fixed(RAW, nds_sqrt64(((long long)(g))<<BP));
}
#else
inline Fixed Fixed::sqrt()
{
long long m, root = 0, left = (long long)g<<FIXED_BP;
for ( m = (long long)1<<( (sizeof(long long)<<3) - 2); m; m >>= 2 )
{
if ( ( left & -m ) > root )
left -= ( root += m ), root += m;
root >>= 1;
}
return Fixed(RAW, root);
}
#endif
inline Fixed sqrt(Fixed a) { return a.sqrt(); }
inline Fixed sqrtf(Fixed a) { return a.sqrt(); }
#endif
#ifdef TARGET_IS_NDS
// Use the libnds lookup tables for trigonometry functions
inline Fixed Fixed::cosf() {
int idx = (((long long)g*(long long)G_1_DIV_PI)>>24)%512;
if(idx < 0)
idx += 512;
return Fixed(RAW, COS_bin[idx] << 4);
}
inline Fixed cosf(Fixed x) { return x.cosf(); }
inline Fixed Fixed::sinf() {
int idx = (((long long)g*(long long)G_1_DIV_PI)>>24)%512;
if(idx < 0)
idx += 512;
return Fixed(RAW, SIN_bin[idx] << 4);
}
inline Fixed sinf(Fixed x) { return x.sinf(); }
inline Fixed Fixed::tanf() {
int idx = (((long long)g*(long long)G_1_DIV_PI)>>24)%512;
if(idx < 0)
idx += 512;
return Fixed(RAW, TAN_bin[idx] << 4);
}
inline Fixed tanf(Fixed x) { return x.tanf(); }
#endif
/*---------------------------------------------------------------------------------
$Id: jtypes.h,v 1.17 2007/07/18 05:20:45 wntrmute Exp $
jtypes.h -- Common types (and a few useful macros)
Copyright (C) 2005
Michael Noland (joat)
Jason Rogers (dovoto)
Dave Murphy (WinterMute)
Chris Double (doublec)
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 NDS_JTYPES_INCLUDE
#define NDS_JTYPES_INCLUDE
//---------------------------------------------------------------------------------
#define PACKED __attribute__ ((packed))
#define packed_struct struct PACKED
//---------------------------------------------------------------------------------
// libgba compatible section macros
//---------------------------------------------------------------------------------
#define ITCM_CODE __attribute__((section(".itcm"), long_call))
#define DTCM_DATA __attribute__((section(".dtcm")))
#define DTCM_BSS __attribute__((section(".sbss")))
#define ALIGN(m) __attribute__((aligned (m)))
#define PACKED __attribute__ ((packed))
#define packed_struct struct PACKED
//---------------------------------------------------------------------------------
// These are linked to the bin2o macro in the Makefile
//---------------------------------------------------------------------------------
#define GETRAW(name) (name)
#define GETRAWSIZE(name) ((int)name##_size)
#define GETRAWEND(name) ((int)name##_end)
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif
#define BIT(n) (1 << (n))
// define libnds types in terms of stdint
#include <stdint.h>
typedef uint8_t uint8;
typedef uint16_t uint16;
typedef uint32_t uint32;
typedef uint64_t uint64;
typedef int8_t int8;
typedef int16_t int16;
typedef int32_t int32;
typedef int64_t int64;
//typedef float float32;
typedef double float64;
typedef volatile uint8_t vuint8;
typedef volatile uint16_t vuint16;
typedef volatile uint32_t vuint32;
typedef volatile uint64_t vuint64;
typedef volatile int8_t vint8;
typedef volatile int16_t vint16;
typedef volatile int32_t vint32;
typedef volatile int64_t vint64;
typedef volatile float vfloat32;
typedef volatile float64 vfloat64;
typedef uint8_t byte;
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;
typedef int8_t s8;
typedef int16_t s16;
typedef int32_t s32;
typedef int64_t s64;
typedef volatile u8 vu8;
typedef volatile u16 vu16;
typedef volatile u32 vu32;
typedef volatile u64 vu64;
typedef volatile s8 vs8;
typedef volatile s16 vs16;
typedef volatile s32 vs32;
typedef volatile s64 vs64;
typedef struct touchPosition {
int16 x;
int16 y;
int16 px;
int16 py;
int16 z1;
int16 z2;
} touchPosition;
#ifndef __cplusplus
/** C++ compatible bool for C
*/
typedef enum { false, true } bool;
#endif
// Handy function pointer typedefs
typedef void ( * IntFn)(void);
typedef void (* VoidFunctionPointer)(void);
typedef void (* fp)(void);
//---------------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------------
Index: Box2D/Box2D/Box2D.h
===================================================================
--- Box2D/Box2D/Box2D.h (revision 70)
+++ Box2D/Box2D/Box2D.h (working copy)
@@ -35,6 +35,7 @@
#include <Box2D/Collision/Shapes/b2CircleShape.h>
#include <Box2D/Collision/Shapes/b2PolygonShape.h>
+#include <Box2D/Collision/Shapes/b2CapsuleShape.h>
#include <Box2D/Collision/b2BroadPhase.h>
#include <Box2D/Collision/b2Distance.h>
Index: Box2D/Box2D/CMakeLists.txt
===================================================================
--- Box2D/Box2D/CMakeLists.txt (revision 70)
+++ Box2D/Box2D/CMakeLists.txt (working copy)
@@ -15,10 +15,12 @@
Collision/b2TimeOfImpact.h
)
set(BOX2D_Shapes_SRCS
+ Collision/Shapes/b2CapsuleShape.cpp
Collision/Shapes/b2CircleShape.cpp
Collision/Shapes/b2PolygonShape.cpp
)
set(BOX2D_Shapes_HDRS
+ Collision/Shapes/b2CapsuleShape.h
Collision/Shapes/b2CircleShape.h
Collision/Shapes/b2PolygonShape.h
Collision/Shapes/b2Shape.h
@@ -53,18 +55,24 @@
Dynamics/b2WorldCallbacks.h
)
set(BOX2D_Contacts_SRCS
+ Dynamics/Contacts/b2CapsuleAndCircleContact.cpp
+ Dynamics/Contacts/b2CapsuleContact.cpp
Dynamics/Contacts/b2CircleContact.cpp
Dynamics/Contacts/b2Contact.cpp
Dynamics/Contacts/b2ContactSolver.cpp
+ Dynamics/Contacts/b2PolygonAndCapsuleContact.cpp
Dynamics/Contacts/b2PolygonAndCircleContact.cpp
Dynamics/Contacts/b2PolygonContact.cpp
Dynamics/Contacts/b2TOISolver.cpp
)
set(BOX2D_Contacts_HDRS
+ Dynamics/Contacts/b2CapsuleAndCircleContact.h
+ Dynamics/Contacts/b2CapsuleContact.h
Dynamics/Contacts/b2CircleContact.h
Dynamics/Contacts/b2Contact.h
Dynamics/Contacts/b2ContactSolver.h
Dynamics/Contacts/b2NullContact.h
+ Dynamics/Contacts/b2PolygonAndCapsuleContact.h
Dynamics/Contacts/b2PolygonAndCircleContact.h
Dynamics/Contacts/b2PolygonContact.h
Dynamics/Contacts/b2TOISolver.h
Index: Box2D/Box2D/Collision/b2Collision.cpp
===================================================================
--- Box2D/Box2D/Collision/b2Collision.cpp (revision 70)
+++ Box2D/Box2D/Collision/b2Collision.cpp (working copy)
@@ -248,3 +248,220 @@
return output.distance < 10.0f * b2_epsilon;
}
+
+
+// Collision Detection in Interactive 3D Environments by Gino van den Bergen
+// From Section 3.4.1
+// x = mu1 * p1 + mu2 * p2
+// mu1 + mu2 = 1 && mu1 >= 0 && mu2 >= 0
+// mu1 = 1 - mu2;
+// x = (1 - mu2) * p1 + mu2 * p2
+// = p1 + mu2 * (p2 - p1)
+// x = s + a * r (s := start, r := end - start)
+// s + a * r = p1 + mu2 * d (d := p2 - p1)
+// -a * r + mu2 * d = b (b := s - p1)
+// [-r d] * [a; mu2] = b
+// Cramer's rule:
+// denom = det[-r d]
+// a = det[b d] / denom
+// mu2 = det[-r b] / denom
+bool b2RaycastSegment(b2RayCastOutput* output, const b2RayCastInput& input, const b2Vec2& p1, const b2Vec2& p2)
+{
+ b2Vec2 s = input.p1;
+ b2Vec2 r = input.p2 - s;
+ b2Vec2 d = p2 - p1;
+ b2Vec2 n = b2Cross(d, 1.0f);
+
+ const float32 k_slop = 100.0f * b2_epsilon;
+ float32 denom = -b2Dot(r, n);
+
+ // Cull back facing collision and ignore parallel segments.
+ if (denom > k_slop)
+ {
+ // Does the segment intersect the infinite line associated with this segment?
+ b2Vec2 b = s - p1;
+ float32 a = b2Dot(b, n);
+
+ if (0.0f <= a && a <= input.maxFraction * denom)
+ {
+ float32 mu2 = -r.x * b.y + r.y * b.x;
+
+ // Does the segment intersect this segment?
+ if (-k_slop * denom <= mu2 && mu2 <= denom * (1.0f + k_slop))
+ {
+ a /= denom;
+ n.Normalize();
+ output->normal = n;
+ output->fraction = a;
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+
+static void FindNearestPointOnLineSegment( b2Vec2* nearest, float32* parameter,
+ const b2Vec2& A1, const b2Vec2& L, const b2Vec2& B,
+ bool infinite_line )
+{
+ float32 D = L.LengthSquared();
+ if (D < b2_epsilon * b2_epsilon)
+ {
+ *nearest = A1;
+ return;
+ }
+
+ b2Vec2 AB = B - A1;
+ *parameter = b2Dot(L, AB) / D;
+ if (!infinite_line)
+ {
+ *parameter = b2Clamp(*parameter, 0.0f, 1.0f);
+ }
+ *nearest = A1 + *parameter * L;
+}
+
+// Based on Game Programming Gems 2
+// Fast, Robust Intersection of 3D Line Segments
+// Graham Rhodes, Applied Research Associates
+b2Vec2 b2NearestPointOnLine(const b2Vec2& point, const b2Vec2& p1, const b2Vec2& p2)
+{
+ b2Vec2 result;
+ float32 unused;
+ FindNearestPointOnLineSegment(&result, &unused, p1, p2 - p1, point, false);
+ return result;
+}
+
+static void FindNearestPointOfParallelLineSegments( b2Vec2* x1, b2Vec2* x2,
+ const b2Vec2& A1, const b2Vec2& A2, const b2Vec2& La,
+ const b2Vec2& B1, const b2Vec2& B2, const b2Vec2& Lb)
+{
+ float32 s, t;
+ FindNearestPointOnLineSegment(x1, &s, A1, La, B1, true);
+ FindNearestPointOnLineSegment(x2, &t, A1, La, B2, true);
+
+ if (s < 0.0f && t < 0.0f)
+ {
+ *x1 = A1;
+ if (s < t)
+ *x2 = B2;
+ else
+ *x2 = B1;
+ return;
+ }
+
+ if (s > 1.0f && t > 1.0f)
+ {
+ *x1 = A2;
+ if (s < t)
+ *x2 = B1;
+ else
+ *x2 = B2;
+ return;
+ }
+
+ float32 temp = 0.5f * (b2Clamp(s, 0.0f, 1.0f) + b2Clamp(t, 0.0f, 1.0f));
+ *x1 = A1 + temp * La;
+
+ float32 unused;
+ FindNearestPointOnLineSegment(x2, &unused, B1, Lb, *x1, true);
+}
+
+static void AdjustNearestPoints(b2Vec2* x1, b2Vec2* x2,
+ const b2Vec2& A1, const b2Vec2& A2, const b2Vec2& La,
+ const b2Vec2& B1, const b2Vec2& B2, const b2Vec2& Lb,
+ float32 s, float32 t)
+{
+ if ((s < 0.0f || s > 1.0f) && (t < 0.0f || t > 1.0f))
+ {
+ s = b2Clamp(s, 0.0f, 1.0f);
+ *x1 = A1 + s * La;
+ FindNearestPointOnLineSegment(x2, &t, B1, Lb, *x1, true);
+ if (t < 0.0f || t > 1.0f)
+ {
+ t = b2Clamp(t, 0.0f, 1.0f);
+ *x2 = B1 + t * Lb;
+ FindNearestPointOnLineSegment(x1, &s, A1, La, *x2, false);
+ FindNearestPointOnLineSegment(x2, &t, B1, Lb, *x1, false);
+ }
+ return;
+ }
+ if (s < 0.0f || s > 1.0f)
+ {
+ s = b2Clamp(s, 0.0f, 1.0f);
+ *x1 = A1 + s * La;
+ FindNearestPointOnLineSegment(x2, &t, B1, Lb, *x1, false);
+ return;
+ }
+ b2Assert(t < 0.0f || t > 1.0f);
+ t = b2Clamp(t, 0.0f, 1.0f);
+ *x2 = B1 + t * Lb;
+ FindNearestPointOnLineSegment(x1, &s, A1, La, *x2, false);
+}
+
+static void IntersectLineSegments( b2Vec2* x1, b2Vec2* x2,
+ const b2Vec2& A1, const b2Vec2& A2,
+ const b2Vec2& B1, const b2Vec2& B2)
+{
+ float32 unused;
+
+ b2Vec2 La = A2 - A1;
+ b2Vec2 Lb = B2 - B1;
+ float32 L11 = La.LengthSquared();
+ float32 L22 = Lb.LengthSquared();
+
+ // Check for degenerate parameters
+ if (L11 < b2_epsilon * b2_epsilon)
+ {
+ *x1 = A1;
+ FindNearestPointOnLineSegment(x2, &unused, B1, Lb, A1, false);
+ return;
+ }
+ if (L22 < b2_epsilon * b2_epsilon)
+ {
+ *x2 = B1;
+ FindNearestPointOnLineSegment(x1, &unused, A1, La, B1, false);
+ return;
+ }
+
+ b2Vec2 AB = B1 - A1;
+ float32 L12 = -b2Dot(La, Lb);
+ float32 DetL = L11 * L22 - L12 * L12;
+
+ // parallel segments
+ if (b2Abs(DetL) < b2_epsilon)
+ {
+ FindNearestPointOfParallelLineSegments(x1, x2, A1, A2, La, B1, B2, Lb);
+ return;
+ }
+
+ float32 ra = b2Dot(La, AB);
+ float32 rb = -b2Dot(Lb, AB);
+
+ float32 t = (L11 * rb - ra * L12) / DetL;
+ float32 s = (ra - L12 * t) / L11;
+
+ // These tests can't quite stay within B2_FLT_EPSILON
+ //b2Assert(b2Abs(s * L11 + t * L12 - ra) < .0001f);
+ //b2Assert(b2Abs(s * L12 + t * L22 - rb) < .0001f);
+
+ *x1 = A1 + s * La;
+ *x2 = B1 + t * Lb;
+
+ if (s < 0.0f || s > 1.0f || t < 0.0f || t > 1.0f)
+ {
+ AdjustNearestPoints(x1, x2, A1, A2, La, B1, B2, Lb, s, t);
+ }
+}
+
+// Based on Game Programming Gems 2
+// Fast, Robust Intersection of 3D Line Segments
+// Graham Rhodes, Applied Research Associates
+float32 b2DistanceBetweenLines( b2Vec2* x1, b2Vec2* x2,
+ const b2Vec2& A1, const b2Vec2& A2,
+ const b2Vec2& B1, const b2Vec2& B2)
+{
+ IntersectLineSegments(x1, x2, A1, A2, B1, B2);
+ return (*x2 - *x1).Length();
+}
\ No newline at end of file
Index: Box2D/Box2D/Collision/b2Collision.h
===================================================================
--- Box2D/Box2D/Collision/b2Collision.h (revision 70)
+++ Box2D/Box2D/Collision/b2Collision.h (working copy)
@@ -27,6 +27,7 @@
/// queries, and TOI queries.
class b2Shape;
+class b2CapsuleShape;
class b2CircleShape;
class b2PolygonShape;
@@ -212,6 +213,18 @@
bool b2TestOverlap(const b2Shape* shapeA, const b2Shape* shapeB,
const b2Transform& xfA, const b2Transform& xfB);
+/// Perform a raycast against a given line segment.
+bool b2RaycastSegment(b2RayCastOutput* output, const b2RayCastInput& input, const b2Vec2& p1, const b2Vec2& p2);
+
+/// Find the nearest point on a line.
+b2Vec2 b2NearestPointOnLine(const b2Vec2& point, const b2Vec2& p1, const b2Vec2& p2);
+
+/// Find the nearest points on between two different lines.
+float32 b2DistanceBetweenLines( b2Vec2* x1, b2Vec2* x2,
+ const b2Vec2& A1, const b2Vec2& A2,
+ const b2Vec2& B1, const b2Vec2& B2);
+
+
// ---------------- Inline Functions ------------------------------------------
inline bool b2AABB::IsValid() const
Index: Box2D/Box2D/Collision/b2Distance.cpp
===================================================================
--- Box2D/Box2D/Collision/b2Distance.cpp (revision 70)
+++ Box2D/Box2D/Collision/b2Distance.cpp (working copy)
@@ -17,6 +17,7 @@
*/
#include <Box2D/Collision/b2Distance.h>
+#include <Box2D/Collision/Shapes/b2CapsuleShape.h>
#include <Box2D/Collision/Shapes/b2CircleShape.h>
#include <Box2D/Collision/Shapes/b2PolygonShape.h>
@@ -44,6 +45,15 @@
m_radius = polygon->m_radius;
}
break;
+
+ case b2Shape::e_capsule:
+ {
+ const b2CapsuleShape* capsule = (b2CapsuleShape*)shape;
+ m_vertices = capsule->m_vertices;
+ m_count = 2;
+ m_radius = capsule->m_radius;
+ }
+ break;
default:
b2Assert(false);
Index: Box2D/Box2D/Collision/Shapes/b2CapsuleShape.cpp
===================================================================
--- Box2D/Box2D/Collision/Shapes/b2CapsuleShape.cpp (revision 0)
+++ Box2D/Box2D/Collision/Shapes/b2CapsuleShape.cpp (revision 0)
@@ -0,0 +1,194 @@
+/*
+* Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com
+*
+* 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.
+*/
+
+#include <Box2D/Collision/Shapes/b2CapsuleShape.h>
+#include <new>
+
+void b2CapsuleShape::SetByExtentsX(float32 radius, float32 length)
+{
+ m_radius = radius;
+ float32 half = length * 0.5f;
+ m_vertices[0] = b2Vec2(-half, 0.0f);
+ m_vertices[1] = b2Vec2(half, 0.0f);
+}
+
+void b2CapsuleShape::SetByExtentsX(float32 radius, float32 length,
+ const b2Vec2& center, float32 angle)
+{
+ SetByExtentsX(radius, length);
+ b2Transform xf;
+ xf.position = center;
+ xf.R.Set(angle);
+
+ m_vertices[0] = b2Mul(xf, m_vertices[0]);
+ m_vertices[1] = b2Mul(xf, m_vertices[1]);
+}
+
+
+void b2CapsuleShape::SetByExtentsY(float32 radius, float32 height)
+{
+ m_radius = radius;
+ float32 half = height * 0.5f;
+ m_vertices[0] = b2Vec2(0.0f, -half);
+ m_vertices[1] = b2Vec2(0.0f, half);
+}
+
+void b2CapsuleShape::SetByExtentsY(float32 radius, float32 height,
+ const b2Vec2& center, float32 angle)
+{
+ SetByExtentsY(radius, height);
+ b2Transform xf;
+ xf.position = center;
+ xf.R.Set(angle);
+
+ m_vertices[0] = b2Mul(xf, m_vertices[0]);
+ m_vertices[1] = b2Mul(xf, m_vertices[1]);
+}
+
+b2Shape* b2CapsuleShape::Clone(b2BlockAllocator* allocator) const
+{
+ void* mem = allocator->Allocate(sizeof(b2CapsuleShape));
+ b2CapsuleShape* clone = new (mem) b2CapsuleShape;
+ *clone = *this;
+ return clone;
+}
+
+bool b2CapsuleShape::TestPoint(const b2Transform& transform, const b2Vec2& p) const
+{
+ b2Vec2 local = b2MulT(transform, p);
+ b2Vec2 d = b2NearestPointOnLine(local, m_vertices[0], m_vertices[1]) - local;
+ return (d.LengthSquared() <= m_radius * m_radius);
+}
+
+bool b2CapsuleShape::RayCast(b2RayCastOutput* output, const b2RayCastInput& input, const b2Transform& transform) const
+{
+ // Test for starting inside first significantly reduces complexity
+ if (TestPoint(transform, input.p1)) {
+ return false;
+ }
+
+ // Project capsule to world
+ b2Vec2 capsule[2];
+ capsule[0] = b2Mul(transform, m_vertices[0]);
+ capsule[1] = b2Mul(transform, m_vertices[1]);
+ b2Vec2 d = capsule[1] - capsule[0];
+
+ // Consider "cylinder"
+
+ // Figure out signed distance from p1 to infinite capsule line
+ float32 ld = b2Cross(d, capsule[0] - input.p1);
+
+ // Only bother if we don't start inside the infinite "cylinder"
+ if (!(ld * ld <= m_radius * m_radius * d.LengthSquared())) {
+
+ // Find a perpendicular vector to the intersect, with length equal to radius
+ b2Vec2 perp = b2Cross(d, m_radius / d.Length());
+
+ // Push the capsule segment by that vector
+ // Must swap if coming from the other side
+ b2Vec2 boundary[2];
+ if (ld < 0) {
+ boundary[0] = capsule[1] - perp;
+ boundary[1] = capsule[0] - perp;
+ }
+ else {
+ boundary[0] = capsule[0] + perp;
+ boundary[1] = capsule[1] + perp;
+ }
+
+ // Check intersection against the adjusted segments.
+ if (b2RaycastSegment(output, input, boundary[0], boundary[1]))
+ return true;
+ }
+
+ // Consider circular caps
+
+ // Precompute some circle values
+ b2Vec2 r = input.p2 - input.p1;
+ float32 rr = r.LengthSquared();
+
+ // Check for short segment
+ if (rr < b2_epsilon)
+ {
+ return false;
+ }
+
+ // Check the circle caps, starting with closer
+ int startingIndex = 0;
+ if ((capsule[1] - input.p1).LengthSquared() < (capsule[0] - input.p1).LengthSquared()) {
+ startingIndex = 1;
+ }
+ b2Vec2 center = capsule[startingIndex];
+ for (int i = 0; i < 2; ++i)
+ {
+ b2Vec2 s = input.p1 - center;
+ float32 b = b2Dot(s, s) - m_radius * m_radius;
+
+ // Should not start inside
+ b2Assert(!(b < 0.0f));
+
+ // Solve quadratic equation.
+ float32 c = b2Dot(s, r);
+ float32 sigma = c * c - rr * b;
+
+ // Check for negative discriminant.
+ if (!(sigma < 0.0f))
+ {
+ // Find the point of intersection of the line with the circle.
+ float32 a = -(c + b2Sqrt(sigma));
+
+ // Is the intersection point on the segment?
+ if (0.0f <= a && a <= input.maxFraction * rr)
+ {
+ a /= rr;
+ output->fraction = a;
+ output->normal = s + a * r;
+ output->normal.Normalize();
+ return true;
+ }
+ }
+ center = capsule[!startingIndex];
+ }
+
+ return false;
+}
+
+void b2CapsuleShape::ComputeAABB(b2AABB* aabb, const b2Transform& transform) const
+{
+ b2Vec2 p1 = transform.position + b2Mul(transform.R, m_vertices[0]);
+ b2Vec2 p2 = transform.position + b2Mul(transform.R, m_vertices[1]);
+ b2Vec2 min = b2Min(p1, p2);
+ b2Vec2 max = b2Max(p1, p2);
+ aabb->lowerBound.Set(min.x - m_radius, min.y - m_radius);
+ aabb->upperBound.Set(max.x + m_radius, max.y + m_radius);
+}
+
+void b2CapsuleShape::ComputeMass(b2MassData* massData, float32 density) const
+{
+ // Area of rectangle + 2 half circles
+ float32 rectHeight = (m_vertices[1] - m_vertices[0]).Length();
+ float32 rectMass = density * rectHeight * m_radius;
+ float32 circleMass = density * b2_pi * m_radius * m_radius;
+ massData->mass = rectMass + circleMass;
+ massData->center = 0.5f * (m_vertices[0] + m_vertices[1]);
+
+ // inertia about the local origin
+ float32 rectInertia = rectMass * (rectHeight * rectHeight + m_radius * m_radius) / 12.0f;
+ float32 circleInertia = circleMass * (0.5f * m_radius * m_radius + rectHeight * rectHeight * .25f);
+ massData->I = rectInertia + circleInertia + massData->mass * massData->center.LengthSquared();
+}
Index: Box2D/Box2D/Collision/Shapes/b2CapsuleShape.h
===================================================================
--- Box2D/Box2D/Collision/Shapes/b2CapsuleShape.h (revision 0)
+++ Box2D/Box2D/Collision/Shapes/b2CapsuleShape.h (revision 0)
@@ -0,0 +1,103 @@
+/*
+* Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com
+*
+* 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 B2_CAPSULE_SHAPE_H
+#define B2_CAPSULE_SHAPE_H
+
+#include <Box2D/Collision/Shapes/b2Shape.h>
+
+/// A circle shape.
+class b2CapsuleShape : public b2Shape
+{
+public:
+ b2CapsuleShape();
+
+ /// Set to a capsule across the X axis, with given width between focii.
+ void SetByExtentsX(float32 radius, float32 width);
+ /// Set to a capsule across the X axis, rotated and transposed.
+ void SetByExtentsX(float32 radius, float32 width,
+ const b2Vec2& center, float32 angle);
+
+ /// Set to a capsule across the Y axis, with given height between focii.
+ void SetByExtentsY(float32 radius, float32 height);
+ /// Set to a capsule across the Y axis, rotated and transposed.
+ void SetByExtentsY(float32 radius, float32 height,
+ const b2Vec2& center, float32 angle);
+
+ /// Implement b2Shape.
+ b2Shape* Clone(b2BlockAllocator* allocator) const;
+
+ /// Implement b2Shape.
+ bool TestPoint(const b2Transform& transform, const b2Vec2& p) const;
+
+ /// Implement b2Shape.
+ bool RayCast(b2RayCastOutput* output, const b2RayCastInput& input, const b2Transform& transform) const;
+
+ /// @see b2Shape::ComputeAABB
+ void ComputeAABB(b2AABB* aabb, const b2Transform& transform) const;
+
+ /// @see b2Shape::ComputeMass
+ void ComputeMass(b2MassData* massData, float32 density) const;
+
+ /// Get the supporting vertex index in the given direction.
+ int32 GetSupport(const b2Vec2& d) const;
+
+ /// Get the supporting vertex in the given direction.
+ const b2Vec2& GetSupportVertex(const b2Vec2& d) const;
+
+ /// Get the vertex count.
+ int32 GetVertexCount() const { return 2; }
+
+ /// Get a vertex by index. Used by b2Distance.
+ const b2Vec2& GetVertex(int32 index) const;
+
+ /// Position of circle centers
+ b2Vec2 m_vertices[2];
+};
+
+inline b2CapsuleShape::b2CapsuleShape()
+{
+ m_type = e_capsule;
+ m_radius = 0.0f;
+ m_vertices[0].SetZero();
+ m_vertices[1].SetZero();
+}
+
+
+inline int32 b2CapsuleShape::GetSupport(const b2Vec2 &d) const
+{
+ if ((m_vertices[0] - d).LengthSquared() <= (m_vertices[1] - d).LengthSquared()) {
+ return 0;
+ }
+ return 1;
+}
+
+inline const b2Vec2& b2CapsuleShape::GetSupportVertex(const b2Vec2 &d) const
+{
+ return GetVertex(GetSupport(d));
+}
+
+inline const b2Vec2& b2CapsuleShape::GetVertex(int32 index) const
+{
+ b2Assert(index == 0 || index == 1);
+ return m_vertices[index];
+}
+
+
+
+#endif
Index: Box2D/Box2D/Collision/Shapes/b2Shape.h
===================================================================
--- Box2D/Box2D/Collision/Shapes/b2Shape.h (revision 70)
+++ Box2D/Box2D/Collision/Shapes/b2Shape.h (working copy)
@@ -48,7 +48,8 @@
e_unknown= -1,
e_circle = 0,
e_polygon = 1,
- e_typeCount = 2,
+ e_capsule = 2,
+ e_typeCount = 3,
};
b2Shape() { m_type = e_unknown; }
Index: Box2D/Box2D/Dynamics/b2Fixture.cpp
===================================================================
--- Box2D/Box2D/Dynamics/b2Fixture.cpp (revision 70)
+++ Box2D/Box2D/Dynamics/b2Fixture.cpp (working copy)
@@ -18,6 +18,7 @@
#include <Box2D/Dynamics/b2Fixture.h>
#include <Box2D/Dynamics/Contacts/b2Contact.h>
+#include <Box2D/Collision/Shapes/b2CapsuleShape.h>
#include <Box2D/Collision/Shapes/b2CircleShape.h>
#include <Box2D/Collision/Shapes/b2PolygonShape.h>
#include <Box2D/Collision/b2BroadPhase.h>
@@ -82,6 +83,14 @@
allocator->Free(s, sizeof(b2PolygonShape));
}
break;
+
+ case b2Shape::e_capsule:
+ {
+ b2CapsuleShape* s = (b2CapsuleShape*)m_shape;
+ s->~b2CapsuleShape();
+ allocator->Free(s, sizeof(b2CapsuleShape));
+ }
+ break;
default:
b2Assert(false);
Index: Box2D/Box2D/Dynamics/b2World.cpp
===================================================================
--- Box2D/Box2D/Dynamics/b2World.cpp (revision 70)
+++ Box2D/Box2D/Dynamics/b2World.cpp (working copy)
@@ -26,6 +26,7 @@
#include <Box2D/Dynamics/Contacts/b2TOISolver.h>
#include <Box2D/Collision/b2Collision.h>
#include <Box2D/Collision/b2BroadPhase.h>
+#include <Box2D/Collision/Shapes/b2CapsuleShape.h>
#include <Box2D/Collision/Shapes/b2CircleShape.h>
#include <Box2D/Collision/Shapes/b2PolygonShape.h>
#include <Box2D/Collision/b2TimeOfImpact.h>
@@ -907,6 +908,18 @@
m_debugDraw->DrawSolidPolygon(vertices, vertexCount, color);
}
break;
+
+ case b2Shape::e_capsule:
+ {
+ b2CapsuleShape* capsule = (b2CapsuleShape*)fixture->GetShape();
+
+ b2Vec2 p1 = b2Mul(xf, capsule->m_vertices[0]);
+ b2Vec2 p2 = b2Mul(xf, capsule->m_vertices[1]);
+ float32 radius = capsule->m_radius;
+
+ m_debugDraw->DrawSolidCapsule(p1, p2, radius, color);
+ }
+ break;
}
}
Index: Box2D/Box2D/Dynamics/b2WorldCallbacks.h
===================================================================
--- Box2D/Box2D/Dynamics/b2WorldCallbacks.h (revision 70)
+++ Box2D/Box2D/Dynamics/b2WorldCallbacks.h (working copy)
@@ -206,6 +206,12 @@
/// Draw a solid circle.
virtual void DrawSolidCircle(const b2Vec2& center, float32 radius, const b2Vec2& axis, const b2Color& color) = 0;
+ /// Draw a capsule.
+ virtual void DrawCapsule(const b2Vec2& p1, const b2Vec2& p2, float32 radius, const b2Color& color) = 0;
+
+ /// Draw a solid capsule.
+ virtual void DrawSolidCapsule(const b2Vec2& p1, const b2Vec2& p2, float32 radius, const b2Color& color) = 0;
+
/// Draw a line segment.
virtual void DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color) = 0;
Index: Box2D/Box2D/Dynamics/Contacts/b2CapsuleAndCircleContact.cpp
===================================================================
--- Box2D/Box2D/Dynamics/Contacts/b2CapsuleAndCircleContact.cpp (revision 0)
+++ Box2D/Box2D/Dynamics/Contacts/b2CapsuleAndCircleContact.cpp (revision 0)
@@ -0,0 +1,63 @@
+/*
+* Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com
+*
+* 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.
+*/
+
+#include <Box2D/Dynamics/Contacts/b2CapsuleAndCircleContact.h>
+#include <Box2D/Dynamics/b2Body.h>
+#include <Box2D/Dynamics/b2Fixture.h>
+#include <Box2D/Dynamics/b2WorldCallbacks.h>
+#include <Box2D/Common/b2BlockAllocator.h>
+#include <Box2D/Collision/b2TimeOfImpact.h>
+#include <Box2D/Collision/Shapes/b2CapsuleShape.h>
+#include <Box2D/Collision/Shapes/b2PolygonShape.h>
+
+#include <new>
+
+b2Contact* b2CapsuleAndCircleContact::Create(b2Fixture* fixtureA, b2Fixture* fixtureB, b2BlockAllocator* allocator)
+{
+ void* mem = allocator->Allocate(sizeof(b2CapsuleAndCircleContact));
+ return new (mem) b2CapsuleAndCircleContact(fixtureA, fixtureB);
+}
+
+void b2CapsuleAndCircleContact::Destroy(b2Contact* contact, b2BlockAllocator* allocator)
+{
+ ((b2CapsuleAndCircleContact*)contact)->~b2CapsuleAndCircleContact();
+ allocator->Free(contact, sizeof(b2CapsuleAndCircleContact));
+}
+
+b2CapsuleAndCircleContact::b2CapsuleAndCircleContact(b2Fixture* fixtureA, b2Fixture* fixtureB)
+ : b2Contact(fixtureA, fixtureB)
+{
+ b2Assert(m_fixtureA->GetType() == b2Shape::e_capsule);
+ b2Assert(m_fixtureB->GetType() == b2Shape::e_circle);
+}
+
+void b2CapsuleAndCircleContact::Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB)
+{
+ b2Body* bodyA = m_fixtureA->GetBody();
+ b2Body* bodyB = m_fixtureB->GetBody();
+
+ b2CapsuleShape* capsule = (b2CapsuleShape*)m_fixtureA->GetShape();
+
+ b2PolygonShape polygon;
+ polygon.SetAsEdge(capsule->m_vertices[0], capsule->m_vertices[1]);
+ polygon.m_radius = capsule->m_radius;
+
+ b2CollidePolygonAndCircle( manifold,
+ &polygon, xfA,
+ (b2CircleShape*)m_fixtureB->GetShape(), xfB);
+}
Index: Box2D/Box2D/Dynamics/Contacts/b2CapsuleAndCircleContact.h
===================================================================
--- Box2D/Box2D/Dynamics/Contacts/b2CapsuleAndCircleContact.h (revision 0)
+++ Box2D/Box2D/Dynamics/Contacts/b2CapsuleAndCircleContact.h (revision 0)
@@ -0,0 +1,38 @@
+/*
+* Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com
+*
+* 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 B2_CAPSULE_AND_CIRCLE_CONTACT_H
+#define B2_CAPSULE_AND_CIRCLE_CONTACT_H
+
+#include <Box2D/Dynamics/Contacts/b2Contact.h>
+
+class b2BlockAllocator;
+
+class b2CapsuleAndCircleContact : public b2Contact
+{
+public:
+ static b2Contact* Create(b2Fixture* fixtureA, b2Fixture* fixtureB, b2BlockAllocator* allocator);
+ static void Destroy(b2Contact* contact, b2BlockAllocator* allocator);
+
+ b2CapsuleAndCircleContact(b2Fixture* fixtureA, b2Fixture* fixtureB);
+ ~b2CapsuleAndCircleContact() {}
+
+ void Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB);
+};
+
+#endif
Index: Box2D/Box2D/Dynamics/Contacts/b2CapsuleContact.cpp
===================================================================
--- Box2D/Box2D/Dynamics/Contacts/b2CapsuleContact.cpp (revision 0)
+++ Box2D/Box2D/Dynamics/Contacts/b2CapsuleContact.cpp (revision 0)
@@ -0,0 +1,66 @@
+/*
+* Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com
+*
+* 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.
+*/
+
+#include <Box2D/Dynamics/Contacts/b2CapsuleContact.h>
+#include <Box2D/Dynamics/b2Body.h>
+#include <Box2D/Dynamics/b2Fixture.h>
+#include <Box2D/Dynamics/b2WorldCallbacks.h>
+#include <Box2D/Common/b2BlockAllocator.h>
+#include <Box2D/Collision/b2TimeOfImpact.h>
+#include <Box2D/Collision/Shapes/b2CapsuleShape.h>
+#include <Box2D/Collision/Shapes/b2PolygonShape.h>
+
+#include <new>
+
+b2Contact* b2CapsuleContact::Create(b2Fixture* fixtureA, b2Fixture* fixtureB, b2BlockAllocator* allocator)
+{
+ void* mem = allocator->Allocate(sizeof(b2CapsuleContact));
+ return new (mem) b2CapsuleContact(fixtureA, fixtureB);
+}
+
+void b2CapsuleContact::Destroy(b2Contact* contact, b2BlockAllocator* allocator)
+{
+ ((b2CapsuleContact*)contact)->~b2CapsuleContact();
+ allocator->Free(contact, sizeof(b2CapsuleContact));
+}
+
+b2CapsuleContact::b2CapsuleContact(b2Fixture* fixtureA, b2Fixture* fixtureB)
+ : b2Contact(fixtureA, fixtureB)
+{
+ b2Assert(m_fixtureA->GetType() == b2Shape::e_capsule);
+ b2Assert(m_fixtureB->GetType() == b2Shape::e_capsule);
+}
+
+void b2CapsuleContact::Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB)
+{
+ b2Body* bodyA = m_fixtureA->GetBody();
+ b2Body* bodyB = m_fixtureB->GetBody();
+
+ b2CapsuleShape* capsule1 = (b2CapsuleShape*)m_fixtureA->GetShape();
+ b2CapsuleShape* capsule2 = (b2CapsuleShape*)m_fixtureB->GetShape();
+
+ b2PolygonShape polygon1, polygon2;
+ polygon1.SetAsEdge(capsule1->m_vertices[0], capsule1->m_vertices[1]);
+ polygon2.SetAsEdge(capsule2->m_vertices[0], capsule2->m_vertices[1]);
+ polygon1.m_radius = capsule1->m_radius;
+ polygon2.m_radius = capsule2->m_radius;
+
+ b2CollidePolygons( manifold,
+ &polygon1, xfA,
+ &polygon2, xfB);
+}
Index: Box2D/Box2D/Dynamics/Contacts/b2CapsuleContact.h
===================================================================
--- Box2D/Box2D/Dynamics/Contacts/b2CapsuleContact.h (revision 0)
+++ Box2D/Box2D/Dynamics/Contacts/b2CapsuleContact.h (revision 0)
@@ -0,0 +1,38 @@
+/*
+* Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com
+*
+* 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 B2_CAPSULE_CONTACT_H
+#define B2_CAPSULE_CONTACT_H
+
+#include <Box2D/Dynamics/Contacts/b2Contact.h>
+
+class b2BlockAllocator;
+
+class b2CapsuleContact : public b2Contact
+{
+public:
+ static b2Contact* Create(b2Fixture* fixtureA, b2Fixture* fixtureB, b2BlockAllocator* allocator);
+ static void Destroy(b2Contact* contact, b2BlockAllocator* allocator);
+
+ b2CapsuleContact(b2Fixture* fixtureA, b2Fixture* fixtureB);
+ ~b2CapsuleContact() {}
+
+ void Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB);
+};
+
+#endif
Index: Box2D/Box2D/Dynamics/Contacts/b2Contact.cpp
===================================================================
--- Box2D/Box2D/Dynamics/Contacts/b2Contact.cpp (revision 70)
+++ Box2D/Box2D/Dynamics/Contacts/b2Contact.cpp (working copy)
@@ -17,7 +17,10 @@
*/
#include <Box2D/Dynamics/Contacts/b2Contact.h>
+#include <Box2D/Dynamics/Contacts/b2CapsuleContact.h>
+#include <Box2D/Dynamics/Contacts/b2CapsuleAndCircleContact.h>
#include <Box2D/Dynamics/Contacts/b2CircleContact.h>
+#include <Box2D/Dynamics/Contacts/b2PolygonAndCapsuleContact.h>
#include <Box2D/Dynamics/Contacts/b2PolygonAndCircleContact.h>
#include <Box2D/Dynamics/Contacts/b2PolygonContact.h>
#include <Box2D/Dynamics/Contacts/b2ContactSolver.h>
@@ -38,6 +41,10 @@
AddType(b2CircleContact::Create, b2CircleContact::Destroy, b2Shape::e_circle, b2Shape::e_circle);
AddType(b2PolygonAndCircleContact::Create, b2PolygonAndCircleContact::Destroy, b2Shape::e_polygon, b2Shape::e_circle);
AddType(b2PolygonContact::Create, b2PolygonContact::Destroy, b2Shape::e_polygon, b2Shape::e_polygon);
+
+ AddType(b2CapsuleContact::Create, b2CapsuleContact::Destroy, b2Shape::e_capsule, b2Shape::e_capsule);
+ AddType(b2CapsuleAndCircleContact::Create, b2CapsuleAndCircleContact::Destroy, b2Shape::e_capsule, b2Shape::e_circle);
+ AddType(b2PolygonAndCapsuleContact::Create, b2PolygonAndCapsuleContact::Destroy, b2Shape::e_polygon, b2Shape::e_capsule);
}
void b2Contact::AddType(b2ContactCreateFcn* createFcn, b2ContactDestroyFcn* destoryFcn,
Index: Box2D/Box2D/Dynamics/Contacts/b2PolygonAndCapsuleContact.cpp
===================================================================
--- Box2D/Box2D/Dynamics/Contacts/b2PolygonAndCapsuleContact.cpp (revision 0)
+++ Box2D/Box2D/Dynamics/Contacts/b2PolygonAndCapsuleContact.cpp (revision 0)
@@ -0,0 +1,63 @@
+/*
+* Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com
+*
+* 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.
+*/
+
+#include <Box2D/Dynamics/Contacts/b2PolygonAndCapsuleContact.h>
+#include <Box2D/Dynamics/b2Body.h>
+#include <Box2D/Dynamics/b2Fixture.h>
+#include <Box2D/Dynamics/b2WorldCallbacks.h>
+#include <Box2D/Common/b2BlockAllocator.h>
+#include <Box2D/Collision/b2TimeOfImpact.h>
+#include <Box2D/Collision/Shapes/b2CapsuleShape.h>
+#include <Box2D/Collision/Shapes/b2PolygonShape.h>
+
+#include <new>
+
+b2Contact* b2PolygonAndCapsuleContact::Create(b2Fixture* fixtureA, b2Fixture* fixtureB, b2BlockAllocator* allocator)
+{
+ void* mem = allocator->Allocate(sizeof(b2PolygonAndCapsuleContact));
+ return new (mem) b2PolygonAndCapsuleContact(fixtureA, fixtureB);
+}
+
+void b2PolygonAndCapsuleContact::Destroy(b2Contact* contact, b2BlockAllocator* allocator)
+{
+ ((b2PolygonAndCapsuleContact*)contact)->~b2PolygonAndCapsuleContact();
+ allocator->Free(contact, sizeof(b2PolygonAndCapsuleContact));
+}
+
+b2PolygonAndCapsuleContact::b2PolygonAndCapsuleContact(b2Fixture* fixtureA, b2Fixture* fixtureB)
+ : b2Contact(fixtureA, fixtureB)
+{
+ b2Assert(m_fixtureA->GetType() == b2Shape::e_polygon);
+ b2Assert(m_fixtureB->GetType() == b2Shape::e_capsule);
+}
+
+void b2PolygonAndCapsuleContact::Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB)
+{
+ b2Body* bodyA = m_fixtureA->GetBody();
+ b2Body* bodyB = m_fixtureB->GetBody();
+
+ b2CapsuleShape* capsule = (b2CapsuleShape*)m_fixtureB->GetShape();
+
+ b2PolygonShape polygon;
+ polygon.SetAsEdge(capsule->m_vertices[0], capsule->m_vertices[1]);
+ polygon.m_radius = capsule->m_radius;
+
+ b2CollidePolygons( manifold,
+ (b2PolygonShape*)m_fixtureA->GetShape(), xfA,
+ &polygon, xfB);
+}
Index: Box2D/Box2D/Dynamics/Contacts/b2PolygonAndCapsuleContact.h
===================================================================
--- Box2D/Box2D/Dynamics/Contacts/b2PolygonAndCapsuleContact.h (revision 0)
+++ Box2D/Box2D/Dynamics/Contacts/b2PolygonAndCapsuleContact.h (revision 0)
@@ -0,0 +1,38 @@
+/*
+* Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com
+*
+* 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 B2_POLYGON_AND_CAPSULE_CONTACT_H
+#define B2_POLYGON_AND_CAPSULE_CONTACT_H
+
+#include <Box2D/Dynamics/Contacts/b2Contact.h>
+
+class b2BlockAllocator;
+
+class b2PolygonAndCapsuleContact : public b2Contact
+{
+public:
+ static b2Contact* Create(b2Fixture* fixtureA, b2Fixture* fixtureB, b2BlockAllocator* allocator);
+ static void Destroy(b2Contact* contact, b2BlockAllocator* allocator);
+
+ b2PolygonAndCapsuleContact(b2Fixture* fixtureA, b2Fixture* fixtureB);
+ ~b2PolygonAndCapsuleContact() {}
+
+ void Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB);
+};
+
+#endif
Index: Box2D/Testbed/Framework/Render.cpp
===================================================================
--- Box2D/Testbed/Framework/Render.cpp (revision 70)
+++ Box2D/Testbed/Framework/Render.cpp (working copy)
@@ -110,6 +110,83 @@
glEnd();
}
+void DebugDraw::DrawCapsule(const b2Vec2& p1, const b2Vec2& p2, float32 radius, const b2Color& color)
+{
+ b2Vec2 displacement = p2 - p1;
+ displacement.Normalize();
+ float32 startingAngle = atan2f(displacement.y, displacement.x) + b2_pi / 2;
+
+ const float32 k_segments = 8.0f;
+ const float32 k_increment = b2_pi / k_segments;
+ float32 theta = startingAngle;
+ glColor3f(color.r, color.g, color.b);
+ glBegin(GL_LINE_LOOP);
+ for (int32 i = 0; i < k_segments; ++i)
+ {
+ b2Vec2 v = p1 + radius * b2Vec2(cosf(theta), sinf(theta));
+ glVertex2f(v.x, v.y);
+ theta += k_increment;
+ }
+ for (int32 i = 0; i < k_segments; ++i)
+ {
+ b2Vec2 v = p2 + radius * b2Vec2(cosf(theta), sinf(theta));
+ glVertex2f(v.x, v.y);
+ theta += k_increment;
+ }
+ glEnd();
+}
+
+void DebugDraw::DrawSolidCapsule(const b2Vec2& p1, const b2Vec2& p2, float32 radius, const b2Color& color)
+{
+ b2Vec2 displacement = p2 - p1;
+ displacement.Normalize();
+ float32 startingAngle = atan2f(displacement.y, displacement.x) + b2_pi / 2;
+
+ const float32 k_segments = 8.0f;
+ const float32 k_increment = b2_pi / k_segments;
+ float32 theta = startingAngle;
+ glEnable(GL_BLEND);
+ glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glColor4f(0.5f * color.r, 0.5f * color.g, 0.5f * color.b, 0.5f);
+ glBegin(GL_TRIANGLE_FAN);
+ for (int32 i = 0; i < k_segments; ++i)
+ {
+ b2Vec2 v = p1 + radius * b2Vec2(cosf(theta), sinf(theta));
+ glVertex2f(v.x, v.y);
+ theta += k_increment;
+ }
+ for (int32 i = 0; i < k_segments; ++i)
+ {
+ b2Vec2 v = p2 + radius * b2Vec2(cosf(theta), sinf(theta));
+ glVertex2f(v.x, v.y);
+ theta += k_increment;
+ }
+ glEnd();
+ glDisable(GL_BLEND);
+
+ theta = startingAngle;
+ glColor4f(color.r, color.g, color.b, 1.0f);
+ glBegin(GL_LINE_LOOP);
+ for (int32 i = 0; i < k_segments; ++i)
+ {
+ b2Vec2 v = p1 + radius * b2Vec2(cosf(theta), sinf(theta));
+ glVertex2f(v.x, v.y);
+ theta += k_increment;
+ }
+ for (int32 i = 0; i < k_segments; ++i)
+ {
+ b2Vec2 v = p2 + radius * b2Vec2(cosf(theta), sinf(theta));
+ glVertex2f(v.x, v.y);
+ theta += k_increment;
+ }
+ glEnd();
+
+ glBegin(GL_LINES);
+ glVertex2f(p1.x, p1.y);
+ glVertex2f(p2.x, p2.y);
+ glEnd();
+}
+
void DebugDraw::DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color)
{
glColor3f(color.r, color.g, color.b);
Index: Box2D/Testbed/Framework/Render.h
===================================================================
--- Box2D/Testbed/Framework/Render.h (revision 70)
+++ Box2D/Testbed/Framework/Render.h (working copy)
@@ -36,6 +36,10 @@
void DrawSolidCircle(const b2Vec2& center, float32 radius, const b2Vec2& axis, const b2Color& color);
+ void DrawCapsule(const b2Vec2& p1, const b2Vec2& p2, float32 radius, const b2Color& color);
+
+ void DrawSolidCapsule(const b2Vec2& p1, const b2Vec2& p2, float32 radius, const b2Color& color);
+
void DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color);
void DrawTransform(const b2Transform& xf);
Index: Box2D/Testbed/Tests/PolyShapes.h
===================================================================
--- Box2D/Testbed/Tests/PolyShapes.h (revision 70)
+++ Box2D/Testbed/Tests/PolyShapes.h (working copy)
@@ -74,6 +74,19 @@
m_debugDraw->DrawPolygon(vertices, vertexCount, color);
}
break;
+
+ case b2Shape::e_capsule:
+ {
+ b2CapsuleShape* capsule = (b2CapsuleShape*)fixture->GetShape();
+
+ b2Vec2 p1 = b2Mul(xf, capsule->m_vertices[0]);
+ b2Vec2 p2 = b2Mul(xf, capsule->m_vertices[1]);
+ float32 radius = capsule->m_radius;
+
+ m_debugDraw->DrawCapsule(p1, p2, radius, color);
+ }
+ break;
+
}
}
@@ -163,6 +176,14 @@
m_circle.m_radius = 0.5f;
}
+ {
+ m_capsules[0].SetByExtentsX(0.5f, 0.5f);
+ }
+
+ {
+ m_capsules[1].SetByExtentsY(0.1f, 1.8f, b2Vec2(0.0f, 1.0f), 0.0f);
+ }
+
m_bodyIndex = 0;
memset(m_bodies, 0, sizeof(m_bodies));
}
@@ -197,7 +218,7 @@
fd.friction = 0.3f;
m_bodies[m_bodyIndex]->CreateFixture(&fd);
}
- else
+ else if (index == 4)
{
b2FixtureDef fd;
fd.shape = &m_circle;
@@ -206,6 +227,15 @@
m_bodies[m_bodyIndex]->CreateFixture(&fd);
}
+ else
+ {
+ b2FixtureDef fd;
+ fd.shape = m_capsules + (index - 5);
+ fd.density = 1.0f;
+ fd.friction = 0.3f;
+
+ m_bodies[m_bodyIndex]->CreateFixture(&fd);
+ }
m_bodyIndex = (m_bodyIndex + 1) % k_maxBodies;
}
@@ -232,6 +262,8 @@
case '3':
case '4':
case '5':
+ case '6':
+ case '7':
Create(key - '1');
break;
@@ -270,7 +302,7 @@
b2Color color(0.4f, 0.7f, 0.8f);
m_debugDraw.DrawCircle(callback.m_circle.m_p, callback.m_circle.m_radius, color);
- m_debugDraw.DrawString(5, m_textLine, "Press 1-5 to drop stuff");
+ m_debugDraw.DrawString(5, m_textLine, "Press 1-7 to drop stuff");
m_textLine += 15;
m_debugDraw.DrawString(5, m_textLine, "Press 'a' to (de)activate some bodies");
m_textLine += 15;
@@ -287,6 +319,7 @@
b2Body* m_bodies[k_maxBodies];
b2PolygonShape m_polygons[4];
b2CircleShape m_circle;
+ b2CapsuleShape m_capsules[2];
};
#endif
Index: Box2D/Testbed/Tests/RayCast.h
===================================================================
--- Box2D/Testbed/Tests/RayCast.h (revision 70)
+++ Box2D/Testbed/Tests/RayCast.h (working copy)
@@ -211,6 +211,14 @@
m_circle.m_radius = 0.5f;
}
+ {
+ m_capsules[0].SetByExtentsX(0.5f, 0.5f);
+ }
+
+ {
+ m_capsules[1].SetByExtentsY(0.1f, 1.8f, b2Vec2(0.0f, 1.0f), 0.0f);
+ }
+
m_bodyIndex = 0;
memset(m_bodies, 0, sizeof(m_bodies));
@@ -251,7 +259,7 @@
fd.friction = 0.3f;
m_bodies[m_bodyIndex]->CreateFixture(&fd);
}
- else
+ else if (index == 4)
{
b2FixtureDef fd;
fd.shape = &m_circle;
@@ -259,6 +267,14 @@
m_bodies[m_bodyIndex]->CreateFixture(&fd);
}
+ else
+ {
+ b2FixtureDef fd;
+ fd.shape = m_capsules + (index - 5);
+ fd.friction = 0.3f;
+
+ m_bodies[m_bodyIndex]->CreateFixture(&fd);
+ }
m_bodyIndex = (m_bodyIndex + 1) % e_maxBodies;
}
@@ -285,6 +301,8 @@
case '3':
case '4':
case '5':
+ case '6':
+ case '7':
Create(key - '1');
break;
@@ -311,7 +329,7 @@
void Step(Settings* settings)
{
Test::Step(settings);
- m_debugDraw.DrawString(5, m_textLine, "Press 1-5 to drop stuff, m to change the mode");
+ m_debugDraw.DrawString(5, m_textLine, "Press 1-7 to drop stuff, m to change the mode");
m_textLine += 15;
m_debugDraw.DrawString(5, m_textLine, "Mode = %d", m_mode);
m_textLine += 15;
@@ -385,6 +403,7 @@
int32 m_userData[e_maxBodies];
b2PolygonShape m_polygons[4];
b2CircleShape m_circle;
+ b2CapsuleShape m_capsules[2];
float32 m_angle;
#pragma once
#include "stdafx.h"
#include "Vector.cpp"
namespace Box2D
{
namespace Net
{
public ref class AABB
{
public:
Vector ^lowerBound, ^upperBound;
bool IsValid()
{
return getAABB().IsValid();
}
AABB(Vector^ min, Vector^ max) : lowerBound(gcnew Vector(min)), upperBound(gcnew Vector(max)) { }
AABB() : lowerBound(gcnew Vector()), upperBound(gcnew Vector()) { }
b2AABB getAABB()
{
b2AABB returnme;
returnme.lowerBound = lowerBound->getVec2();
returnme.upperBound = upperBound->getVec2();
return returnme;
}
};
}
}