Added Box2D

This commit is contained in:
Julian Nießner
2018-05-06 12:43:20 +02:00
parent cb5469bb89
commit d175d433a8
351 changed files with 123545 additions and 1 deletions

View File

@@ -0,0 +1,119 @@
/*
* 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);
}

View File

@@ -0,0 +1,102 @@
/*
* 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

View File

@@ -0,0 +1,46 @@
/*
* 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);
}

View File

@@ -0,0 +1,54 @@
/*
* 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

View File

@@ -0,0 +1,47 @@
/*
* 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);
}

View File

@@ -0,0 +1,54 @@
/*
* 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

View File

@@ -0,0 +1,110 @@
/*
* 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;
}

View File

@@ -0,0 +1,151 @@
/*
* 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

View File

@@ -0,0 +1,70 @@
/*
* 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);
}

View File

@@ -0,0 +1,59 @@
/*
* 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

View File

@@ -0,0 +1,72 @@
/*
* 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);
}

View File

@@ -0,0 +1,69 @@
/*
* 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

View File

@@ -0,0 +1,477 @@
/*
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

View File

@@ -0,0 +1,139 @@
/*---------------------------------------------------------------------------------
$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
//---------------------------------------------------------------------------------

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,32 @@
#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;
}
};
}
}

View File

@@ -0,0 +1,40 @@
#include "stdafx.h"
using namespace System;
using namespace System::Reflection;
using namespace System::Runtime::CompilerServices;
using namespace System::Runtime::InteropServices;
using namespace System::Security::Permissions;
//
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
//
[assembly:AssemblyTitleAttribute("Box2DNet")];
[assembly:AssemblyDescriptionAttribute("A .NET wrapper for the Box2D physics library")];
[assembly:AssemblyConfigurationAttribute("")];
[assembly:AssemblyCompanyAttribute("")];
[assembly:AssemblyProductAttribute("Box2DNet")];
[assembly:AssemblyCopyrightAttribute("Copyright (c) Jay Lemmon 2008")];
[assembly:AssemblyTrademarkAttribute("")];
[assembly:AssemblyCultureAttribute("")];
//
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the value or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly:AssemblyVersionAttribute("1.0.*")];
[assembly:ComVisible(false)];
[assembly:CLSCompliantAttribute(true)];
[assembly:SecurityPermission(SecurityAction::RequestMinimum, UnmanagedCode = true)];

View File

@@ -0,0 +1,243 @@
#pragma once
#include "Stdafx.h"
#include "Vector.cpp"
#include "Shape.cpp"
#include "ShapeDef.cpp"
namespace Box2D
{
namespace Net
{
/// <summary>
/// A rigid body. Internal computation are done in terms
/// of the center of mass position. The center of mass may
/// be offset from the body's origin.
/// </summary>
public ref class Body
{
internal:
b2Body *body;
Body(b2Body *bodyRef) : body(bodyRef) { }
public:
/// <summary>
/// Set the position of the body's origin and rotation (radians).
/// This breaks any contacts and wakes the other bodies.
/// </summary>
void SetXForm(Vector^ position, float32 rotation)
{
body->SetXForm(position->getVec2(), rotation);
}
/// <summary>
/// Get the position of the body's origin. The body's origin does not
/// necessarily coincide with the center of mass. It depends on how the
/// shapes are created.
/// </summary>
XForm^ GetXForm()
{
return gcnew XForm(body->GetXForm());
}
///<summary>Accesses the linear velocity of the center of mass.</summary>
property Vector^ LinearVelocity
{
Vector^ get()
{
return gcnew Vector(body->GetLinearVelocity());
}
void set(Vector^ value)
{
body->SetLinearVelocity(value->getVec2());
}
}
///<summary>Accesses the angular velocity.</summary>
property float32 AngularVelocity
{
float32 get()
{
return body->GetAngularVelocity();
}
void set(float32 value)
{
body->SetAngularVelocity(value);
}
}
///<summary> Apply a force at a world point. Additive. </summary>
void ApplyForce(Vector^ Force, Vector^ Point)
{
body->ApplyForce(Force->getVec2(), Point->getVec2());
}
///<summary> Apply a torque. Additive. </summary>
void ApplyTorque(float32 Torque)
{
body->ApplyTorque(Torque);
}
///<summary> Apply an impulse at a point. This immediately modifies the velocity. </summary>
void ApplyImpulse(Vector^ Impulse, Vector^ Point)
{
body->ApplyImpulse(Impulse->getVec2(), Point->getVec2());
}
///<summary>Accesses the Mass.</summary>
property float32 Mass
{
float32 get()
{
return body->GetMass();
}
}
///<summary>Accesses the Mass.</summary>
property float32 Inertia
{
float32 get()
{
return body->GetInertia();
}
}
/// <summary>
/// Get the world coordinates of a point give the local coordinates
/// relative to the body's center of mass.
/// </summary>
Vector^ GetWorldPoint(Vector^ LocalPoint)
{
return gcnew Vector(body->GetWorldPoint(LocalPoint->getVec2()));
}
/// <summary>
/// Get the world coordinates of a vector given the local coordinates.
/// </summary>
Vector^ GetWorldVector(Vector^ LocalVector)
{
return gcnew Vector(body->GetWorldVector(LocalVector->getVec2()));
}
/// <summary>
/// Returns a local point relative to the center of mass given a world point.
/// </summary>
Vector^ GetLocalPoint(Vector^ WorldPoint)
{
return gcnew Vector(body->GetLocalPoint(WorldPoint->getVec2()));
}
/// <summary>
/// Returns a local vector given a world vector.
/// </summary>
Vector^ GetLocalVector(Vector^ WorldVector)
{
return gcnew Vector(body->GetLocalVector(WorldVector->getVec2()));
}
///<summary>Is this body static (immovable)</summary>
property bool Static
{
bool get()
{
return body->IsStatic();
}
}
///<summary>Is this body frozen</summary>
property bool Frozen
{
bool get()
{
return body->IsFrozen();
}
}
///<summary>Is this body sleeping</summary>
property bool Sleeping
{
bool get()
{
return body->IsSleeping();
}
}
///<summary>You can disable sleeping on this particular body.</summary>
property bool AllowSleeping
{
bool get()
{
return body->IsSleeping();
}
void set(bool value)
{
body->AllowSleeping(value);
}
}
property bool Bullet
{
bool get()
{
return body->IsBullet();
}
void set(bool value)
{
body->SetBullet(value);
}
}
void WakeUp()
{
body->WakeUp();
}
///<summary> Get the list of all shapes attached to this body.</summary>
property IList<Shape^>^ Shapes
{
IList<Shape^>^ get()
{
List<Shape^>^ list = gcnew List<Shape^>();
for(b2Shape *shape = body->GetShapeList(); shape; shape = shape->GetNext())
list->Add(gcnew Shape(shape));
return list;
}
}
void CreateShape(ShapeDef^ def)
{
body->CreateShape(def->def);
}
void DestroyShape(Shape^ shape)
{
body->DestroyShape(shape->shape);
}
void SetMassFromShapes()
{
body->SetMassFromShapes();
}
//TODO:
//void* GetUserData();
//const b2Mat22& GetRotationMatrix() const;
};
}
}
/*
TODO:
public:
// Get the list of all contacts attached to this body.
b2ContactNode* GetContactList();
// Get the list of all joints attached to this body.
b2JointNode* GetJointList();
*/

View File

@@ -0,0 +1,168 @@
#pragma once
#include "stdafx.h"
#include "Vector.cpp"
#include "ShapeDef.cpp"
using namespace System::Collections::Generic;
namespace Box2D
{
namespace Net
{
/// The type of body.
public enum class BodyType
{
e_staticBody = ::b2BodyDef::e_staticBody, ///< A static body should not move and has infinite mass.
e_dynamicBody = ::b2BodyDef::e_dynamicBody ///< A regular moving body.
};
public ref class BodyDef
{
internal:
b2BodyDef *def;
public:
BodyDef() : def(new b2BodyDef()) { }
virtual ~BodyDef()
{
delete def;
}
property Vector^ Position
{
Vector^ get()
{
return gcnew Vector(def->position);
}
void set(Vector^ value)
{
def->position = value->getVec2();
}
}
property float32 Angle
{
float32 get()
{
return def->angle;
}
void set(float32 value)
{
def->angle = value;
}
}
property float32 LinearDamping
{
float32 get()
{
return def->linearDamping;
}
void set(float32 value)
{
def->linearDamping = value;
}
}
property float32 AngularDamping
{
float32 get()
{
return def->angularDamping;
}
void set(float32 value)
{
def->angularDamping = value;
}
}
property bool AllowSleep
{
bool get()
{
return def->allowSleep;
}
void set(bool value)
{
def->allowSleep = value;
}
}
property bool IsBullet
{
bool get()
{
return def->isBullet;
}
void set(bool value)
{
def->isBullet = value;
}
}
property bool IsSleeping
{
bool get()
{
return def->isSleeping;
}
void set(bool value)
{
def->isSleeping = value;
}
}
property bool FixedRotation
{
bool get()
{
return def->fixedRotation;
}
void set(bool value)
{
def->fixedRotation = value;
}
}
property BodyType BodyType
{
Box2D::Net::BodyType get()
{
return (Box2D::Net::BodyType)def->type;
}
void set(Box2D::Net::BodyType value)
{
def->type = ((::b2BodyDef::Type)value);
}
}
//TODO:
/*property Object^ UserData
{
Object^ get()
{
Object^ ReturnMe;
System::Runtime::InteropServices::Marshal::PtrToStructure((System::IntPtr)def->userData, ReturnMe);
return ReturnMe;
}
void set(Object^ value)
{
def->userData = value;
}
}*/
};
}
}

View File

@@ -0,0 +1,291 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Name="Box2D.Net"
ProjectGUID="{0E95DBB9-EA97-407B-811C-810B225E79D2}"
RootNamespace="Box2DNet"
Keyword="ManagedCProj"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
ManagedExtensions="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\Include\"
PreprocessorDefinitions="WIN32;_DEBUG"
RuntimeLibrary="3"
UsePrecompiledHeader="1"
GenerateXMLDocumentationFiles="true"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="$(NoInherit)"
LinkIncremental="2"
GenerateDebugInformation="true"
AssemblyDebug="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="2"
CharacterSet="1"
ManagedExtensions="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\..\Include\"
PreprocessorDefinitions="WIN32;NDEBUG"
RuntimeLibrary="2"
UsePrecompiledHeader="1"
WarningLevel="3"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="$(NoInherit)"
LinkIncremental="1"
GenerateDebugInformation="true"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
<AssemblyReference
RelativePath="System.dll"
AssemblyName="System, Version=2.0.0.0, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL"
/>
<AssemblyReference
RelativePath="System.Data.dll"
AssemblyName="System.Data, Version=2.0.0.0, PublicKeyToken=b77a5c561934e089, processorArchitecture=x86"
/>
<AssemblyReference
RelativePath="System.XML.dll"
AssemblyName="System.Xml, Version=2.0.0.0, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL"
/>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath=".\AssemblyInfo.cpp"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath=".\Stdafx.h"
>
</File>
</Filter>
<Filter
Name="Wrappers"
>
<File
RelativePath=".\AABB.cpp"
>
</File>
<File
RelativePath=".\Body.cpp"
>
</File>
<File
RelativePath=".\BodyDef.cpp"
>
</File>
<File
RelativePath=".\Contact.cpp"
>
</File>
<File
RelativePath=".\Delegates.cpp"
>
</File>
<File
RelativePath=".\Joint.cpp"
>
</File>
<File
RelativePath=".\JointDef.cpp"
>
</File>
<File
RelativePath=".\Manifold.cpp"
>
</File>
<File
RelativePath=".\ManifoldPoint.cpp"
>
</File>
<File
RelativePath=".\MassData.cpp"
>
</File>
<File
RelativePath=".\Matrix.cpp"
>
</File>
<File
RelativePath=".\RevoluteJoint.cpp"
>
</File>
<File
RelativePath=".\Shape.cpp"
>
</File>
<File
RelativePath=".\Shape.h"
>
</File>
<File
RelativePath=".\ShapeDef.cpp"
>
</File>
<File
RelativePath=".\ShapeType.cpp"
>
</File>
<File
RelativePath=".\VariousImplementations.cpp"
>
</File>
<File
RelativePath=".\Vector.cpp"
>
</File>
<File
RelativePath=".\World.cpp"
>
</File>
<File
RelativePath=".\XForm.cpp"
>
</File>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -0,0 +1,53 @@
#pragma once
#include "stdafx.h"
#include "Shape.cpp"
#include "Manifold.cpp"
namespace Box2D
{
namespace Net
{
public ref class Contact
{
internal:
b2Contact *contact;
Contact(b2Contact *contactRef) : contact(contactRef) { }
public:
property Shape^ Shape1
{
Shape^ get()
{
return gcnew Shape(contact->GetShape1());
}
}
property Shape^ Shape2
{
Shape^ get()
{
return gcnew Shape(contact->GetShape2());
}
}
Contact^ GetNext()
{
return gcnew Contact(contact->GetNext());
}
Manifold^ GetManifolds()
{
return gcnew Manifold(contact->GetManifolds());
}
property int ManifoldCount
{
int get()
{
return contact->GetManifoldCount();
}
}
};
}
}

View File

@@ -0,0 +1,28 @@
#pragma once
#include "stdafx.h"
#include "Joint.cpp"
#include "Body.cpp"
namespace Box2D
{
namespace Net
{
/// <summary>
/// If a body is destroyed, then any joints attached to it are also destroyed.
/// This prevents memory leaks, but you may unexpectedly be left with an
/// orphaned joint pointer.
/// Box2D will notify you when a joint is implicitly destroyed.
/// It is NOT called if you directly destroy a joint.
/// DO NOT modify the Box2D world inside this callback.
/// </summary>
public delegate void NotifyJointDestroyed(Joint);
/// <summary>
/// Return true if collision calculations should be performed between shape1 and shape2
/// Box2D has a default implementation for this, so only add a new delegate if you
/// want to override the default behavior.
/// </summary>
public delegate bool CollisionFilter(Shape shape1, Shape shape2);
}
}

View File

@@ -0,0 +1,106 @@
#pragma once
#include "stdafx.h"
#include "Body.cpp"
#include "JointDef.cpp"
namespace Box2D
{
namespace Net
{
public ref class Joint
{
internal:
b2Joint *joint;
Joint(b2Joint *jointRef) : joint(jointRef) { }
public:
property JointType JointType
{
Box2D::Net::JointType get()
{
return (Box2D::Net::JointType) joint->GetType();
}
}
property Body^ Body1
{
Body^ get()
{
return gcnew Body(joint->GetBody1());
}
}
property Body^ Body2
{
Body^ get()
{
return gcnew Body(joint->GetBody2());
}
}
property Vector^ Anchor1
{
Vector^ get()
{
return gcnew Vector(joint->GetAnchor1());
}
}
property Vector^ Anchor2
{
Vector^ get()
{
return gcnew Vector(joint->GetAnchor2());
}
}
Vector^ GetReactionForce()
{
return gcnew Vector(joint->GetReactionForce());
}
float32 GetReactionTorque()
{
return joint->GetReactionTorque();
}
Joint^ GetNext()
{
return gcnew Joint(joint->GetNext());
}
//TODO:
/*
void* GetUserData();
*/
};
public ref class MouseJoint : public Joint
{
internal:
b2MouseJoint *mouseJoint;
MouseJoint(b2MouseJoint *joint) : Joint(joint), mouseJoint(joint) { }
public:
MouseJoint(Joint^ joint) : Joint(joint->joint), mouseJoint(0)
{
if(joint->JointType == Box2D::Net::JointType::e_mouseJoint &&
reinterpret_cast<b2MouseJoint *>(joint->joint))
{
mouseJoint = reinterpret_cast<b2MouseJoint *>(joint->joint);
}
else
{
throw gcnew System::Exception("Attempting to convert a Joint to a MouseJoint, "
"but the joint is not a mouse joint.");
}
}
void SetTarget(Vector^ Target)
{
mouseJoint->SetTarget(Target->getVec2());
}
};
}
}

View File

@@ -0,0 +1,178 @@
#pragma once
#include "stdafx.h"
#include "Body.cpp"
#include "Vector.cpp"
using namespace System::Runtime::InteropServices;
namespace Box2D
{
namespace Net
{
//TODO: is there a way to automatically include the b2JointType as an enum here?
public enum class JointType
{
e_unknownJoint = ::e_unknownJoint,
e_revoluteJoint = ::e_revoluteJoint,
e_prismaticJoint = ::e_prismaticJoint,
e_distanceJoint = ::e_distanceJoint,
e_pulleyJoint = ::e_pulleyJoint,
e_mouseJoint = ::e_mouseJoint,
e_gearJoint = ::e_gearJoint
};
public ref class JointDef
{
internal:
b2JointDef *def;
JointDef() : def(new b2JointDef()) { }
JointDef(b2JointDef *justBuilt) : def(justBuilt) { }
virtual ~JointDef()
{
delete def;
}
public:
property JointType Type
{
JointType get()
{
return (JointType)def->type;
}
void set(JointType value)
{
def->type = (b2JointType)value;
}
}
property Object^ UserData
{
Object^ get()
{
return System::Runtime::InteropServices::GCHandle::FromIntPtr((System::IntPtr)def->userData).Target;
}
void set(Object^ value)
{
GCHandle^ gch = GCHandle::Alloc(value);
def->userData = (void *)gch->ToIntPtr(*gch);
}
}
property Body^ Body1
{
Body^ get()
{
return gcnew Body(def->body1);
}
void set(Body^ value)
{
def->body1 = value->body;
}
}
property Body^ Body2
{
Body^ get()
{
return gcnew Body(def->body2);
}
void set(Body^ value)
{
def->body2 = value->body;
}
}
property bool CollideConnected
{
bool get()
{
return def->collideConnected;
}
void set(bool value)
{
def->collideConnected = value;
}
}
};
public ref class MouseJointDef : public JointDef
{
internal:
b2MouseJointDef *mouseJoint;
public:
MouseJointDef() : JointDef(mouseJoint = new b2MouseJointDef()) { }
property Vector^ Target
{
Vector^ get()
{
return gcnew Vector(mouseJoint->target);
}
void set(Vector^ value)
{
mouseJoint->target = value->getVec2();
}
}
property float32 MaxForce
{
float32 get()
{
return mouseJoint->maxForce;
}
void set(float32 value)
{
mouseJoint->maxForce = value;
}
}
property float32 FrequencyHz
{
float32 get()
{
return mouseJoint->frequencyHz;
}
void set(float32 value)
{
mouseJoint->frequencyHz = value;
}
}
property float32 DampingRatio
{
float32 get()
{
return mouseJoint->dampingRatio;
}
void set(float32 value)
{
mouseJoint->dampingRatio = value;
}
}
property float32 TimeStep
{
float32 get()
{
return mouseJoint->timeStep;
}
void set(float32 value)
{
mouseJoint->timeStep = value;
}
}
};
}
}

View File

@@ -0,0 +1,44 @@
#pragma once
#include "stdafx.h"
#include "Vector.cpp"
//#include "ContactPoint.cpp"
#include "ManifoldPoint.cpp"
using namespace System::Collections::Generic;
namespace Box2D
{
namespace Net
{
public ref class Manifold
{
internal:
b2Manifold *fold;
Manifold(b2Manifold *foldRef) : fold(foldRef) { }
public:
property Vector^ Normal
{
Vector^ get()
{
return gcnew Vector(fold->normal);
}
}
property IList<ManifoldPoint^ >^ Points
{
IList<ManifoldPoint^ >^ get()
{
//TODO: implement
List<ManifoldPoint^>^ list = gcnew List<ManifoldPoint^>;
for(int x = 0; x < fold->pointCount; ++x)
list->Add(gcnew ManifoldPoint(&fold->points[x]));
return list;
}
}
};
}
}

View File

@@ -0,0 +1,100 @@
#pragma once
#include "stdafx.h"
#include "Vector.cpp"
namespace Box2D
{
namespace Net
{
//TODO: is this class really necessary for the public interface?
public ref class ManifoldPoint
{
internal:
b2ManifoldPoint *point;
ManifoldPoint(b2ManifoldPoint *pointRef) : point(pointRef) { }
public:
property Vector^ LocalPoint1
{
Vector^ get()
{
return gcnew Vector(point->localPoint1);
}
void set(Vector^ value)
{
point->localPoint1 = value->getVec2();
}
}
property Vector^ LocalPoint2
{
Vector^ get()
{
return gcnew Vector(point->localPoint2);
}
void set(Vector^ value)
{
point->localPoint2 = value->getVec2();
}
}
property float32 Separation
{
float32 get()
{
return point->separation;
}
void set(float32 value)
{
point->separation = value;
}
}
property float32 NormalForce
{
float32 get()
{
return point->normalForce;
}
void set(float32 value)
{
point->normalForce = value;
}
}
property float32 TangentForce
{
float32 get()
{
return point->tangentForce;
}
void set(float32 value)
{
point->tangentForce = value;
}
}
//TODO: marshall b2ContactID
/*
property b2ContactID ID
{
b2ContactID get()
{
return point->id;
}
void set(b2ContactID value)
{
point->id = value;
}
}
*/
};
}
}

View File

@@ -0,0 +1,64 @@
#pragma once
#include "stdafx.h"
#include "Vector.cpp"
namespace Box2D
{
namespace Net
{
public ref class MassData
{
internal:
bool DeleteWhenDone;
b2MassData *data;
MassData(b2MassData *dataRef) : data(dataRef), DeleteWhenDone(false) { }
public:
MassData() : data(new b2MassData()), DeleteWhenDone(true) { }
virtual ~MassData()
{
if(DeleteWhenDone)
delete data;
}
property float32 Mass
{
float32 get()
{
return data->mass;
}
void set(float32 value)
{
data->mass = value;
}
}
property float32 I
{
float32 get()
{
return data->I;
}
void set(float32 value)
{
data->I = value;
}
}
property Vector^ Center
{
Vector^ get()
{
return gcnew Vector(data->center);
}
void set(Vector^ value)
{
data->center = value->getVec2();
}
}
};
}
}

View File

@@ -0,0 +1,94 @@
#pragma once
#include "Stdafx.h"
#include "Vector.cpp"
namespace Box2D
{
namespace Net
{
public ref class Matrix
{
internal:
Matrix(const b2Mat22 &matrix) : col1(gcnew Vector(matrix.col1)), col2(gcnew Vector(matrix.col2)) { }
b2Mat22 getMat22()
{
return b2Mat22(col1->getVec2(), col2->getVec2());
}
public:
Vector ^col1, ^col2;
Matrix() : col1(gcnew Vector()), col2(gcnew Vector()) {}
Matrix(Vector^ c1, Vector^ c2) : col1(gcnew Vector(c1)), col2(gcnew Vector(c2)) { }
explicit Matrix(float32 angle)
{
Set(angle);
}
void Set(Vector^ c1, Vector^ c2)
{
col1->X = c1->X;
col1->Y = c1->Y;
col2->X = c2->X;
col2->Y = c2->Y;
}
void Set(float32 angle)
{
float32 c = cosf(angle), s = sinf(angle);
col1->X = c; col2->X = -s;
col1->Y = s; col2->Y = c;
}
void SetIdentity()
{
col1->X = 1; col2->X = 0;
col1->Y = 0; col2->Y = 1;
}
static Vector^ operator * (Matrix^ mat, Vector^ a)
{
return gcnew Vector(b2Mul(mat->getMat22(), a->getVec2()));
}
};
}
}
/*
struct b2Mat22
{
void SetZero()
{
col1.x = 0.0f; col2.x = 0.0f;
col1.y = 0.0f; col2.y = 0.0f;
}
b2Mat22 Invert() const
{
float32 a = col1.x, b = col2.x, c = col1.y, d = col2.y;
b2Mat22 B;
float32 det = a * d - b * c;
b2Assert(det != 0.0f);
det = 1.0f / det;
B.col1.x = det * d; B.col2.x = -det * b;
B.col1.y = -det * c; B.col2.y = det * a;
return B;
}
// Solve A * x = b
b2Vec2 Solve(const b2Vec2& b) const
{
float32 a11 = col1.x, a12 = col2.x, a21 = col1.y, a22 = col2.y;
float32 det = a11 * a22 - a12 * a21;
b2Assert(det != 0.0f);
det = 1.0f / det;
b2Vec2 x;
x.x = det * (a22 * b.x - a12 * b.y);
x.y = det * (a11 * b.y - a21 * b.x);
return x;
}
b2Vec2 col1, col2;
};
*/

View File

@@ -0,0 +1,190 @@
#pragma once
#include "stdafx.h"
#include "Joint.cpp"
#include "JointDef.cpp"
namespace Box2D
{
namespace Net
{
public ref class RevoluteJointDef : public JointDef
{
public:
RevoluteJointDef() : JointDef(new b2RevoluteJointDef()) { }
property Vector^ LocalAnchor1
{
Vector^ get()
{
return gcnew Vector(reinterpret_cast<b2RevoluteJointDef *>(def)->localAnchor1);
}
void set(Vector^ value)
{
reinterpret_cast<b2RevoluteJointDef *>(def)->localAnchor1 = value->getVec2();
}
}
property Vector^ LocalAnchor2
{
Vector^ get()
{
return gcnew Vector(reinterpret_cast<b2RevoluteJointDef *>(def)->localAnchor2);
}
void set(Vector^ value)
{
reinterpret_cast<b2RevoluteJointDef *>(def)->localAnchor2 = value->getVec2();
}
}
property float32 LowerAngle
{
float32 get()
{
return reinterpret_cast<b2RevoluteJointDef *>(def)->lowerAngle;
}
void set(float32 value)
{
reinterpret_cast<b2RevoluteJointDef *>(def)->lowerAngle = value;
}
}
property float32 UpperAngle
{
float32 get()
{
return reinterpret_cast<b2RevoluteJointDef *>(def)->upperAngle;
}
void set(float32 value)
{
reinterpret_cast<b2RevoluteJointDef *>(def)->upperAngle = value;
}
}
property float32 MotorTorque
{
float32 get()
{
return reinterpret_cast<b2RevoluteJointDef *>(def)->maxMotorTorque;
}
void set(float32 value)
{
reinterpret_cast<b2RevoluteJointDef *>(def)->maxMotorTorque = value;
}
}
property float32 MotorSpeed
{
float32 get()
{
return reinterpret_cast<b2RevoluteJointDef *>(def)->motorSpeed;
}
void set(float32 value)
{
reinterpret_cast<b2RevoluteJointDef *>(def)->motorSpeed = value;
}
}
property bool EnableLimit
{
bool get()
{
return reinterpret_cast<b2RevoluteJointDef *>(def)->enableLimit;
}
void set(bool value)
{
reinterpret_cast<b2RevoluteJointDef *>(def)->enableLimit = value;
}
}
property bool EnableMotor
{
bool get()
{
return reinterpret_cast<b2RevoluteJointDef *>(def)->enableMotor;
}
void set(bool value)
{
reinterpret_cast<b2RevoluteJointDef *>(def)->enableMotor = value;
}
}
void Initialize(Body^ body1, Body^ body2, Vector^ Anchor)
{
reinterpret_cast<b2RevoluteJointDef*>(def)->Initialize(body1->body, body2->body, Anchor->getVec2());
}
};
public ref class RevoluteJoint : public Joint
{
internal:
RevoluteJoint(b2RevoluteJoint *jointRef) : Joint(jointRef) { }
public:
property Vector^ Anchor1
{
Vector^ get()
{
return gcnew Vector(reinterpret_cast<b2RevoluteJoint*>(joint)->GetAnchor1());
}
}
property Vector^ Anchor2
{
Vector^ get()
{
return gcnew Vector(reinterpret_cast<b2RevoluteJoint*>(joint)->GetAnchor2());
}
}
Vector^ GetReactionForce()
{
return gcnew Vector(reinterpret_cast<b2RevoluteJoint*>(joint)->GetReactionForce());
}
float32 GetReactionTorque()
{
return (reinterpret_cast<b2RevoluteJoint*>(joint)->GetReactionTorque());
}
property float32 JointAngle
{
float32 get()
{
return (reinterpret_cast<b2RevoluteJoint*>(joint)->GetJointAngle());
}
}
property float32 JointSpeed
{
float32 get()
{
return (reinterpret_cast<b2RevoluteJoint*>(joint)->GetJointSpeed());
}
}
float32 GetMotorTorque()
{
return reinterpret_cast<b2RevoluteJoint*>(joint)->GetMotorTorque();
}
void SetMotorSpeed(float32 speed)
{
reinterpret_cast<b2RevoluteJoint*>(joint)->SetMotorSpeed(speed);
}
void SetMotorTorque(float32 torque)
{
reinterpret_cast<b2RevoluteJoint*>(joint)->SetMaxMotorTorque(torque);
}
};
}
}

View File

@@ -0,0 +1,153 @@
#pragma once
#include "stdafx.h"
#include "Vector.cpp"
#include "Matrix.cpp"
#include "ShapeType.cpp"
#include "XForm.cpp"
using namespace System::Collections::Generic;
namespace Box2D
{
namespace Net
{
ref class Body;
public ref class Shape
{
internal:
b2Shape *shape;
Shape(b2Shape *shapeRef) : shape(shapeRef) { }
public:
bool TestPoint(XForm^ xf, Vector^ p)
{
return shape->TestPoint(xf->getXForm(), p->getVec2());
}
property ShapeType ShapeType
{
Box2D::Net::ShapeType get()
{
return (Box2D::Net::ShapeType)shape->GetType();
}
}
/// <summary>
/// Get the parent body of this shape.
/// </summary>
property Body^ Body
{
Box2D::Net::Body^ get();
}
/*
/// <summary>
/// Get the world position.
/// </summary>
property Vector^ Position
{
Vector^ get()
{
return gcnew Vector(shape->Get->GetPosition());
}
}
*/
/*
property Matrix^ Rotation
{
Matrix^ get()
{
return gcnew Matrix(shape->GetRotationMatrix());
}
}
*/
//TODO:
//void* GetUserData();
//
// Remove and then add proxy from the broad-phase.
// This is used to refresh the collision filters.
//virtual void ResetProxy(b2BroadPhase* broadPhase) = 0;
/// <summary>
/// Get the next shape in the parent body's shape list.
/// </summary>
Shape^ GetNext()
{
return gcnew Shape(shape->GetNext());
}
};
public ref class CircleShape : public Shape
{
internal:
b2CircleShape *circleShape;
CircleShape(b2CircleShape *shapeRef) : Shape(shapeRef), circleShape(shapeRef) { }
public:
CircleShape(Shape^ shape) : Shape(shape->shape), circleShape(0)
{
if(shape->ShapeType == Box2D::Net::ShapeType::e_circleShape &&
reinterpret_cast<b2CircleShape *>(shape->shape))
{
circleShape = reinterpret_cast<b2CircleShape*>(shape->shape);
}
else
{
throw gcnew System::Exception("Attempting to convert a Shape to a CircleShape,"
"but the Shape is not a circle shape.");
}
}
//TODO: this is not technically part of the "public" interface for CircleShape
property float32 Radius
{
float32 get()
{
return circleShape->m_radius;
}
void set(float32 value)
{
circleShape->m_radius = value;
}
}
};
public ref class PolyShape : public Shape
{
internal:
b2PolygonShape *polyShape;
PolyShape(b2PolygonShape *shapeRef) : Shape(shapeRef), polyShape(shapeRef) { }
public:
PolyShape(Shape^ shape) : Shape(shape->shape), polyShape(0)
{
if(shape->ShapeType == Box2D::Net::ShapeType::e_polygonShape &&
reinterpret_cast<b2PolygonShape *>(shape->shape))
{
polyShape = reinterpret_cast<b2PolygonShape*>(shape->shape);
}
else
{
throw gcnew System::Exception("Attempting to convert a Shape to a PolyShape,"
"but the Shape is not a poly shape.");
}
}
property IList<Vector^>^ Vertices
{
IList<Vector^>^ get()
{
List<Vector^>^ list = gcnew List<Vector^>();
for(int x = 0; x < polyShape->m_vertexCount; ++x)
list->Add(gcnew Vector(polyShape->m_vertices[x]));
return list;
}
}
};
}
}

View File

@@ -0,0 +1,125 @@
#pragma once
#include "stdafx.h"
using namespace System::Collections::Generic;
namespace Box2D
{
namespace Net
{
ref class Body;
enum class ShapeType;
ref class Vector;
ref class Matrix;
public ref class Shape
{
internal:
b2Shape *shape;
Shape(b2Shape *shapeRef) : shape(shapeRef) { }
public:
bool TestPoint(Vector^ p);
property ShapeType ShapeType
{
ShapeType get();
}
/// <summary>
/// Get the parent body of this shape.
/// </summary>
property Body^ Body;
/// <summary>
/// Get the world position.
/// </summary>
property Vector^ Position;
property Matrix^ Rotation;
//TODO:
//void* GetUserData();
//
// Remove and then add proxy from the broad-phase.
// This is used to refresh the collision filters.
//virtual void ResetProxy(b2BroadPhase* broadPhase) = 0;
/// <summary>
/// Get the next shape in the parent body's shape list.
/// </summary>
Shape^ GetNext();
};
public ref class CircleShape : public Shape
{
internal:
b2CircleShape *circleShape;
CircleShape(b2CircleShape *shapeRef) : Shape(shapeRef), circleShape(shapeRef) { }
public:
CircleShape(Shape^ shape) : Shape(shape->shape), circleShape(0)
{
if(shape->ShapeType == Box2D::Net::ShapeType::e_circleShape &&
reinterpret_cast<b2CircleShape *>(shape->shape))
{
circleShape = reinterpret_cast<b2CircleShape*>(shape->shape);
}
else
{
throw gcnew System::Exception("Attempting to convert a Shape to a CircleShape,"
"but the Shape is not a circle shape.");
}
}
//TODO: this is not technically part of the "public" interface for CircleShape
property float32 Radius
{
float32 get()
{
return circleShape->m_radius;
}
void set(float32 value)
{
circleShape->m_radius = value;
}
}
};
public ref class PolyShape : public Shape
{
internal:
b2PolyShape *polyShape;
PolyShape(b2PolyShape *shapeRef) : Shape(shapeRef), polyShape(shapeRef) { }
public:
PolyShape(Shape^ shape) : Shape(shape->shape), polyShape(0)
{
if(shape->ShapeType == Box2D::Net::ShapeType::e_polyShape &&
reinterpret_cast<b2PolyShape *>(shape->shape))
{
polyShape = reinterpret_cast<b2PolyShape*>(shape->shape);
}
else
{
throw gcnew System::Exception("Attempting to convert a Shape to a PolyShape,"
"but the Shape is not a poly shape.");
}
}
property IList<Vector^>^ Vertices
{
IList<Vector^>^ get()
{
List<Vector^>^ list = gcnew List<Vector^>();
for(int x = 0; x < polyShape->m_vertexCount; ++x)
list->Add(gcnew Vector(polyShape->m_vertices[x]));
return list;
}
}
};
}
}

View File

@@ -0,0 +1,202 @@
#pragma once
#include "stdafx.h"
#include "MassData.cpp"
#include "ShapeType.cpp"
using namespace System::Collections::Generic;
namespace Box2D
{
namespace Net
{
public ref class ShapeDef
{
internal:
bool DeleteOnDtor;
b2ShapeDef *def;
ShapeDef(b2ShapeDef *defRef) : def(defRef), DeleteOnDtor(false) { }
//Needs to work for derivative types, too
b2ShapeDef GetShapeDef()
{
return *def;
}
public:
virtual ~ShapeDef()
{
if(DeleteOnDtor)
delete def;
}
property ShapeType ShapeType
{
Box2D::Net::ShapeType get()
{
return (Box2D::Net::ShapeType) def->type;
}
void set(Box2D::Net::ShapeType value)
{
def->type = b2ShapeType(value);
}
}
property float32 Friction
{
float32 get()
{
return def->friction;
}
void set(float32 value)
{
def->friction = value;
}
}
property float32 Restitution
{
float32 get()
{
return def->restitution;
}
void set(float32 value)
{
def->restitution = value;
}
}
property float32 Density
{
float32 get()
{
return def->density;
}
void set(float32 value)
{
def->density = value;
}
}
/// <summary>
/// The collision category bits. Normally you would just set one bit.
/// </summary>
property unsigned __int16 CategoryBits
{
unsigned __int16 get()
{
return def->categoryBits;
}
void set(unsigned __int16 value)
{
def->categoryBits = value;
}
}
/// <summary>
/// The collision mask bits. This states the categories that this
/// shape would accept for collision.
/// </summary>
property unsigned __int16 MaskBits
{
unsigned __int16 get()
{
return def->maskBits;
}
void set(unsigned __int16 value)
{
def->maskBits = value;
}
}
/// <summary>
/// Collision groups allow a certain group of objects to never collide (negative)
/// or always collide (positive). Zero means no collision group. Non-zero group
/// filtering always wins against the mask bits.
/// </summary>
property unsigned __int16 GroupIndex
{
unsigned __int16 get()
{
return def->groupIndex;
}
void set(unsigned __int16 value)
{
def->groupIndex = value;
}
}
//TODO:
//void* userData;
};
public ref class CircleDef : public ShapeDef
{
public:
CircleDef() : ShapeDef(new b2CircleDef())
{
ShapeDef::DeleteOnDtor = (true);
}
property float32 Radius
{
float32 get()
{
return reinterpret_cast<b2CircleDef*>(def)->radius;
}
void set(float32 value)
{
reinterpret_cast<b2CircleDef*>(def)->radius = value;
}
}
};
public ref class PolygonDef : public ShapeDef
{
public:
PolygonDef() : ShapeDef(new b2PolygonDef())
{
DeleteOnDtor = (true);
}
void SetAsBox(float X, float Y)
{
reinterpret_cast<b2PolygonDef*>(def)->SetAsBox(X, Y);
}
void SetAsBox(float X, float Y, Vector^ Center, float Angle)
{
reinterpret_cast<b2PolygonDef*>(def)->SetAsBox(X, Y, Center->getVec2(), Angle);
}
property IList<Vector^>^ Verticies
{
IList<Vector^>^ get()
{
List<Vector^>^ list = gcnew List<Vector^>();
for(int x = 0; x < reinterpret_cast<b2PolygonDef*>(def)->vertexCount; ++x)
{
list->Add(gcnew Vector(reinterpret_cast<b2PolygonDef*>(def)->vertices[x]));
}
return list;
}
void set(IList<Vector^>^ value)
{
b2PolygonDef* Def = reinterpret_cast<b2PolygonDef*>(def);
for(int x = 0; x < value->Count; ++x)
Def->vertices[x] = value[x]->getVec2();
}
}
};
}
}

View File

@@ -0,0 +1,18 @@
#pragma once
#include "stdafx.h"
namespace Box2D
{
namespace Net
{
//TODO: is there a way to auto incorporate shape types?
public enum class ShapeType
{
e_unknownShape = ::e_unknownShape,
e_circleShape = ::e_circleShape,
e_polygonShape = ::e_polygonShape,
e_shapeTypeCount = ::e_shapeTypeCount
};
}
}

View File

@@ -0,0 +1,8 @@
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently,
// but are changed infrequently
#pragma once
#include "Box2D.h"

View File

@@ -0,0 +1,16 @@
#pragma once
#include "stdafx.h"
#include "Shape.cpp"
#include "Body.cpp"
namespace Box2D
{
namespace Net
{
Body^ Shape::Body::get()
{
return gcnew Box2D::Net::Body(shape->GetBody());
}
}
}

View File

@@ -0,0 +1,81 @@
#pragma once
#include "Stdafx.h"
namespace Box2D
{
namespace Net
{
public ref class Vector
{
internal:
b2Vec2 getVec2()
{
return b2Vec2(X, Y);
}
public:
//TODO: this needs to be read only outside the class,
//because if you have a vector as a get property, and
//try to set the X,Y components, it won't take to the
//original vector:
//
//ie: Shape.Extents.X += 10;
//won't behave like you think it should (or will it?)
float32 X, Y;
Vector() : X(0), Y(0) { }
Vector(float32 x, float32 y) : X(x), Y(y) { }
Vector(Vector^ other) : X(other->X), Y(other->Y) { }
Vector(const b2Vec2 &other) : X(other.x), Y(other.y) { }
/*
Vector^ Set(float32 x, float32 y)
{
X = x;
Y = y;
return this;
}
*/
///Defines basic vector addition
static Vector^ operator +(Vector^ a, Vector^ b)
{
return gcnew Vector(a->X + b->X, a->Y + b->Y);
}
///<summary>Negates a vector (that is, returns (-X, -Y)</summary>
static Vector^ operator - (Vector^ a)
{
return gcnew Vector(-a->X, -a->Y);
}
///<summary>Defines basic vector subtraction</summary>
static Vector^ operator - (Vector^ a, Vector^ b)
{
return gcnew Vector(a->X - b->X, a->Y - b->Y);
}
///<summary>Scalar multiplication for a vector</summary>
static Vector^ operator * (Vector^ a, float32 b)
{
return gcnew Vector(a->X * b, a->Y * b);
}
/*
static Vector^ operator = (Vector^ a, Vector^ b)
{
a.X = b.X;
a.Y = b.Y;
}
*/
///<summary>Returns a string representation of this vector</summary>
virtual System::String^ ToString() override
{
return gcnew System::String("<" + X + ", " + Y + ">");
}
};
}
}

View File

@@ -0,0 +1,162 @@
#pragma once
#include "Stdafx.h"
#include "AABB.cpp"
#include "Body.cpp"
#include "BodyDef.cpp"
#include "Joint.cpp"
#include "JointDef.cpp"
#include "Contact.cpp"
namespace Box2D
{
namespace Net
{
public ref class World
{
b2World *world;
public:
World(AABB^ worldAABB, Vector^ gravity, bool doSleep) : world(new b2World(
worldAABB->getAABB(), gravity->getVec2(), doSleep)) { }
~World()
{
delete world;
}
/// <summary> Create rigid body from a definition </summary>
Body^ CreateBody(BodyDef^ def)
{
return gcnew Body(world->CreateBody(def->def));
}
///<summary>
/// Destroy rigid bodies. Destruction is deferred until the the next call to Step.
/// This is done so that bodies may be destroyed while you iterate through the contact list.
///</summary>
void DestroyBody(Body^ body)
{
world->DestroyBody(body->body);
}
/// <summary>
/// The world provides a single ground body with no collision shapes. You
/// can use this to simplify the creation of joints.
/// </summary>
Body^ GetGroundBody()
{
return gcnew Body(world->GetGroundBody());
}
void Step(float32 timeStep, int32 iterations)
{
world->Step(timeStep, iterations);
}
Joint^ CreateJoint(JointDef^ def)
{
return gcnew Joint(world->CreateJoint(def->def));
}
void DestroyJoint(Joint^ joint)
{
world->DestroyJoint(joint->joint);
}
property IList<Body^>^ Bodies
{
IList<Body^>^ get()
{
List<Body^>^ list = gcnew List<Body^>();
for(b2Body *body = world->GetBodyList(); body; body = body->GetNext())
list->Add(gcnew Body(body));
return list;
}
}
property IList<Joint^>^ Joints
{
IList<Joint^>^ get()
{
List<Joint^>^ list = gcnew List<Joint^>();
for(b2Joint *joint = world->GetJointList(); joint; joint = joint->GetNext())
list->Add(gcnew Joint(joint));
return list;
}
}
Joint^ GetJointList()
{
return gcnew Joint(world->GetJointList());
}
///<summary> You can use these to iterate over all the bodies, joints, and contacts. </summary>
/*
Contact^ GetContactList()
{
return gcnew Contact(world->C>GetContactList());
}
*/
/// <summary>
/// Query the world for all shapes that potentially overlap the
/// provided AABB. You provide a shape pointer buffer of specified
/// size. The number of shapes found is returned.
/// </summary>
IList<Shape^>^ Query(AABB^ aabb)
{
const int32 k_maxCount = 25;
b2Shape* shapes[k_maxCount];
int32 count = world->Query(aabb->getAABB(), shapes, k_maxCount);
List<Shape^>^ list = gcnew List<Shape^>();
for(int x = 0; x < count; ++x)
list->Add(gcnew Shape(shapes[x]));
return list;
}
static property bool PositionCorrection
{
bool get()
{
return b2World::s_enablePositionCorrection == 1;
}
void set(bool value)
{
b2World::s_enablePositionCorrection = value ? 1 : 0;
}
}
static property bool WarmStarting
{
bool get()
{
return b2World::s_enableWarmStarting == 1;
}
void set(bool value)
{
b2World::s_enableWarmStarting = value ? 1 : 0;
}
}
};
}
}
/*
class b2World
{
public:
// Register a world listener to receive important events that can
// help prevent your code from crashing.
void SetListener(b2WorldListener* listener);
// Register a collision filter to provide specific control over collision.
// Otherwise the default filter is used (b2CollisionFilter).
void SetFilter(b2CollisionFilter* filter);
*/

View File

@@ -0,0 +1,47 @@
#pragma once
#include "stdafx.h"
#include "Vector.cpp"
#include "Matrix.cpp"
namespace Box2D
{
namespace Net
{
public ref class XForm
{
internal:
b2XForm *xform;
bool DeleteOnDtor;
XForm(b2XForm *XForm) : xform(XForm), DeleteOnDtor(false) { }
XForm(b2XForm XForm) : xform(new b2XForm(XForm)), DeleteOnDtor(false) { }
b2XForm getXForm()
{
return *xform;
}
public:
XForm() : xform(new b2XForm()), DeleteOnDtor(true) { }
~XForm()
{
if(DeleteOnDtor)
delete xform;
}
property Vector^ Position
{
Vector^ get()
{
return gcnew Vector(xform->position);
}
}
property Matrix^ Rotation
{
Matrix^ get()
{
return gcnew Matrix(xform->R);
}
}
};
}
}

View File

@@ -0,0 +1,220 @@
namespace TestBed.Net
{
partial class MainWindow
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.panel1 = new System.Windows.Forms.Panel();
this.OpenGLControl = new Tao.Platform.Windows.SimpleOpenGlControl();
this.panel2 = new System.Windows.Forms.Panel();
this.label3 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.numericUpDown2 = new System.Windows.Forms.NumericUpDown();
this.numericUpDown1 = new System.Windows.Forms.NumericUpDown();
this.checkBox2 = new System.Windows.Forms.CheckBox();
this.checkBox1 = new System.Windows.Forms.CheckBox();
this.TestsComboBox = new System.Windows.Forms.ComboBox();
this.label1 = new System.Windows.Forms.Label();
this.RedrawTimer = new System.Windows.Forms.Timer(this.components);
this.panel1.SuspendLayout();
this.panel2.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.numericUpDown2)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit();
this.SuspendLayout();
//
// panel1
//
this.panel1.Controls.Add(this.OpenGLControl);
this.panel1.Location = new System.Drawing.Point(12, 12);
this.panel1.Name = "panel1";
this.panel1.Size = new System.Drawing.Size(372, 242);
this.panel1.TabIndex = 3;
//
// OpenGLControl
//
this.OpenGLControl.AccumBits = ((byte)(0));
this.OpenGLControl.AutoCheckErrors = true;
this.OpenGLControl.AutoFinish = true;
this.OpenGLControl.AutoMakeCurrent = true;
this.OpenGLControl.AutoSwapBuffers = true;
this.OpenGLControl.BackColor = System.Drawing.Color.Black;
this.OpenGLControl.ColorBits = ((byte)(32));
this.OpenGLControl.DepthBits = ((byte)(16));
this.OpenGLControl.Location = new System.Drawing.Point(106, 62);
this.OpenGLControl.Name = "OpenGLControl";
this.OpenGLControl.Size = new System.Drawing.Size(137, 103);
this.OpenGLControl.StencilBits = ((byte)(0));
this.OpenGLControl.TabIndex = 1;
this.OpenGLControl.PreviewKeyDown += new System.Windows.Forms.PreviewKeyDownEventHandler(this.OpenGLControl_PreviewKeyDown);
this.OpenGLControl.MouseDown += new System.Windows.Forms.MouseEventHandler(this.OpenGLControl_MouseDown);
this.OpenGLControl.MouseMove += new System.Windows.Forms.MouseEventHandler(this.OpenGLControl_MouseMove);
this.OpenGLControl.MouseUp += new System.Windows.Forms.MouseEventHandler(this.OpenGLControl_MouseUp);
//
// panel2
//
this.panel2.Controls.Add(this.label3);
this.panel2.Controls.Add(this.label2);
this.panel2.Controls.Add(this.numericUpDown2);
this.panel2.Controls.Add(this.numericUpDown1);
this.panel2.Controls.Add(this.checkBox2);
this.panel2.Controls.Add(this.checkBox1);
this.panel2.Controls.Add(this.TestsComboBox);
this.panel2.Controls.Add(this.label1);
this.panel2.Location = new System.Drawing.Point(390, 12);
this.panel2.Name = "panel2";
this.panel2.Size = new System.Drawing.Size(170, 242);
this.panel2.TabIndex = 4;
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(18, 81);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(32, 13);
this.label3.TabIndex = 10;
this.label3.Text = "Hertz";
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(18, 55);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(50, 13);
this.label2.TabIndex = 9;
this.label2.Text = "Iterations";
//
// numericUpDown2
//
this.numericUpDown2.Location = new System.Drawing.Point(71, 79);
this.numericUpDown2.Name = "numericUpDown2";
this.numericUpDown2.Size = new System.Drawing.Size(71, 20);
this.numericUpDown2.TabIndex = 8;
this.numericUpDown2.Value = new decimal(new int[] {
60,
0,
0,
0});
//
// numericUpDown1
//
this.numericUpDown1.Location = new System.Drawing.Point(71, 53);
this.numericUpDown1.Name = "numericUpDown1";
this.numericUpDown1.Size = new System.Drawing.Size(71, 20);
this.numericUpDown1.TabIndex = 7;
this.numericUpDown1.Value = new decimal(new int[] {
60,
0,
0,
0});
//
// checkBox2
//
this.checkBox2.AutoSize = true;
this.checkBox2.Checked = true;
this.checkBox2.CheckState = System.Windows.Forms.CheckState.Checked;
this.checkBox2.Location = new System.Drawing.Point(21, 128);
this.checkBox2.Name = "checkBox2";
this.checkBox2.Size = new System.Drawing.Size(93, 17);
this.checkBox2.TabIndex = 6;
this.checkBox2.Text = "Warm Starting";
this.checkBox2.UseVisualStyleBackColor = true;
//
// checkBox1
//
this.checkBox1.AutoSize = true;
this.checkBox1.Checked = true;
this.checkBox1.CheckState = System.Windows.Forms.CheckState.Checked;
this.checkBox1.Location = new System.Drawing.Point(21, 105);
this.checkBox1.Name = "checkBox1";
this.checkBox1.Size = new System.Drawing.Size(114, 17);
this.checkBox1.TabIndex = 5;
this.checkBox1.Text = "Position Correction";
this.checkBox1.UseVisualStyleBackColor = true;
//
// TestsComboBox
//
this.TestsComboBox.FormattingEnabled = true;
this.TestsComboBox.Location = new System.Drawing.Point(21, 26);
this.TestsComboBox.Name = "TestsComboBox";
this.TestsComboBox.Size = new System.Drawing.Size(121, 21);
this.TestsComboBox.TabIndex = 3;
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(67, 10);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(33, 13);
this.label1.TabIndex = 4;
this.label1.Text = "Tests";
//
// RedrawTimer
//
this.RedrawTimer.Enabled = true;
this.RedrawTimer.Interval = 30;
this.RedrawTimer.Tag = "";
this.RedrawTimer.Tick += new System.EventHandler(this.RedrawTimer_Tick);
//
// MainWindow
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(572, 457);
this.Controls.Add(this.panel2);
this.Controls.Add(this.panel1);
this.Name = "MainWindow";
this.Text = "MainWindow";
this.Resize += new System.EventHandler(this.MainWindow_Resize);
this.Load += new System.EventHandler(this.MainWindow_Load);
this.panel1.ResumeLayout(false);
this.panel2.ResumeLayout(false);
this.panel2.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.numericUpDown2)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Panel panel1;
private Tao.Platform.Windows.SimpleOpenGlControl OpenGLControl;
private System.Windows.Forms.Panel panel2;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.ComboBox TestsComboBox;
private System.Windows.Forms.Timer RedrawTimer;
private System.Windows.Forms.CheckBox checkBox2;
private System.Windows.Forms.CheckBox checkBox1;
private System.Windows.Forms.NumericUpDown numericUpDown2;
private System.Windows.Forms.NumericUpDown numericUpDown1;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Label label2;
}
}

View File

@@ -0,0 +1,132 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Tao.OpenGl;
using Box2D.Net;
using System.Reflection;
namespace TestBed.Net
{
public partial class MainWindow : Form
{
private Settings Settings = new Settings();
private Test mCurrentTest;
public Test CurrentTest
{
get
{
return mCurrentTest;
}
set
{
//Call code to reset current test
mCurrentTest = value;
}
}
public MainWindow()
{
InitializeComponent();
//Find all Tests in this module
foreach (Type type in Assembly.GetExecutingAssembly().GetExportedTypes())
{
Test test = new Test();
if (type.IsSubclassOf(test.GetType()))
{
TestsComboBox.Items.Add(System.Activator.CreateInstance(type));
}
}
TestsComboBox.SelectedIndex = 0;
CurrentTest = (Test)System.Activator.CreateInstance(TestsComboBox.SelectedItem.GetType());
OpenGLControl.Dock = DockStyle.Fill;
}
private void MainWindow_Load(object sender, EventArgs e)
{
OpenGLControl.InitializeContexts();
panel1.Dock = DockStyle.Fill;
panel2.Dock = DockStyle.Right;
MainWindow_Resize(null, null);
RedrawTimer.Interval = (int)(1000.0f / (float)Settings.Hz);
RedrawTimer.Start();
}
private void MainWindow_Resize(object sender, EventArgs e)
{
Size size = new Size(OpenGLControl.Size.Width - panel2.Width, OpenGLControl.Size.Height);
Renderer.InitOpenGL(size, CurrentTest.Zoom, CurrentTest.ViewOffset);
Renderer.OpenGLDraw(CurrentTest);
}
private void OpenGLControl_Paint(object sender, PaintEventArgs e)
{
Renderer.OpenGLDraw(CurrentTest);
}
private Vector RelativeCoordinates(Point MousePoint)
{
float Height = (float)OpenGLControl.Size.Height;
float Width = (float)(OpenGLControl.Size.Width - panel2.Width);
if(Height <= 0)
Height = 1;
float AspectRatio = Width / Height;
Vector relative = new Vector(
(float)MousePoint.X / Width,
(float)MousePoint.Y / Height);
relative -= new Vector(.5f, .5f);
relative *= 2;
relative.Y *= -1;
relative.X *= AspectRatio;
return relative;
}
private void OpenGLControl_MouseMove(object sender, MouseEventArgs e)
{
CurrentTest.MouseMove(RelativeCoordinates(e.Location));
}
private void OpenGLControl_MouseUp(object sender, MouseEventArgs e)
{
CurrentTest.MouseUp(RelativeCoordinates(e.Location));
}
private void OpenGLControl_MouseDown(object sender, MouseEventArgs e)
{
CurrentTest.MouseDown(RelativeCoordinates(e.Location));
}
private void RedrawTimer_Tick(object sender, EventArgs e)
{
CurrentTest.Step(Settings);
Renderer.OpenGLDraw(CurrentTest);
OpenGLControl.Draw();
int errorCode = 0;
if ((errorCode = Gl.glGetError()) > 0)
{
RedrawTimer.Stop();
//Handled by the OpenGLControl
//MessageBox.Show(Glu.gluErrorString(errorCode));
}
}
private void OpenGLControl_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
if(e.KeyCode == Keys.R)
CurrentTest = (Test)System.Activator.CreateInstance(CurrentTest.GetType());
else
CurrentTest.KeyPress(e.KeyCode);
}
}
}

View File

@@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="RedrawTimer.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root>

View File

@@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Text;
using Box2D.Net;
using System.Windows.Forms;
namespace TestBed.Net
{
class Program
{
static void Main(string[] args)
{
Console.Title = "Box2D.Net Test Bed";
Application.EnableVisualStyles();
MainWindow win = new MainWindow();
Console.Write("Loading the OpenGL display window. Please be patient... ");
//Show above the console
win.Show();
win.BringToFront(); //Doesn't bring above the console?
win.TopMost = true; //Hacky fix instead:
win.TopMost = false;
Console.WriteLine("DONE");
Application.Run(win);
}
}
}

View File

@@ -0,0 +1,33 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("TestBed.Net")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("TestBed.Net")]
[assembly: AssemblyCopyright("Copyright © 2008")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("c08bf3be-733a-49ed-820b-ad4f13ff3a00")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -0,0 +1,176 @@
using System;
using System.Collections.Generic;
using System.Text;
using Tao.OpenGl;
using Box2D.Net;
using System.Windows.Forms;
namespace TestBed.Net
{
static class Renderer
{
public static void InitOpenGL(System.Drawing.Size WidthHeight, float viewZoom, Vector ViewOffset)
{
int Width = WidthHeight.Width;
int Height = WidthHeight.Height;
Height = Height > 0 ? Height : 1;
Gl.glDisable(Gl.GL_CULL_FACE);
Gl.glClearColor(.5f, .5f, .5f, 1);
float AspectRatio = (float)Width / (float)Height;
Gl.glViewport(0, 0, Width, Height);
Gl.glMatrixMode(Gl.GL_PROJECTION);
Gl.glLoadIdentity();
Glu.gluOrtho2D(-AspectRatio, AspectRatio, -1, 1);
Gl.glMatrixMode(Gl.GL_MODELVIEW);
}
public static void OpenGLDraw(Test test)
{
Gl.glClear(Gl.GL_COLOR_BUFFER_BIT);
Gl.glMatrixMode(Gl.GL_MODELVIEW);
Gl.glLoadIdentity();
Gl.glScalef(1.0f / test.Zoom, 1.0f / test.Zoom, 1.0f / test.Zoom);
Gl.glTranslatef(-test.ViewOffset.X, -test.ViewOffset.Y, 0);
Gl.glPushMatrix();
DrawBodies(test.world.Bodies);
DrawJoints(test.world.Joints);
Gl.glPopMatrix();
}
public static void DrawJoints(IList<Joint> joints)
{
foreach (Joint joint in joints)
{
DrawJoint(joint, System.Drawing.Color.LawnGreen);
}
}
public static void DrawBodies(IList<Body> bodies)
{
foreach(Body body in bodies)
foreach (Shape shape in body.Shapes)
{
System.Drawing.Color color = System.Drawing.Color.White;
if (body.Static)
color = System.Drawing.Color.LightGreen; //Color(0.5f, 0.9f, 0.5f)
else if (body.Sleeping)
color = System.Drawing.Color.LightBlue;
//else if(body == bomb)
DrawShape(body.GetXForm(), shape, System.Drawing.Color.White);
}
}
public static void DrawShape(XForm xform, Shape shape, System.Drawing.Color c)
{
switch (shape.ShapeType)
{
case ShapeType.e_circleShape:
{
Vector x = xform.Position;
float r = (new CircleShape(shape)).Radius;
float segments = 16;
double increment = 2 * Math.PI / segments;
Gl.glColor3ub(c.R, c.G, c.B);
Gl.glBegin(Gl.GL_LINE_LOOP);
for (double i = 0, theta = 0; i < segments; ++i, theta += increment)
{
Vector d = new Vector(r * (float)Math.Cos(theta), r * (float)Math.Sin(theta));
Vector v = x + d;
Gl.glVertex2f(v.X, v.Y);
}
Gl.glEnd();
//Draw a line from the circle's center to it's right side
//so we can visually inspect rotations.
Gl.glBegin(Gl.GL_LINES);
Gl.glVertex2f(x.X, x.Y);
Vector ax = xform.Rotation.col1;
Gl.glVertex2f(x.X + r * ax.X, x.Y + r * ax.Y);
Gl.glEnd();
}
break;
case ShapeType.e_polygonShape:
{
Gl.glColor3ub(c.R, c.G, c.B);
Gl.glBegin(Gl.GL_LINE_LOOP);
foreach (Vector vertex in (new PolyShape(shape)).Vertices)
{
Vector vertprime = xform.Rotation * vertex + xform.Position;
Gl.glVertex2f(vertprime.X, vertprime.Y);
}
Gl.glEnd();
}
break;
}
}
public static void DrawAABB(AABB aabb, System.Drawing.Color c)
{
Gl.glColor3b(c.R, c.G, c.B);
Gl.glBegin(Gl.GL_LINE_LOOP);
Gl.glVertex2f(aabb.lowerBound.X, aabb.lowerBound.Y);
Gl.glVertex2f(aabb.upperBound.X, aabb.lowerBound.Y);
Gl.glVertex2f(aabb.upperBound.X, aabb.upperBound.Y);
Gl.glVertex2f(aabb.lowerBound.X, aabb.upperBound.Y);
Gl.glEnd();
}
public static void DrawJoint(Joint joint, System.Drawing.Color color)
{
Body b1 = joint.Body1;
Body b2 = joint.Body2;
Vector x1 = b1.GetXForm().Position;
Vector x2 = b2.GetXForm().Position;
Vector p1 = joint.Anchor2;
Vector p2 = joint.Anchor1;
Gl.glColor3ub(color.R, color.G, color.B);
Gl.glBegin(Gl.GL_LINES);
switch (joint.JointType)
{
case JointType.e_mouseJoint:
case JointType.e_distanceJoint:
Gl.glVertex2f(p1.X, p1.Y);
Gl.glVertex2f(p2.X, p2.Y);
break;
/*
* case JointType.e_pulleyJoint:
{
b2PulleyJoint* pulley = (b2PulleyJoint*)joint;
b2Vec2 s1 = pulley->GetGroundPoint1();
b2Vec2 s2 = pulley->GetGroundPoint2();
glVertex2f(s1.x, s1.y);
glVertex2f(p1.x, p1.y);
glVertex2f(s2.x, s2.y);
glVertex2f(p2.x, p2.y);
}
break;
*/
default:
Gl.glVertex2f(x1.X, x1.Y);
Gl.glVertex2f(p1.X, p1.Y);
Gl.glVertex2f(x2.X, x2.Y);
Gl.glVertex2f(p2.X, p2.Y);
break;
}
Gl.glEnd();
}
}
}

View File

@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace TestBed.Net
{
public class Settings
{
public float Hz = 60;
public int IterationCount = 10;
public bool DrawStats = false;
public bool DrawContacts = false;
public bool DrawImpulses = false;
public bool DrawAABBs = false;
public bool DrawPairs = false;
public bool WarmStarting = true;
public bool PositionCorrection = true;
public bool Pause = false;
}
}

View File

@@ -0,0 +1,179 @@
using System;
using System.Collections.Generic;
using System.Text;
using Box2D.Net;
using Tao.OpenGl;
namespace TestBed.Net
{
public class Test
{
public World world;
public MouseJoint mouseJoint;
public Body bomb;
public float Zoom = 20;
public Vector ViewOffset = new Vector();
public Vector Mouse = null;
public Test()
{
AABB worldAABB = new AABB(new Vector(-100.0f, -100.0f), new Vector(100.0f, 200.0f));
Vector gravity = new Vector(0, -10);
bool doSleep = true;
world = new World(worldAABB, gravity, doSleep);
//m_textLine = 30;
//
//m_listener.test = this;
//m_world->SetListener(&m_listener);
}
public void Step(Settings settings)
{
if(settings.Pause)
return;
float timeStep = settings.Hz > 0 ? 1.0f / settings.Hz : 0;
World.WarmStarting = settings.WarmStarting;
World.PositionCorrection = settings.PositionCorrection;
world.Step(timeStep, settings.IterationCount);
//m_world->m_broadPhase->Validate();
}
Vector RelativeToWorld(Vector Relative)
{
Vector working = Relative;
working *= Zoom;
working -= ViewOffset;
return working;
}
/// <summary>
/// Handles what happens when a user clicks the mouse
/// </summary>
/// <param name="p">
/// The position of the mouse click in relative coordinates.
/// </param>
public void MouseDown(Vector point)
{
Vector p = RelativeToWorld(point);
if (mouseJoint != null)
throw new Exception("ASSERT: mouseJoint should be null");
// Make a small box.
Vector d = new Vector(.001f, .001f);
AABB aabb = new AABB(p - d, p + d);
// Query the world for overlapping shapes.
IList<Shape> shapes = world.Query(aabb);
Body body = null;
foreach (Shape shape in shapes)
{
if (shape.Body.Static == false &&
shape.TestPoint(shape.Body.GetXForm(), p))
{
body = shape.Body;
break;
}
}
if (body != null)
{
MouseJointDef md = new MouseJointDef();
md.Body1 = world.GetGroundBody();
md.Body2 = body;
md.Target = p;
md.MaxForce = 1000 * body.Mass;
mouseJoint = new MouseJoint(world.CreateJoint(md));
body.WakeUp();
}
}
public void MouseUp(Vector point)
{
Vector p = RelativeToWorld(point);
if (mouseJoint != null)
{
world.DestroyJoint(mouseJoint);
mouseJoint = null;
}
}
public void MouseMove(Vector point)
{
Vector p = RelativeToWorld(point);
if (mouseJoint != null)
mouseJoint.SetTarget(p);
}
public void KeyPress(System.Windows.Forms.Keys key)
{
switch (key)
{
case System.Windows.Forms.Keys.Space:
LaunchBomb();
break;
case System.Windows.Forms.Keys.Left:
ViewOffset.X -= 1;
break;
case System.Windows.Forms.Keys.Right:
ViewOffset.X += 1;
break;
case System.Windows.Forms.Keys.Up:
ViewOffset.Y += 1;
break;
case System.Windows.Forms.Keys.Down:
ViewOffset.Y -= 1;
break;
case System.Windows.Forms.Keys.X:
Zoom -= 1;
break;
case System.Windows.Forms.Keys.Z:
Zoom += 1;
break;
}
}
void LaunchBomb()
{
if (bomb != null)
{
world.DestroyBody(bomb);
bomb = null;
}
BodyDef bd = new BodyDef();
bd.BodyType = BodyType.e_dynamicBody;
bd.AllowSleep = true;
Random rand = new Random();
bd.Position = new Vector((float)rand.NextDouble() * 30 - 15, 30.0f);
bd.IsBullet = true;
bomb = world.CreateBody(bd);
bomb.LinearVelocity = bd.Position * -5;
CircleDef sd = new CircleDef();
sd.Radius = 0.3f;
sd.Density = 20.0f;
sd.Restitution = 0.1f;
bomb.CreateShape(sd);
bomb.SetMassFromShapes();
}
public override string ToString()
{
return GetType().Name;
}
};
}

View File

@@ -0,0 +1,74 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.50727</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{B2F62680-048C-46AA-B1B2-7731252E1304}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>TestBed.Net</RootNamespace>
<AssemblyName>TestBed.Net</AssemblyName>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
<Reference Include="Tao.FreeGlut, Version=2.4.0.1, Culture=neutral, PublicKeyToken=6e602a6ad6c0d06d, processorArchitecture=MSIL" />
<Reference Include="Tao.OpenGl, Version=2.1.0.4, Culture=neutral, PublicKeyToken=1ca010269a4501ef, processorArchitecture=MSIL" />
<Reference Include="Tao.Platform.Windows, Version=1.0.0.4, Culture=neutral, PublicKeyToken=701104b2da67a104, processorArchitecture=MSIL" />
</ItemGroup>
<ItemGroup>
<Compile Include="MainWindow.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="MainWindow.Designer.cs">
<DependentUpon>MainWindow.cs</DependentUpon>
</Compile>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Renderer.cs" />
<Compile Include="Settings.cs" />
<Compile Include="Test.cs" />
<Compile Include="Tests\Bridge.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Box2D.Net.vcproj">
<Project>{0E95DBB9-EA97-407B-811C-810B225E79D2}</Project>
<Name>Box2D.Net</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="MainWindow.resx">
<SubType>Designer</SubType>
<DependentUpon>MainWindow.cs</DependentUpon>
</EmbeddedResource>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -0,0 +1,59 @@
using System;
using System.Collections.Generic;
using System.Text;
using Box2D.Net;
namespace TestBed.Net.Tests
{
public class Bridge : TestBed.Net.Test
{
public Bridge()
{
Body ground;
{
PolygonDef sd = new PolygonDef();
sd.ShapeType = ShapeType.e_polygonShape;
sd.SetAsBox(50.0f, 10.0f);
BodyDef bd = new BodyDef();
bd.Position = new Vector(0, -10);
ground = world.CreateBody(bd);
ground.CreateShape(sd);
}
{
PolygonDef sd = new PolygonDef();
sd.SetAsBox(0.5f, 0.125f);
sd.Density = 20.0f;
sd.Friction = 0.2f;
BodyDef bd = new BodyDef();
bd.BodyType = BodyType.e_dynamicBody;
RevoluteJointDef jd = new RevoluteJointDef();
const float numPlanks = 30;
Body prevBody = ground;
for (float i = 0; i < numPlanks; ++i)
{
bd.Position = new Vector(-14.5f + i, 5);
Body body = world.CreateBody(bd);
body.CreateShape(sd);
body.SetMassFromShapes();
Vector anchor = new Vector(-15 + i, 5);
jd.Initialize(prevBody, body, anchor);
world.CreateJoint(jd);
prevBody = body;
}
Vector anchor2 = new Vector(-15 + numPlanks, 5);
jd.Initialize(prevBody, ground, anchor2);
world.CreateJoint(jd);
}
}
}
}

View File

@@ -0,0 +1,36 @@
cmake_minimum_required(VERSION 2.6)
set(BOX2D_VERSION 2.1.0)
set(BOX2D_BUILD_STATIC true)
set(BOX2D_DIR ../../../Box2D)
subdirs(${BOX2D_DIR}/Box2D)
project(iPhoneTestbed)
include_directories(${BOX2D_DIR} ${BOX2D_DIR}/Testbed/Tests)
file(GLOB iPhoneTestbed_Classes_SRCS Classes/*.mm)
source_group(Classes FILES ${iPhoneTestbed_Classes_SRCS})
set(CMAKE_OSX_SYSROOT iphoneos)
set(CMAKE_OSX_DEPLOYMENT_TARGET "")
set(CMAKE_OSX_ARCHITECTURES $(ARCHS_STANDARD_32_BIT))
set(CMAKE_EXE_LINKER_FLAGS "-framework Foundation -framework CoreGraphics -framework QuartzCore -framework OpenGLES -framework UIKit")
set(MACOSX_BUNDLE_PRODUCT_NAME \${PRODUCT_NAME})
set(MACOSX_BUNDLE_GUI_IDENTIFIER "com.mycompany.\${PRODUCT_NAME:identifier}")
add_executable(iPhoneTestbed MACOSX_BUNDLE
${iPhoneTestbed_Classes_SRCS}
main.m
)
target_link_libraries(iPhoneTestbed Box2D)
set_target_properties(iPhoneTestbed PROPERTIES MACOSX_BUNDLE_INFO_PLIST Info.plist.in XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "iPhone Developer")
set(APP_NAME \${TARGET_BUILD_DIR}/\${FULL_PRODUCT_NAME})
find_program(IBTOOL ibtool HINTS "/usr/bin" "${OSX_DEVELOPER_ROOT}/usr/bin")
set(NIB MainWindow)
add_custom_command(TARGET iPhoneTestbed POST_BUILD
COMMAND /Developer/Library/PrivateFrameworks/DevToolsCore.framework/Resources/pbxcp -exclude .DS_Store -exclude CVS -exclude .svn -resolve-src-symlinks Resources/* ${APP_NAME}
COMMAND ${IBTOOL} --errors --warnings --notices --output-format human-readable-text --compile ${iPhoneTestbed_BINARY_DIR}/\${CONFIGURATION}/${PROJECT_NAME}.app/${NIB}.nib ${NIB}.xib
)

View File

@@ -0,0 +1,24 @@
//
// Box2DAppDelegate.h
// Box2D
//
// Box2D iPhone port by Simon Oliver - http://www.simonoliver.com - http://www.handcircus.com
//
#import <UIKit/UIKit.h>
#import "TestEntriesViewController.h"
#import "Delegates.h"
@class Box2DView;
@interface Box2DAppDelegate : NSObject <UIApplicationDelegate,TestSelectDelegate> {
UIWindow *window;
Box2DView *glView;
TestEntriesViewController *testEntriesView;
}
@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet Box2DView *glView;
@end

View File

@@ -0,0 +1,62 @@
//
// Box2DAppDelegate.m
// Box2D
//
// Box2D iPhone port by Simon Oliver - http://www.simonoliver.com - http://www.handcircus.com
//
#import <UIKit/UIKit.h>
#import "Box2DAppDelegate.h"
#import "Box2DView.h"
@implementation Box2DAppDelegate
@synthesize window;
@synthesize glView;
- (void)applicationDidFinishLaunching:(UIApplication *)application {
[application setStatusBarHidden:true];
[glView removeFromSuperview];
glView.animationInterval = 1.0 / 60.0;
testEntriesView=[[TestEntriesViewController alloc] initWithStyle:UITableViewStylePlain];
[testEntriesView setDelegate:self];
[glView setDelegate:self];
[window addSubview:[testEntriesView view]];
}
-(void) selectTest:(int) testIndex
{
[[testEntriesView view] removeFromSuperview];
[window addSubview:glView];
[glView startAnimation];
[glView selectTestEntry:testIndex];
}
-(void) leaveTest
{
[glView stopAnimation];
[glView removeFromSuperview];
[window addSubview:[testEntriesView view]];
}
- (void)applicationWillResignActive:(UIApplication *)application {
glView.animationInterval = 1.0 / 5.0;
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
glView.animationInterval = 1.0 / 60.0;
}
- (void)dealloc {
[window release];
[glView release];
[super dealloc];
}
@end

View File

@@ -0,0 +1,63 @@
//
// Box2DView.h
// Box2D OpenGL View
//
// Box2D iPhone port by Simon Oliver - http://www.simonoliver.com - http://www.handcircus.com
//
#import <UIKit/UIKit.h>
#import <OpenGLES/EAGL.h>
#import <OpenGLES/ES1/gl.h>
#import <OpenGLES/ES1/glext.h>
#import "iPhoneTest.h"
#import "Delegates.h"
/*
This class wraps the CAEAGLLayer from CoreAnimation into a convenient UIView subclass.
The view content is basically an EAGL surface you render your OpenGL scene into.
Note that setting the view non-opaque will only work if the EAGL surface has an alpha channel.
*/
@interface Box2DView : UIView <UIAccelerometerDelegate> {
@private
/* The pixel dimensions of the backbuffer */
GLint backingWidth;
GLint backingHeight;
EAGLContext *context;
/* OpenGL names for the renderbuffer and framebuffers used to render to this view */
GLuint viewRenderbuffer, viewFramebuffer;
/* OpenGL name for the depth buffer that is attached to viewFramebuffer, if it exists (0 if it does not exist) */
GLuint depthRenderbuffer;
NSTimer *animationTimer;
NSTimeInterval animationInterval;
TestEntry* entry;
Test* test;
// Position offset and scale
float sceneScale;
CGPoint positionOffset;
CGPoint lastWorldTouch;
CGPoint lastScreenTouch;
bool panning;
int doubleClickValidCountdown;
id<TestSelectDelegate> _delegate;
}
@property(assign) id<TestSelectDelegate> delegate;
@property NSTimeInterval animationInterval;
- (void)startAnimation;
- (void)stopAnimation;
- (void)drawView;
-(void) selectTestEntry:(int) testIndex;
@end

View File

@@ -0,0 +1,299 @@
//
// Box2DView.mm
// Box2D OpenGL View
//
// Box2D iPhone port by Simon Oliver - http://www.simonoliver.com - http://www.handcircus.com
//
#import <QuartzCore/QuartzCore.h>
#import <OpenGLES/EAGLDrawable.h>
#import "Box2DView.h"
#define USE_DEPTH_BUFFER 0
#define kAccelerometerFrequency 30
#define FRAMES_BETWEEN_PRESSES_FOR_DOUBLE_CLICK 10
Settings settings;
// A class extension to declare private methods
@interface Box2DView ()
@property (nonatomic, retain) EAGLContext *context;
@property (nonatomic, assign) NSTimer *animationTimer;
- (BOOL) createFramebuffer;
- (void) destroyFramebuffer;
@end
@implementation Box2DView
@synthesize context;
@synthesize animationTimer;
@synthesize animationInterval;
@synthesize delegate=_delegate;
// You must implement this method
+ (Class)layerClass {
return [CAEAGLLayer class];
}
//The GL view is stored in the nib file. When it's unarchived it's sent -initWithCoder:
- (id)initWithCoder:(NSCoder*)coder {
if ((self = [super initWithCoder:coder])) {
// Get the layer
CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
eaglLayer.opaque = YES;
eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:NO], kEAGLDrawablePropertyRetainedBacking, kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil];
context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
if (!context || ![EAGLContext setCurrentContext:context]) {
[self release];
return nil;
}
animationInterval = 1.0 / 60.0;
sceneScale=10.0f;
positionOffset=CGPointMake(0, 0);
lastWorldTouch=CGPointMake(0, 0);
[[UIAccelerometer sharedAccelerometer] setUpdateInterval:(1.0 / kAccelerometerFrequency)];
[[UIAccelerometer sharedAccelerometer] setDelegate:self];
//[self setMultipleTouchEnabled:YES];
}
return self;
}
-(void) selectTestEntry:(int) testIndex
{
// Destroy existing scene
delete test;
entry = g_testEntries + testIndex;
test = entry->createFcn();
doubleClickValidCountdown=0;
sceneScale=10.0f;
positionOffset=CGPointMake(0, 0);
lastWorldTouch=CGPointMake(0, 0);
}
- (void)drawView {
if (doubleClickValidCountdown>0) doubleClickValidCountdown--;
[EAGLContext setCurrentContext:context];
glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
glViewport(0, 0, backingWidth, backingHeight);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrthof(-sceneScale, sceneScale, -sceneScale*1.5f, sceneScale*1.5f, -1.0f, 1.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(positionOffset.x, positionOffset.y,0);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnableClientState(GL_VERTEX_ARRAY);
test->Step(&settings);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
[context presentRenderbuffer:GL_RENDERBUFFER_OES];
}
- (void)layoutSubviews {
[EAGLContext setCurrentContext:context];
[self destroyFramebuffer];
[self createFramebuffer];
[self drawView];
}
- (BOOL)createFramebuffer {
glGenFramebuffersOES(1, &viewFramebuffer);
glGenRenderbuffersOES(1, &viewRenderbuffer);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);
[context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(CAEAGLLayer*)self.layer];
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, viewRenderbuffer);
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);
if (USE_DEPTH_BUFFER) {
glGenRenderbuffersOES(1, &depthRenderbuffer);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES, backingWidth, backingHeight);
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);
}
if(glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) {
NSLog(@"failed to make complete framebuffer object %x", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES));
return NO;
}
return YES;
}
- (void)destroyFramebuffer {
glDeleteFramebuffersOES(1, &viewFramebuffer);
viewFramebuffer = 0;
glDeleteRenderbuffersOES(1, &viewRenderbuffer);
viewRenderbuffer = 0;
if(depthRenderbuffer) {
glDeleteRenderbuffersOES(1, &depthRenderbuffer);
depthRenderbuffer = 0;
}
}
- (void)startAnimation {
self.animationTimer = [NSTimer scheduledTimerWithTimeInterval:animationInterval target:self selector:@selector(drawView) userInfo:nil repeats:YES];
}
- (void)stopAnimation {
self.animationTimer = nil;
}
- (void)setAnimationTimer:(NSTimer *)newTimer {
[animationTimer invalidate];
animationTimer = newTimer;
}
- (void)setAnimationInterval:(NSTimeInterval)interval {
animationInterval = interval;
if (animationTimer) {
[self stopAnimation];
[self startAnimation];
}
}
- (void)dealloc {
[self stopAnimation];
if ([EAGLContext currentContext] == context) {
[EAGLContext setCurrentContext:nil];
}
[context release];
[super dealloc];
}
-(CGPoint) screenSpaceToWorldSpace:(CGPoint) screenLocation
{
screenLocation.x-=160;
screenLocation.y-=240;
screenLocation.x/=160;
screenLocation.y/=160;
screenLocation.x*=sceneScale;
screenLocation.y*=-sceneScale;
screenLocation.x-=positionOffset.x;
screenLocation.y-=positionOffset.y;
return screenLocation;
}
- (void) touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event
{
if (doubleClickValidCountdown>0)
{
[_delegate leaveTest];
return;
}
doubleClickValidCountdown=FRAMES_BETWEEN_PRESSES_FOR_DOUBLE_CLICK;
panning=false;
for (UITouch *touch in touches)
{
CGPoint touchLocation=[touch locationInView:self];
CGPoint worldPosition=[self screenSpaceToWorldSpace:touchLocation];
//printf("Screen touched %f,%f -> %f,%f\n",touchLocation.x,touchLocation.y,worldPosition.x,worldPosition.y);
lastScreenTouch=touchLocation;
lastWorldTouch=worldPosition;
b2Vec2 p = b2Vec2(lastWorldTouch.x,lastWorldTouch.y);
test->MouseDown(p);
//test->ShiftMouseDown(p);
if (!test->m_mouseJoint) panning=true;
}
}
- (void) touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
{
for (UITouch *touch in touches)
{
CGPoint touchLocation=[touch locationInView:self];
CGPoint worldPosition=[self screenSpaceToWorldSpace:touchLocation];
//printf("Screen touched %f,%f -> %f,%f\n",touchLocation.x,touchLocation.y,worldPosition.x,worldPosition.y);
CGPoint screenDistanceMoved=CGPointMake(touchLocation.x-lastScreenTouch.x,touchLocation.y-lastScreenTouch.y);
if (panning)
{
screenDistanceMoved.x/=160;
screenDistanceMoved.y/=160;
screenDistanceMoved.x*=sceneScale;
screenDistanceMoved.y*=-sceneScale;
positionOffset.x+=screenDistanceMoved.x;
positionOffset.y+=screenDistanceMoved.y;
}
lastScreenTouch=touchLocation;
lastWorldTouch=worldPosition;
test->MouseMove(b2Vec2(lastWorldTouch.x,lastWorldTouch.y));
}
}
- (void) touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event
{
test->MouseUp(b2Vec2(lastWorldTouch.x,lastWorldTouch.y));
}
- (void) accelerometer:(UIAccelerometer*)accelerometer didAccelerate:(UIAcceleration*)acceleration
{
// Only run for valid values
if (acceleration.y!=0 && acceleration.x!=0)
{
if (test) test->SetGravity(acceleration.x,acceleration.y);
}
}
@end

View File

@@ -0,0 +1,14 @@
/*
* Delegates.h
* Box2D
*
* Box2D iPhone port by Simon Oliver - http://www.simonoliver.com - http://www.handcircus.com
*
*
*/
@protocol TestSelectDelegate <NSObject>
-(void) selectTest:(int) testIndex;
-(void) leaveTest;
@end

View File

@@ -0,0 +1,58 @@
/*
* Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
*
* iPhone port by Simon Oliver - http://www.simonoliver.com - http://www.handcircus.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 RENDER_H
#define RENDER_H
#import <UIKit/UIKit.h>
#import <OpenGLES/EAGL.h>
#import <OpenGLES/ES1/gl.h>
#import <OpenGLES/ES1/glext.h>
#include <Box2D/Box2D.h>
struct b2AABB;
// This class implements debug drawing callbacks that are invoked
// inside b2World::Step.
class GLESDebugDraw : public b2Draw
{
public:
void DrawPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color);
void DrawSolidPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color);
void DrawCircle(const b2Vec2& center, float32 radius, const b2Color& color);
void DrawSolidCircle(const b2Vec2& center, float32 radius, const b2Vec2& axis, const b2Color& color);
void DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color);
void DrawTransform(const b2Transform& xf);
void DrawPoint(const b2Vec2& p, float32 size, const b2Color& color);
void DrawString(int x, int y, const char* string, ...);
void DrawAABB(b2AABB* aabb, const b2Color& color);
};
#endif

View File

@@ -0,0 +1,149 @@
/*
* Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
*
* iPhone port by Simon Oliver - http://www.simonoliver.com - http://www.handcircus.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 "GLES-Render.h"
#include <cstdio>
#include <cstdarg>
#include <cstring>
void GLESDebugDraw::DrawPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color)
{
glColor4f(color.r, color.g, color.b,1);
glVertexPointer(2, GL_FLOAT, 0, vertices);
glDrawArrays(GL_LINE_LOOP, 0, vertexCount);
}
void GLESDebugDraw::DrawSolidPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color)
{
glVertexPointer(2, GL_FLOAT, 0, vertices);
glColor4f(color.r, color.g, color.b,0.5f);
glDrawArrays(GL_TRIANGLE_FAN, 0, vertexCount);
glColor4f(color.r, color.g, color.b,1);
glDrawArrays(GL_LINE_LOOP, 0, vertexCount);
}
void GLESDebugDraw::DrawCircle(const b2Vec2& center, float32 radius, const b2Color& color)
{
const float32 k_segments = 16.0f;
int vertexCount=16;
const float32 k_increment = 2.0f * b2_pi / k_segments;
float32 theta = 0.0f;
GLfloat glVertices[vertexCount*2];
for (int32 i = 0; i < k_segments; ++i)
{
b2Vec2 v = center + radius * b2Vec2(cosf(theta), sinf(theta));
glVertices[i*2]=v.x;
glVertices[i*2+1]=v.y;
theta += k_increment;
}
glColor4f(color.r, color.g, color.b,1);
glVertexPointer(2, GL_FLOAT, 0, glVertices);
glDrawArrays(GL_TRIANGLE_FAN, 0, vertexCount);
}
void GLESDebugDraw::DrawSolidCircle(const b2Vec2& center, float32 radius, const b2Vec2& axis, const b2Color& color)
{
const float32 k_segments = 16.0f;
int vertexCount=16;
const float32 k_increment = 2.0f * b2_pi / k_segments;
float32 theta = 0.0f;
GLfloat glVertices[vertexCount*2];
for (int32 i = 0; i < k_segments; ++i)
{
b2Vec2 v = center + radius * b2Vec2(cosf(theta), sinf(theta));
glVertices[i*2]=v.x;
glVertices[i*2+1]=v.y;
theta += k_increment;
}
glColor4f(color.r, color.g, color.b,0.5f);
glVertexPointer(2, GL_FLOAT, 0, glVertices);
glDrawArrays(GL_TRIANGLE_FAN, 0, vertexCount);
glColor4f(color.r, color.g, color.b,1);
glDrawArrays(GL_LINE_LOOP, 0, vertexCount);
// Draw the axis line
DrawSegment(center,center+radius*axis,color);
}
void GLESDebugDraw::DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color)
{
glColor4f(color.r, color.g, color.b,1);
GLfloat glVertices[] = {
p1.x,p1.y,p2.x,p2.y
};
glVertexPointer(2, GL_FLOAT, 0, glVertices);
glDrawArrays(GL_LINES, 0, 2);
}
void GLESDebugDraw::DrawTransform(const b2Transform& xf)
{
b2Vec2 p1 = xf.position, p2;
const float32 k_axisScale = 0.4f;
p2 = p1 + k_axisScale * xf.R.col1;
DrawSegment(p1,p2,b2Color(1,0,0));
p2 = p1 + k_axisScale * xf.R.col2;
DrawSegment(p1,p2,b2Color(0,1,0));
}
void GLESDebugDraw::DrawPoint(const b2Vec2& p, float32 size, const b2Color& color)
{
glColor4f(color.r, color.g, color.b,1);
glPointSize(size);
GLfloat glVertices[] = {
p.x,p.y
};
glVertexPointer(2, GL_FLOAT, 0, glVertices);
glDrawArrays(GL_POINTS, 0, 1);
glPointSize(1.0f);
}
void GLESDebugDraw::DrawString(int x, int y, const char *string, ...)
{
/* Unsupported as yet. Could replace with bitmap font renderer at a later date */
}
void GLESDebugDraw::DrawAABB(b2AABB* aabb, const b2Color& c)
{
glColor4f(c.r, c.g, c.b,1);
GLfloat glVertices[] = {
aabb->lowerBound.x, aabb->lowerBound.y,
aabb->upperBound.x, aabb->lowerBound.y,
aabb->upperBound.x, aabb->upperBound.y,
aabb->lowerBound.x, aabb->upperBound.y
};
glVertexPointer(2, GL_FLOAT, 0, glVertices);
glDrawArrays(GL_LINE_LOOP, 0, 8);
}

View File

@@ -0,0 +1,19 @@
//
// TestEntriesViewController.h
// Box2D
//
// Box2D iPhone port by Simon Oliver - http://www.simonoliver.com - http://www.handcircus.com
//
#import <UIKit/UIKit.h>
#import "iPhoneTest.h"
#import "Delegates.h"
@interface TestEntriesViewController : UITableViewController {
int32 testCount;
id<TestSelectDelegate> _delegate;
}
@property(assign) id<TestSelectDelegate> delegate;
@end

View File

@@ -0,0 +1,75 @@
//
// TestEntriesViewController.m
// Box2D
//
// Box2D iPhone port by Simon Oliver - http://www.simonoliver.com - http://www.handcircus.com
//
#import "TestEntriesViewController.h"
@implementation TestEntriesViewController
@synthesize delegate=_delegate;
- (id)initWithStyle:(UITableViewStyle)style {
if (self = [super initWithStyle:style]) {
testCount = 0;
TestEntry* e = g_testEntries;
while (e->createFcn)
{
++testCount;
++e;
}
}
return self;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview
// Release anything that's not essential, such as cached data
}
#pragma mark Table view methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return testCount;
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
}
// Set up the cell...
TestEntry* e = g_testEntries;
e+=indexPath.row;
cell.textLabel.text = [NSString stringWithUTF8String:e->name];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[_delegate selectTest:indexPath.row];
}
- (void)dealloc {
[super dealloc];
}
@end

View File

@@ -0,0 +1,189 @@
/*
* Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
*
* iPhone port by Simon Oliver - http://www.simonoliver.com - http://www.handcircus.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 TEST_H
#define TEST_H
#import <UIKit/UIKit.h>
#include <Box2D/Box2D.h>
#include "GLES-Render.h"
#include <cstdlib>
class Test;
struct Settings;
typedef Test* TestCreateFcn();
#define RAND_LIMIT 32767
/// Random number in range [-1,1]
inline float32 RandomFloat()
{
float32 r = (float32)(rand() & (RAND_LIMIT));
r /= RAND_LIMIT;
r = 2.0f * r - 1.0f;
return r;
}
/// Random floating point number in range [lo, hi]
inline float32 RandomFloat(float32 lo, float32 hi)
{
float32 r = (float32)(rand() & (RAND_LIMIT));
r /= RAND_LIMIT;
r = (hi - lo) * r + lo;
return r;
}
/// Test settings. Some can be controlled in the GUI.
struct Settings
{
Settings() :
viewCenter(0.0f, 20.0f),
hz(60.0f),
velocityIterations(8),
positionIterations(3),
drawShapes(1),
drawJoints(1),
drawAABBs(0),
drawPairs(0),
drawContactPoints(0),
drawContactNormals(0),
drawContactForces(0),
drawFrictionForces(0),
drawCOMs(0),
drawStats(0),
enableWarmStarting(1),
enableContinuous(1),
enableSubStepping(0),
pause(0),
singleStep(0)
{}
b2Vec2 viewCenter;
float32 hz;
int32 velocityIterations;
int32 positionIterations;
int32 drawShapes;
int32 drawJoints;
int32 drawAABBs;
int32 drawPairs;
int32 drawContactPoints;
int32 drawContactNormals;
int32 drawContactForces;
int32 drawFrictionForces;
int32 drawCOMs;
int32 drawStats;
int32 enableWarmStarting;
int32 enableContinuous;
int32 enableSubStepping;
int32 pause;
int32 singleStep;
};
struct TestEntry
{
const char *name;
TestCreateFcn *createFcn;
};
extern TestEntry g_testEntries[];
// This is called when a joint in the world is implicitly destroyed
// because an attached body is destroyed. This gives us a chance to
// nullify the mouse joint.
class DestructionListener : public b2DestructionListener
{
public:
void SayGoodbye(b2Fixture* fixture) { B2_NOT_USED(fixture); }
void SayGoodbye(b2Joint* joint);
Test* test;
};
const int32 k_maxContactPoints = 2048;
struct ContactPoint
{
b2Fixture* fixtureA;
b2Fixture* fixtureB;
b2Vec2 normal;
b2Vec2 position;
b2PointState state;
};
class Test : public b2ContactListener
{
public:
Test();
virtual ~Test();
void SetGravity(float x,float y);
void SetTextLine(int32 line) { m_textLine = line; }
void DrawTitle(int x, int y, const char *string);
virtual void Step(Settings* settings);
virtual void Keyboard(unsigned char key) { B2_NOT_USED(key); }
void ShiftMouseDown(const b2Vec2& p);
virtual void MouseDown(const b2Vec2& p);
virtual void MouseUp(const b2Vec2& p);
void MouseMove(const b2Vec2& p);
void LaunchBomb();
void LaunchBomb(const b2Vec2& position, const b2Vec2& velocity);
void SpawnBomb(const b2Vec2& worldPt);
void CompleteBombSpawn(const b2Vec2& p);
// Let derived tests know that a joint was destroyed.
virtual void JointDestroyed(b2Joint* joint) { B2_NOT_USED(joint); }
// Callbacks for derived classes.
virtual void BeginContact(b2Contact* contact) { B2_NOT_USED(contact); }
virtual void EndContact(b2Contact* contact) { B2_NOT_USED(contact); }
virtual void PreSolve(b2Contact* contact, const b2Manifold* oldManifold);
virtual void PostSolve(b2Contact* contact, const b2ContactImpulse* impulse)
{
B2_NOT_USED(contact);
B2_NOT_USED(impulse);
}
protected:
friend class DestructionListener;
friend class BoundaryListener;
friend class ContactListener;
b2Body* m_groundBody;
b2AABB m_worldAABB;
ContactPoint m_points[k_maxContactPoints];
int32 m_pointCount;
DestructionListener m_destructionListener;
GLESDebugDraw m_debugDraw;
int32 m_textLine;
b2World* m_world;
b2Body* m_bomb;
b2MouseJoint* m_mouseJoint;
b2Vec2 m_bombSpawnPoint;
bool m_bombSpawning;
b2Vec2 m_mouseWorld;
int32 m_stepCount;
};
#endif

View File

@@ -0,0 +1,415 @@
/*
* Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com
*
* iPhone port by Simon Oliver - http://www.simonoliver.com - http://www.handcircus.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 "iPhoneTest.h"
#include "GLES-Render.h"
#include <cstdio>
void DestructionListener::SayGoodbye(b2Joint* joint)
{
if (test->m_mouseJoint == joint)
{
test->m_mouseJoint = NULL;
}
else
{
test->JointDestroyed(joint);
}
}
Test::Test()
: m_debugDraw()
{
b2Vec2 gravity;
gravity.Set(0.0f, -10.0f);
bool doSleep = true;
m_world = new b2World(gravity, doSleep);
m_bomb = NULL;
m_textLine = 30;
m_mouseJoint = NULL;
m_pointCount = 0;
m_destructionListener.test = this;
m_world->SetDestructionListener(&m_destructionListener);
m_world->SetContactListener(this);
m_world->SetDebugDraw(&m_debugDraw);
m_bombSpawning = false;
m_stepCount = 0;
b2BodyDef bodyDef;
m_groundBody = m_world->CreateBody(&bodyDef);
}
Test::~Test()
{
// By deleting the world, we delete the bomb, mouse joint, etc.
delete m_world;
m_world = NULL;
}
void Test::SetGravity( float x, float y)
{
float tVectorLength=sqrt(x*x+y*y);
float newGravityX=9.81f*x/tVectorLength;
float newGravityY=9.81f*y/tVectorLength;
m_world->SetGravity(b2Vec2(newGravityX,newGravityY));
}
void Test::PreSolve(b2Contact* contact, const b2Manifold* oldManifold)
{
const b2Manifold* manifold = contact->GetManifold();
if (manifold->pointCount == 0)
{
return;
}
b2Fixture* fixtureA = contact->GetFixtureA();
b2Fixture* fixtureB = contact->GetFixtureB();
b2PointState state1[b2_maxManifoldPoints], state2[b2_maxManifoldPoints];
b2GetPointStates(state1, state2, oldManifold, manifold);
b2WorldManifold worldManifold;
contact->GetWorldManifold(&worldManifold);
for (int32 i = 0; i < manifold->pointCount && m_pointCount < k_maxContactPoints; ++i)
{
ContactPoint* cp = m_points + m_pointCount;
cp->fixtureA = fixtureA;
cp->fixtureB = fixtureB;
cp->position = worldManifold.points[i];
cp->normal = worldManifold.normal;
cp->state = state2[i];
++m_pointCount;
}
}
void Test::DrawTitle(int x, int y, const char *string)
{
m_debugDraw.DrawString(x, y, string);
}
class QueryCallback : public b2QueryCallback
{
public:
QueryCallback(const b2Vec2& point)
{
m_point = point;
m_fixture = NULL;
}
bool ReportFixture(b2Fixture* fixture)
{
b2Body* body = fixture->GetBody();
if (body->GetType() == b2_dynamicBody)
{
bool inside = fixture->TestPoint(m_point);
if (inside)
{
m_fixture = fixture;
// We are done, terminate the query.
return false;
}
}
// Continue the query.
return true;
}
b2Vec2 m_point;
b2Fixture* m_fixture;
};
void Test::MouseDown(const b2Vec2& p)
{
m_mouseWorld = p;
if (m_mouseJoint != NULL)
{
return;
}
// Make a small box.
b2AABB aabb;
b2Vec2 d;
d.Set(0.001f, 0.001f);
aabb.lowerBound = p - d;
aabb.upperBound = p + d;
// Query the world for overlapping shapes.
QueryCallback callback(p);
m_world->QueryAABB(&callback, aabb);
if (callback.m_fixture)
{
b2Body* body = callback.m_fixture->GetBody();
b2MouseJointDef md;
md.bodyA = m_groundBody;
md.bodyB = body;
md.target = p;
#ifdef TARGET_FLOAT32_IS_FIXED
md.maxForce = (body->GetMass() < 16.0)?
(1000.0f * body->GetMass()) : float32(16000.0);
#else
md.maxForce = 1000.0f * body->GetMass();
#endif
m_mouseJoint = (b2MouseJoint*)m_world->CreateJoint(&md);
body->SetAwake(true);
}
}
void Test::SpawnBomb(const b2Vec2& worldPt)
{
m_bombSpawnPoint = worldPt;
m_bombSpawning = true;
}
void Test::CompleteBombSpawn(const b2Vec2& p)
{
if (m_bombSpawning == false)
{
return;
}
const float multiplier = 30.0f;
b2Vec2 vel = m_bombSpawnPoint - p;
vel *= multiplier;
LaunchBomb(m_bombSpawnPoint,vel);
m_bombSpawning = false;
}
void Test::ShiftMouseDown(const b2Vec2& p)
{
m_mouseWorld = p;
if (m_mouseJoint != NULL)
{
return;
}
SpawnBomb(p);
}
void Test::MouseUp(const b2Vec2& p)
{
if (m_mouseJoint)
{
m_world->DestroyJoint(m_mouseJoint);
m_mouseJoint = NULL;
}
if (m_bombSpawning)
{
CompleteBombSpawn(p);
}
}
void Test::MouseMove(const b2Vec2& p)
{
m_mouseWorld = p;
if (m_mouseJoint)
{
m_mouseJoint->SetTarget(p);
}
}
void Test::LaunchBomb()
{
b2Vec2 p(RandomFloat(-15.0f, 15.0f), 30.0f);
b2Vec2 v = -5.0f * p;
LaunchBomb(p, v);
}
void Test::LaunchBomb(const b2Vec2& position, const b2Vec2& velocity)
{
if (m_bomb)
{
m_world->DestroyBody(m_bomb);
m_bomb = NULL;
}
b2BodyDef bd;
bd.type = b2_dynamicBody;
bd.position = position;
bd.bullet = true;
m_bomb = m_world->CreateBody(&bd);
m_bomb->SetLinearVelocity(velocity);
b2CircleShape circle;
circle.m_radius = 0.3f;
b2FixtureDef fd;
fd.shape = &circle;
fd.density = 20.0f;
fd.restitution = 0.0f;
b2Vec2 minV = position - b2Vec2(0.3f,0.3f);
b2Vec2 maxV = position + b2Vec2(0.3f,0.3f);
b2AABB aabb;
aabb.lowerBound = minV;
aabb.upperBound = maxV;
m_bomb->CreateFixture(&fd);
}
void Test::Step(Settings* settings)
{
float32 timeStep = settings->hz > 0.0f ? 1.0f / settings->hz : float32(0.0f);
if (settings->pause)
{
if (settings->singleStep)
{
settings->singleStep = 0;
}
else
{
timeStep = 0.0f;
}
m_debugDraw.DrawString(5, m_textLine, "****PAUSED****");
m_textLine += 15;
}
uint32 flags = 0;
flags += settings->drawShapes * b2Draw::e_shapeBit;
flags += settings->drawJoints * b2Draw::e_jointBit;
flags += settings->drawAABBs * b2Draw::e_aabbBit;
flags += settings->drawPairs * b2Draw::e_pairBit;
flags += settings->drawCOMs * b2Draw::e_centerOfMassBit;
m_debugDraw.SetFlags(flags);
m_world->SetWarmStarting(settings->enableWarmStarting > 0);
m_world->SetContinuousPhysics(settings->enableContinuous > 0);
m_world->SetSubStepping(settings->enableSubStepping > 0);
m_pointCount = 0;
m_world->Step(timeStep, settings->velocityIterations, settings->positionIterations);
m_world->DrawDebugData();
if (timeStep > 0.0f)
{
++m_stepCount;
}
if (settings->drawStats)
{
m_debugDraw.DrawString(5, m_textLine, "bodies/contacts/joints/proxies = %d/%d/%d",
m_world->GetBodyCount(), m_world->GetContactCount(), m_world->GetJointCount(), m_world->GetProxyCount());
m_textLine += 15;
}
if (m_mouseJoint)
{
b2Vec2 p1 = m_mouseJoint->GetAnchorB();
b2Vec2 p2 = m_mouseJoint->GetTarget();
glPointSize(4.0f);
glColor4f(0.0f, 1.0f, 0.0f, 1.0f);
GLbyte verts1[2 * 3] = {
p1.x, p1.y, 0.0f,
p2.x, p2.y, 0.0f
};
glVertexPointer(3, GL_BYTE, 0, verts1);
glDrawArrays(GL_POINTS, 0, 2);
glPointSize(1.0f);
glColor4f(0.8f, 0.8f, 0.8f, 1.0f);
GLbyte verts2[2 * 3] = {
p1.x, p1.y, 0.0f,
p2.x, p2.y, 0.0f
};
glVertexPointer(3, GL_BYTE, 0, verts2);
glDrawArrays(GL_LINES, 0, 2);
}
if (m_bombSpawning)
{
glPointSize(4.0f);
glColor4f(0.0f, 0.0f, 1.0f, 1.0f);
glColor4f(0.0f, 0.0f, 1.0f, 1.0f);
GLbyte verts1[1 * 3] = {
m_bombSpawnPoint.x, m_bombSpawnPoint.y, 0.0f
};
glVertexPointer(3, GL_BYTE, 0, verts1);
glDrawArrays(GL_POINTS, 0, 1);
glColor4f(0.8f, 0.8f, 0.8f, 1.0f);
GLbyte verts2[2 * 3] = {
m_mouseWorld.x, m_mouseWorld.y, 0.0f,
m_bombSpawnPoint.x, m_bombSpawnPoint.y, 0.0f
};
glVertexPointer(3, GL_BYTE, 0, verts2);
glDrawArrays(GL_LINES, 0, 2);
}
if (settings->drawContactPoints)
{
//const float32 k_impulseScale = 0.1f;
const float32 k_axisScale = 0.3f;
for (int32 i = 0; i < m_pointCount; ++i)
{
ContactPoint* point = m_points + i;
if (point->state == b2_addState)
{
// Add
m_debugDraw.DrawPoint(point->position, 10.0f, b2Color(0.3f, 0.95f, 0.3f));
}
else if (point->state == b2_persistState)
{
// Persist
m_debugDraw.DrawPoint(point->position, 5.0f, b2Color(0.3f, 0.3f, 0.95f));
}
if (settings->drawContactNormals == 1)
{
b2Vec2 p1 = point->position;
b2Vec2 p2 = p1 + k_axisScale * point->normal;
m_debugDraw.DrawSegment(p1, p2, b2Color(0.9f, 0.9f, 0.9f));
}
else if (settings->drawContactForces == 1)
{
//b2Vec2 p1 = point->position;
//b2Vec2 p2 = p1 + k_forceScale * point->normalForce * point->normal;
//DrawSegment(p1, p2, b2Color(0.9f, 0.9f, 0.3f));
}
if (settings->drawFrictionForces == 1)
{
//b2Vec2 tangent = b2Cross(point->normal, 1.0f);
//b2Vec2 p1 = point->position;
//b2Vec2 p2 = p1 + k_forceScale * point->tangentForce * tangent;
//DrawSegment(p1, p2, b2Color(0.9f, 0.9f, 0.3f));
}
}
}
}

View File

@@ -0,0 +1,111 @@
/*
* 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 "iPhoneTest.h"
#include <cstring>
using namespace std;
#include "ApplyForce.h"
#include "BodyTypes.h"
#include "Breakable.h"
#include "Bridge.h"
#include "BulletTest.h"
#include "Cantilever.h"
#include "Car.h"
#include "ContinuousTest.h"
#include "Chain.h"
#include "CharacterCollision.h"
#include "CollisionFiltering.h"
#include "CollisionProcessing.h"
#include "CompoundShapes.h"
#include "Confined.h"
#include "DistanceTest.h"
#include "Dominos.h"
#include "DynamicTreeTest.h"
#include "EdgeShapes.h"
#include "EdgeTest.h"
#include "Gears.h"
#include "OneSidedPlatform.h"
#include "Pinball.h"
#include "PolyCollision.h"
#include "PolyShapes.h"
#include "Prismatic.h"
#include "Pulleys.h"
#include "Pyramid.h"
#include "RayCast.h"
#include "Revolute.h"
#include "Rope.h"
#include "RopeJoint.h"
#include "SensorTest.h"
#include "ShapeEditing.h"
#include "SliderCrank.h"
#include "SphereStack.h"
#include "TheoJansen.h"
#include "Tiles.h"
#include "TimeOfImpact.h"
#include "VaryingFriction.h"
#include "VaryingRestitution.h"
#include "VerticalStack.h"
#include "Web.h"
TestEntry g_testEntries[] =
{
{"Pulleys", Pulleys::Create},
{"SphereStack", SphereStack::Create},
{"Tiles", Tiles::Create},
{"Polygon Shapes", PolyShapes::Create},
{"Rope", Rope::Create},
{"Web", Web::Create},
{"Car", Car::Create},
{"Vertical Stack", VerticalStack::Create},
{"RopeJoint", RopeJoint::Create},
{"Character Collision", CharacterCollision::Create},
{"Edge Test", EdgeTest::Create},
{"One-Sided Platform", OneSidedPlatform::Create},
{"Pinball", Pinball::Create},
{"Bullet Test", BulletTest::Create},
{"Continuous Test", ContinuousTest::Create},
{"Time of Impact", TimeOfImpact::Create},
{"Ray-Cast", RayCast::Create},
{"Confined", Confined::Create},
{"Pyramid", Pyramid::Create},
{"Varying Restitution", VaryingRestitution::Create},
{"Theo Jansen's Walker", TheoJansen::Create},
{"Body Types", BodyTypes::Create},
{"Prismatic", Prismatic::Create},
{"Edge Shapes", EdgeShapes::Create},
{"PolyCollision", PolyCollision::Create},
{"Apply Force", ApplyForce::Create},
{"Cantilever", Cantilever::Create},
{"Bridge", Bridge::Create},
{"Breakable", Breakable::Create},
{"Chain", Chain::Create},
{"Collision Filtering", CollisionFiltering::Create},
{"Collision Processing", CollisionProcessing::Create},
{"Compound Shapes", CompoundShapes::Create},
{"Distance Test", DistanceTest::Create},
{"Dominos", Dominos::Create},
{"Dynamic Tree", DynamicTreeTest::Create},
{"Gears", Gears::Create},
{"Revolute", Revolute::Create},
{"Sensor Test", SensorTest::Create},
{"Shape Editing", ShapeEditing::Create},
{"Slider Crank", SliderCrank::Create},
{"Varying Friction", VaryingFriction::Create},
{NULL, NULL}
};

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleDisplayName</key>
<string>${MACOSX_BUNDLE_PRODUCT_NAME}</string>
<key>CFBundleExecutable</key>
<string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${MACOSX_BUNDLE_PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSMainNibFile</key>
<string>MainWindow</string>
</dict>
</plist>

View File

@@ -0,0 +1,232 @@
<?xml version="1.0" encoding="UTF-8"?>
<archive type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="7.03">
<data>
<int key="IBDocument.SystemTarget">528</int>
<string key="IBDocument.SystemVersion">9G55</string>
<string key="IBDocument.InterfaceBuilderVersion">677</string>
<string key="IBDocument.AppKitVersion">949.43</string>
<string key="IBDocument.HIToolboxVersion">353.00</string>
<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
<bool key="EncodedWithXMLCoder">YES</bool>
<integer value="8"/>
</object>
<object class="NSArray" key="IBDocument.PluginDependencies">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
</object>
<object class="NSMutableDictionary" key="IBDocument.Metadata">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSArray" key="dict.sortedKeys">
<bool key="EncodedWithXMLCoder">YES</bool>
</object>
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
</object>
</object>
<object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="IBProxyObject" id="841351856">
<string key="IBProxiedObjectIdentifier">IBFilesOwner</string>
</object>
<object class="IBProxyObject" id="191355593">
<string key="IBProxiedObjectIdentifier">IBFirstResponder</string>
</object>
<object class="IBUICustomObject" id="664661524"/>
<object class="IBUIWindow" id="380026005">
<reference key="NSNextResponder"/>
<int key="NSvFlags">1316</int>
<object class="NSMutableArray" key="NSSubviews">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="IBUIView" id="773737154">
<reference key="NSNextResponder" ref="380026005"/>
<int key="NSvFlags">1298</int>
<string key="NSFrameSize">{320, 480}</string>
<reference key="NSSuperview" ref="380026005"/>
<object class="NSColor" key="IBUIBackgroundColor">
<int key="NSColorSpace">3</int>
<bytes key="NSWhite">MQA</bytes>
<object class="NSColorSpace" key="NSCustomColorSpace">
<int key="NSID">2</int>
</object>
</object>
<bool key="IBUIClearsContextBeforeDrawing">NO</bool>
</object>
</object>
<object class="NSPSMatrix" key="NSFrameMatrix"/>
<string key="NSFrameSize">{320, 480}</string>
<reference key="NSSuperview"/>
<object class="NSColor" key="IBUIBackgroundColor">
<int key="NSColorSpace">1</int>
<bytes key="NSRGB">MSAxIDEAA</bytes>
</object>
<bool key="IBUIClearsContextBeforeDrawing">NO</bool>
<bool key="IBUIVisibleAtLaunch">YES</bool>
</object>
</object>
<object class="IBObjectContainer" key="IBDocument.Objects">
<object class="NSMutableArray" key="connectionRecords">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchOutletConnection" key="connection">
<string key="label">delegate</string>
<reference key="source" ref="841351856"/>
<reference key="destination" ref="664661524"/>
</object>
<int key="connectionID">4</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchOutletConnection" key="connection">
<string key="label">window</string>
<reference key="source" ref="664661524"/>
<reference key="destination" ref="380026005"/>
</object>
<int key="connectionID">5</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchOutletConnection" key="connection">
<string key="label">glView</string>
<reference key="source" ref="664661524"/>
<reference key="destination" ref="773737154"/>
</object>
<int key="connectionID">9</int>
</object>
</object>
<object class="IBMutableOrderedSet" key="objectRecords">
<object class="NSArray" key="orderedObjects">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="IBObjectRecord">
<int key="objectID">0</int>
<object class="NSArray" key="object" id="957960031">
<bool key="EncodedWithXMLCoder">YES</bool>
</object>
<reference key="children" ref="1000"/>
<nil key="parent"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">2</int>
<reference key="object" ref="380026005"/>
<object class="NSMutableArray" key="children">
<bool key="EncodedWithXMLCoder">YES</bool>
<reference ref="773737154"/>
</object>
<reference key="parent" ref="957960031"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">-1</int>
<reference key="object" ref="841351856"/>
<reference key="parent" ref="957960031"/>
<string type="base64-UTF8" key="objectName">RmlsZSdzIE93bmVyA</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">3</int>
<reference key="object" ref="664661524"/>
<reference key="parent" ref="957960031"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">8</int>
<reference key="object" ref="773737154"/>
<reference key="parent" ref="380026005"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">-2</int>
<reference key="object" ref="191355593"/>
<reference key="parent" ref="957960031"/>
</object>
</object>
</object>
<object class="NSMutableDictionary" key="flattenedProperties">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSMutableArray" key="dict.sortedKeys">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>-1.CustomClassName</string>
<string>-2.CustomClassName</string>
<string>2.IBAttributePlaceholdersKey</string>
<string>2.IBEditorWindowLastContentRect</string>
<string>2.IBPluginDependency</string>
<string>3.CustomClassName</string>
<string>3.IBPluginDependency</string>
<string>8.CustomClassName</string>
<string>8.IBPluginDependency</string>
</object>
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>UIApplication</string>
<string>UIResponder</string>
<object class="NSMutableDictionary">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSArray" key="dict.sortedKeys">
<bool key="EncodedWithXMLCoder">YES</bool>
</object>
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
</object>
</object>
<string>{{500, 343}, {320, 480}}</string>
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string>Box2DAppDelegate</string>
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string>Box2DView</string>
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
</object>
</object>
<object class="NSMutableDictionary" key="unlocalizedProperties">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSArray" key="dict.sortedKeys">
<bool key="EncodedWithXMLCoder">YES</bool>
</object>
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
</object>
</object>
<nil key="activeLocalization"/>
<object class="NSMutableDictionary" key="localizations">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSArray" key="dict.sortedKeys">
<bool key="EncodedWithXMLCoder">YES</bool>
</object>
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
</object>
</object>
<nil key="sourceID"/>
<int key="maxID">9</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes">
<object class="NSMutableArray" key="referencedPartialClassDescriptions">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="IBPartialClassDescription">
<string key="className">Box2DAppDelegate</string>
<string key="superclassName">NSObject</string>
<object class="NSMutableDictionary" key="outlets">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSMutableArray" key="dict.sortedKeys">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>glView</string>
<string>window</string>
</object>
<object class="NSMutableArray" key="dict.values">
<bool key="EncodedWithXMLCoder">YES</bool>
<string>Box2DView</string>
<string>UIWindow</string>
</object>
</object>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">Classes/Box2DAppDelegate.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">Box2DView</string>
<string key="superclassName">UIView</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">Classes/Box2DView.h</string>
</object>
</object>
</object>
</object>
<int key="IBDocument.localizationMode">0</int>
<string key="IBDocument.LastKnownRelativeProjectPath">Box2D.xcodeproj</string>
<int key="IBDocument.defaultPropertyAccessControl">3</int>
</data>
</archive>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@@ -0,0 +1,17 @@
//
// main.m
// Box2D
//
// Created by Simon Oliver on 14/01/2009.
// Copyright HandCircus 2009. All rights reserved.
//
#import <UIKit/UIKit.h>
int main(int argc, char *argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, nil, nil);
[pool release];
return retVal;
}

View File

@@ -0,0 +1,3 @@
This folder contains user contributions. Contributions are _not_ supported by the Box2D project.
Contributions may not compile or function correctly.

View File

@@ -0,0 +1,187 @@
#include "Biped.h"
#include "BipedDef.h"
Biped::Biped(b2World* w, const b2Vec2& position)
{
m_world = w;
BipedDef def;
b2BodyDef bd;
// create body parts
bd = def.LFootDef;
bd.position += position;
LFoot = w->CreateBody(&bd);
LFoot->CreateFixture(&def.LFootPoly);
LFoot->SetMassFromShapes();
bd = def.RFootDef;
bd.position += position;
RFoot = w->CreateBody(&bd);
RFoot->CreateFixture(&def.RFootPoly);
RFoot->SetMassFromShapes();
bd = def.LCalfDef;
bd.position += position;
LCalf = w->CreateBody(&bd);
LCalf->CreateFixture(&def.LCalfPoly);
LCalf->SetMassFromShapes();
bd = def.RCalfDef;
bd.position += position;
RCalf = w->CreateBody(&bd);
RCalf->CreateFixture(&def.RCalfPoly);
RCalf->SetMassFromShapes();
bd = def.LThighDef;
bd.position += position;
LThigh = w->CreateBody(&bd);
LThigh->CreateFixture(&def.LThighPoly);
LThigh->SetMassFromShapes();
bd = def.RThighDef;
bd.position += position;
RThigh = w->CreateBody(&bd);
RThigh->CreateFixture(&def.RThighPoly);
RThigh->SetMassFromShapes();
bd = def.PelvisDef;
bd.position += position;
Pelvis = w->CreateBody(&bd);
Pelvis->CreateFixture(&def.PelvisPoly);
Pelvis->SetMassFromShapes();
bd = def.StomachDef;
bd.position += position;
Stomach = w->CreateBody(&bd);
Stomach->CreateFixture(&def.StomachPoly);
Stomach->SetMassFromShapes();
bd = def.ChestDef;
bd.position += position;
Chest = w->CreateBody(&bd);
Chest->CreateFixture(&def.ChestPoly);
Chest->SetMassFromShapes();
bd = def.NeckDef;
bd.position += position;
Neck = w->CreateBody(&bd);
Neck->CreateFixture(&def.NeckPoly);
Neck->SetMassFromShapes();
bd = def.HeadDef;
bd.position += position;
Head = w->CreateBody(&bd);
Head->CreateFixture(&def.HeadCirc);
Head->SetMassFromShapes();
bd = def.LUpperArmDef;
bd.position += position;
LUpperArm = w->CreateBody(&bd);
LUpperArm->CreateFixture(&def.LUpperArmPoly);
LUpperArm->SetMassFromShapes();
bd = def.RUpperArmDef;
bd.position += position;
RUpperArm = w->CreateBody(&bd);
RUpperArm->CreateFixture(&def.RUpperArmPoly);
RUpperArm->SetMassFromShapes();
bd = def.LForearmDef;
bd.position += position;
LForearm = w->CreateBody(&bd);
LForearm->CreateFixture(&def.LForearmPoly);
LForearm->SetMassFromShapes();
bd = def.RForearmDef;
bd.position += position;
RForearm = w->CreateBody(&bd);
RForearm->CreateFixture(&def.RForearmPoly);
RForearm->SetMassFromShapes();
bd = def.LHandDef;
bd.position += position;
LHand = w->CreateBody(&bd);
LHand->CreateFixture(&def.LHandPoly);
LHand->SetMassFromShapes();
bd = def.RHandDef;
bd.position += position;
RHand = w->CreateBody(&bd);
RHand->CreateFixture(&def.RHandPoly);
RHand->SetMassFromShapes();
// link body parts
def.LAnkleDef.body1 = LFoot;
def.LAnkleDef.body2 = LCalf;
def.RAnkleDef.body1 = RFoot;
def.RAnkleDef.body2 = RCalf;
def.LKneeDef.body1 = LCalf;
def.LKneeDef.body2 = LThigh;
def.RKneeDef.body1 = RCalf;
def.RKneeDef.body2 = RThigh;
def.LHipDef.body1 = LThigh;
def.LHipDef.body2 = Pelvis;
def.RHipDef.body1 = RThigh;
def.RHipDef.body2 = Pelvis;
def.LowerAbsDef.body1 = Pelvis;
def.LowerAbsDef.body2 = Stomach;
def.UpperAbsDef.body1 = Stomach;
def.UpperAbsDef.body2 = Chest;
def.LowerNeckDef.body1 = Chest;
def.LowerNeckDef.body2 = Neck;
def.UpperNeckDef.body1 = Chest;
def.UpperNeckDef.body2 = Head;
def.LShoulderDef.body1 = Chest;
def.LShoulderDef.body2 = LUpperArm;
def.RShoulderDef.body1 = Chest;
def.RShoulderDef.body2 = RUpperArm;
def.LElbowDef.body1 = LForearm;
def.LElbowDef.body2 = LUpperArm;
def.RElbowDef.body1 = RForearm;
def.RElbowDef.body2 = RUpperArm;
def.LWristDef.body1 = LHand;
def.LWristDef.body2 = LForearm;
def.RWristDef.body1 = RHand;
def.RWristDef.body2 = RForearm;
// create joints
LAnkle = (b2RevoluteJoint*)w->CreateJoint(&def.LAnkleDef);
RAnkle = (b2RevoluteJoint*)w->CreateJoint(&def.RAnkleDef);
LKnee = (b2RevoluteJoint*)w->CreateJoint(&def.LKneeDef);
RKnee = (b2RevoluteJoint*)w->CreateJoint(&def.RKneeDef);
LHip = (b2RevoluteJoint*)w->CreateJoint(&def.LHipDef);
RHip = (b2RevoluteJoint*)w->CreateJoint(&def.RHipDef);
LowerAbs = (b2RevoluteJoint*)w->CreateJoint(&def.LowerAbsDef);
UpperAbs = (b2RevoluteJoint*)w->CreateJoint(&def.UpperAbsDef);
LowerNeck = (b2RevoluteJoint*)w->CreateJoint(&def.LowerNeckDef);
UpperNeck = (b2RevoluteJoint*)w->CreateJoint(&def.UpperNeckDef);
LShoulder = (b2RevoluteJoint*)w->CreateJoint(&def.LShoulderDef);
RShoulder = (b2RevoluteJoint*)w->CreateJoint(&def.RShoulderDef);
LElbow = (b2RevoluteJoint*)w->CreateJoint(&def.LElbowDef);
RElbow = (b2RevoluteJoint*)w->CreateJoint(&def.RElbowDef);
LWrist = (b2RevoluteJoint*)w->CreateJoint(&def.LWristDef);
RWrist = (b2RevoluteJoint*)w->CreateJoint(&def.RWristDef);
}
Biped::~Biped(void)
{
m_world->DestroyBody(LFoot);
m_world->DestroyBody(RFoot);
m_world->DestroyBody(LCalf);
m_world->DestroyBody(RCalf);
m_world->DestroyBody(LThigh);
m_world->DestroyBody(RThigh);
m_world->DestroyBody(Pelvis);
m_world->DestroyBody(Stomach);
m_world->DestroyBody(Chest);
m_world->DestroyBody(Neck);
m_world->DestroyBody(Head);
m_world->DestroyBody(LUpperArm);
m_world->DestroyBody(RUpperArm);
m_world->DestroyBody(LForearm);
m_world->DestroyBody(RForearm);
m_world->DestroyBody(LHand);
m_world->DestroyBody(RHand);
}

View File

@@ -0,0 +1,25 @@
#ifndef BIPED_H
#define BIPED_H
#include "Box2D.h"
// Ragdoll class thanks to darkzerox.
class Biped
{
public:
Biped(b2World*, const b2Vec2& position);
~Biped();
private:
b2World* m_world;
b2Body *LFoot, *RFoot, *LCalf, *RCalf, *LThigh, *RThigh,
*Pelvis, *Stomach, *Chest, *Neck, *Head,
*LUpperArm, *RUpperArm, *LForearm, *RForearm, *LHand, *RHand;
b2RevoluteJoint *LAnkle, *RAnkle, *LKnee, *RKnee, *LHip, *RHip,
*LowerAbs, *UpperAbs, *LowerNeck, *UpperNeck,
*LShoulder, *RShoulder, *LElbow, *RElbow, *LWrist, *RWrist;
};
#endif

View File

@@ -0,0 +1,478 @@
#include "BipedDef.h"
int16 BipedDef::count = 0;
const float32 k_scale = 3.0f;
BipedDef::BipedDef()
{
SetMotorTorque(2.0f);
SetMotorSpeed(0.0f);
SetDensity(20.0f);
SetRestitution(0.0f);
SetLinearDamping(0.0f);
SetAngularDamping(0.005f);
SetGroupIndex(--count);
EnableMotor();
EnableLimit();
DefaultVertices();
DefaultPositions();
DefaultJoints();
LFootPoly.friction = RFootPoly.friction = 0.85f;
}
void BipedDef::IsFast(bool b)
{
B2_NOT_USED(b);
/*
LFootDef.isFast = b;
RFootDef.isFast = b;
LCalfDef.isFast = b;
RCalfDef.isFast = b;
LThighDef.isFast = b;
RThighDef.isFast = b;
PelvisDef.isFast = b;
StomachDef.isFast = b;
ChestDef.isFast = b;
NeckDef.isFast = b;
HeadDef.isFast = b;
LUpperArmDef.isFast = b;
RUpperArmDef.isFast = b;
LForearmDef.isFast = b;
RForearmDef.isFast = b;
LHandDef.isFast = b;
RHandDef.isFast = b;
*/
}
void BipedDef::SetGroupIndex(int16 i)
{
LFootPoly.filter.groupIndex = i;
RFootPoly.filter.groupIndex = i;
LCalfPoly.filter.groupIndex = i;
RCalfPoly.filter.groupIndex = i;
LThighPoly.filter.groupIndex = i;
RThighPoly.filter.groupIndex = i;
PelvisPoly.filter.groupIndex = i;
StomachPoly.filter.groupIndex = i;
ChestPoly.filter.groupIndex = i;
NeckPoly.filter.groupIndex = i;
HeadCirc.filter.groupIndex = i;
LUpperArmPoly.filter.groupIndex = i;
RUpperArmPoly.filter.groupIndex = i;
LForearmPoly.filter.groupIndex = i;
RForearmPoly.filter.groupIndex = i;
LHandPoly.filter.groupIndex = i;
RHandPoly.filter.groupIndex = i;
}
void BipedDef::SetLinearDamping(float f)
{
LFootDef.linearDamping = f;
RFootDef.linearDamping = f;
LCalfDef.linearDamping = f;
RCalfDef.linearDamping = f;
LThighDef.linearDamping = f;
RThighDef.linearDamping = f;
PelvisDef.linearDamping = f;
StomachDef.linearDamping = f;
ChestDef.linearDamping = f;
NeckDef.linearDamping = f;
HeadDef.linearDamping = f;
LUpperArmDef.linearDamping = f;
RUpperArmDef.linearDamping = f;
LForearmDef.linearDamping = f;
RForearmDef.linearDamping = f;
LHandDef.linearDamping = f;
RHandDef.linearDamping = f;
}
void BipedDef::SetAngularDamping(float f)
{
LFootDef.angularDamping = f;
RFootDef.angularDamping = f;
LCalfDef.angularDamping = f;
RCalfDef.angularDamping = f;
LThighDef.angularDamping = f;
RThighDef.angularDamping = f;
PelvisDef.angularDamping = f;
StomachDef.angularDamping = f;
ChestDef.angularDamping = f;
NeckDef.angularDamping = f;
HeadDef.angularDamping = f;
LUpperArmDef.angularDamping = f;
RUpperArmDef.angularDamping = f;
LForearmDef.angularDamping = f;
RForearmDef.angularDamping = f;
LHandDef.angularDamping = f;
RHandDef.angularDamping = f;
}
void BipedDef::SetMotorTorque(float f)
{
LAnkleDef.maxMotorTorque = f;
RAnkleDef.maxMotorTorque = f;
LKneeDef.maxMotorTorque = f;
RKneeDef.maxMotorTorque = f;
LHipDef.maxMotorTorque = f;
RHipDef.maxMotorTorque = f;
LowerAbsDef.maxMotorTorque = f;
UpperAbsDef.maxMotorTorque = f;
LowerNeckDef.maxMotorTorque = f;
UpperNeckDef.maxMotorTorque = f;
LShoulderDef.maxMotorTorque = f;
RShoulderDef.maxMotorTorque = f;
LElbowDef.maxMotorTorque = f;
RElbowDef.maxMotorTorque = f;
LWristDef.maxMotorTorque = f;
RWristDef.maxMotorTorque = f;
}
void BipedDef::SetMotorSpeed(float f)
{
LAnkleDef.motorSpeed = f;
RAnkleDef.motorSpeed = f;
LKneeDef.motorSpeed = f;
RKneeDef.motorSpeed = f;
LHipDef.motorSpeed = f;
RHipDef.motorSpeed = f;
LowerAbsDef.motorSpeed = f;
UpperAbsDef.motorSpeed = f;
LowerNeckDef.motorSpeed = f;
UpperNeckDef.motorSpeed = f;
LShoulderDef.motorSpeed = f;
RShoulderDef.motorSpeed = f;
LElbowDef.motorSpeed = f;
RElbowDef.motorSpeed = f;
LWristDef.motorSpeed = f;
RWristDef.motorSpeed = f;
}
void BipedDef::SetDensity(float f)
{
LFootPoly.density = f;
RFootPoly.density = f;
LCalfPoly.density = f;
RCalfPoly.density = f;
LThighPoly.density = f;
RThighPoly.density = f;
PelvisPoly.density = f;
StomachPoly.density = f;
ChestPoly.density = f;
NeckPoly.density = f;
HeadCirc.density = f;
LUpperArmPoly.density = f;
RUpperArmPoly.density = f;
LForearmPoly.density = f;
RForearmPoly.density = f;
LHandPoly.density = f;
RHandPoly.density = f;
}
void BipedDef::SetRestitution(float f)
{
LFootPoly.restitution = f;
RFootPoly.restitution = f;
LCalfPoly.restitution = f;
RCalfPoly.restitution = f;
LThighPoly.restitution = f;
RThighPoly.restitution = f;
PelvisPoly.restitution = f;
StomachPoly.restitution = f;
ChestPoly.restitution = f;
NeckPoly.restitution = f;
HeadCirc.restitution = f;
LUpperArmPoly.restitution = f;
RUpperArmPoly.restitution = f;
LForearmPoly.restitution = f;
RForearmPoly.restitution = f;
LHandPoly.restitution = f;
RHandPoly.restitution = f;
}
void BipedDef::EnableLimit()
{
SetLimit(true);
}
void BipedDef::DisableLimit()
{
SetLimit(false);
}
void BipedDef::SetLimit(bool b)
{
LAnkleDef.enableLimit = b;
RAnkleDef.enableLimit = b;
LKneeDef.enableLimit = b;
RKneeDef.enableLimit = b;
LHipDef.enableLimit = b;
RHipDef.enableLimit = b;
LowerAbsDef.enableLimit = b;
UpperAbsDef.enableLimit = b;
LowerNeckDef.enableLimit = b;
UpperNeckDef.enableLimit = b;
LShoulderDef.enableLimit = b;
RShoulderDef.enableLimit = b;
LElbowDef.enableLimit = b;
RElbowDef.enableLimit = b;
LWristDef.enableLimit = b;
RWristDef.enableLimit = b;
}
void BipedDef::EnableMotor()
{
SetMotor(true);
}
void BipedDef::DisableMotor()
{
SetMotor(false);
}
void BipedDef::SetMotor(bool b)
{
LAnkleDef.enableMotor = b;
RAnkleDef.enableMotor = b;
LKneeDef.enableMotor = b;
RKneeDef.enableMotor = b;
LHipDef.enableMotor = b;
RHipDef.enableMotor = b;
LowerAbsDef.enableMotor = b;
UpperAbsDef.enableMotor = b;
LowerNeckDef.enableMotor = b;
UpperNeckDef.enableMotor = b;
LShoulderDef.enableMotor = b;
RShoulderDef.enableMotor = b;
LElbowDef.enableMotor = b;
RElbowDef.enableMotor = b;
LWristDef.enableMotor = b;
RWristDef.enableMotor = b;
}
BipedDef::~BipedDef(void)
{
}
void BipedDef::DefaultVertices()
{
{ // feet
LFootPoly.vertexCount = RFootPoly.vertexCount = 5;
LFootPoly.vertices[0] = RFootPoly.vertices[0] = k_scale * b2Vec2(.033f,.143f);
LFootPoly.vertices[1] = RFootPoly.vertices[1] = k_scale * b2Vec2(.023f,.033f);
LFootPoly.vertices[2] = RFootPoly.vertices[2] = k_scale * b2Vec2(.267f,.035f);
LFootPoly.vertices[3] = RFootPoly.vertices[3] = k_scale * b2Vec2(.265f,.065f);
LFootPoly.vertices[4] = RFootPoly.vertices[4] = k_scale * b2Vec2(.117f,.143f);
}
{ // calves
LCalfPoly.vertexCount = RCalfPoly.vertexCount = 4;
LCalfPoly.vertices[0] = RCalfPoly.vertices[0] = k_scale * b2Vec2(.089f,.016f);
LCalfPoly.vertices[1] = RCalfPoly.vertices[1] = k_scale * b2Vec2(.178f,.016f);
LCalfPoly.vertices[2] = RCalfPoly.vertices[2] = k_scale * b2Vec2(.205f,.417f);
LCalfPoly.vertices[3] = RCalfPoly.vertices[3] = k_scale * b2Vec2(.095f,.417f);
}
{ // thighs
LThighPoly.vertexCount = RThighPoly.vertexCount = 4;
LThighPoly.vertices[0] = RThighPoly.vertices[0] = k_scale * b2Vec2(.137f,.032f);
LThighPoly.vertices[1] = RThighPoly.vertices[1] = k_scale * b2Vec2(.243f,.032f);
LThighPoly.vertices[2] = RThighPoly.vertices[2] = k_scale * b2Vec2(.318f,.343f);
LThighPoly.vertices[3] = RThighPoly.vertices[3] = k_scale * b2Vec2(.142f,.343f);
}
{ // pelvis
PelvisPoly.vertexCount = 5;
PelvisPoly.vertices[0] = k_scale * b2Vec2(.105f,.051f);
PelvisPoly.vertices[1] = k_scale * b2Vec2(.277f,.053f);
PelvisPoly.vertices[2] = k_scale * b2Vec2(.320f,.233f);
PelvisPoly.vertices[3] = k_scale * b2Vec2(.112f,.233f);
PelvisPoly.vertices[4] = k_scale * b2Vec2(.067f,.152f);
}
{ // stomach
StomachPoly.vertexCount = 4;
StomachPoly.vertices[0] = k_scale * b2Vec2(.088f,.043f);
StomachPoly.vertices[1] = k_scale * b2Vec2(.284f,.043f);
StomachPoly.vertices[2] = k_scale * b2Vec2(.295f,.231f);
StomachPoly.vertices[3] = k_scale * b2Vec2(.100f,.231f);
}
{ // chest
ChestPoly.vertexCount = 4;
ChestPoly.vertices[0] = k_scale * b2Vec2(.091f,.042f);
ChestPoly.vertices[1] = k_scale * b2Vec2(.283f,.042f);
ChestPoly.vertices[2] = k_scale * b2Vec2(.177f,.289f);
ChestPoly.vertices[3] = k_scale * b2Vec2(.065f,.289f);
}
{ // head
HeadCirc.radius = k_scale * .115f;
}
{ // neck
NeckPoly.vertexCount = 4;
NeckPoly.vertices[0] = k_scale * b2Vec2(.038f,.054f);
NeckPoly.vertices[1] = k_scale * b2Vec2(.149f,.054f);
NeckPoly.vertices[2] = k_scale * b2Vec2(.154f,.102f);
NeckPoly.vertices[3] = k_scale * b2Vec2(.054f,.113f);
}
{ // upper arms
LUpperArmPoly.vertexCount = RUpperArmPoly.vertexCount = 5;
LUpperArmPoly.vertices[0] = RUpperArmPoly.vertices[0] = k_scale * b2Vec2(.092f,.059f);
LUpperArmPoly.vertices[1] = RUpperArmPoly.vertices[1] = k_scale * b2Vec2(.159f,.059f);
LUpperArmPoly.vertices[2] = RUpperArmPoly.vertices[2] = k_scale * b2Vec2(.169f,.335f);
LUpperArmPoly.vertices[3] = RUpperArmPoly.vertices[3] = k_scale * b2Vec2(.078f,.335f);
LUpperArmPoly.vertices[4] = RUpperArmPoly.vertices[4] = k_scale * b2Vec2(.064f,.248f);
}
{ // forearms
LForearmPoly.vertexCount = RForearmPoly.vertexCount = 4;
LForearmPoly.vertices[0] = RForearmPoly.vertices[0] = k_scale * b2Vec2(.082f,.054f);
LForearmPoly.vertices[1] = RForearmPoly.vertices[1] = k_scale * b2Vec2(.138f,.054f);
LForearmPoly.vertices[2] = RForearmPoly.vertices[2] = k_scale * b2Vec2(.149f,.296f);
LForearmPoly.vertices[3] = RForearmPoly.vertices[3] = k_scale * b2Vec2(.088f,.296f);
}
{ // hands
LHandPoly.vertexCount = RHandPoly.vertexCount = 5;
LHandPoly.vertices[0] = RHandPoly.vertices[0] = k_scale * b2Vec2(.066f,.031f);
LHandPoly.vertices[1] = RHandPoly.vertices[1] = k_scale * b2Vec2(.123f,.020f);
LHandPoly.vertices[2] = RHandPoly.vertices[2] = k_scale * b2Vec2(.160f,.127f);
LHandPoly.vertices[3] = RHandPoly.vertices[3] = k_scale * b2Vec2(.127f,.178f);
LHandPoly.vertices[4] = RHandPoly.vertices[4] = k_scale * b2Vec2(.074f,.178f);;
}
}
void BipedDef::DefaultJoints()
{
//b.LAnkleDef.body1 = LFoot;
//b.LAnkleDef.body2 = LCalf;
//b.RAnkleDef.body1 = RFoot;
//b.RAnkleDef.body2 = RCalf;
{ // ankles
b2Vec2 anchor = k_scale * b2Vec2(-.045f,-.75f);
LAnkleDef.localAnchor1 = RAnkleDef.localAnchor1 = anchor - LFootDef.position;
LAnkleDef.localAnchor2 = RAnkleDef.localAnchor2 = anchor - LCalfDef.position;
LAnkleDef.referenceAngle = RAnkleDef.referenceAngle = 0.0f;
LAnkleDef.lowerAngle = RAnkleDef.lowerAngle = -0.523598776f;
LAnkleDef.upperAngle = RAnkleDef.upperAngle = 0.523598776f;
}
//b.LKneeDef.body1 = LCalf;
//b.LKneeDef.body2 = LThigh;
//b.RKneeDef.body1 = RCalf;
//b.RKneeDef.body2 = RThigh;
{ // knees
b2Vec2 anchor = k_scale * b2Vec2(-.030f,-.355f);
LKneeDef.localAnchor1 = RKneeDef.localAnchor1 = anchor - LCalfDef.position;
LKneeDef.localAnchor2 = RKneeDef.localAnchor2 = anchor - LThighDef.position;
LKneeDef.referenceAngle = RKneeDef.referenceAngle = 0.0f;
LKneeDef.lowerAngle = RKneeDef.lowerAngle = 0;
LKneeDef.upperAngle = RKneeDef.upperAngle = 2.61799388f;
}
//b.LHipDef.body1 = LThigh;
//b.LHipDef.body2 = Pelvis;
//b.RHipDef.body1 = RThigh;
//b.RHipDef.body2 = Pelvis;
{ // hips
b2Vec2 anchor = k_scale * b2Vec2(.005f,-.045f);
LHipDef.localAnchor1 = RHipDef.localAnchor1 = anchor - LThighDef.position;
LHipDef.localAnchor2 = RHipDef.localAnchor2 = anchor - PelvisDef.position;
LHipDef.referenceAngle = RHipDef.referenceAngle = 0.0f;
LHipDef.lowerAngle = RHipDef.lowerAngle = -2.26892803f;
LHipDef.upperAngle = RHipDef.upperAngle = 0;
}
//b.LowerAbsDef.body1 = Pelvis;
//b.LowerAbsDef.body2 = Stomach;
{ // lower abs
b2Vec2 anchor = k_scale * b2Vec2(.035f,.135f);
LowerAbsDef.localAnchor1 = anchor - PelvisDef.position;
LowerAbsDef.localAnchor2 = anchor - StomachDef.position;
LowerAbsDef.referenceAngle = 0.0f;
LowerAbsDef.lowerAngle = -0.523598776f;
LowerAbsDef.upperAngle = 0.523598776f;
}
//b.UpperAbsDef.body1 = Stomach;
//b.UpperAbsDef.body2 = Chest;
{ // upper abs
b2Vec2 anchor = k_scale * b2Vec2(.045f,.320f);
UpperAbsDef.localAnchor1 = anchor - StomachDef.position;
UpperAbsDef.localAnchor2 = anchor - ChestDef.position;
UpperAbsDef.referenceAngle = 0.0f;
UpperAbsDef.lowerAngle = -0.523598776f;
UpperAbsDef.upperAngle = 0.174532925f;
}
//b.LowerNeckDef.body1 = Chest;
//b.LowerNeckDef.body2 = Neck;
{ // lower neck
b2Vec2 anchor = k_scale * b2Vec2(-.015f,.575f);
LowerNeckDef.localAnchor1 = anchor - ChestDef.position;
LowerNeckDef.localAnchor2 = anchor - NeckDef.position;
LowerNeckDef.referenceAngle = 0.0f;
LowerNeckDef.lowerAngle = -0.174532925f;
LowerNeckDef.upperAngle = 0.174532925f;
}
//b.UpperNeckDef.body1 = Chest;
//b.UpperNeckDef.body2 = Head;
{ // upper neck
b2Vec2 anchor = k_scale * b2Vec2(-.005f,.630f);
UpperNeckDef.localAnchor1 = anchor - ChestDef.position;
UpperNeckDef.localAnchor2 = anchor - HeadDef.position;
UpperNeckDef.referenceAngle = 0.0f;
UpperNeckDef.lowerAngle = -0.610865238f;
UpperNeckDef.upperAngle = 0.785398163f;
}
//b.LShoulderDef.body1 = Chest;
//b.LShoulderDef.body2 = LUpperArm;
//b.RShoulderDef.body1 = Chest;
//b.RShoulderDef.body2 = RUpperArm;
{ // shoulders
b2Vec2 anchor = k_scale * b2Vec2(-.015f,.545f);
LShoulderDef.localAnchor1 = RShoulderDef.localAnchor1 = anchor - ChestDef.position;
LShoulderDef.localAnchor2 = RShoulderDef.localAnchor2 = anchor - LUpperArmDef.position;
LShoulderDef.referenceAngle = RShoulderDef.referenceAngle = 0.0f;
LShoulderDef.lowerAngle = RShoulderDef.lowerAngle = -1.04719755f;
LShoulderDef.upperAngle = RShoulderDef.upperAngle = 3.14159265f;
}
//b.LElbowDef.body1 = LForearm;
//b.LElbowDef.body2 = LUpperArm;
//b.RElbowDef.body1 = RForearm;
//b.RElbowDef.body2 = RUpperArm;
{ // elbows
b2Vec2 anchor = k_scale * b2Vec2(-.005f,.290f);
LElbowDef.localAnchor1 = RElbowDef.localAnchor1 = anchor - LForearmDef.position;
LElbowDef.localAnchor2 = RElbowDef.localAnchor2 = anchor - LUpperArmDef.position;
LElbowDef.referenceAngle = RElbowDef.referenceAngle = 0.0f;
LElbowDef.lowerAngle = RElbowDef.lowerAngle = -2.7925268f;
LElbowDef.upperAngle = RElbowDef.upperAngle = 0;
}
//b.LWristDef.body1 = LHand;
//b.LWristDef.body2 = LForearm;
//b.RWristDef.body1 = RHand;
//b.RWristDef.body2 = RForearm;
{ // wrists
b2Vec2 anchor = k_scale * b2Vec2(-.010f,.045f);
LWristDef.localAnchor1 = RWristDef.localAnchor1 = anchor - LHandDef.position;
LWristDef.localAnchor2 = RWristDef.localAnchor2 = anchor - LForearmDef.position;
LWristDef.referenceAngle = RWristDef.referenceAngle = 0.0f;
LWristDef.lowerAngle = RWristDef.lowerAngle = -0.174532925f;
LWristDef.upperAngle = RWristDef.upperAngle = 0.174532925f;
}
}
void BipedDef::DefaultPositions()
{
LFootDef.position = RFootDef.position = k_scale * b2Vec2(-.122f,-.901f);
LCalfDef.position = RCalfDef.position = k_scale * b2Vec2(-.177f,-.771f);
LThighDef.position = RThighDef.position = k_scale * b2Vec2(-.217f,-.391f);
LUpperArmDef.position = RUpperArmDef.position = k_scale * b2Vec2(-.127f,.228f);
LForearmDef.position = RForearmDef.position = k_scale * b2Vec2(-.117f,-.011f);
LHandDef.position = RHandDef.position = k_scale * b2Vec2(-.112f,-.136f);
PelvisDef.position = k_scale * b2Vec2(-.177f,-.101f);
StomachDef.position = k_scale * b2Vec2(-.142f,.088f);
ChestDef.position = k_scale * b2Vec2(-.132f,.282f);
NeckDef.position = k_scale * b2Vec2(-.102f,.518f);
HeadDef.position = k_scale * b2Vec2(.022f,.738f);
}

View File

@@ -0,0 +1,51 @@
#ifndef BIPED_DEF_H
#define BIPED_DEF_H
#include "Box2D.h"
class BipedDef
{
public:
BipedDef();
~BipedDef(void);
void SetMotorTorque(float);
void SetMotorSpeed(float);
void SetDensity(float);
void SetFriction(float);
void SetRestitution(float);
void SetLinearDamping(float);
void SetAngularDamping(float);
void EnableLimit();
void DisableLimit();
void SetLimit(bool);
void EnableMotor();
void DisableMotor();
void SetMotor(bool);
void SetGroupIndex(int16);
void SetPosition(float, float);
void SetPosition(b2Vec2);
void IsFast(bool);
static int16 count;
b2BodyDef LFootDef, RFootDef, LCalfDef, RCalfDef, LThighDef, RThighDef,
PelvisDef, StomachDef, ChestDef, NeckDef, HeadDef,
LUpperArmDef, RUpperArmDef, LForearmDef, RForearmDef, LHandDef, RHandDef;
b2PolygonDef LFootPoly, RFootPoly, LCalfPoly, RCalfPoly, LThighPoly, RThighPoly,
PelvisPoly, StomachPoly, ChestPoly, NeckPoly,
LUpperArmPoly, RUpperArmPoly, LForearmPoly, RForearmPoly, LHandPoly, RHandPoly;
b2CircleDef HeadCirc;
b2RevoluteJointDef LAnkleDef, RAnkleDef, LKneeDef, RKneeDef, LHipDef, RHipDef,
LowerAbsDef, UpperAbsDef, LowerNeckDef, UpperNeckDef,
LShoulderDef, RShoulderDef, LElbowDef, RElbowDef, LWristDef, RWristDef;
void DefaultVertices();
void DefaultPositions();
void DefaultJoints();
};
#endif

View File

@@ -0,0 +1,87 @@
/*
* 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 BIPED_TEST_H
#define BIPED_TEST_H
#include "Biped.h"
class BipedTest : public Test
{
public:
BipedTest()
{
const float32 k_restitution = 1.4f;
{
b2BodyDef bd;
bd.position.Set(0.0f, 20.0f);
b2Body* body = m_world->CreateBody(&bd);
b2PolygonDef sd;
sd.density = 0.0f;
sd.restitution = k_restitution;
sd.SetAsBox(0.1f, 10.0f, b2Vec2(-10.0f, 0.0f), 0.0f);
body->CreateFixture(&sd);
sd.SetAsBox(0.1f, 10.0f, b2Vec2(10.0f, 0.0f), 0.0f);
body->CreateFixture(&sd);
sd.SetAsBox(0.1f, 10.0f, b2Vec2(0.0f, -10.0f), 0.5f * b2_pi);
body->CreateFixture(&sd);
sd.SetAsBox(0.1f, 10.0f, b2Vec2(0.0f, 10.0f), -0.5f * b2_pi);
body->CreateFixture(&sd);
}
m_biped = new Biped(m_world, b2Vec2(0.0f, 20.0f));
for (int32 i = 0; i < 8; ++i)
{
b2BodyDef bd;
bd.position.Set(5.0f, 20.0f + i);
bd.isBullet = true;
b2Body* body = m_world->CreateBody(&bd);
body->SetLinearVelocity(b2Vec2(0.0f, -100.0f));
body->SetAngularVelocity(RandomFloat(-50.0f, 50.0f));
b2CircleDef sd;
sd.radius = 0.25f;
sd.density = 15.0f;
sd.restitution = k_restitution;
body->CreateFixture(&sd);
body->SetMassFromShapes();
}
}
~BipedTest()
{
delete m_biped;
}
static Test* Create()
{
return new BipedTest;
}
Biped* m_biped;
};
#endif

View File

@@ -0,0 +1,603 @@
/*
* 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.
*/
/* Testbed example showing deformable and breakable bodies using the soft
* b2DistanceJoint and a small,liteweight triangle mesher.
* 2008-05-09 / nimodo
*/
#ifndef BREAKABLE_BODY_H
#define BREAKABLE_BODY_H
#include "TriangleMesh.h"
/// utility macro
#define H(x) (x)/2.0f
#define N_MAXVERTEX 256
class BreakableBody : public Test
{
public:
BreakableBody()
{
/// geometries
float32 gx = 100.0f, gy = 1.0f,
dx = 34.0f, br = 0.3f;
float32 sx=-dx-H(dx), sy = 30.f;
/// break joint, if the reactionforce exceeds:
maxAllowableForce = 100.0f;
m_drawMode = m_staticBodies = false;
m_drawCount = 0;
/// ground
{
b2PolygonDef sd;
b2BodyDef bd;
b2Body* ground;
bd.position.Set(0.0f, 0.0f);
ground = m_world->CreateBody(&bd);
/// bottom
sd.SetAsBox( H(gx), H(gy) );
ground->CreateFixture(&sd);
sd.SetAsBox( H(dx), H(gy), b2Vec2(-dx,sy-1.0f), 0.0f );
ground->CreateFixture(&sd);
}
/// dyn bodies
{
b2PolygonDef pd;
b2DistanceJointDef dj;
dj.dampingRatio = 0.0f;
dj.collideConnected = true;
ExampleData('B');
dj.frequencyHz = 20.f;
pd.density = 1.0f/70.0f;
pd.friction = 0.4f;
pd.restitution = 0.01f;
CreateSoftBody( b2Vec2(sx,sy), 0, 0, pd, dj,
nodes,n_nodes, segments,n_segments, holes,n_holes) ;
ExampleData('@');
dj.frequencyHz = 20.f;
pd.density = 1.0f/36.0f;
pd.friction = 0.1f;
pd.restitution = 0.5f;
CreateSoftBody( b2Vec2(sx+6.f,sy), 0, 0, pd, dj,
nodes,n_nodes, segments,n_segments, holes,n_holes) ;
ExampleData('x');
dj.frequencyHz = 20.0f;
pd.density = 1.0f/60.0f;
pd.friction = 0.6f;
pd.restitution = 0.0f;
CreateSoftBody( b2Vec2(sx+13.f,sy), 0, 0, pd, dj,
nodes,n_nodes, segments,n_segments, holes,n_holes) ;
ExampleData('2');
pd.density = 0.01f;
pd.friction = 0.3f;
pd.restitution = 0.3f;
CreateSoftBody( b2Vec2(sx+20.f,sy), 0, 0, pd, dj,
nodes,n_nodes, segments,n_segments, holes,n_holes) ;
ExampleData('D');
CreateSoftBody( b2Vec2(sx+28.f,sy), 0, 0, pd, dj,
nodes,n_nodes, segments,n_segments, holes,n_holes) ;
ExampleData('b');
dj.frequencyHz = 10.0f;
dj.dampingRatio = 20.0f;
pd.friction = 0.9f;
pd.restitution = 0.01f;
pd.density = 0.01f;
CreateSoftBody( b2Vec2(-5.f,5.f*gy), 0, 0, pd, dj,
nodes,n_nodes, segments,n_segments, holes,n_holes) ;
b2CircleDef cd;
b2BodyDef bd;
b2Body* b;
cd.radius = br;
cd.density= 0.001f;
bd.position.Set(0.0f,10.0f*gy);
for (int32 i=0; i<60; i++ )
{
b = m_world->CreateBody(&bd);
b->CreateFixture (&cd);
b->SetMassFromShapes();
}
}
}
/// Create compound (soft) body using a triangle mesh
/// If meshDensity is 0, a minimal grid is generated.
/// Actually pd and dj define the behaviour for all triangles
void CreateSoftBody(b2Vec2 pos, int32 meshDensity,int32 options,
b2PolygonDef pd, b2DistanceJointDef dj,
tmVertex* nodes,int32 n_nodes,
tmSegmentId *segments=NULL, int32 n_segments=0,
tmVertex* holes=NULL, int32 n_holes=0)
{
int32 i;
/// TriangleMesh defs
tmTriangle *triangles;
TriangleMesh md;
/// box2d defs
b2BodyDef bd;
b2Body *b;
/// in case of meshDensit>3 ...
md.SetMaxVertexCount(meshDensity);
if (options>0) md.SetOptions(options);
/// triangulator main
md.Mesh( nodes, n_nodes, segments,n_segments, holes, n_holes );
md.PrintData();
/// bodies (triangles)
triangles = md.GetTriangles();
if ( triangles==NULL ) return;
pd.vertexCount = 3;
for ( i=0; i<md.GetTriangleCount(); i++ )
{
if ( triangles[i].inside )
{
/// triangle -> b2PolygonDef
pd.vertices[0].Set(triangles[i].v[0]->x, triangles[i].v[0]->y);
pd.vertices[1].Set(triangles[i].v[1]->x, triangles[i].v[1]->y);
pd.vertices[2].Set(triangles[i].v[2]->x, triangles[i].v[2]->y);
bd.position.Set(pos.x,pos.y);
b = m_world->CreateBody(&bd);
b->CreateFixture(&pd);
b->SetMassFromShapes();
/// we need the body pointer in the triangles for the joints later
triangles[i].userData = (void *)b;
}
}
/// joints
/// for each triangle-pair in edges, connect with a distance joint
tmEdge *edges;
tmTriangle *t0,*t1;
b2Body *b1,*b2;
edges = md.GetEdges();
for ( i=0; i<md.GetEdgeCount(); i++ )
{
t0 = edges[i].t[0];
t1 = edges[i].t[1];
if ( (t0->inside==false) || (t1->inside==false) ) continue;
/// Get bodies
b1 = (b2Body*)t0->userData;
b2 = (b2Body*)t1->userData;
if ( b1==NULL || b2==NULL ) continue;
dj.Initialize( b1,b2, b1->GetWorldCenter(), b2->GetWorldCenter());
m_world->CreateJoint(&dj);
}
/// clean TriangleMesh
md.FreeMemory();
}
/// maybe here to check for maximal reaction forces to break a body
void Step(Settings* settings)
{
b2Joint *jStressed=NULL;
float32 F=0.0f, tmp;
Test::Step(settings);
for (b2Joint* j = m_world->GetJointList(); j; j = j->GetNext())
{
tmp = j->GetReactionForce(settings->hz).Length();
if ( tmp>F )
{
F = tmp;
jStressed = j;
}
}
if ( jStressed && (F>maxAllowableForce) )
{
m_world->DestroyJoint(jStressed);
}
m_debugDraw.DrawString(1, m_textLine,"max.reactionforce=%.0f allowable=%.0f change:-+", (float)F,(float)maxAllowableForce);
m_textLine += 12;
m_debugDraw.DrawString(1, m_textLine,"drawmode(%s):d mesh:m static(%s):s", (m_drawMode)?"on":"off", (m_staticBodies)?"on":"off");
m_textLine += 12;
for ( int32 i=0; i<m_drawCount-1; i++ )
{
b2Vec2 p1,p2;
p1.Set(m_drawVertices[i].x,m_drawVertices[i].y);
p2.Set(m_drawVertices[i+1].x,m_drawVertices[i+1].y);
m_debugDraw.DrawSegment(p1,p2,b2Color(0.6f,0.2f,0.2f));
}
}
/// default constructor for TestEntries.cpp
static Test* Create()
{
return new BreakableBody;
}
void Keyboard(unsigned char key)
{
switch (key)
{
case '-':
maxAllowableForce -= 5.0f;
break;
case '+':
maxAllowableForce += 5.0f;
break;
case 'd':
m_drawMode = !m_drawMode;
break;
case 's':
m_staticBodies = !m_staticBodies;
break;
case 'm':
if ( m_drawCount>0 )
{
b2PolygonDef pd;
b2DistanceJointDef dj;
dj.collideConnected = true;
dj.frequencyHz = 20.f;
dj.dampingRatio = 10.0f;
pd.density = (m_staticBodies) ? 0.0f : 1.0f/32.0f;
pd.friction = 0.99f;
pd.restitution = 0.01f;
CreateSoftBody( b2Vec2(0.0f,0.0f), 0, tmO_SEGMENTBOUNDARY|tmO_GRADING,
pd, dj, m_drawVertices, m_drawCount) ;
m_drawCount = 0;
m_drawMode = false;
}
break;
}
}
void MouseDown(const b2Vec2& p)
{
if ( m_drawMode && (m_drawCount<N_MAXVERTEX) )
{
m_drawVertices[m_drawCount].x = p.x;
m_drawVertices[m_drawCount].y = p.y;
m_drawCount++;
}
else Test::MouseDown(p);
}
/*
void MouseMove(const b2Vec2& p)
{
m_lastPoint = p;
if (m_drawMode)
{
}
}
*/
void MouseUp(const b2Vec2& p)
{
Test::MouseUp(p);
}
/// examples
void ExampleData(char which)
{
/// @ - ring
static tmVertex ring_nodes[] = {
{ 6.00f, 3.00f},
{ 5.12f, 5.12f},
{ 3.00f, 6.00f},
{ 0.88f, 5.12f},
{ 0.00f, 3.00f},
{ 0.88f, 0.88f},
{ 3.00f, 0.00f},
{ 5.12f, 0.88f},
{ 4.50f, 3.00f},
{ 4.06f, 4.06f},
{ 3.00f, 4.50f},
{ 1.94f, 4.06f},
{ 1.50f, 3.00f},
{ 1.94f, 1.94f},
{ 3.00f, 1.50f},
{ 4.06f, 1.94f}
};
static tmSegmentId ring_segments[] = {
{ 9, 10 },
{ 10, 11 },
{ 11, 12 },
{ 12, 13 },
{ 13, 14 },
{ 14, 15 },
{ 15, 16 },
{ 16, 9 }
};
static tmVertex ring_holes[] = {
{ 3.00f, 3.00f}
};
/// 'B'
static tmVertex B_nodes[] = {
{ 0.00f, 0.00f},
{ 4.00f, 0.00f},
{ 5.00f, 2.00f},
{ 5.00f, 4.00f},
{ 4.00f, 5.00f},
{ 5.00f, 6.00f},
{ 5.00f, 8.00f},
{ 4.00f, 9.00f},
{ 0.00f, 9.00f},
{ 0.00f, 5.00f},
{ 1.50f, 1.50f},
{ 3.50f, 1.50f},
{ 3.50f, 4.00f},
{ 1.50f, 4.00f},
{ 1.50f, 6.00f},
{ 3.50f, 6.00f},
{ 3.50f, 8.50f},
{ 1.50f, 8.50f}
};
static tmSegmentId B_segments[] = {
{ 1, 2 },
{ 2, 3 },
{ 3, 4 },
{ 4, 5 },
{ 5, 6 },
{ 6, 7 },
{ 7, 8 },
{ 8, 9 },
{ 9, 10 },
{ 10, 1 },
{ 11, 12 },
{ 12, 13 },
{ 13, 14 },
{ 14, 11 },
{ 15, 16 },
{ 16, 17 },
{ 17, 18 },
{ 18, 15 }
};
static tmVertex B_holes[] = {
{ 5.00f, 5.00f},
{ 2.50f, 2.50f},
{ 2.50f, 7.00f}
};
/// 'D'
static tmVertex D_nodes[] = {
{ 0.00f, 0.00f},
{ 4.00f, 0.00f},
{ 5.00f, 2.50f},
{ 5.00f, 7.00f},
{ 4.00f, 9.00f},
{ 0.00f, 9.00f},
{ 0.00f, 5.00f},
{ 1.50f, 2.50f},
{ 3.50f, 2.50f},
{ 3.50f, 7.00f},
{ 1.50f, 7.00f},
};
static tmSegmentId D_segments[] = {
{ 1, 2 },
{ 2, 3 },
{ 3, 4 },
{ 4, 5 },
{ 5, 6 },
{ 6, 7 },
{ 7, 1 },
{ 8, 9 },
{ 9, 10 },
{ 10, 11 },
{ 11, 8 },
};
static tmVertex D_holes[] = {
{ 2.50f, 5.00f},
};
/// 'x'
static tmVertex x_nodes[] = {
{ 0.00f, 0.00f},
{ 1.00f, 0.00f},
{ 5.00f, 0.00f},
{ 6.00f, 0.00f},
{ 6.00f, 1.00f},
{ 6.00f, 5.00f},
{ 6.00f, 6.00f},
{ 1.00f, 6.00f},
{ 5.00f, 6.00f},
{ 0.00f, 6.00f},
{ 0.00f, 5.00f},
{ 0.00f, 1.00f},
{ 3.00f, 2.00f},
{ 4.00f, 3.00f},
{ 3.00f, 4.00f},
{ 2.00f, 3.00f}
};
static tmSegmentId x_segments[] = {
{ 2, 13 },
{ 3, 13 },
{ 5, 14 },
{ 6, 14 },
{ 8, 15 },
{ 9, 15 },
{ 11, 16 },
{ 12, 16 }
};
static tmVertex x_holes[] = {
{ 3.00f, 1.00f},
{ 5.00f, 3.00f},
{ 3.00f, 5.00f},
{ 1.00f, 3.00f},
};
/// '2'
static tmVertex two_nodes[] = {
{ 0.00f, 0.00f},
{ 6.00f, 0.00f},
{ 6.00f, 1.00f},
{ 2.00f, 1.00f},
{ 2.00f, 2.00f},
{ 6.00f, 6.00f},
{ 6.00f, 8.00f},
{ 5.00f, 9.00f},
{ 2.00f, 9.00f},
{ 1.00f, 7.50f},
{ 0.00f, 2.50f},
{ 5.00f, 6.50f},
{ 5.00f, 8.00f},
{ 2.50f, 8.00f},
{ 2.00f, 7.50f},
};
static tmSegmentId two_segments[] = {
{ 1, 2 },
{ 2, 3 },
{ 3, 4 },
{ 4, 5 },
{ 5, 6 },
{ 6, 7 },
{ 7, 8 },
{ 8, 9 },
{ 9, 10 },
{ 10, 15 },
{ 11, 12 },
{ 12, 13 },
{ 13, 14 },
{ 14, 15 },
};
static tmVertex two_holes[] = {
{ 3.00f, 5.00f},
{ 4.00f, 3.00f},
};
/// '-' beam
static tmVertex beam_nodes[] = {
{ 0.00f, 0.00f},
{ 32.00f, 0.00f},
{ 32.00f, 3.00f},
{ 0.00f, 3.00f},
};
static tmSegmentId *beam_segments = NULL;
static tmVertex *beam_holes = NULL;
/// 'b' a box
static tmVertex b_nodes[] = {
{ 0.00f, 0.00f},
{ 10.00f, 0.00f},
{ 10.00f, 10.00f},
{ 0.00f, 10.00f},
{ 2.00f, 2.00f},
{ 8.00f, 2.00f},
{ 8.00f, 8.00f},
{ 2.00f, 8.00f},
};
static tmSegmentId b_segments[] = {
{ 5, 6 },
{ 6, 7 },
{ 7, 8 },
{ 8, 5 },
};
static tmVertex b_holes[] = {
{ 5.0f, 5.0f},
};
/// choose...
switch( which )
{
case 'B':
nodes = B_nodes;
segments = B_segments;
holes = B_holes;
n_nodes = sizeof(B_nodes)/sizeof(tmVertex);
n_segments = (segments) ? sizeof(B_segments)/sizeof(tmSegmentId) : 0;
n_holes = (holes) ? sizeof(B_holes)/sizeof(tmVertex) : 0;
break;
case 'D':
nodes = D_nodes;
segments = D_segments;
holes = D_holes;
n_nodes = sizeof(D_nodes)/sizeof(tmVertex);
n_segments = (segments) ? sizeof(D_segments)/sizeof(tmSegmentId) : 0;
n_holes = (holes) ? sizeof(D_holes)/sizeof(tmVertex) : 0;
break;
case 'x':
nodes = x_nodes;
segments = x_segments;
holes = x_holes;
n_nodes = sizeof(x_nodes)/sizeof(tmVertex);
n_segments = (segments) ? sizeof(x_segments)/sizeof(tmSegmentId) : 0;
n_holes = (holes) ? sizeof(x_holes)/sizeof(tmVertex) : 0;
break;
case '@':
nodes = ring_nodes;
segments = ring_segments;
holes = ring_holes ;
n_nodes = sizeof(ring_nodes)/sizeof(tmVertex);
n_segments = (segments) ? sizeof(ring_segments)/sizeof(tmSegmentId) : 0;
n_holes = (holes) ? sizeof(ring_holes)/sizeof(tmVertex) : 0;
break;
case '2':
nodes = two_nodes;
segments = two_segments;
holes = two_holes ;
n_nodes = sizeof(two_nodes)/sizeof(tmVertex);
n_segments = (segments) ? sizeof(two_segments)/sizeof(tmSegmentId) : 0;
n_holes = (holes) ? sizeof(two_holes)/sizeof(tmVertex) : 0;
break;
case '-':
nodes = beam_nodes;
segments = beam_segments;
holes = beam_holes ;
n_nodes = sizeof(beam_nodes)/sizeof(tmVertex);
n_segments = (segments) ? sizeof(beam_segments)/sizeof(tmSegmentId) : 0;
n_holes = (holes) ? sizeof(beam_holes)/sizeof(tmVertex) : 0;
break;
case 'b':
nodes = b_nodes;
segments = b_segments;
holes = b_holes;
n_nodes = sizeof(b_nodes)/sizeof(tmVertex);
n_segments = (segments) ? sizeof(b_segments)/sizeof(tmSegmentId) : 0;
n_holes = (holes) ? sizeof(b_holes)/sizeof(tmVertex) : 0;
break;
}
}
///
bool m_drawMode, m_staticBodies;
tmVertex m_drawVertices[N_MAXVERTEX];
int32 m_drawCount;
///
float32 maxAllowableForce;
/// temporary vars to hold the examples
tmVertex *nodes;
int32 n_nodes;
tmVertex *holes;
int32 n_holes;
tmSegmentId *segments;
int32 n_segments;
};
#undef H
#endif

View File

@@ -0,0 +1,215 @@
/*
* Copyright (c) 2008-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 CAR_H
#define CAR_H
// Adapted from SpiritWalkers by darkzerox
class Car : public Test
{
public:
Car()
{
{ // car body
b2PolygonDef poly1, poly2;
// bottom half
poly1.vertexCount = 5;
poly1.vertices[4].Set(-2.2f,-0.74f);
poly1.vertices[3].Set(-2.2f,0);
poly1.vertices[2].Set(1.0f,0);
poly1.vertices[1].Set(2.2f,-0.2f);
poly1.vertices[0].Set(2.2f,-0.74f);
poly1.filter.groupIndex = -1;
poly1.density = 20.0f;
poly1.friction = 0.68f;
poly1.filter.groupIndex = -1;
// top half
poly2.vertexCount = 4;
poly2.vertices[3].Set(-1.7f,0);
poly2.vertices[2].Set(-1.3f,0.7f);
poly2.vertices[1].Set(0.5f,0.74f);
poly2.vertices[0].Set(1.0f,0);
poly2.filter.groupIndex = -1;
poly2.density = 5.0f;
poly2.friction = 0.68f;
poly2.filter.groupIndex = -1;
b2BodyDef bd;
bd.position.Set(-35.0f, 2.8f);
m_vehicle = m_world->CreateBody(&bd);
m_vehicle->CreateFixture(&poly1);
m_vehicle->CreateFixture(&poly2);
m_vehicle->SetMassFromShapes();
}
{ // vehicle wheels
b2CircleDef circ;
circ.density = 40.0f;
circ.radius = 0.38608f;
circ.friction = 0.8f;
circ.filter.groupIndex = -1;
b2BodyDef bd;
bd.allowSleep = false;
bd.position.Set(-33.8f, 2.0f);
m_rightWheel = m_world->CreateBody(&bd);
m_rightWheel->CreateFixture(&circ);
m_rightWheel->SetMassFromShapes();
bd.position.Set(-36.2f, 2.0f);
m_leftWheel = m_world->CreateBody(&bd);
m_leftWheel->CreateFixture(&circ);
m_leftWheel->SetMassFromShapes();
}
{ // join wheels to chassis
b2Vec2 anchor;
b2RevoluteJointDef jd;
jd.Initialize(m_vehicle, m_leftWheel, m_leftWheel->GetWorldCenter());
jd.collideConnected = false;
jd.enableMotor = true;
jd.maxMotorTorque = 10.0f;
jd.motorSpeed = 0.0f;
m_leftJoint = (b2RevoluteJoint*)m_world->CreateJoint(&jd);
jd.Initialize(m_vehicle, m_rightWheel, m_rightWheel->GetWorldCenter());
jd.collideConnected = false;
m_rightJoint = (b2RevoluteJoint*)m_world->CreateJoint(&jd);
}
{ // ground
b2PolygonDef box;
box.SetAsBox(19.5f, 0.5f);
box.friction = 0.62f;
b2BodyDef bd;
bd.position.Set(-25.0f, 1.0f);
b2Body* ground = m_world->CreateBody(&bd);
ground->CreateFixture(&box);
}
{ // more ground
b2PolygonDef box;
b2BodyDef bd;
box.SetAsBox(9.5f, 0.5f, b2Vec2_zero, 0.1f * b2_pi);
box.friction = 0.62f;
bd.position.Set(27.0f - 30.0f, 3.1f);
b2Body* ground = m_world->CreateBody(&bd);
ground->CreateFixture(&box);
}
{ // more ground
b2PolygonDef box;
b2BodyDef bd;
box.SetAsBox(9.5f, 0.5f, b2Vec2_zero, -0.1f * b2_pi);
box.friction = 0.62f;
bd.position.Set(55.0f - 30.0f, 3.1f);
b2Body* ground = m_world->CreateBody(&bd);
ground->CreateFixture(&box);
}
{ // more ground
b2PolygonDef box;
b2BodyDef bd;
box.SetAsBox(9.5f, 0.5f, b2Vec2_zero, 0.03f * b2_pi);
box.friction = 0.62f;
bd.position.Set(41.0f, 2.0f);
b2Body* ground = m_world->CreateBody(&bd);
ground->CreateFixture(&box);
}
{ // more ground
b2PolygonDef box;
b2BodyDef bd;
box.SetAsBox(5.0f, 0.5f, b2Vec2_zero, 0.15f * b2_pi);
box.friction = 0.62f;
bd.position.Set(50.0f, 4.0f);
b2Body* ground = m_world->CreateBody(&bd);
ground->CreateFixture(&box);
}
{ // more ground
b2PolygonDef box;
b2BodyDef bd;
box.SetAsBox(20.0f, 0.5f);
box.friction = 0.62f;
bd.position.Set(85.0f, 2.0f);
b2Body* ground = m_world->CreateBody(&bd);
ground->CreateFixture(&box);
}
}
void Step(Settings* settings)
{
m_debugDraw.DrawString(5, m_textLine, "Keys: left = a, brake = s, right = d");
m_textLine += 15;
Test::Step(settings);
}
void Keyboard(unsigned char key)
{
switch (key)
{
case 'a':
m_leftJoint->SetMaxMotorTorque(800.0f);
m_leftJoint->SetMotorSpeed(12.0f);
break;
case 's':
m_leftJoint->SetMaxMotorTorque(100.0f);
m_leftJoint->SetMotorSpeed(0.0f);
break;
case 'd':
m_leftJoint->SetMaxMotorTorque(1200.0f);
m_leftJoint->SetMotorSpeed(-36.0f);
break;
}
}
static Test* Create()
{
return new Car;
}
b2Body* m_leftWheel;
b2Body* m_rightWheel;
b2Body* m_vehicle;
b2RevoluteJoint* m_leftJoint;
b2RevoluteJoint* m_rightJoint;
};
#endif

View File

@@ -0,0 +1,260 @@
/*
* 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.
*/
// Contributed by caspin.
#ifndef CONTACT_CB_H
#define CONTACT_CB_H
#include <set>
#include <deque>
#include <sstream>
#include <string>
#include <iostream>
bool key_comp( const ContactPoint& lhs, const ContactPoint& rhs )
{
if( lhs.fixtureA < rhs.fixtureA ) return true;
if( lhs.fixtureA == rhs.fixtureA && lhs.fixtureB < rhs.fixtureB ) return true;
if( lhs.fixtureA == rhs.fixtureA && lhs.fixtureB == rhs.fixtureB && lhs.id.key < rhs.id.key ) return true;
return false;
}
class ContactCB : public Test
{
public:
ContactCB()
: m_set(&key_comp)
{
b2PolygonDef sd;
sd.friction = 0;
sd.vertexCount = 3;
sd.vertices[0].Set(10,10);
sd.vertices[1].Set(9,7);
sd.vertices[2].Set(10,0);
m_world->GetGroundBody()->CreateFixture(&sd);
sd.vertices[0].Set(9,7);
sd.vertices[1].Set(8,0);
sd.vertices[2].Set(10,0);
m_world->GetGroundBody()->CreateFixture(&sd);
sd.vertices[0].Set(9,7);
sd.vertices[1].Set(8,5);
sd.vertices[2].Set(8,0);
m_world->GetGroundBody()->CreateFixture(&sd);
sd.vertices[0].Set(8,5);
sd.vertices[1].Set(7,4);
sd.vertices[2].Set(8,0);
m_world->GetGroundBody()->CreateFixture(&sd);
sd.vertices[0].Set(7,4);
sd.vertices[1].Set(5,0);
sd.vertices[2].Set(8,0);
m_world->GetGroundBody()->CreateFixture(&sd);
sd.vertices[0].Set(7,4);
sd.vertices[1].Set(5,3);
sd.vertices[2].Set(5,0);
m_world->GetGroundBody()->CreateFixture(&sd);
sd.vertices[0].Set(5,3);
sd.vertices[1].Set(2,2);
sd.vertices[2].Set(5,0);
m_world->GetGroundBody()->CreateFixture(&sd);
sd.vertices[0].Set(2,2);
sd.vertices[1].Set(0,0);
sd.vertices[2].Set(5,0);
m_world->GetGroundBody()->CreateFixture(&sd);
sd.vertices[0].Set(2,2);
sd.vertices[1].Set(-2,2);
sd.vertices[2].Set(0,0);
m_world->GetGroundBody()->CreateFixture(&sd);
sd.vertices[2].Set(-2,2);
sd.vertices[1].Set(0,0);
sd.vertices[0].Set(-5,0);
m_world->GetGroundBody()->CreateFixture(&sd);
sd.vertices[2].Set(-5,3);
sd.vertices[1].Set(-2,2);
sd.vertices[0].Set(-5,0);
m_world->GetGroundBody()->CreateFixture(&sd);
sd.vertices[2].Set(-7,4);
sd.vertices[1].Set(-5,3);
sd.vertices[0].Set(-5,0);
m_world->GetGroundBody()->CreateFixture(&sd);
sd.vertices[2].Set(-7,4);
sd.vertices[1].Set(-5,0);
sd.vertices[0].Set(-8,0);
m_world->GetGroundBody()->CreateFixture(&sd);
sd.vertices[2].Set(-8,5);
sd.vertices[1].Set(-7,4);
sd.vertices[0].Set(-8,0);
m_world->GetGroundBody()->CreateFixture(&sd);
sd.vertices[2].Set(-9,7);
sd.vertices[1].Set(-8,5);
sd.vertices[0].Set(-8,0);
m_world->GetGroundBody()->CreateFixture(&sd);
sd.vertices[2].Set(-9,7);
sd.vertices[1].Set(-8,0);
sd.vertices[0].Set(-10,0);
m_world->GetGroundBody()->CreateFixture(&sd);
sd.vertices[2].Set(-10,10);
sd.vertices[1].Set(-9,7);
sd.vertices[0].Set(-10,0);
m_world->GetGroundBody()->CreateFixture(&sd);
sd.SetAsBox(.5,6,b2Vec2(10.5,6),0);
m_world->GetGroundBody()->CreateFixture(&sd);
sd.SetAsBox(.5,6,b2Vec2(-10.5,6),0);
m_world->GetGroundBody()->CreateFixture(&sd);
b2BodyDef bd;
bd.position.Set(9.5,60);
b2Body* m_ball = m_world->CreateBody( &bd );
#if 1
b2PolygonDef cd;
cd.vertexCount = 8;
float32 w = 0.95f;
float32 b = w / (2.0f + sqrtf(2.0f));
float32 s = sqrtf(2.0f) * b;
cd.vertices[0].Set(0.5f * s, 0.0f);
cd.vertices[1].Set(0.5f * w, b);
cd.vertices[2].Set(0.5f * w, b + s);
cd.vertices[3].Set(0.5f * s, w);
cd.vertices[4].Set(-0.5f * s, w);
cd.vertices[5].Set(-0.5f * w, b + s);
cd.vertices[6].Set(-0.5f * w, b);
cd.vertices[7].Set(-0.5f * s, 0.0f);
cd.density = 1.0f;
#else
b2CircleDef cd;
cd.radius = 0.33f;
cd.friction = 0;
cd.density = 1;
#endif
m_ball_shape = m_ball->CreateFixture(&cd);
m_ball->SetMassFromShapes();
}
void Step(Settings* settings)
{
Test::Step(settings);
std::ostringstream oss;
oss << std::hex;
for (int32 i=0; i< m_pointCount; ++i)
{
#if 0
if (m_points[i].shape1 > m_points[i].shape2)
{
b2Swap(m_points[i].shape1, m_points[i].shape2);
m_points[i].normal *= -1.0f;
m_points[i].velocity *= -1.0f;
}
#endif
oss.str("");
switch( m_points[i].state )
{
case e_contactAdded:
{
if( ! m_set.insert( m_points[i] ).second )
{
oss << "ERROR ";
}
else
{
oss << " ";
}
oss << "added: " << m_points[i].fixtureA << " -> " << m_points[i].fixtureB;
oss << " : " << m_points[i].id.key;
m_strings.push_back( oss.str() );
std::cout << oss.str() << std::endl;
break;
}
case e_contactRemoved:
{
if( m_set.find( m_points[i] ) == m_set.end() )
{
oss << "ERROR ";
}
else
{
oss << " ";
}
oss << "removed: " << m_points[i].fixtureA << " -> " << m_points[i].fixtureB;
oss << " : " << m_points[i].id.key;
m_strings.push_back( oss.str() );
std::cout << oss.str() << std::endl;
m_set.erase( m_points[i] );
break;
}
case e_contactPersisted:
{
if( m_set.find( m_points[i] ) == m_set.end() )
{
oss << "ERROR persist: " << m_points[i].fixtureA << " -> ";
oss << m_points[i].fixtureB << " : " << m_points[i].id.key;
m_strings.push_back( oss.str() );
std::cout << oss.str() << std::endl;
}
break;
}
}
}
while( m_strings.size() > 15 )
{
m_strings.pop_front();
}
for( unsigned i=0; i<m_strings.size(); ++i )
{
m_debugDraw.DrawString(5, m_textLine, m_strings[i].c_str() );
m_textLine += 15;
}
}
static Test* Create()
{
return new ContactCB;
}
b2Body* m_ball;
b2Body* m_bullet;
b2Fixture* m_ball_shape;
std::set<ContactPoint,bool(*)(const ContactPoint&,const ContactPoint&)> m_set;
std::deque<std::string> m_strings;
};
#endif // CONTACT_CB_H

View File

@@ -0,0 +1,294 @@
/*
* 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 DYNAMIC_EDGES_H
#define DYNAMIC_EDGES_H
class DynamicEdges : public Test
{
public:
DynamicEdges()
{
{
b2BodyDef bd;
bd.position.Set(0.0f, -10.0f);
b2Body* body = m_world->CreateBody(&bd);
b2PolygonDef sd;
sd.SetAsBox(50.0f, 10.0f);
body->CreateFixture(&sd);
}
{
b2CircleDef sd1;
sd1.radius = 0.5f;
sd1.localPosition.Set(-0.5f, 0.5f);
sd1.density = 2.0f;
b2CircleDef sd2;
sd2.radius = 0.5f;
sd2.localPosition.Set(0.5f, 0.5f);
sd2.density = 0.0f; // massless
for (int i = 0; i < 10; ++i)
{
float32 x = RandomFloat(-0.1f, 0.1f);
b2BodyDef bd;
bd.position.Set(x + 5.0f, 1.05f + 2.5f * i);
bd.angle = RandomFloat(-b2_pi, b2_pi);
b2Body* body = m_world->CreateBody(&bd);
body->CreateFixture(&sd1);
body->CreateFixture(&sd2);
body->SetMassFromShapes();
}
}
{
b2PolygonDef sd1;
sd1.SetAsBox(0.25f, 0.5f);
sd1.density = 2.0f;
b2PolygonDef sd2;
sd2.SetAsBox(0.25f, 0.5f, b2Vec2(0.0f, -0.5f), 0.5f * b2_pi);
sd2.density = 2.0f;
for (int i = 0; i < 10; ++i)
{
float32 x = RandomFloat(-0.1f, 0.1f);
b2BodyDef bd;
bd.position.Set(x - 5.0f, 1.05f + 2.5f * i);
bd.angle = RandomFloat(-b2_pi, b2_pi);
b2Body* body = m_world->CreateBody(&bd);
body->CreateFixture(&sd1);
body->CreateFixture(&sd2);
body->SetMassFromShapes();
}
}
{
b2XForm xf1;
xf1.R.Set(0.3524f * b2_pi);
xf1.position = b2Mul(xf1.R, b2Vec2(1.0f, 0.0f));
b2PolygonDef sd1;
sd1.vertexCount = 3;
sd1.vertices[0] = b2Mul(xf1, b2Vec2(-1.0f, 0.0f));
sd1.vertices[1] = b2Mul(xf1, b2Vec2(1.0f, 0.0f));
sd1.vertices[2] = b2Mul(xf1, b2Vec2(0.0f, 0.5f));
sd1.density = 2.0f;
b2XForm xf2;
xf2.R.Set(-0.3524f * b2_pi);
xf2.position = b2Mul(xf2.R, b2Vec2(-1.0f, 0.0f));
b2PolygonDef sd2;
sd2.vertexCount = 3;
sd2.vertices[0] = b2Mul(xf2, b2Vec2(-1.0f, 0.0f));
sd2.vertices[1] = b2Mul(xf2, b2Vec2(1.0f, 0.0f));
sd2.vertices[2] = b2Mul(xf2, b2Vec2(0.0f, 0.5f));
sd2.density = 2.0f;
for (int32 i = 0; i < 10; ++i)
{
float32 x = RandomFloat(-0.1f, 0.1f);
b2BodyDef bd;
bd.position.Set(x, 2.05f + 2.5f * i);
bd.angle = 0.0f;
b2Body* body = m_world->CreateBody(&bd);
body->CreateFixture(&sd1);
body->CreateFixture(&sd2);
body->SetMassFromShapes();
}
}
{
b2PolygonDef sd_bottom;
sd_bottom.SetAsBox( 1.5f, 0.15f );
sd_bottom.density = 4.0f;
b2PolygonDef sd_left;
sd_left.SetAsBox(0.15f, 2.7f, b2Vec2(-1.45f, 2.35f), 0.2f);
sd_left.density = 4.0f;
b2PolygonDef sd_right;
sd_right.SetAsBox(0.15f, 2.7f, b2Vec2(1.45f, 2.35f), -0.2f);
sd_right.density = 4.0f;
b2BodyDef bd;
bd.position.Set( 0.0f, 2.0f );
b2Body* body = m_world->CreateBody(&bd);
body->CreateFixture(&sd_bottom);
body->CreateFixture(&sd_left);
body->CreateFixture(&sd_right);
body->SetMassFromShapes();
}
{
float32 loop1[] =
{
0.063134534f,8.3695248f,
0.94701801f,9.3165428f,
0.0f,9.0640047f,
-0.12626907f,10.326695f,
1.4520943f,11.77879f,
2.2728432f,10.137292f,
2.3991123f,11.147444f,
3.5986685f,10.958041f,
3.9143411f,7.3593722f,
4.1668793f,9.4428119f,
5.4295699f,9.3165428f,
6.2503189f,8.3063903f,
6.6922606f,10.137292f,
4.9876282f,9.8216191f,
4.7350901f,10.958041f,
7.2604714f,11.652521f,
10.732871f,11.147444f,
10.480333f,10.642368f,
10.732871f,9.8216191f,
11.55362f,9.4428119f,
12.374369f,9.3796773f,
13.005714f,9.8216191f,
13.195118f,10.38983f,
13.005714f,10.768637f,
12.626907f,10.894906f,
12.753176f,11.526252f,
13.573925f,11.715655f,
14.836616f,11.399982f,
16.351844f,10.768637f,
17.867073f,11.399982f,
17.803939f,10.263561f,
17.361997f,8.3063903f,
17.803939f,8.1801212f,
18.056477f,9.5059464f,
18.182746f,11.336848f,
18.561553f,11.210579f,
18.561553f,9.6322155f,
18.561553f,7.7381795f,
18.687822f,5.5284708f,
19.382302f,5.6547398f,
19.066629f,8.1801212f,
19.003495f,10.263561f,
19.066629f,11.463117f,
19.887378f,11.841924f,
20.708127f,11.273713f,
21.0238f,10.011023f,
20.708127f,7.2962377f,
21.086934f,6.2860852f,
21.150069f,3.7607038f,
20.392455f,2.5611476f,
18.624688f,2.5611476f,
20.771262f,2.1192059f,
20.771262f,0.22516988f,
18.624688f,-0.2799064f,
13.826463f,0.16203534f,
14.015867f,1.7403987f,
13.195118f,2.1823404f,
12.626907f,1.5509951f,
12.879445f,0.85651522f,
12.626907f,0.35143895f,
10.543467f,1.298457f,
11.490485f,3.9501074f,
13.889598f,3.6344347f,
13.889598f,2.9399549f,
14.584077f,3.8869729f,
11.932427f,5.2127981f,
9.7227183f,4.0132419f,
10.796005f,3.5081657f,
9.7858528f,3.2556275f,
10.796005f,2.4980131f,
7.9549513f,1.7403987f,
9.6595837f,1.424726f,
9.217642f,0.66711162f,
8.270624f,-0.090502792f,
7.0079333f,0.85651522f,
6.1240498f,-0.15363733f,
6.1240498f,3.192493f,
5.6821081f,2.4348786f,
4.9876282f,2.1192059f,
4.1037447f,1.8666678f,
3.0304576f,1.8666678f,
2.0834396f,2.245475f,
1.6414979f,2.6242822f,
1.3258252f,3.5081657f,
1.2626907f,0.47770802f,
0.63134534f,0.035766276f,
0.063134534f,0.98278429f
};
float32 loop2[] =
{
8.270624f,6.1598161f,
8.270624f,5.3390672f,
8.7757003f,5.086529f,
9.4701801f,5.5284708f,
9.217642f,6.033547f,
8.7757003f,6.4123542f
};
b2Vec2 b2Loop1[87];
b2Vec2 b2Loop2[6];
for (int32 i = 86; i >= 0; i--) {
b2Loop1[86 - i].Set(loop1[i*2] + 10.0f, loop1[i*2 + 1] + 1.0f);
}
/*for (int32 i = 0; i < 87; i++) {
b2Loop1[i].Set(loop1[i*2] + 10.0f, loop1[i*2 + 1] + 1.0f);
}*/
for (int32 i = 0; i < 6; i++) {
b2Loop2[i].Set(loop2[i*2], loop2[i*2 + 1]);
}
b2BodyDef bd;
bd.position.Set( 0.0f, 0.0f );
b2Body* body = m_world->CreateBody(&bd);
b2CircleDef weight;
weight.filter.maskBits = 0x0000;
weight.density = 4.0f;
weight.radius = 0.5f;
weight.localPosition.Set(8.9f, 5.75f);
body->CreateFixture(&weight);
b2EdgeChainDef edgeDef;
edgeDef.vertexCount = 6;
edgeDef.vertices = b2Loop2;
b2CreateEdgeChain(body, &edgeDef);
body->SetMassFromShapes();
body = m_world->CreateBody(&bd);
weight.radius = 5.0f;
weight.localPosition.Set(20.5f, 7.0f);
body->CreateFixture(&weight);
edgeDef.vertexCount = 87;
edgeDef.vertices = b2Loop1;
b2CreateEdgeChain(body, &edgeDef);
body->SetMassFromShapes();
}
}
static Test* Create()
{
return new DynamicEdges;
}
};
#endif

View File

@@ -0,0 +1,465 @@
/*
* 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 ELASTIC_BODY_H
#define ELASTIC_BODY_H
class ElasticBody : public Test
{
public:
b2Body* bodies[64];
b2Body* m_ground;
b2Body* m_elev;
b2PrismaticJoint* m_joint_elev;
/// Main...
ElasticBody()
{
/// Bottom static body
{
b2PolygonDef sd;
sd.SetAsBox(50.0f, 2.0f);
sd.friction = 0.1f;
sd.restitution = 0.1f;
b2BodyDef bd;
bd.position.Set(-1.0f, -7.5f);
m_ground = m_world->CreateBody(&bd);
m_ground->CreateFixture(&sd);
}
/// Upper static body
{
b2PolygonDef sd;
sd.SetAsBox(20.0f, 0.50f,b2Vec2(0.f,0.f),0.047f*b2_pi);
sd.friction = 0.01f;
sd.restitution = 0.001f;
b2BodyDef bd;
bd.position.Set(-20.f, 93.0f);
b2Body* g = m_world->CreateBody(&bd);
g->CreateFixture(&sd);
sd.SetAsBox(15.f, 0.50f,b2Vec2(-15.0f,12.5f),0.0f);
g->CreateFixture(&sd);
sd.SetAsBox(20.f,0.5f,b2Vec2(0.0f,-25.0f),-0.5f);
g->CreateFixture(&sd);
}
/// Left channel left wall
{
b2PolygonDef sd;
sd.SetAsBox(0.7f, 55.0f);
sd.friction = 0.1f;
sd.restitution = 0.1f;
b2BodyDef bd;
bd.position.Set(-49.3f, 50.0f);
b2Body* g = m_world->CreateBody(&bd);
g->CreateFixture(&sd);
}
/// Right wall
{
b2PolygonDef sd;
sd.SetAsBox(0.7f, 55.0f);
sd.friction = 0.1f;
sd.restitution = 0.1f;
b2BodyDef bd;
bd.position.Set(45.f, 50.0f);
b2Body* g = m_world->CreateBody(&bd);
g->CreateFixture(&sd);
}
/// Left channel right upper wall
{
b2PolygonDef sd;
sd.SetAsBox(0.5f, 20.0f);
sd.friction = 0.05f;
sd.restitution = 0.01f;
b2BodyDef bd;
bd.position.Set(-42.0f, 70.0f);
bd.angle = -0.03f*b2_pi;
b2Body* g = m_world->CreateBody(&bd);
g->CreateFixture(&sd);
}
/// Left channel right lower wall
{
b2PolygonDef sd;
sd.SetAsBox(0.50f, 23.0f);
sd.friction = 0.05f;
sd.restitution = 0.01f;
b2BodyDef bd;
bd.position.Set(-44.0f, 27.0f);
b2Body* g = m_world->CreateBody(&bd);
g->CreateFixture(&sd);
/// Bottom motors
b2CircleDef cd;
cd.radius = 3.0f;
cd.density = 15.0f;
cd.friction = 1.f;
cd.restitution = 0.2f;
/// 1.
bd.position.Set(-40.0f,2.5f);
b2Body* body = m_world->CreateBody(&bd);
body->CreateFixture(&cd);
body->SetMassFromShapes();
b2RevoluteJointDef jr;
jr.Initialize (g,body,body->GetWorldCenter()+b2Vec2(0.f,1.f));
jr.maxMotorTorque = 30000.f;
jr.enableMotor = true;
jr.motorSpeed = 20.f;
m_world->CreateJoint(&jr);
/// 1. left down
bd.position.Set(-46.0f,-2.5f);
cd. radius = 1.5f; jr.motorSpeed = -20.f;
body = m_world->CreateBody(&bd);
body->CreateFixture(&cd);
sd.SetAsBox(2.0f, 0.50f);
body->CreateFixture(&sd);
body->SetMassFromShapes();
jr.Initialize (g,body,body->GetWorldCenter());
m_world->CreateJoint(&jr);
/// 2.
cd.radius = 3.0f; jr.motorSpeed = 20.f;
bd.position.Set(-32.0f,2.5f);
body = m_world->CreateBody(&bd);
body->CreateFixture(&cd);
body->SetMassFromShapes();
jr.Initialize (g,body,body->GetWorldCenter()+b2Vec2(0.f,1.f));
m_world->CreateJoint(&jr);
/// 3.
jr.motorSpeed = 20.f;
bd.position.Set(-24.0f,1.5f);
body = m_world->CreateBody(&bd);
body->CreateFixture(&cd);
body->SetMassFromShapes();
jr.Initialize (g,body,body->GetWorldCenter()+b2Vec2(0.f,1.f));
m_world->CreateJoint(&jr);
/// 4.
bd.position.Set(-16.0f,0.8f);
body = m_world->CreateBody(&bd);
body->CreateFixture(&cd);
body->SetMassFromShapes();
jr.Initialize (g,body,body->GetWorldCenter()+b2Vec2(0.f,1.f));
m_world->CreateJoint(&jr);
/// 5.
bd.position.Set(-8.0f,0.5f);
body = m_world->CreateBody(&bd);
body->CreateFixture(&cd);
body->SetMassFromShapes();
jr.Initialize (g,body,body->GetWorldCenter()+b2Vec2(0.f,1.f));
m_world->CreateJoint(&jr);
/// 6.
bd.position.Set(0.0f,0.1f);
body = m_world->CreateBody(&bd);
body->CreateFixture(&cd);
body->SetMassFromShapes();
jr.Initialize (g,body,body->GetWorldCenter()+b2Vec2(0.f,1.f));
m_world->CreateJoint(&jr);
/// 7.
bd.position.Set(8.0f,-0.5f);
body = m_world->CreateBody(&bd);
body->CreateFixture(&cd);
sd.SetAsBox(3.7f, 0.5f);
body->CreateFixture(&sd);
body->SetMassFromShapes();
jr.Initialize (g,body,body->GetWorldCenter()+b2Vec2(0.f,1.f));
m_world->CreateJoint(&jr);
/// 8. right rotator
sd.SetAsBox(5.f, 0.5f);
sd.density = 2.0f;
bd.position.Set(18.0f,1.f);
b2Body* rightmotor = m_world->CreateBody(&bd);
rightmotor->CreateFixture(&sd);
sd.SetAsBox(4.5f, 0.5f, b2Vec2(0.f,0.f),b2_pi/3.f);
rightmotor->CreateFixture(&sd);
sd.SetAsBox(4.5f, 0.5f, b2Vec2(0.f,0.f),b2_pi*2.f/3.f);
rightmotor->CreateFixture(&sd);
cd.radius = 4.2f;
rightmotor->CreateFixture(&cd);
rightmotor->SetMassFromShapes();
jr.Initialize (g,rightmotor,rightmotor->GetWorldCenter());
jr.maxMotorTorque = 70000.f;
jr.motorSpeed = -4.f;
m_world->CreateJoint(&jr);
/// 9. left rotator
sd.SetAsBox(8.5f, 0.5f);
sd.density = 2.0f;
bd.position.Set(-34.0f,17.f);
body = m_world->CreateBody(&bd);
body->CreateFixture(&sd);
sd.SetAsBox(8.5f, 0.5f, b2Vec2(0.f,0.f),b2_pi*.5f);
body->CreateFixture(&sd);
cd.radius = 7.f;
cd.friction = 0.9f;
body->CreateFixture(&cd);
body->SetMassFromShapes();
jr.Initialize (g,body,body->GetWorldCenter());
jr.maxMotorTorque = 100000.f;
jr.motorSpeed = -5.f;
m_world->CreateJoint(&jr);
/// big compressor
sd.SetAsBox(3.0f,4.f);
sd.density = 10.0f;
bd.position.Set(-16.0f,17.f);
b2Body *hammerleft = m_world->CreateBody(&bd);
hammerleft->CreateFixture(&sd);
hammerleft->SetMassFromShapes();
b2DistanceJointDef jd;
jd.Initialize(body, hammerleft, body->GetWorldCenter()+b2Vec2(0.f,6.f), hammerleft->GetWorldCenter() );
m_world->CreateJoint(&jd);
bd.position.Set(4.0f,17.f);
b2Body *hammerright = m_world->CreateBody(&bd);
hammerright->CreateFixture(&sd);
hammerright->SetMassFromShapes();
jd.Initialize(body, hammerright, body->GetWorldCenter()-b2Vec2(0.f,6.f), hammerright->GetWorldCenter() );
m_world->CreateJoint(&jd);
/// pusher
sd.SetAsBox(6.f,0.75f);
bd.position.Set(-21.0f,9.f);
b2Body* pusher = m_world->CreateBody(&bd);
pusher->CreateFixture(&sd);
sd.SetAsBox(2.f,1.5f,b2Vec2(-5.f,0.f),0.f);
pusher->SetMassFromShapes();
pusher->CreateFixture(&sd);
jd.Initialize(rightmotor,pusher,rightmotor->GetWorldCenter()+b2Vec2(-8.0f,0.f),
pusher->GetWorldCenter()+b2Vec2(5.0f,0.f) );
m_world->CreateJoint(&jd);
}
/// Static bodies above motors
{
b2PolygonDef sd;
b2CircleDef cd;
sd.SetAsBox(9.0f, 0.5f);
sd.friction = 0.05f;
sd.restitution = 0.01f;
b2BodyDef bd;
bd.position.Set(-15.5f, 12.f);
bd.angle = 0.0;
b2Body* g = m_world->CreateBody(&bd);
g->CreateFixture(&sd);
sd.SetAsBox(8.f, 0.5f, b2Vec2(23.f,0.f),0.f);
g->CreateFixture(&sd);
/// compressor statics
sd.SetAsBox(7.0f, 0.5f, b2Vec2(-2.f,9.f),0.f);
g->CreateFixture(&sd);
sd.SetAsBox(9.0f, 0.5f, b2Vec2(22.f,9.f),0.f);
g->CreateFixture(&sd);
sd.SetAsBox(19.0f, 0.5f, b2Vec2(-9.f,15.f),-0.05f);
g->CreateFixture(&sd);
sd.SetAsBox(4.7f, 0.5f, b2Vec2(15.f,11.5f),-0.5f);
g->CreateFixture(&sd);
/// below compressor
sd.SetAsBox(26.0f, 0.3f, b2Vec2(17.f,-4.4f),-0.02f);
g->CreateFixture(&sd);
cd.radius = 1.0f; cd.friction = 1.0;
cd.localPosition = b2Vec2(29.f,-6.f);
g->CreateFixture(&cd);
cd.radius = 0.7f;
cd.localPosition = b2Vec2(-2.f,-4.5f);
g->CreateFixture(&cd);
}
/// Elevator
{
b2BodyDef bd;
b2CircleDef cd;
b2PolygonDef sd;
bd.position.Set(40.0f,4.0f);
m_elev = m_world->CreateBody(&bd);
sd.SetAsBox(0.5f, 2.5f,b2Vec2(3.0f,-3.0f), 0.f);
sd.density = 1.f;
sd.friction = 0.01f;
m_elev->CreateFixture(&sd);
sd.SetAsBox(7.0f, 0.5f, b2Vec2(-3.5f,-5.5f), 0.f);
m_elev->CreateFixture(&sd);
sd.SetAsBox(0.5f, 2.5f, b2Vec2(-11.f,-3.5f), 0.f);
m_elev->CreateFixture(&sd);
m_elev->SetMassFromShapes();
b2PrismaticJointDef jp;
jp.Initialize(m_ground,m_elev, bd.position, b2Vec2(0.0f, 1.0f));
jp.lowerTranslation = 0.0f;
jp.upperTranslation = 100.0f;
jp.enableLimit = true;
jp.enableMotor = true;
jp.maxMotorForce = 10000.f;
jp.motorSpeed = 0.f;
m_joint_elev = (b2PrismaticJoint*)m_world->CreateJoint(&jp);
/// Korb
sd.SetAsBox(2.3f, 0.5f,b2Vec2(1.f,0.0f), 0.0f);
sd.density = 0.5f;
bd.position.Set(29.0f,6.5f);
b2Body* body = m_world->CreateBody(&bd);
body->CreateFixture(&sd);
sd.SetAsBox(2.5f, 0.5f,b2Vec2(3.0f,-2.f), b2_pi/2.f);
body->CreateFixture(&sd);
sd.SetAsBox(4.6f, 0.5f,b2Vec2(7.8f,-4.0f), 0.f);
body->CreateFixture(&sd);
sd.SetAsBox(0.5f, 4.5f,b2Vec2(12.f,0.0f), 0.f);
body->CreateFixture(&sd);
sd.SetAsBox(0.5f, 0.5f,b2Vec2(13.f,4.0f), 0.f);
body->CreateFixture(&sd);
cd.radius = 0.7f; cd.density = 1.f; cd.friction = 0.01f;
cd.localPosition = b2Vec2(0.f,0.f);
body->CreateFixture(&cd);
body->SetMassFromShapes();
b2RevoluteJointDef jr;
jr.Initialize(m_elev,body, bd.position);
jr.enableLimit = true;
jr.lowerAngle = -0.2f;
jr.upperAngle = b2_pi*1.1f;
jr.collideConnected = true;
m_world->CreateJoint(&jr);
/// upper body exit
sd.SetAsBox(14.0f, 0.5f,b2Vec2(-3.5f,-10.0f), 0.0f);
bd.position.Set(17.5f,96.0f);
body = m_world->CreateBody(&bd);
body->CreateFixture(&sd);
}
/// "Elastic body" 64 bodies - something like a lin. elastic compound
/// connected via dynamic forces (springs)
{
b2PolygonDef sd;
sd.SetAsBox(0.55f, 0.55f);
sd.density = 1.5f;
sd.friction = 0.01f;
sd.filter.groupIndex = -1;
b2Vec2 startpoint(30.f,20.f);
b2BodyDef bd;
bd.isBullet = false;
bd.allowSleep = false;
for (int i = 0; i < 8; ++i)
{
for (int j = 0; j < 8; ++j)
{
bd.position.Set(j*1.02f, 2.51f + 1.02f * i);
bd.position += startpoint;
b2Body* body = m_world->CreateBody(&bd);
bodies[8*i+j] = body;
body->CreateFixture(&sd);
body->SetMassFromShapes();
}
}
}
}
/// Apply dynamic forces (springs) and check elevator state
void Step(Settings* settings)
{
Test::Step(settings);
for (int i=0; i<8; ++i){
for (int j=0; j<8; ++j){
b2Vec2 zero(0.0f,0.0f);
b2Vec2 down(0.0f, -0.5f);
b2Vec2 up(0.0f, 0.5f);
b2Vec2 right(0.5f, 0.0f);
b2Vec2 left(-0.5f, 0.0f);
int ind = i*8+j;
int indr = ind+1;
int indd = ind+8;
float32 spring = 500.0f;
float32 damp = 5.0f;
if (j<7) {
AddSpringForce(*(bodies[ind]),zero,*(bodies[indr]),zero,spring, damp, 1.0f);
AddSpringForce(*(bodies[ind]),right,*(bodies[indr]),left,0.5f*spring, damp, 0.0f);
}
if (i<7) {
AddSpringForce(*(bodies[ind]),zero,*(bodies[indd]),zero,spring, damp, 1.0f);
AddSpringForce(*(bodies[ind]),up,*(bodies[indd]),down,0.5f*spring,damp,0.0f);
}
int inddr = indd + 1;
int inddl = indd - 1;
float32 drdist = sqrtf(2.0f);
if (i < 7 && j < 7){
AddSpringForce(*(bodies[ind]),zero,*(bodies[inddr]),zero,spring, damp, drdist);
}
if (i < 7 && j > 0){
AddSpringForce(*(bodies[ind]),zero,*(bodies[inddl]),zero,spring, damp, drdist);
}
indr = ind+2;
indd = ind+8*2;
if (j<6) {
AddSpringForce(*(bodies[ind]),zero,*(bodies[indr]),zero,spring, damp, 2.0f);
}
if (i<6) {
AddSpringForce(*(bodies[ind]),zero,*(bodies[indd]),zero,spring,damp,2.0f);
}
inddr = indd + 2;
inddl = indd - 2;
drdist = sqrtf(2.0f)*2.0f;
if (i < 6 && j < 6){
AddSpringForce(*(bodies[ind]),zero,*(bodies[inddr]),zero,spring, damp, drdist);
}
if (i < 6 && j > 1){
AddSpringForce(*(bodies[ind]),zero,*(bodies[inddl]),zero,spring, damp, drdist);
}
}
}
/// Check if bodies are near elevator
/// Look if the body to lift is near the elevator
b2Vec2 p1 = bodies[0]->GetWorldCenter();
b2Vec2 p2 = bodies[63]->GetWorldCenter();
/// m_elev: elevator prism. joint
b2Vec2 e = m_elev->GetWorldCenter() + b2Vec2(0.f,7.f);
// maybe not the best way to do it...
// Bodies reached the elevator side
if ( p1.x>e.x || p2.x>e.x ) {
// go up
if ( ( p1.y<e.y || p2.y<e.y ) &&
( m_joint_elev->GetJointTranslation()<=m_joint_elev->GetLowerLimit()+1.f ) )
{
m_joint_elev->SetMotorSpeed(20.f);
//printf("lift goes up trans: %G\n",m_joint_elev->GetJointTranslation());
}
}
// go down
if ( (m_joint_elev->GetJointTranslation()>=m_joint_elev->GetUpperLimit()-2.f) )
{
m_joint_elev->SetMotorSpeed(-15.f);
//printf("lift goes down: %G\n",m_joint_elev->GetJointTranslation());
}
}
/// Add a spring force
void AddSpringForce(b2Body& bA, b2Vec2& localA, b2Body& bB, b2Vec2& localB, float32 k, float32 friction, float32 desiredDist)
{
b2Vec2 pA = bA.GetWorldPoint(localA);
b2Vec2 pB = bB.GetWorldPoint(localB);
b2Vec2 diff = pB - pA;
//Find velocities of attach points
b2Vec2 vA = bA.GetLinearVelocity() - b2Cross(bA.GetWorldVector(localA), bA.GetAngularVelocity());
b2Vec2 vB = bB.GetLinearVelocity() - b2Cross(bB.GetWorldVector(localB), bB.GetAngularVelocity());
b2Vec2 vdiff = vB-vA;
float32 dx = diff.Normalize(); //normalizes diff and puts length into dx
float32 vrel = vdiff.x*diff.x + vdiff.y*diff.y;
float32 forceMag = -k*(dx-desiredDist) - friction*vrel;
diff *= forceMag; // diff *= forceMag
bB.ApplyForce(diff, bA.GetWorldPoint(localA));
diff *= -1.0f;
bA.ApplyForce(diff, bB.GetWorldPoint(localB));
}
/// Default constructor
static Test* Create()
{
return new ElasticBody;
}
};
#endif

View File

@@ -0,0 +1,91 @@
/*
* 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 PYRAMID_STATIC_EDGES_H
#define PYRAMID_STATIC_EDGES_H
class PyramidStaticEdges : public Test
{
public:
PyramidStaticEdges()
{
{
float32 coords[] =
{
50.0f,0.0f,
-50.0f,0.0f
};
b2Vec2 verts[2];
for (int32 i = 0; i < 2; i++)
{
verts[i].Set(coords[i*2], coords[i*2 + 1]);
}
b2BodyDef bd;
bd.position.Set( 0.0f, 0.0f );
b2Body* body = m_world->CreateBody(&bd);
b2EdgeDef edgeDef;
edgeDef.vertex1 = verts[0];
edgeDef.vertex2 = verts[1];
body->CreateFixture(&edgeDef);
//body->SetMassFromShapes();
}
{
b2PolygonDef sd;
float32 a = 0.5f;
sd.SetAsBox(a, a);
sd.density = 5.0f;
b2Vec2 x(-10.0f, 1.0f);
b2Vec2 y;
b2Vec2 deltaX(0.5625f, 2.0f);
b2Vec2 deltaY(1.125f, 0.0f);
const int32 N = 2;
for (int32 i = 0; i < N; ++i)
{
y = x;
for (int32 j = i; j < N; ++j)
{
b2BodyDef bd;
bd.position = y;
b2Body* body = m_world->CreateBody(&bd);
body->CreateFixture(&sd);
body->SetMassFromShapes();
y += deltaY;
}
x += deltaX;
}
}
}
static Test* Create()
{
return new PyramidStaticEdges;
}
};
#endif

View File

@@ -0,0 +1,278 @@
/*
* 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 STATIC_EDGES_H
#define STATIC_EDGES_H
class StaticEdges : public Test
{
public:
StaticEdges()
{
#if 0
{
b2CircleDef sd;
sd.radius = 0.5f;
sd.localPosition.SetZero();
sd.density = 2.0f;
b2BodyDef bd;
bd.position.Set(0.0f, 2.0f);
b2Body* body = m_world->CreateBody(&bd);
body->CreateFixture(&sd);
body->SetMassFromShapes();
}
#endif
{
b2CircleDef sd1;
sd1.radius = 0.5f;
sd1.localPosition.Set(-0.5f, 0.5f);
sd1.density = 2.0f;
b2CircleDef sd2;
sd2.radius = 0.5f;
sd2.localPosition.Set(0.5f, 0.5f);
sd2.density = 0.0f; // massless
for (int i = 0; i < 10; ++i)
{
float32 x = RandomFloat(-0.1f, 0.1f);
b2BodyDef bd;
bd.position.Set(x + 5.0f, 1.05f + 2.5f * i);
bd.angle = RandomFloat(-b2_pi, b2_pi);
b2Body* body = m_world->CreateBody(&bd);
body->CreateFixture(&sd1);
body->CreateFixture(&sd2);
body->SetMassFromShapes();
}
}
{
b2PolygonDef sd1;
sd1.SetAsBox(0.25f, 0.5f);
sd1.density = 2.0f;
b2PolygonDef sd2;
sd2.SetAsBox(0.25f, 0.5f, b2Vec2(0.0f, -0.5f), 0.5f * b2_pi);
sd2.density = 2.0f;
for (int i = 0; i < 10; ++i)
{
float32 x = RandomFloat(-0.1f, 0.1f);
b2BodyDef bd;
bd.position.Set(x - 5.0f, 1.05f + 2.5f * i);
bd.angle = RandomFloat(-b2_pi, b2_pi);
b2Body* body = m_world->CreateBody(&bd);
body->CreateFixture(&sd1);
body->CreateFixture(&sd2);
body->SetMassFromShapes();
}
}
{
b2XForm xf1;
xf1.R.Set(0.3524f * b2_pi);
xf1.position = b2Mul(xf1.R, b2Vec2(1.0f, 0.0f));
b2PolygonDef sd1;
sd1.vertexCount = 3;
sd1.vertices[0] = b2Mul(xf1, b2Vec2(-1.0f, 0.0f));
sd1.vertices[1] = b2Mul(xf1, b2Vec2(1.0f, 0.0f));
sd1.vertices[2] = b2Mul(xf1, b2Vec2(0.0f, 0.5f));
sd1.density = 2.0f;
b2XForm xf2;
xf2.R.Set(-0.3524f * b2_pi);
xf2.position = b2Mul(xf2.R, b2Vec2(-1.0f, 0.0f));
b2PolygonDef sd2;
sd2.vertexCount = 3;
sd2.vertices[0] = b2Mul(xf2, b2Vec2(-1.0f, 0.0f));
sd2.vertices[1] = b2Mul(xf2, b2Vec2(1.0f, 0.0f));
sd2.vertices[2] = b2Mul(xf2, b2Vec2(0.0f, 0.5f));
sd2.density = 2.0f;
for (int32 i = 0; i < 10; ++i)
{
float32 x = RandomFloat(-0.1f, 0.1f);
b2BodyDef bd;
bd.position.Set(x, 2.05f + 2.5f * i);
bd.angle = 0.0f;
b2Body* body = m_world->CreateBody(&bd);
body->CreateFixture(&sd1);
body->CreateFixture(&sd2);
body->SetMassFromShapes();
}
}
{
float32 loop1[] =
{
0.063134534f,8.3695248f,
0.94701801f,9.3165428f,
0.0f,9.0640047f,
-0.12626907f,10.326695f,
1.4520943f,11.77879f,
2.2728432f,10.137292f,
2.3991123f,11.147444f,
3.5986685f,10.958041f,
3.9143411f,7.3593722f,
4.1668793f,9.4428119f,
5.4295699f,9.3165428f,
6.2503189f,8.3063903f,
6.6922606f,10.137292f,
4.9876282f,9.8216191f,
4.7350901f,10.958041f,
7.2604714f,11.652521f,
10.732871f,11.147444f,
10.480333f,10.642368f,
10.732871f,9.8216191f,
11.55362f,9.4428119f,
12.374369f,9.3796773f,
13.005714f,9.8216191f,
13.195118f,10.38983f,
13.005714f,10.768637f,
12.626907f,10.894906f,
12.753176f,11.526252f,
13.573925f,11.715655f,
14.836616f,11.399982f,
16.351844f,10.768637f,
17.867073f,11.399982f,
17.803939f,10.263561f,
17.361997f,8.3063903f,
17.803939f,8.1801212f,
18.056477f,9.5059464f,
18.182746f,11.336848f,
18.561553f,11.210579f,
18.561553f,9.6322155f,
18.561553f,7.7381795f,
18.687822f,5.5284708f,
19.382302f,5.6547398f,
19.066629f,8.1801212f,
19.003495f,10.263561f,
19.066629f,11.463117f,
19.887378f,11.841924f,
20.708127f,11.273713f,
21.0238f,10.011023f,
20.708127f,7.2962377f,
21.086934f,6.2860852f,
21.150069f,3.7607038f,
20.392455f,2.5611476f,
18.624688f,2.5611476f,
20.771262f,2.1192059f,
20.771262f,0.22516988f,
18.624688f,-0.2799064f,
13.826463f,0.16203534f,
14.015867f,1.7403987f,
13.195118f,2.1823404f,
12.626907f,1.5509951f,
12.879445f,0.85651522f,
12.626907f,0.35143895f,
10.543467f,1.298457f,
11.490485f,3.9501074f,
13.889598f,3.6344347f,
13.889598f,2.9399549f,
14.584077f,3.8869729f,
11.932427f,5.2127981f,
9.7227183f,4.0132419f,
10.796005f,3.5081657f,
9.7858528f,3.2556275f,
10.796005f,2.4980131f,
7.9549513f,1.7403987f,
9.6595837f,1.424726f,
9.217642f,0.66711162f,
8.270624f,-0.090502792f,
7.0079333f,0.85651522f,
6.1240498f,-0.15363733f,
6.1240498f,3.192493f,
5.6821081f,2.4348786f,
4.9876282f,2.1192059f,
4.1037447f,1.8666678f,
3.0304576f,1.8666678f,
2.0834396f,2.245475f,
1.6414979f,2.6242822f,
1.3258252f,3.5081657f,
1.2626907f,0.47770802f,
0.63134534f,0.035766276f,
0.063134534f,0.98278429f
};
float32 loop2[] =
{
8.270624f,6.1598161f,
8.270624f,5.3390672f,
8.7757003f,5.086529f,
9.4701801f,5.5284708f,
9.217642f,6.033547f,
8.7757003f,6.4123542f
};
float32 loop3[] =
{
-5.0f, 10.0f,
5.0f, 10.0f,
5.0f, 0.0f,
-5.0f, 0.0f,
};
b2Vec2 pointLoop1[87];
b2Vec2 pointLoop2[6];
b2Vec2 pointLoop3[4];
for (int32 i = 0; i < 87; i++)
{
pointLoop1[i].Set(loop1[i*2] - 10.0f, loop1[i*2 + 1]);
}
for (int32 i = 0; i < 6; i++)
{
pointLoop2[i].Set(loop2[i*2] - 10.0f, loop2[i*2 + 1]);
}
for (int32 i = 0; i < 4; i++)
{
pointLoop3[i].Set(loop3[i*2], loop3[i*2 + 1]);
}
b2BodyDef bd;
bd.position.Set( 0.0f, 0.0f );
b2Body* body = m_world->CreateBody(&bd);
b2EdgeChainDef edgeDef;
edgeDef.vertexCount = 87;
edgeDef.vertices = pointLoop1;
b2CreateEdgeChain(body, &edgeDef);
edgeDef.vertexCount = 6;
edgeDef.vertices = pointLoop2;
b2CreateEdgeChain(body, &edgeDef);
//edgeDef.vertexCount = 4;
//edgeDef.vertices = pointLoop3;
//b2CreateEdgeChain(body, &edgeDef);
}
}
static Test* Create()
{
return new StaticEdges;
}
};
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,123 @@
/*
* Copyright (c) 2007 Eric Jordan
*
* 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_H
#define B2_POLYGON_H
#include "Box2D.h"
#include "b2Triangle.h"
class b2Polygon;
int32 remainder(int32 x, int32 modulus);
int32 TriangulatePolygon(float32* xv, float32* yv, int32 vNum, b2Triangle* results);
bool IsEar(int32 i, float32* xv, float32* yv, int32 xvLength); //Not for external use
int32 PolygonizeTriangles(b2Triangle* triangulated, int32 triangulatedLength, b2Polygon* polys, int32 polysLength);
int32 DecomposeConvex(b2Polygon* p, b2Polygon* results, int32 maxPolys);
void DecomposeConvexAndAddTo(b2Polygon* p, b2Body* bd, b2FixtureDef* prototype);
b2Polygon ConvexHull(b2Vec2* v, int nVert);
b2Polygon ConvexHull(float32* cloudX, float32* cloudY, int32 nVert);
void ReversePolygon(float32* x, float32* y, int n);
b2Polygon TraceEdge(b2Polygon* p); //For use with self-intersecting polygons, finds outline
class b2Polygon {
public:
const static int32 maxVerticesPerPolygon = b2_maxPolygonVertices;
float32* x; //vertex arrays
float32* y;
int32 nVertices;
float32 area;
bool areaIsSet;
b2Polygon(float32* _x, float32* _y, int32 nVert);
b2Polygon(b2Vec2* v, int32 nVert);
b2Polygon();
~b2Polygon();
float32 GetArea();
void MergeParallelEdges(float32 tolerance);
b2Vec2* GetVertexVecs();
b2Polygon(b2Triangle& t);
void Set(const b2Polygon& p);
bool IsConvex();
bool IsCCW();
bool IsUsable(bool printError);
bool IsUsable();
bool IsSimple();
void AddTo(b2FixtureDef& pd);
b2Polygon* Add(b2Triangle& t);
void print(){
printFormatted();
// for (int32 i=0; i<nVertices; ++i){
// printf("i: %d, x:%f, y:%f\n",i,x[i],y[i]);
// }
}
void printFormatted(){
printf("float xv[] = {");
for (int32 i=0; i<nVertices; ++i){
printf("%ff,",x[i]);
}
printf("};\nfloat yv[] = {");
for (int32 i=0; i<nVertices; ++i){
printf("%ff,",y[i]);
}
printf("};\n");
}
b2Polygon(const b2Polygon& p){
nVertices = p.nVertices;
area = p.area;
areaIsSet = p.areaIsSet;
x = new float32[nVertices];
y = new float32[nVertices];
memcpy(x, p.x, nVertices * sizeof(float32));
memcpy(y, p.y, nVertices * sizeof(float32));
}
};
const int32 MAX_CONNECTED = 32;
const float32 COLLAPSE_DIST_SQR = FLT_EPSILON*FLT_EPSILON;//0.1f;//1000*FLT_EPSILON*1000*FLT_EPSILON;
class b2PolyNode{
public:
b2Vec2 position;
b2PolyNode* connected[MAX_CONNECTED];
int32 nConnected;
bool visited;
b2PolyNode(b2Vec2& pos);
b2PolyNode();
void AddConnection(b2PolyNode& toMe);
void RemoveConnection(b2PolyNode& fromMe);
void RemoveConnectionByIndex(int32 index);
bool IsConnectedTo(b2PolyNode& me);
b2PolyNode* GetRightestConnection(b2PolyNode* incoming);
b2PolyNode* GetRightestConnection(b2Vec2& incomingDir);
};
#endif

View File

@@ -0,0 +1,77 @@
/*
* Copyright (c) 2007 Eric Jordan
*
* 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 "b2Triangle.h"
//Constructor automatically fixes orientation to ccw
b2Triangle::b2Triangle(float32 x1, float32 y1, float32 x2, float32 y2, float32 x3, float32 y3){
x = new float32[3];
y = new float32[3];
float32 dx1 = x2-x1;
float32 dx2 = x3-x1;
float32 dy1 = y2-y1;
float32 dy2 = y3-y1;
float32 cross = dx1*dy2-dx2*dy1;
bool ccw = (cross>0);
if (ccw){
x[0] = x1; x[1] = x2; x[2] = x3;
y[0] = y1; y[1] = y2; y[2] = y3;
} else{
x[0] = x1; x[1] = x3; x[2] = x2;
y[0] = y1; y[1] = y3; y[2] = y2;
}
}
b2Triangle::b2Triangle(){
x = new float32[3];
y = new float32[3];
}
b2Triangle::~b2Triangle(){
delete[] x;
delete[] y;
}
void b2Triangle::Set(const b2Triangle& toMe) {
for (int32 i=0; i<3; ++i) {
x[i] = toMe.x[i];
y[i] = toMe.y[i];
}
}
bool b2Triangle::IsInside(float32 _x, float32 _y){
if (_x < x[0] && _x < x[1] && _x < x[2]) return false;
if (_x > x[0] && _x > x[1] && _x > x[2]) return false;
if (_y < y[0] && _y < y[1] && _y < y[2]) return false;
if (_y > y[0] && _y > y[1] && _y > y[2]) return false;
float32 vx2 = _x-x[0]; float32 vy2 = _y-y[0];
float32 vx1 = x[1]-x[0]; float32 vy1 = y[1]-y[0];
float32 vx0 = x[2]-x[0]; float32 vy0 = y[2]-y[0];
float32 dot00 = vx0*vx0+vy0*vy0;
float32 dot01 = vx0*vx1+vy0*vy1;
float32 dot02 = vx0*vx2+vy0*vy2;
float32 dot11 = vx1*vx1+vy1*vy1;
float32 dot12 = vx1*vx2+vy1*vy2;
float32 invDenom = 1.0f / (dot00*dot11 - dot01*dot01);
float32 u = (dot11*dot02 - dot01*dot12)*invDenom;
float32 v = (dot00*dot12 - dot01*dot02)*invDenom;
return ((u>=0)&&(v>=0)&&(u+v<=1));
}

View File

@@ -0,0 +1,36 @@
/*
* Copyright (c) 2007 Eric Jordan
*
* 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_TRIANGLE_H
#define B2_TRIANGLE_H
#include "b2Math.h"
class b2Triangle{
public:
float* x;
float* y;
b2Triangle();
b2Triangle(float32 x1, float32 y1, float32 x2, float32 y2, float32 x3, float32 y3);
~b2Triangle();
bool IsInside(float32 _x, float32 _y);
void Set(const b2Triangle& toMe);
};
#endif