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