rollmorad hinzugefügt

This commit is contained in:
2015-11-15 23:18:06 +00:00
commit 948a6775ab
850 changed files with 117333 additions and 0 deletions
@@ -0,0 +1,92 @@
/*
* 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_CIRCLE_SHAPE_H
#define B2_CIRCLE_SHAPE_H
#include "b2Shape.h"
/// This structure is used to build circle shapes.
struct b2CircleDef : public b2ShapeDef
{
b2CircleDef()
{
type = e_circleShape;
localPosition.SetZero();
radius = 1.0f;
}
b2Vec2 localPosition;
float32 radius;
};
/// A circle shape.
class b2CircleShape : public b2Shape
{
public:
/// @see b2Shape::TestPoint
bool TestPoint(const b2XForm& transform, const b2Vec2& p) const;
/// @see b2Shape::TestSegment
bool TestSegment( const b2XForm& transform,
float32* lambda,
b2Vec2* normal,
const b2Segment& segment,
float32 maxLambda) const;
/// @see b2Shape::ComputeAABB
void ComputeAABB(b2AABB* aabb, const b2XForm& transform) const;
/// @see b2Shape::ComputeSweptAABB
void ComputeSweptAABB( b2AABB* aabb,
const b2XForm& transform1,
const b2XForm& transform2) const;
/// @see b2Shape::ComputeMass
void ComputeMass(b2MassData* massData) const;
/// Get the local position of this circle in its parent body.
const b2Vec2& GetLocalPosition() const;
/// Get the radius of this circle.
float32 GetRadius() const;
private:
friend class b2Shape;
b2CircleShape(const b2ShapeDef* def);
void UpdateSweepRadius(const b2Vec2& center);
// Local position in parent body
b2Vec2 m_localPosition;
float32 m_radius;
};
inline const b2Vec2& b2CircleShape::GetLocalPosition() const
{
return m_localPosition;
}
inline float32 b2CircleShape::GetRadius() const
{
return m_radius;
}
#endif
@@ -0,0 +1,163 @@
/*
* 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_POLYGON_SHAPE_H
#define B2_POLYGON_SHAPE_H
#include "b2Shape.h"
/// Convex polygon. The vertices must be in CCW order for a right-handed
/// coordinate system with the z-axis coming out of the screen.
struct b2PolygonDef : public b2ShapeDef
{
b2PolygonDef()
{
type = e_polygonShape;
vertexCount = 0;
}
/// Build vertices to represent an axis-aligned box.
/// @param hx the half-width.
/// @param hy the half-height.
void SetAsBox(float32 hx, float32 hy);
/// Build vertices to represent an oriented box.
/// @param hx the half-width.
/// @param hy the half-height.
/// @param center the center of the box in local coordinates.
/// @param angle the rotation of the box in local coordinates.
void SetAsBox(float32 hx, float32 hy, const b2Vec2& center, float32 angle);
/// The polygon vertices in local coordinates.
b2Vec2 vertices[b2_maxPolygonVertices];
/// The number of polygon vertices.
int32 vertexCount;
};
/// A convex polygon.
class b2PolygonShape : public b2Shape
{
public:
/// @see b2Shape::TestPoint
bool TestPoint(const b2XForm& transform, const b2Vec2& p) const;
/// @see b2Shape::TestSegment
bool TestSegment( const b2XForm& transform,
float32* lambda,
b2Vec2* normal,
const b2Segment& segment,
float32 maxLambda) const;
/// @see b2Shape::ComputeAABB
void ComputeAABB(b2AABB* aabb, const b2XForm& transform) const;
/// @see b2Shape::ComputeSweptAABB
void ComputeSweptAABB( b2AABB* aabb,
const b2XForm& transform1,
const b2XForm& transform2) const;
/// @see b2Shape::ComputeMass
void ComputeMass(b2MassData* massData) const;
/// Get the oriented bounding box relative to the parent body.
const b2OBB& GetOBB() const;
/// Get local centroid relative to the parent body.
const b2Vec2& GetCentroid() const;
/// Get the vertex count.
int32 GetVertexCount() const;
/// Get the vertices in local coordinates.
const b2Vec2* GetVertices() const;
/// Get the core vertices in local coordinates. These vertices
/// represent a smaller polygon that is used for time of impact
/// computations.
const b2Vec2* GetCoreVertices() const;
/// Get the edge normal vectors. There is one for each vertex.
const b2Vec2* GetNormals() const;
/// Get the first vertex and apply the supplied transform.
b2Vec2 GetFirstVertex(const b2XForm& xf) const;
/// Get the centroid and apply the supplied transform.
b2Vec2 Centroid(const b2XForm& xf) const;
/// Get the support point in the given world direction.
/// Use the supplied transform.
b2Vec2 Support(const b2XForm& xf, const b2Vec2& d) const;
private:
friend class b2Shape;
b2PolygonShape(const b2ShapeDef* def);
void UpdateSweepRadius(const b2Vec2& center);
// Local position of the polygon centroid.
b2Vec2 m_centroid;
b2OBB m_obb;
b2Vec2 m_vertices[b2_maxPolygonVertices];
b2Vec2 m_normals[b2_maxPolygonVertices];
b2Vec2 m_coreVertices[b2_maxPolygonVertices];
int32 m_vertexCount;
};
inline b2Vec2 b2PolygonShape::GetFirstVertex(const b2XForm& xf) const
{
return b2Mul(xf, m_coreVertices[0]);
}
inline const b2OBB& b2PolygonShape::GetOBB() const
{
return m_obb;
}
inline const b2Vec2& b2PolygonShape::GetCentroid() const
{
return m_centroid;
}
inline int32 b2PolygonShape::GetVertexCount() const
{
return m_vertexCount;
}
inline const b2Vec2* b2PolygonShape::GetVertices() const
{
return m_vertices;
}
inline const b2Vec2* b2PolygonShape::GetCoreVertices() const
{
return m_coreVertices;
}
inline const b2Vec2* b2PolygonShape::GetNormals() const
{
return m_normals;
}
#endif
@@ -0,0 +1,285 @@
/*
* 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_SHAPE_H
#define B2_SHAPE_H
#include "../../Common/b2Math.h"
#include "../b2Collision.h"
class b2BlockAllocator;
class b2Body;
class b2BroadPhase;
/// This holds the mass data computed for a shape.
struct b2MassData
{
/// The mass of the shape, usually in kilograms.
float32 mass;
/// The position of the shape's centroid relative to the shape's origin.
b2Vec2 center;
/// The rotational inertia of the shape.
float32 I;
};
/// This holds contact filtering data.
struct b2FilterData
{
/// The collision category bits. Normally you would just set one bit.
uint16 categoryBits;
/// The collision mask bits. This states the categories that this
/// shape would accept for collision.
uint16 maskBits;
/// 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.
int16 groupIndex;
};
/// The various collision shape types supported by Box2D.
enum b2ShapeType
{
e_unknownShape = -1,
e_circleShape,
e_polygonShape,
e_shapeTypeCount,
};
/// A shape definition is used to construct a shape. This class defines an
/// abstract shape definition. You can reuse shape definitions safely.
struct b2ShapeDef
{
/// The constructor sets the default shape definition values.
b2ShapeDef()
{
type = e_unknownShape;
userData = NULL;
friction = 0.2f;
restitution = 0.0f;
density = 0.0f;
filter.categoryBits = 0x0001;
filter.maskBits = 0xFFFF;
filter.groupIndex = 0;
isSensor = false;
}
virtual ~b2ShapeDef() {}
/// Holds the shape type for down-casting.
b2ShapeType type;
/// Use this to store application specify shape data.
void* userData;
/// The shape's friction coefficient, usually in the range [0,1].
float32 friction;
/// The shape's restitution (elasticity) usually in the range [0,1].
float32 restitution;
/// The shape's density, usually in kg/m^2.
float32 density;
/// A sensor shape collects contact information but never generates a collision
/// response.
bool isSensor;
/// Contact filtering data.
b2FilterData filter;
};
/// A shape is used for collision detection. Shapes are created in b2World.
/// You can use shape for collision detection before they are attached to the world.
/// @warning you cannot reuse shapes.
class b2Shape
{
public:
/// Get the type of this shape. You can use this to down cast to the concrete shape.
/// @return the shape type.
b2ShapeType GetType() const;
/// Is this shape a sensor (non-solid)?
/// @return the true if the shape is a sensor.
bool IsSensor() const;
/// Set the contact filtering data. You must call b2World::Refilter to correct
/// existing contacts/non-contacts.
void SetFilterData(const b2FilterData& filter);
/// Get the contact filtering data.
const b2FilterData& GetFilterData() const;
/// Get the parent body of this shape. This is NULL if the shape is not attached.
/// @return the parent body.
b2Body* GetBody();
/// Get the next shape in the parent body's shape list.
/// @return the next shape.
b2Shape* GetNext();
/// Get the user data that was assigned in the shape definition. Use this to
/// store your application specific data.
void* GetUserData();
/// Set the user data. Use this to store your application specific data.
void SetUserData(void* data);
/// Test a point for containment in this shape. This only works for convex shapes.
/// @param xf the shape world transform.
/// @param p a point in world coordinates.
virtual bool TestPoint(const b2XForm& xf, const b2Vec2& p) const = 0;
/// Perform a ray cast against this shape.
/// @param xf the shape world transform.
/// @param lambda returns the hit fraction. You can use this to compute the contact point
/// p = (1 - lambda) * segment.p1 + lambda * segment.p2.
/// @param normal returns the normal at the contact point. If there is no intersection, the normal
/// is not set.
/// @param segment defines the begin and end point of the ray cast.
/// @param maxLambda a number typically in the range [0,1].
/// @return true if there was an intersection.
virtual bool TestSegment( const b2XForm& xf,
float32* lambda,
b2Vec2* normal,
const b2Segment& segment,
float32 maxLambda) const = 0;
/// Given a transform, compute the associated axis aligned bounding box for this shape.
/// @param aabb returns the axis aligned box.
/// @param xf the world transform of the shape.
virtual void ComputeAABB(b2AABB* aabb, const b2XForm& xf) const = 0;
/// Given two transforms, compute the associated swept axis aligned bounding box for this shape.
/// @param aabb returns the axis aligned box.
/// @param xf1 the starting shape world transform.
/// @param xf2 the ending shape world transform.
virtual void ComputeSweptAABB( b2AABB* aabb,
const b2XForm& xf1,
const b2XForm& xf2) const = 0;
/// Compute the mass properties of this shape using its dimensions and density.
/// The inertia tensor is computed about the local origin, not the centroid.
/// @param massData returns the mass data for this shape.
virtual void ComputeMass(b2MassData* massData) const = 0;
/// Get the maximum radius about the parent body's center of mass.
float32 GetSweepRadius() const;
/// Get the coefficient of friction.
float32 GetFriction() const;
/// Get the coefficient of restitution.
float32 GetRestitution() const;
protected:
friend class b2Body;
friend class b2World;
static b2Shape* Create(const b2ShapeDef* def, b2BlockAllocator* allocator);
static void Destroy(b2Shape* shape, b2BlockAllocator* allocator);
b2Shape(const b2ShapeDef* def);
virtual ~b2Shape();
void CreateProxy(b2BroadPhase* broadPhase, const b2XForm& xf);
void DestroyProxy(b2BroadPhase* broadPhase);
bool Synchronize(b2BroadPhase* broadPhase, const b2XForm& xf1, const b2XForm& xf2);
void RefilterProxy(b2BroadPhase* broadPhase, const b2XForm& xf);
virtual void UpdateSweepRadius(const b2Vec2& center) = 0;
b2ShapeType m_type;
b2Shape* m_next;
b2Body* m_body;
// Sweep radius relative to the parent body's center of mass.
float32 m_sweepRadius;
float32 m_density;
float32 m_friction;
float32 m_restitution;
uint16 m_proxyId;
b2FilterData m_filter;
bool m_isSensor;
void* m_userData;
};
inline b2ShapeType b2Shape::GetType() const
{
return m_type;
}
inline bool b2Shape::IsSensor() const
{
return m_isSensor;
}
inline void b2Shape::SetFilterData(const b2FilterData& filter)
{
m_filter = filter;
}
inline const b2FilterData& b2Shape::GetFilterData() const
{
return m_filter;
}
inline void* b2Shape::GetUserData()
{
return m_userData;
}
inline void b2Shape::SetUserData(void* data)
{
m_userData = data;
}
inline b2Body* b2Shape::GetBody()
{
return m_body;
}
inline b2Shape* b2Shape::GetNext()
{
return m_next;
}
inline float32 b2Shape::GetSweepRadius() const
{
return m_sweepRadius;
}
inline float32 b2Shape::GetFriction() const
{
return m_friction;
}
inline float32 b2Shape::GetRestitution() const
{
return m_restitution;
}
#endif
@@ -0,0 +1,146 @@
/*
* 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_BROAD_PHASE_H
#define B2_BROAD_PHASE_H
/*
This broad phase uses the Sweep and Prune algorithm as described in:
Collision Detection in Interactive 3D Environments by Gino van den Bergen
Also, some ideas, such as using integral values for fast compares comes from
Bullet (http:/www.bulletphysics.com).
*/
#include "../Common/b2Settings.h"
#include "b2Collision.h"
#include "b2PairManager.h"
#include <climits>
#ifdef TARGET_FLOAT32_IS_FIXED
#define B2BROADPHASE_MAX (USHRT_MAX/2)
#else
#define B2BROADPHASE_MAX USHRT_MAX
#endif
const uint16 b2_invalid = B2BROADPHASE_MAX;
const uint16 b2_nullEdge = B2BROADPHASE_MAX;
struct b2BoundValues;
struct b2Bound
{
bool IsLower() const { return (value & 1) == 0; }
bool IsUpper() const { return (value & 1) == 1; }
uint16 value;
uint16 proxyId;
uint16 stabbingCount;
};
struct b2Proxy
{
uint16 GetNext() const { return lowerBounds[0]; }
void SetNext(uint16 next) { lowerBounds[0] = next; }
bool IsValid() const { return overlapCount != b2_invalid; }
uint16 lowerBounds[2], upperBounds[2];
uint16 overlapCount;
uint16 timeStamp;
void* userData;
};
class b2BroadPhase
{
public:
b2BroadPhase(const b2AABB& worldAABB, b2PairCallback* callback);
~b2BroadPhase();
// Use this to see if your proxy is in range. If it is not in range,
// it should be destroyed. Otherwise you may get O(m^2) pairs, where m
// is the number of proxies that are out of range.
bool InRange(const b2AABB& aabb) const;
// Create and destroy proxies. These call Flush first.
uint16 CreateProxy(const b2AABB& aabb, void* userData);
void DestroyProxy(int32 proxyId);
// Call MoveProxy as many times as you like, then when you are done
// call Commit to finalized the proxy pairs (for your time step).
void MoveProxy(int32 proxyId, const b2AABB& aabb);
void Commit();
// Get a single proxy. Returns NULL if the id is invalid.
b2Proxy* GetProxy(int32 proxyId);
// Query an AABB for overlapping proxies, returns the user data and
// the count, up to the supplied maximum count.
int32 Query(const b2AABB& aabb, void** userData, int32 maxCount);
void Validate();
void ValidatePairs();
private:
void ComputeBounds(uint16* lowerValues, uint16* upperValues, const b2AABB& aabb);
bool TestOverlap(b2Proxy* p1, b2Proxy* p2);
bool TestOverlap(const b2BoundValues& b, b2Proxy* p);
void Query(int32* lowerIndex, int32* upperIndex, uint16 lowerValue, uint16 upperValue,
b2Bound* bounds, int32 boundCount, int32 axis);
void IncrementOverlapCount(int32 proxyId);
void IncrementTimeStamp();
public:
friend class b2PairManager;
b2PairManager m_pairManager;
b2Proxy m_proxyPool[b2_maxProxies];
uint16 m_freeProxy;
b2Bound m_bounds[2][2*b2_maxProxies];
uint16 m_queryResults[b2_maxProxies];
int32 m_queryResultCount;
b2AABB m_worldAABB;
b2Vec2 m_quantizationFactor;
int32 m_proxyCount;
uint16 m_timeStamp;
static bool s_validate;
};
inline bool b2BroadPhase::InRange(const b2AABB& aabb) const
{
b2Vec2 d = b2Max(aabb.lowerBound - m_worldAABB.upperBound, m_worldAABB.lowerBound - aabb.upperBound);
return b2Max(d.x, d.y) < 0.0f;
}
inline b2Proxy* b2BroadPhase::GetProxy(int32 proxyId)
{
if (proxyId == b2_nullProxy || m_proxyPool[proxyId].IsValid() == false)
{
return NULL;
}
return m_proxyPool + proxyId;
}
#endif
@@ -0,0 +1,154 @@
/*
* 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_COLLISION_H
#define B2_COLLISION_H
#include "../Common/b2Math.h"
#include <climits>
/// @file
/// Structures and functions used for computing contact points, distance
/// queries, and TOI queries.
class b2Shape;
class b2CircleShape;
class b2PolygonShape;
const uint8 b2_nullFeature = UCHAR_MAX;
/// Contact ids to facilitate warm starting.
union b2ContactID
{
/// The features that intersect to form the contact point
struct Features
{
uint8 referenceEdge; ///< The edge that defines the outward contact normal.
uint8 incidentEdge; ///< The edge most anti-parallel to the reference edge.
uint8 incidentVertex; ///< The vertex (0 or 1) on the incident edge that was clipped.
uint8 flip; ///< A value of 1 indicates that the reference edge is on shape2.
} features;
uint32 key; ///< Used to quickly compare contact ids.
};
/// A manifold point is a contact point belonging to a contact
/// manifold. It holds details related to the geometry and dynamics
/// of the contact points.
/// The point is stored in local coordinates because CCD
/// requires sub-stepping in which the separation is stale.
struct b2ManifoldPoint
{
b2Vec2 localPoint1; ///< local position of the contact point in body1
b2Vec2 localPoint2; ///< local position of the contact point in body2
float32 separation; ///< the separation of the shapes along the normal vector
float32 normalImpulse; ///< the non-penetration impulse
float32 tangentImpulse; ///< the friction impulse
b2ContactID id; ///< uniquely identifies a contact point between two shapes
};
/// A manifold for two touching convex shapes.
struct b2Manifold
{
b2ManifoldPoint points[b2_maxManifoldPoints]; ///< the points of contact
b2Vec2 normal; ///< the shared unit normal vector
int32 pointCount; ///< the number of manifold points
};
/// A line segment.
struct b2Segment
{
/// Ray cast against this segment with another segment.
bool TestSegment(float32* lambda, b2Vec2* normal, const b2Segment& segment, float32 maxLambda) const;
b2Vec2 p1; ///< the starting point
b2Vec2 p2; ///< the ending point
};
/// An axis aligned bounding box.
struct b2AABB
{
/// Verify that the bounds are sorted.
bool IsValid() const;
b2Vec2 lowerBound; ///< the lower vertex
b2Vec2 upperBound; ///< the upper vertex
};
/// An oriented bounding box.
struct b2OBB
{
b2Mat22 R; ///< the rotation matrix
b2Vec2 center; ///< the local centroid
b2Vec2 extents; ///< the half-widths
};
/// Compute the collision manifold between two circles.
void b2CollideCircles(b2Manifold* manifold,
const b2CircleShape* circle1, const b2XForm& xf1,
const b2CircleShape* circle2, const b2XForm& xf2);
/// Compute the collision manifold between a polygon and a circle.
void b2CollidePolygonAndCircle(b2Manifold* manifold,
const b2PolygonShape* polygon, const b2XForm& xf1,
const b2CircleShape* circle, const b2XForm& xf2);
/// Compute the collision manifold between two circles.
void b2CollidePolygons(b2Manifold* manifold,
const b2PolygonShape* polygon1, const b2XForm& xf1,
const b2PolygonShape* polygon2, const b2XForm& xf2);
/// Compute the distance between two shapes and the closest points.
/// @return the distance between the shapes or zero if they are overlapped/touching.
float32 b2Distance(b2Vec2* x1, b2Vec2* x2,
const b2Shape* shape1, const b2XForm& xf1,
const b2Shape* shape2, const b2XForm& xf2);
/// Compute the time when two shapes begin to touch or touch at a closer distance.
/// @warning the sweeps must have the same time interval.
/// @return the fraction between [0,1] in which the shapes first touch.
/// fraction=0 means the shapes begin touching/overlapped, and fraction=1 means the shapes don't touch.
float32 b2TimeOfImpact(const b2Shape* shape1, const b2Sweep& sweep1,
const b2Shape* shape2, const b2Sweep& sweep2);
// ---------------- Inline Functions ------------------------------------------
inline bool b2AABB::IsValid() const
{
b2Vec2 d = upperBound - lowerBound;
bool valid = d.x >= 0.0f && d.y >= 0.0f;
valid = valid && lowerBound.IsValid() && upperBound.IsValid();
return valid;
}
inline bool b2TestOverlap(const b2AABB& a, const b2AABB& b)
{
b2Vec2 d1, d2;
d1 = b.lowerBound - a.upperBound;
d2 = a.lowerBound - b.upperBound;
if (d1.x > 0.0f || d1.y > 0.0f)
return false;
if (d2.x > 0.0f || d2.y > 0.0f)
return false;
return true;
}
#endif
@@ -0,0 +1,121 @@
/*
* 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.
*/
// The pair manager is used by the broad-phase to quickly add/remove/find pairs
// of overlapping proxies. It is based closely on code provided by Pierre Terdiman.
// http://www.codercorner.com/IncrementalSAP.txt
#ifndef B2_PAIR_MANAGER_H
#define B2_PAIR_MANAGER_H
#include "../Common/b2Settings.h"
#include "../Common/b2Math.h"
#include <climits>
class b2BroadPhase;
struct b2Proxy;
const uint16 b2_nullPair = USHRT_MAX;
const uint16 b2_nullProxy = USHRT_MAX;
const int32 b2_tableCapacity = b2_maxPairs; // must be a power of two
const int32 b2_tableMask = b2_tableCapacity - 1;
struct b2Pair
{
enum
{
e_pairBuffered = 0x0001,
e_pairRemoved = 0x0002,
e_pairFinal = 0x0004,
};
void SetBuffered() { status |= e_pairBuffered; }
void ClearBuffered() { status &= ~e_pairBuffered; }
bool IsBuffered() { return (status & e_pairBuffered) == e_pairBuffered; }
void SetRemoved() { status |= e_pairRemoved; }
void ClearRemoved() { status &= ~e_pairRemoved; }
bool IsRemoved() { return (status & e_pairRemoved) == e_pairRemoved; }
void SetFinal() { status |= e_pairFinal; }
bool IsFinal() { return (status & e_pairFinal) == e_pairFinal; }
void* userData;
uint16 proxyId1;
uint16 proxyId2;
uint16 next;
uint16 status;
};
struct b2BufferedPair
{
uint16 proxyId1;
uint16 proxyId2;
};
class b2PairCallback
{
public:
virtual ~b2PairCallback() {}
// This should return the new pair user data. It is ok if the
// user data is null.
virtual void* PairAdded(void* proxyUserData1, void* proxyUserData2) = 0;
// This should free the pair's user data. In extreme circumstances, it is possible
// this will be called with null pairUserData because the pair never existed.
virtual void PairRemoved(void* proxyUserData1, void* proxyUserData2, void* pairUserData) = 0;
};
class b2PairManager
{
public:
b2PairManager();
void Initialize(b2BroadPhase* broadPhase, b2PairCallback* callback);
void AddBufferedPair(int32 proxyId1, int32 proxyId2);
void RemoveBufferedPair(int32 proxyId1, int32 proxyId2);
void Commit();
private:
b2Pair* Find(int32 proxyId1, int32 proxyId2);
b2Pair* Find(int32 proxyId1, int32 proxyId2, uint32 hashValue);
b2Pair* AddPair(int32 proxyId1, int32 proxyId2);
void* RemovePair(int32 proxyId1, int32 proxyId2);
void ValidateBuffer();
void ValidateTable();
public:
b2BroadPhase *m_broadPhase;
b2PairCallback *m_callback;
b2Pair m_pairs[b2_maxPairs];
uint16 m_freePair;
int32 m_pairCount;
b2BufferedPair m_pairBuffer[b2_maxPairs];
int32 m_pairBufferCount;
uint16 m_hashTable[b2_tableCapacity];
};
#endif