Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

FIX use of box2d svn trunk

  • Loading branch information...
commit 1999f25d73645f783842b8da6b1c23736dede589 1 parent 0c47576
@PoUpA PoUpA authored
Showing with 9,500 additions and 2,488 deletions.
  1. +1 −1  application/Makefile
  2. +17 −4 application/lib/box2d/Box2D.h
  3. +43 −41 application/lib/box2d/Collision/Shapes/b2CircleShape.cpp
  4. +40 −37 application/lib/box2d/Collision/Shapes/b2CircleShape.h
  5. +184 −0 application/lib/box2d/Collision/Shapes/b2EdgeShape.cpp
  6. +194 −0 application/lib/box2d/Collision/Shapes/b2EdgeShape.h
  7. +221 −184 application/lib/box2d/Collision/Shapes/b2PolygonShape.cpp
  8. +56 −89 application/lib/box2d/Collision/Shapes/b2PolygonShape.h
  9. +1 −149 application/lib/box2d/Collision/Shapes/b2Shape.cpp
  10. +43 −202 application/lib/box2d/Collision/Shapes/b2Shape.h
  11. +274 −3 application/lib/box2d/Collision/b2BroadPhase.cpp
  12. +13 −1 application/lib/box2d/Collision/b2BroadPhase.h
  13. +17 −17 application/lib/box2d/Collision/b2CollideCircle.cpp
  14. +363 −0 application/lib/box2d/Collision/b2CollideEdge.cpp
  15. +40 −54 application/lib/box2d/Collision/b2CollidePoly.cpp
  16. +69 −1 application/lib/box2d/Collision/b2Collision.cpp
  17. +63 −26 application/lib/box2d/Collision/b2Collision.h
  18. +478 −272 application/lib/box2d/Collision/b2Distance.cpp
  19. +192 −0 application/lib/box2d/Collision/b2Distance.h
  20. +322 −0 application/lib/box2d/Collision/b2DynamicTree.cpp
  21. +266 −0 application/lib/box2d/Collision/b2DynamicTree.h
  22. +1 −1  application/lib/box2d/Collision/b2PairManager.cpp
  23. +1 −1  application/lib/box2d/Collision/b2PairManager.h
  24. +404 −22 application/lib/box2d/Collision/b2TimeOfImpact.cpp
  25. +41 −0 application/lib/box2d/Collision/b2TimeOfImpact.h
  26. +3 −1 application/lib/box2d/Common/b2BlockAllocator.cpp
  27. +1 −1  application/lib/box2d/Common/b2BlockAllocator.h
  28. +23 −26 application/lib/box2d/Common/b2Math.cpp
  29. +189 −71 application/lib/box2d/Common/b2Math.h
  30. +2 −2 application/lib/box2d/Common/b2Settings.cpp
  31. +31 −22 application/lib/box2d/Common/b2Settings.h
  32. +1 −1  application/lib/box2d/Common/b2StackAllocator.cpp
  33. +1 −1  application/lib/box2d/Common/b2StackAllocator.h
  34. +43 −26 application/lib/box2d/Dynamics/Contacts/b2CircleContact.cpp
  35. +7 −5 application/lib/box2d/Dynamics/Contacts/b2CircleContact.h
  36. +46 −42 application/lib/box2d/Dynamics/Contacts/b2Contact.cpp
  37. +27 −27 application/lib/box2d/Dynamics/Contacts/b2Contact.h
  38. +489 −117 application/lib/box2d/Dynamics/Contacts/b2ContactSolver.cpp
  39. +9 −8 application/lib/box2d/Dynamics/Contacts/b2ContactSolver.h
  40. +140 −0 application/lib/box2d/Dynamics/Contacts/b2EdgeAndCircleContact.cpp
  41. +50 −0 application/lib/box2d/Dynamics/Contacts/b2EdgeAndCircleContact.h
  42. +7 −1 application/lib/box2d/Dynamics/Contacts/b2NullContact.h
  43. +44 −29 application/lib/box2d/Dynamics/Contacts/b2PolyAndCircleContact.cpp
  44. +7 −5 application/lib/box2d/Dynamics/Contacts/b2PolyAndCircleContact.h
  45. +174 −0 application/lib/box2d/Dynamics/Contacts/b2PolyAndEdgeContact.cpp
  46. +47 −0 application/lib/box2d/Dynamics/Contacts/b2PolyAndEdgeContact.h
  47. +43 −27 application/lib/box2d/Dynamics/Contacts/b2PolyContact.cpp
  48. +7 −5 application/lib/box2d/Dynamics/Contacts/b2PolyContact.h
  49. +119 −0 application/lib/box2d/Dynamics/Controllers/b2BuoyancyController.cpp
  50. +102 −0 application/lib/box2d/Dynamics/Controllers/b2BuoyancyController.h
  51. +46 −0 application/lib/box2d/Dynamics/Controllers/b2ConstantAccelController.cpp
  52. +54 −0 application/lib/box2d/Dynamics/Controllers/b2ConstantAccelController.h
  53. +47 −0 application/lib/box2d/Dynamics/Controllers/b2ConstantForceController.cpp
  54. +54 −0 application/lib/box2d/Dynamics/Controllers/b2ConstantForceController.h
  55. +110 −0 application/lib/box2d/Dynamics/Controllers/b2Controller.cpp
  56. +133 −0 application/lib/box2d/Dynamics/Controllers/b2Controller.h
  57. +70 −0 application/lib/box2d/Dynamics/Controllers/b2GravityController.cpp
  58. +59 −0 application/lib/box2d/Dynamics/Controllers/b2GravityController.h
  59. +72 −0 application/lib/box2d/Dynamics/Controllers/b2TensorDampingController.cpp
  60. +69 −0 application/lib/box2d/Dynamics/Controllers/b2TensorDampingController.h
  61. +10 −7 application/lib/box2d/Dynamics/Joints/b2DistanceJoint.cpp
  62. +3 −3 application/lib/box2d/Dynamics/Joints/b2DistanceJoint.h
  63. +27 −23 application/lib/box2d/Dynamics/Joints/b2GearJoint.cpp
  64. +4 −4 application/lib/box2d/Dynamics/Joints/b2GearJoint.h
  65. +12 −0 application/lib/box2d/Dynamics/Joints/b2Joint.cpp
  66. +18 −7 application/lib/box2d/Dynamics/Joints/b2Joint.h
  67. +559 −0 application/lib/box2d/Dynamics/Joints/b2LineJoint.cpp
  68. +168 −0 application/lib/box2d/Dynamics/Joints/b2LineJoint.h
  69. +40 −33 application/lib/box2d/Dynamics/Joints/b2MouseJoint.cpp
  70. +7 −12 application/lib/box2d/Dynamics/Joints/b2MouseJoint.h
  71. +330 −221 application/lib/box2d/Dynamics/Joints/b2PrismaticJoint.cpp
  72. +10 −13 application/lib/box2d/Dynamics/Joints/b2PrismaticJoint.h
  73. +42 −44 application/lib/box2d/Dynamics/Joints/b2PulleyJoint.cpp
  74. +6 −11 application/lib/box2d/Dynamics/Joints/b2PulleyJoint.h
  75. +208 −133 application/lib/box2d/Dynamics/Joints/b2RevoluteJoint.cpp
  76. +6 −8 application/lib/box2d/Dynamics/Joints/b2RevoluteJoint.h
  77. +82 −68 application/lib/box2d/Dynamics/b2Body.cpp
  78. +167 −32 application/lib/box2d/Dynamics/b2Body.h
  79. +65 −67 application/lib/box2d/Dynamics/b2ContactManager.cpp
  80. +3 −3 application/lib/box2d/Dynamics/b2ContactManager.h
  81. +93 −0 application/lib/box2d/Dynamics/b2EdgeChain.cpp
  82. +229 −0 application/lib/box2d/Dynamics/b2EdgeChain.h
  83. +237 −0 application/lib/box2d/Dynamics/b2Fixture.cpp
  84. +789 −0 application/lib/box2d/Dynamics/b2Fixture.h
  85. +129 −66 application/lib/box2d/Dynamics/b2Island.cpp
  86. +20 −4 application/lib/box2d/Dynamics/b2Island.h
  87. +296 −133 application/lib/box2d/Dynamics/b2World.cpp
  88. +89 −24 application/lib/box2d/Dynamics/b2World.h
  89. +19 −8 application/lib/box2d/Dynamics/b2WorldCallbacks.cpp
  90. +15 −10 application/lib/box2d/Dynamics/b2WorldCallbacks.h
  91. +1 −1  application/polukili.pnproj
  92. +1 −0  application/source/Actor.cpp
  93. +1 −0  application/source/Actor.h
  94. +3 −3 application/source/ActorAction.h
  95. +3 −2 application/source/Bullets/Bullet.cpp
  96. +1 −1  application/source/Bullets/Bullet.h
  97. +2 −2 application/source/Ennemies/Bee.cpp
  98. +3 −3 application/source/Level.cpp
  99. +95 −19 application/source/Players/Player.cpp
  100. +37 −1 application/source/Players/Player.h
  101. BIN  polukili/data/cross_hair.png
View
2  application/Makefile
@@ -22,7 +22,7 @@ include $(DEVKITPPC)/wii_rules
#---------------------------------------------------------------------------------
TARGET := ../polukili/boot
BUILD := build
-SOURCES := source source/Bullets source/Ennemies source/Items source/Pets source/Players lib/box2d/Collision lib/box2d/Collision/Shapes lib/box2d/Common lib/box2d/Dynamics lib/box2d/Dynamics/Contacts lib/box2d/Dynamics/Joints
+SOURCES := source source/Bullets source/Ennemies source/Items source/Pets source/Players lib/box2d/Collision lib/box2d/Collision/Shapes lib/box2d/Common lib/box2d/Dynamics lib/box2d/Dynamics/Contacts lib/box2d/Dynamics/Controllers lib/box2d/Dynamics/Joints
DATA :=
TEXTURES := textures
INCLUDES := source lib/box2d
View
21 application/lib/box2d/Box2D.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
+* 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
@@ -35,18 +35,31 @@ For discussion please visit http://www.box2d.org/forum
#include "Collision/Shapes/b2CircleShape.h"
#include "Collision/Shapes/b2PolygonShape.h"
+#include "Collision/Shapes/b2EdgeShape.h"
#include "Collision/b2BroadPhase.h"
+#include "Collision/b2Distance.h"
+#include "Collision/b2DynamicTree.h"
+#include "Collision/b2TimeOfImpact.h"
+#include "Dynamics/b2Body.h"
+#include "Dynamics/b2EdgeChain.h"
+#include "Dynamics/b2Fixture.h"
#include "Dynamics/b2WorldCallbacks.h"
#include "Dynamics/b2World.h"
-#include "Dynamics/b2Body.h"
#include "Dynamics/Contacts/b2Contact.h"
#include "Dynamics/Joints/b2DistanceJoint.h"
+#include "Dynamics/Joints/b2GearJoint.h"
+#include "Dynamics/Joints/b2LineJoint.h"
#include "Dynamics/Joints/b2MouseJoint.h"
#include "Dynamics/Joints/b2PrismaticJoint.h"
-#include "Dynamics/Joints/b2RevoluteJoint.h"
#include "Dynamics/Joints/b2PulleyJoint.h"
-#include "Dynamics/Joints/b2GearJoint.h"
+#include "Dynamics/Joints/b2RevoluteJoint.h"
+
+#include "Dynamics/Controllers/b2BuoyancyController.h"
+#include "Dynamics/Controllers/b2ConstantForceController.h"
+#include "Dynamics/Controllers/b2ConstantAccelController.h"
+#include "Dynamics/Controllers/b2GravityController.h"
+#include "Dynamics/Controllers/b2TensorDampingController.h"
#endif
View
84 application/lib/box2d/Collision/Shapes/b2CircleShape.cpp
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
+* 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
@@ -18,28 +18,9 @@
#include "b2CircleShape.h"
-b2CircleShape::b2CircleShape(const b2ShapeDef* def)
-: b2Shape(def)
-{
- b2Assert(def->type == e_circleShape);
- const b2CircleDef* circleDef = (const b2CircleDef*)def;
-
- m_type = e_circleShape;
- m_localPosition = circleDef->localPosition;
- m_radius = circleDef->radius;
-}
-
-void b2CircleShape::UpdateSweepRadius(const b2Vec2& center)
-{
- // Update the sweep radius (maximum radius) as measured from
- // a local center point.
- b2Vec2 d = m_localPosition - center;
- m_sweepRadius = d.Length() + m_radius - b2_toiSlop;
-}
-
bool b2CircleShape::TestPoint(const b2XForm& transform, const b2Vec2& p) const
{
- b2Vec2 center = transform.position + b2Mul(transform.R, m_localPosition);
+ b2Vec2 center = transform.position + b2Mul(transform.R, m_p);
b2Vec2 d = p - center;
return b2Dot(d, d) <= m_radius * m_radius;
}
@@ -48,20 +29,21 @@ bool b2CircleShape::TestPoint(const b2XForm& transform, const b2Vec2& p) const
// From Section 3.1.2
// x = s + a * r
// norm(x) = radius
-bool b2CircleShape::TestSegment(const b2XForm& transform,
+b2SegmentCollide b2CircleShape::TestSegment(const b2XForm& transform,
float32* lambda,
b2Vec2* normal,
const b2Segment& segment,
float32 maxLambda) const
{
- b2Vec2 position = transform.position + b2Mul(transform.R, m_localPosition);
+ b2Vec2 position = transform.position + b2Mul(transform.R, m_p);
b2Vec2 s = segment.p1 - position;
float32 b = b2Dot(s, s) - m_radius * m_radius;
// Does the segment start inside the circle?
if (b < 0.0f)
{
- return false;
+ *lambda = 0;
+ return b2_startsInsideCollide;
}
// Solve quadratic equation.
@@ -73,7 +55,7 @@ bool b2CircleShape::TestSegment(const b2XForm& transform,
// Check for negative discriminant and short segment.
if (sigma < 0.0f || rr < B2_FLT_EPSILON)
{
- return false;
+ return b2_missCollide;
}
// Find the point of intersection of the line with the circle.
@@ -86,35 +68,55 @@ bool b2CircleShape::TestSegment(const b2XForm& transform,
*lambda = a;
*normal = s + a * r;
normal->Normalize();
- return true;
+ return b2_hitCollide;
}
- return false;
+ return b2_missCollide;
}
void b2CircleShape::ComputeAABB(b2AABB* aabb, const b2XForm& transform) const
{
- b2Vec2 p = transform.position + b2Mul(transform.R, m_localPosition);
+ b2Vec2 p = transform.position + b2Mul(transform.R, m_p);
aabb->lowerBound.Set(p.x - m_radius, p.y - m_radius);
aabb->upperBound.Set(p.x + m_radius, p.y + m_radius);
}
-void b2CircleShape::ComputeSweptAABB(b2AABB* aabb, const b2XForm& transform1, const b2XForm& transform2) const
+
+void b2CircleShape::ComputeMass(b2MassData* massData, float32 density) const
{
- b2Vec2 p1 = transform1.position + b2Mul(transform1.R, m_localPosition);
- b2Vec2 p2 = transform2.position + b2Mul(transform2.R, m_localPosition);
- b2Vec2 lower = b2Min(p1, p2);
- b2Vec2 upper = b2Max(p1, p2);
+ massData->mass = density * b2_pi * m_radius * m_radius;
+ massData->center = m_p;
- aabb->lowerBound.Set(lower.x - m_radius, lower.y - m_radius);
- aabb->upperBound.Set(upper.x + m_radius, upper.y + m_radius);
+ // inertia about the local origin
+ massData->I = massData->mass * (0.5f * m_radius * m_radius + b2Dot(m_p, m_p));
}
-void b2CircleShape::ComputeMass(b2MassData* massData) const
+float32 b2CircleShape::ComputeSubmergedArea( const b2Vec2& normal,
+ float32 offset,
+ const b2XForm& xf,
+ b2Vec2* c) const
{
- massData->mass = m_density * b2_pi * m_radius * m_radius;
- massData->center = m_localPosition;
-
- // inertia about the local origin
- massData->I = massData->mass * (0.5f * m_radius * m_radius + b2Dot(m_localPosition, m_localPosition));
+ b2Vec2 p = b2Mul(xf,m_p);
+ float32 l = -(b2Dot(normal,p) - offset);
+ if(l<-m_radius+B2_FLT_EPSILON){
+ //Completely dry
+ return 0;
+ }
+ if(l>m_radius){
+ //Completely wet
+ *c = p;
+ return b2_pi*m_radius*m_radius;
+ }
+
+ //Magic
+ float32 r2 = m_radius*m_radius;
+ float32 l2 = l*l;
+ //TODO: write b2Sqrt to handle fixed point case.
+ float32 area = r2 * (asin(l/m_radius) + b2_pi/2.0f)+ l * b2Sqrt(r2 - l2);
+ float32 com = -2.0f/3.0f*pow(r2-l2,1.5f)/area;
+
+ c->x = p.x + normal.x * com;
+ c->y = p.y + normal.y * com;
+
+ return area;
}
View
77 application/lib/box2d/Collision/Shapes/b2CircleShape.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
+* 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
@@ -21,29 +21,17 @@
#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:
+ b2CircleShape() { m_type = b2_circleShape; }
+
/// @see b2Shape::TestPoint
bool TestPoint(const b2XForm& transform, const b2Vec2& p) const;
/// @see b2Shape::TestSegment
- bool TestSegment( const b2XForm& transform,
+ b2SegmentCollide TestSegment( const b2XForm& transform,
float32* lambda,
b2Vec2* normal,
const b2Segment& segment,
@@ -52,41 +40,56 @@ class b2CircleShape : public b2Shape
/// @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;
+ void ComputeMass(b2MassData* massData, float32 density) const;
- /// Get the local position of this circle in its parent body.
- const b2Vec2& GetLocalPosition() const;
+ /// @see b2Shape::ComputeSubmergedArea
+ float32 ComputeSubmergedArea( const b2Vec2& normal,
+ float32 offset,
+ const b2XForm& xf,
+ b2Vec2* c) const;
- /// Get the radius of this circle.
- float32 GetRadius() const;
+ /// @see b2Shape::ComputeSweepRadius
+ float32 ComputeSweepRadius(const b2Vec2& pivot) const;
-private:
+ /// Get the supporting vertex index in the given direction.
+ int32 GetSupport(const b2Vec2& d) const;
- friend class b2Shape;
+ /// Get the supporting vertex in the given direction.
+ const b2Vec2& GetSupportVertex(const b2Vec2& d) const;
- b2CircleShape(const b2ShapeDef* def);
+ /// Get the vertex count.
+ int32 GetVertexCount() const { return 1; }
- void UpdateSweepRadius(const b2Vec2& center);
+ /// Get a vertex by index. Used by b2Distance.
+ const b2Vec2& GetVertex(int32 index) const;
- // Local position in parent body
- b2Vec2 m_localPosition;
- float32 m_radius;
+ /// Position
+ b2Vec2 m_p;
};
-inline const b2Vec2& b2CircleShape::GetLocalPosition() const
+inline int32 b2CircleShape::GetSupport(const b2Vec2 &d) const
+{
+ B2_NOT_USED(d);
+ return 0;
+}
+
+inline const b2Vec2& b2CircleShape::GetSupportVertex(const b2Vec2 &d) const
+{
+ B2_NOT_USED(d);
+ return m_p;
+}
+
+inline const b2Vec2& b2CircleShape::GetVertex(int32 index) const
{
- return m_localPosition;
+ B2_NOT_USED(index);
+ b2Assert(index == 0);
+ return m_p;
}
-inline float32 b2CircleShape::GetRadius() const
+inline float32 b2CircleShape::ComputeSweepRadius(const b2Vec2& pivot) const
{
- return m_radius;
+ return b2Distance(m_p, pivot);
}
#endif
View
184 application/lib/box2d/Collision/Shapes/b2EdgeShape.cpp
@@ -0,0 +1,184 @@
+/*
+* 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 "b2EdgeShape.h"
+
+b2EdgeShape::b2EdgeShape()
+{
+ m_type = b2_edgeShape;
+ m_radius = b2_polygonRadius;
+ m_prevEdge = NULL;
+ m_nextEdge = NULL;
+}
+
+b2EdgeShape::~b2EdgeShape()
+{
+ if (m_prevEdge)
+ {
+ m_prevEdge->m_nextEdge = NULL;
+ }
+
+ if (m_nextEdge)
+ {
+ m_nextEdge->m_prevEdge = NULL;
+ }
+}
+
+void b2EdgeShape::Set(const b2Vec2& v1, const b2Vec2& v2)
+{
+ m_v1 = v1;
+ m_v2 = v2;
+
+ m_direction = m_v2 - m_v1;
+ m_length = m_direction.Normalize();
+ m_normal.Set(m_direction.y, -m_direction.x);
+
+ m_cornerDir1 = m_normal;
+ m_cornerDir2 = -1.0f * m_normal;
+}
+
+bool b2EdgeShape::TestPoint(const b2XForm& transform, const b2Vec2& p) const
+{
+ B2_NOT_USED(transform);
+ B2_NOT_USED(p);
+ return false;
+}
+
+b2SegmentCollide b2EdgeShape::TestSegment(const b2XForm& transform,
+ float32* lambda,
+ b2Vec2* normal,
+ const b2Segment& segment,
+ float32 maxLambda) const
+{
+ b2Vec2 r = segment.p2 - segment.p1;
+ b2Vec2 v1 = b2Mul(transform, m_v1);
+ b2Vec2 d = b2Mul(transform, m_v2) - v1;
+ b2Vec2 n = b2Cross(d, 1.0f);
+
+ const float32 k_slop = 100.0f * B2_FLT_EPSILON;
+ float32 denom = -b2Dot(r, n);
+
+ // Cull back facing collision and ignore parallel segments.
+ if (denom > k_slop)
+ {
+ // Does the segment intersect the infinite line associated with this segment?
+ b2Vec2 b = segment.p1 - v1;
+ float32 a = b2Dot(b, n);
+
+ if (0.0f <= a && a <= maxLambda * denom)
+ {
+ float32 mu2 = -r.x * b.y + r.y * b.x;
+
+ // Does the segment intersect this segment?
+ if (-k_slop * denom <= mu2 && mu2 <= denom * (1.0f + k_slop))
+ {
+ a /= denom;
+ n.Normalize();
+ *lambda = a;
+ *normal = n;
+ return b2_hitCollide;
+ }
+ }
+ }
+
+ return b2_missCollide;
+}
+
+void b2EdgeShape::ComputeAABB(b2AABB* aabb, const b2XForm& transform) const
+{
+ b2Vec2 v1 = b2Mul(transform, m_v1);
+ b2Vec2 v2 = b2Mul(transform, m_v2);
+
+ b2Vec2 r(m_radius, m_radius);
+ aabb->lowerBound = b2Min(v1, v2) - r;
+ aabb->upperBound = b2Max(v1, v2) + r;
+}
+
+void b2EdgeShape::ComputeMass(b2MassData* massData, float32 density) const
+{
+ B2_NOT_USED(density);
+
+ massData->mass = 0.0f;
+ massData->center = m_v1;
+ massData->I = 0.0f;
+}
+
+void b2EdgeShape::SetPrevEdge(b2EdgeShape* edge, const b2Vec2& cornerDir, bool convex)
+{
+ m_prevEdge = edge;
+ m_cornerDir1 = cornerDir;
+ m_cornerConvex1 = convex;
+}
+
+void b2EdgeShape::SetNextEdge(b2EdgeShape* edge, const b2Vec2& cornerDir, bool convex)
+{
+ m_nextEdge = edge;
+ m_cornerDir2 = cornerDir;
+ m_cornerConvex2 = convex;
+}
+
+float32 b2EdgeShape::ComputeSubmergedArea( const b2Vec2& normal,
+ float32 offset,
+ const b2XForm& xf,
+ b2Vec2* c) const
+{
+ //Note that v0 is independent of any details of the specific edge
+ //We are relying on v0 being consistent between multiple edges of the same body
+ b2Vec2 v0 = offset * normal;
+ //b2Vec2 v0 = xf.position + (offset - b2Dot(normal, xf.position)) * normal;
+
+ b2Vec2 v1 = b2Mul(xf, m_v1);
+ b2Vec2 v2 = b2Mul(xf, m_v2);
+
+ float32 d1 = b2Dot(normal, v1) - offset;
+ float32 d2 = b2Dot(normal, v2) - offset;
+
+ if (d1 > 0.0f)
+ {
+ if (d2 > 0.0f)
+ {
+ return 0.0f;
+ }
+ else
+ {
+ v1 = -d2 / (d1 - d2) * v1 + d1 / (d1 - d2) * v2;
+ }
+ }
+ else
+ {
+ if (d2 > 0.0f)
+ {
+ v2 = -d2 / (d1 - d2) * v1 + d1 / (d1 - d2) * v2;
+ }
+ else
+ {
+ //Nothing
+ }
+ }
+
+ // v0,v1,v2 represents a fully submerged triangle
+ float32 k_inv3 = 1.0f / 3.0f;
+
+ // Area weighted centroid
+ *c = k_inv3 * (v0 + v1 + v2);
+
+ b2Vec2 e1 = v1 - v0;
+ b2Vec2 e2 = v2 - v0;
+
+ return 0.5f * b2Cross(e1, e2);
+}
View
194 application/lib/box2d/Collision/Shapes/b2EdgeShape.h
@@ -0,0 +1,194 @@
+/*
+* Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com
+*
+* This software is provided 'as-is', without any express or implied
+* warranty. In no event will the authors be held liable for any damages
+* arising from the use of this software.
+* Permission is granted to anyone to use this software for any purpose,
+* including commercial applications, and to alter it and redistribute it
+* freely, subject to the following restrictions:
+* 1. The origin of this software must not be misrepresented; you must not
+* claim that you wrote the original software. If you use this software
+* in a product, an acknowledgment in the product documentation would be
+* appreciated but is not required.
+* 2. Altered source versions must be plainly marked as such, and must not be
+* misrepresented as being the original software.
+* 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef B2_EDGE_SHAPE_H
+#define B2_EDGE_SHAPE_H
+
+#include "b2Shape.h"
+
+/// A circle shape.
+class b2EdgeShape : public b2Shape
+{
+public:
+ b2EdgeShape();
+ ~b2EdgeShape();
+
+ /// Initialize this edge using the two vertices.
+ void Set(const b2Vec2& v1, const b2Vec2& v2);
+
+ /// @see b2Shape::TestPoint
+ bool TestPoint(const b2XForm& transform, const b2Vec2& p) const;
+
+ /// @see b2Shape::TestSegment
+ b2SegmentCollide 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::ComputeMass
+ void ComputeMass(b2MassData* massData, float32 density) const;
+
+ /// @warning This only gives a consistent and sensible answer when when summed over a body only contains loops of edges
+ /// @see b2Shape::ComputeSubmergedArea
+ float32 ComputeSubmergedArea( const b2Vec2& normal,
+ float32 offset,
+ const b2XForm& xf,
+ b2Vec2* c) const;
+
+ /// @see b2Shape::ComputeSweepRadius
+ float32 ComputeSweepRadius(const b2Vec2& pivot) const;
+
+ /// Linear distance from vertex1 to vertex2:
+ float32 GetLength() const;
+
+ /// Local position of vertex in parent body
+ const b2Vec2& GetVertex1() const;
+
+ /// Local position of vertex in parent body
+ const b2Vec2& GetVertex2() const;
+
+ /// Perpendicular unit vector point, pointing from the solid side to the empty side:
+ const b2Vec2& GetNormalVector() const;
+
+ /// Parallel unit vector, pointing from vertex1 to vertex2:
+ const b2Vec2& GetDirectionVector() const;
+
+ const b2Vec2& GetCorner1Vector() const;
+
+ const b2Vec2& GetCorner2Vector() const;
+
+ bool Corner1IsConvex() const;
+
+ bool Corner2IsConvex() const;
+
+ /// Get the supporting vertex index in the given direction.
+ int32 GetSupport(const b2Vec2& d) const;
+
+ /// Get the supporting vertex in the given direction.
+ const b2Vec2& GetSupportVertex(const b2Vec2& d) const;
+
+ /// Get the vertex count.
+ int32 GetVertexCount() const { return 2; }
+
+ /// Get a vertex by index. Used by b2Distance.
+ const b2Vec2& GetVertex(int32 index) const;
+
+ /// Get the next edge in the chain.
+ b2EdgeShape* GetNextEdge() const;
+
+ /// Get the previous edge in the chain.
+ b2EdgeShape* GetPrevEdge() const;
+
+ void SetPrevEdge(b2EdgeShape* edge, const b2Vec2& cornerDir, bool convex);
+ void SetNextEdge(b2EdgeShape* edge, const b2Vec2& cornerDir, bool convex);
+
+ b2Vec2 m_v1;
+ b2Vec2 m_v2;
+
+ float32 m_length;
+
+ b2Vec2 m_normal;
+
+ b2Vec2 m_direction;
+
+ // Unit vector halfway between m_direction and m_prevEdge.m_direction:
+ b2Vec2 m_cornerDir1;
+
+ // Unit vector halfway between m_direction and m_nextEdge.m_direction:
+ b2Vec2 m_cornerDir2;
+
+ bool m_cornerConvex1;
+ bool m_cornerConvex2;
+
+ b2EdgeShape* m_nextEdge;
+ b2EdgeShape* m_prevEdge;
+};
+
+inline float32 b2EdgeShape::GetLength() const
+{
+ return m_length;
+}
+
+inline const b2Vec2& b2EdgeShape::GetVertex1() const
+{
+ return m_v1;
+}
+
+inline const b2Vec2& b2EdgeShape::GetVertex2() const
+{
+ return m_v2;
+}
+
+inline const b2Vec2& b2EdgeShape::GetNormalVector() const
+{
+ return m_normal;
+}
+
+inline const b2Vec2& b2EdgeShape::GetDirectionVector() const
+{
+ return m_direction;
+}
+
+inline const b2Vec2& b2EdgeShape::GetCorner1Vector() const
+{
+ return m_cornerDir1;
+}
+
+inline const b2Vec2& b2EdgeShape::GetCorner2Vector() const
+{
+ return m_cornerDir2;
+}
+
+inline int32 b2EdgeShape::GetSupport(const b2Vec2& d) const
+{
+ return b2Dot(m_v1, d) > b2Dot(m_v2, d) ? 0 : 1;
+}
+
+inline const b2Vec2& b2EdgeShape::GetSupportVertex(const b2Vec2& d) const
+{
+ return b2Dot(m_v1, d) > b2Dot(m_v2, d) ? m_v1 : m_v2;
+}
+
+inline const b2Vec2& b2EdgeShape::GetVertex(int32 index) const
+{
+ b2Assert(0 <= index && index < 2);
+ return (&m_v1)[index];
+}
+
+inline bool b2EdgeShape::Corner1IsConvex() const
+{
+ return m_cornerConvex1;
+}
+
+inline bool b2EdgeShape::Corner2IsConvex() const
+{
+ return m_cornerConvex2;
+}
+
+inline float32 b2EdgeShape::ComputeSweepRadius(const b2Vec2& pivot) const
+{
+ float32 ds1 = b2DistanceSquared(m_v1, pivot);
+ float32 ds2 = b2DistanceSquared(m_v2, pivot);
+ return b2Sqrt(b2Max(ds1, ds2));
+}
+
+#endif
View
405 application/lib/box2d/Collision/Shapes/b2PolygonShape.cpp
@@ -1,6 +1,5 @@
-
/*
-* Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
+* 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
@@ -19,25 +18,42 @@
#include "b2PolygonShape.h"
-void b2PolygonDef::SetAsBox(float32 hx, float32 hy)
+void b2PolygonShape::SetAsBox(float32 hx, float32 hy)
{
- vertexCount = 4;
- vertices[0].Set(-hx, -hy);
- vertices[1].Set( hx, -hy);
- vertices[2].Set( hx, hy);
- vertices[3].Set(-hx, hy);
+ m_vertexCount = 4;
+ m_vertices[0].Set(-hx, -hy);
+ m_vertices[1].Set( hx, -hy);
+ m_vertices[2].Set( hx, hy);
+ m_vertices[3].Set(-hx, hy);
+ m_normals[0].Set(0.0f, -1.0f);
+ m_normals[1].Set(1.0f, 0.0f);
+ m_normals[2].Set(0.0f, 1.0f);
+ m_normals[3].Set(-1.0f, 0.0f);
+ m_centroid.SetZero();
}
-void b2PolygonDef::SetAsBox(float32 hx, float32 hy, const b2Vec2& center, float32 angle)
+void b2PolygonShape::SetAsBox(float32 hx, float32 hy, const b2Vec2& center, float32 angle)
{
- SetAsBox(hx, hy);
+ m_vertexCount = 4;
+ m_vertices[0].Set(-hx, -hy);
+ m_vertices[1].Set( hx, -hy);
+ m_vertices[2].Set( hx, hy);
+ m_vertices[3].Set(-hx, hy);
+ m_normals[0].Set(0.0f, -1.0f);
+ m_normals[1].Set(1.0f, 0.0f);
+ m_normals[2].Set(0.0f, 1.0f);
+ m_normals[3].Set(-1.0f, 0.0f);
+ m_centroid = center;
+
b2XForm xf;
xf.position = center;
xf.R.Set(angle);
- for (int32 i = 0; i < vertexCount; ++i)
+ // Transform vertices and normals.
+ for (int32 i = 0; i < m_vertexCount; ++i)
{
- vertices[i] = b2Mul(xf, vertices[i]);
+ m_vertices[i] = b2Mul(xf, m_vertices[i]);
+ m_normals[i] = b2Mul(xf.R, m_normals[i]);
}
}
@@ -87,69 +103,15 @@ static b2Vec2 ComputeCentroid(const b2Vec2* vs, int32 count)
return c;
}
-// http://www.geometrictools.com/Documentation/MinimumAreaRectangle.pdf
-static void ComputeOBB(b2OBB* obb, const b2Vec2* vs, int32 count)
-{
- b2Assert(count <= b2_maxPolygonVertices);
- b2Vec2 p[b2_maxPolygonVertices + 1];
- for (int32 i = 0; i < count; ++i)
- {
- p[i] = vs[i];
- }
- p[count] = p[0];
-
- float32 minArea = B2_FLT_MAX;
-
- for (int32 i = 1; i <= count; ++i)
- {
- b2Vec2 root = p[i-1];
- b2Vec2 ux = p[i] - root;
- float32 length = ux.Normalize();
- b2Assert(length > B2_FLT_EPSILON);
- b2Vec2 uy(-ux.y, ux.x);
- b2Vec2 lower(B2_FLT_MAX, B2_FLT_MAX);
- b2Vec2 upper(-B2_FLT_MAX, -B2_FLT_MAX);
-
- for (int32 j = 0; j < count; ++j)
- {
- b2Vec2 d = p[j] - root;
- b2Vec2 r;
- r.x = b2Dot(ux, d);
- r.y = b2Dot(uy, d);
- lower = b2Min(lower, r);
- upper = b2Max(upper, r);
- }
-
- float32 area = (upper.x - lower.x) * (upper.y - lower.y);
- if (area < 0.95f * minArea)
- {
- minArea = area;
- obb->R.col1 = ux;
- obb->R.col2 = uy;
- b2Vec2 center = 0.5f * (lower + upper);
- obb->center = root + b2Mul(obb->R, center);
- obb->extents = 0.5f * (upper - lower);
- }
- }
-
- b2Assert(minArea < B2_FLT_MAX);
-}
-
-b2PolygonShape::b2PolygonShape(const b2ShapeDef* def)
- : b2Shape(def)
+void b2PolygonShape::Set(const b2Vec2* vertices, int32 count)
{
- b2Assert(def->type == e_polygonShape);
- m_type = e_polygonShape;
- const b2PolygonDef* poly = (const b2PolygonDef*)def;
-
- // Get the vertices transformed into the body frame.
- m_vertexCount = poly->vertexCount;
- b2Assert(3 <= m_vertexCount && m_vertexCount <= b2_maxPolygonVertices);
+ b2Assert(3 <= count && count <= b2_maxPolygonVertices);
+ m_vertexCount = count;
// Copy vertices.
for (int32 i = 0; i < m_vertexCount; ++i)
{
- m_vertices[i] = poly->vertices[i];
+ m_vertices[i] = vertices[i];
}
// Compute normals. Ensure the edges have non-zero length.
@@ -164,82 +126,34 @@ b2PolygonShape::b2PolygonShape(const b2ShapeDef* def)
}
#ifdef _DEBUG
- // Ensure the polygon is convex.
+ // Ensure the polygon is convex and the interior
+ // is to the left of each edge.
for (int32 i = 0; i < m_vertexCount; ++i)
{
+ int32 i1 = i;
+ int32 i2 = i + 1 < m_vertexCount ? i + 1 : 0;
+ b2Vec2 edge = m_vertices[i2] - m_vertices[i1];
+
for (int32 j = 0; j < m_vertexCount; ++j)
{
// Don't check vertices on the current edge.
- if (j == i || j == (i + 1) % m_vertexCount)
+ if (j == i1 || j == i2)
{
continue;
}
- // Your polygon is non-convex (it has an indentation).
- // Or your polygon is too skinny.
- float32 s = b2Dot(m_normals[i], m_vertices[j] - m_vertices[i]);
- b2Assert(s < -b2_linearSlop);
- }
- }
+ b2Vec2 r = m_vertices[j] - m_vertices[i1];
- // Ensure the polygon is counter-clockwise.
- for (int32 i = 1; i < m_vertexCount; ++i)
- {
- float32 cross = b2Cross(m_normals[i-1], m_normals[i]);
-
- // Keep asinf happy.
- cross = b2Clamp(cross, -1.0f, 1.0f);
-
- // You have consecutive edges that are almost parallel on your polygon.
- float32 angle = asinf(cross);
- b2Assert(angle > b2_angularSlop);
+ // Your polygon is non-convex (it has an indentation) or
+ // has colinear edges.
+ float32 s = b2Cross(edge, r);
+ b2Assert(s > 0.0f);
+ }
}
#endif
// Compute the polygon centroid.
- m_centroid = ComputeCentroid(poly->vertices, poly->vertexCount);
-
- // Compute the oriented bounding box.
- ComputeOBB(&m_obb, m_vertices, m_vertexCount);
-
- // Create core polygon shape by shifting edges inward.
- // Also compute the min/max radius for CCD.
- for (int32 i = 0; i < m_vertexCount; ++i)
- {
- int32 i1 = i - 1 >= 0 ? i - 1 : m_vertexCount - 1;
- int32 i2 = i;
-
- b2Vec2 n1 = m_normals[i1];
- b2Vec2 n2 = m_normals[i2];
- b2Vec2 v = m_vertices[i] - m_centroid;;
-
- b2Vec2 d;
- d.x = b2Dot(n1, v) - b2_toiSlop;
- d.y = b2Dot(n2, v) - b2_toiSlop;
-
- // Shifting the edge inward by b2_toiSlop should
- // not cause the plane to pass the centroid.
-
- // Your shape has a radius/extent less than b2_toiSlop.
- b2Assert(d.x >= 0.0f);
- b2Assert(d.y >= 0.0f);
- b2Mat22 A;
- A.col1.x = n1.x; A.col2.x = n1.y;
- A.col1.y = n2.x; A.col2.y = n2.y;
- m_coreVertices[i] = A.Solve(d) + m_centroid;
- }
-}
-
-void b2PolygonShape::UpdateSweepRadius(const b2Vec2& center)
-{
- // Update the sweep radius (maximum radius) as measured from
- // a local center point.
- m_sweepRadius = 0.0f;
- for (int32 i = 0; i < m_vertexCount; ++i)
- {
- b2Vec2 d = m_coreVertices[i] - center;
- m_sweepRadius = b2Max(m_sweepRadius, d.Length());
- }
+ m_centroid = ComputeCentroid(m_vertices, m_vertexCount);
}
bool b2PolygonShape::TestPoint(const b2XForm& xf, const b2Vec2& p) const
@@ -258,7 +172,7 @@ bool b2PolygonShape::TestPoint(const b2XForm& xf, const b2Vec2& p) const
return true;
}
-bool b2PolygonShape::TestSegment(
+b2SegmentCollide b2PolygonShape::TestSegment(
const b2XForm& xf,
float32* lambda,
b2Vec2* normal,
@@ -280,28 +194,37 @@ bool b2PolygonShape::TestSegment(
float32 numerator = b2Dot(m_normals[i], m_vertices[i] - p1);
float32 denominator = b2Dot(m_normals[i], d);
- // Note: we want this predicate without division:
- // lower < numerator / denominator, where denominator < 0
- // Since denominator < 0, we have to flip the inequality:
- // lower < numerator / denominator <==> denominator * lower > numerator.
-
- if (denominator < 0.0f && numerator < lower * denominator)
- {
- // Increase lower.
- // The segment enters this half-space.
- lower = numerator / denominator;
- index = i;
+ if (denominator == 0.0f)
+ {
+ if (numerator < 0.0f)
+ {
+ return b2_missCollide;
+ }
}
- else if (denominator > 0.0f && numerator < upper * denominator)
+ else
{
- // Decrease upper.
- // The segment exits this half-space.
- upper = numerator / denominator;
+ // Note: we want this predicate without division:
+ // lower < numerator / denominator, where denominator < 0
+ // Since denominator < 0, we have to flip the inequality:
+ // lower < numerator / denominator <==> denominator * lower > numerator.
+ if (denominator < 0.0f && numerator < lower * denominator)
+ {
+ // Increase lower.
+ // The segment enters this half-space.
+ lower = numerator / denominator;
+ index = i;
+ }
+ else if (denominator > 0.0f && numerator < upper * denominator)
+ {
+ // Decrease upper.
+ // The segment exits this half-space.
+ upper = numerator / denominator;
+ }
}
if (upper < lower)
{
- return false;
+ return b2_missCollide;
}
}
@@ -311,34 +234,31 @@ bool b2PolygonShape::TestSegment(
{
*lambda = lower;
*normal = b2Mul(xf.R, m_normals[index]);
- return true;
+ return b2_hitCollide;
}
- return false;
+ *lambda = 0;
+ return b2_startsInsideCollide;
}
void b2PolygonShape::ComputeAABB(b2AABB* aabb, const b2XForm& xf) const
{
- b2Mat22 R = b2Mul(xf.R, m_obb.R);
- b2Mat22 absR = b2Abs(R);
- b2Vec2 h = b2Mul(absR, m_obb.extents);
- b2Vec2 position = xf.position + b2Mul(xf.R, m_obb.center);
- aabb->lowerBound = position - h;
- aabb->upperBound = position + h;
-}
+ b2Vec2 lower = b2Mul(xf, m_vertices[0]);
+ b2Vec2 upper = lower;
-void b2PolygonShape::ComputeSweptAABB(b2AABB* aabb,
- const b2XForm& transform1,
- const b2XForm& transform2) const
-{
- b2AABB aabb1, aabb2;
- ComputeAABB(&aabb1, transform1);
- ComputeAABB(&aabb2, transform2);
- aabb->lowerBound = b2Min(aabb1.lowerBound, aabb2.lowerBound);
- aabb->upperBound = b2Max(aabb1.upperBound, aabb2.upperBound);
+ for (int32 i = 1; i < m_vertexCount; ++i)
+ {
+ b2Vec2 v = b2Mul(xf, m_vertices[i]);
+ lower = b2Min(lower, v);
+ upper = b2Max(upper, v);
+ }
+
+ b2Vec2 r(m_radius, m_radius);
+ aabb->lowerBound = lower - r;
+ aabb->upperBound = upper + r;
}
-void b2PolygonShape::ComputeMass(b2MassData* massData) const
+void b2PolygonShape::ComputeMass(b2MassData* massData, float32 density) const
{
// Polygon mass, centroid, and inertia.
// Let rho be the polygon density in mass per unit area.
@@ -413,7 +333,7 @@ void b2PolygonShape::ComputeMass(b2MassData* massData) const
}
// Total mass
- massData->mass = m_density * area;
+ massData->mass = density * area;
// Center of mass
b2Assert(area > B2_FLT_EPSILON);
@@ -421,29 +341,146 @@ void b2PolygonShape::ComputeMass(b2MassData* massData) const
massData->center = center;
// Inertia tensor relative to the local origin.
- massData->I = m_density * I;
+ massData->I = density * I;
}
-b2Vec2 b2PolygonShape::Centroid(const b2XForm& xf) const
-{
- return b2Mul(xf, m_centroid);
-}
-b2Vec2 b2PolygonShape::Support(const b2XForm& xf, const b2Vec2& d) const
+float32 b2PolygonShape::ComputeSubmergedArea( const b2Vec2& normal,
+ float32 offset,
+ const b2XForm& xf,
+ b2Vec2* c) const
{
- b2Vec2 dLocal = b2MulT(xf.R, d);
+ //Transform plane into shape co-ordinates
+ b2Vec2 normalL = b2MulT(xf.R,normal);
+ float32 offsetL = offset - b2Dot(normal,xf.position);
+
+ float32 depths[b2_maxPolygonVertices];
+ int32 diveCount = 0;
+ int32 intoIndex = -1;
+ int32 outoIndex = -1;
+
+ bool lastSubmerged = false;
+ int32 i;
+ for (i = 0; i < m_vertexCount; ++i)
+ {
+ depths[i] = b2Dot(normalL,m_vertices[i]) - offsetL;
+ bool isSubmerged = depths[i]<-B2_FLT_EPSILON;
+ if (i > 0)
+ {
+ if (isSubmerged)
+ {
+ if (!lastSubmerged)
+ {
+ intoIndex = i-1;
+ diveCount++;
+ }
+ }
+ else
+ {
+ if (lastSubmerged)
+ {
+ outoIndex = i-1;
+ diveCount++;
+ }
+ }
+ }
+ lastSubmerged = isSubmerged;
+ }
- int32 bestIndex = 0;
- float32 bestValue = b2Dot(m_coreVertices[0], dLocal);
- for (int32 i = 1; i < m_vertexCount; ++i)
+ switch(diveCount)
{
- float32 value = b2Dot(m_coreVertices[i], dLocal);
- if (value > bestValue)
+ case 0:
+ if (lastSubmerged)
+ {
+ //Completely submerged
+ b2MassData md;
+ ComputeMass(&md, 1.0f);
+ *c = b2Mul(xf,md.center);
+ return md.mass;
+ }
+ else
+ {
+ //Completely dry
+ return 0;
+ }
+ break;
+
+ case 1:
+ if(intoIndex==-1)
+ {
+ intoIndex = m_vertexCount-1;
+ }
+ else
{
- bestIndex = i;
- bestValue = value;
+ outoIndex = m_vertexCount-1;
}
+ break;
+ }
+
+ int32 intoIndex2 = (intoIndex+1) % m_vertexCount;
+ int32 outoIndex2 = (outoIndex+1) % m_vertexCount;
+
+ float32 intoLambda = (0 - depths[intoIndex]) / (depths[intoIndex2] - depths[intoIndex]);
+ float32 outoLambda = (0 - depths[outoIndex]) / (depths[outoIndex2] - depths[outoIndex]);
+
+ b2Vec2 intoVec( m_vertices[intoIndex].x*(1-intoLambda)+m_vertices[intoIndex2].x*intoLambda,
+ m_vertices[intoIndex].y*(1-intoLambda)+m_vertices[intoIndex2].y*intoLambda);
+ b2Vec2 outoVec( m_vertices[outoIndex].x*(1-outoLambda)+m_vertices[outoIndex2].x*outoLambda,
+ m_vertices[outoIndex].y*(1-outoLambda)+m_vertices[outoIndex2].y*outoLambda);
+
+ // Initialize accumulator
+ float32 area = 0;
+ b2Vec2 center(0,0);
+ b2Vec2 p2 = m_vertices[intoIndex2];
+ b2Vec2 p3;
+
+ float32 k_inv3 = 1.0f / 3.0f;
+
+ // An awkward loop from intoIndex2+1 to outIndex2
+ i = intoIndex2;
+ while (i != outoIndex2)
+ {
+ i = (i+1) % m_vertexCount;
+ if (i == outoIndex2)
+ p3 = outoVec;
+ else
+ p3 = m_vertices[i];
+
+ // Add the triangle formed by intoVec,p2,p3
+ {
+ b2Vec2 e1 = p2 - intoVec;
+ b2Vec2 e2 = p3 - intoVec;
+
+ float32 D = b2Cross(e1, e2);
+
+ float32 triangleArea = 0.5f * D;
+
+ area += triangleArea;
+
+ // Area weighted centroid
+ center += triangleArea * k_inv3 * (intoVec + p2 + p3);
+
+ }
+ //
+ p2=p3;
+ }
+
+ // Normalize and transform centroid
+ center *= 1.0f / area;
+
+ *c = b2Mul(xf,center);
+
+ return area;
+}
+
+float32 b2PolygonShape::ComputeSweepRadius(const b2Vec2& pivot) const
+{
+ b2Assert(m_vertexCount > 0);
+ float32 sr = b2DistanceSquared(m_vertices[0], pivot);
+ for (int32 i = 1; i < m_vertexCount; ++i)
+ {
+ sr = b2Max(sr, b2DistanceSquared(m_vertices[i], pivot));
}
- return b2Mul(xf, m_coreVertices[bestIndex]);
+ return b2Sqrt(sr);
}
View
145 application/lib/box2d/Collision/Shapes/b2PolygonShape.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
+* 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
@@ -21,15 +21,16 @@
#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
+/// A convex polygon. It is assumed that the interior of the polygon is to
+/// the left of each edge.
+class b2PolygonShape : public b2Shape
{
- b2PolygonDef()
- {
- type = e_polygonShape;
- vertexCount = 0;
- }
+public:
+ b2PolygonShape() { m_type = b2_polygonShape; m_radius = b2_polygonRadius; }
+
+ /// Copy vertices. This assumes the vertices define a convex polygon.
+ /// It is assumed that the exterior is the the right of each edge.
+ void Set(const b2Vec2* vertices, int32 vertexCount);
/// Build vertices to represent an axis-aligned box.
/// @param hx the half-width.
@@ -43,23 +44,11 @@ struct b2PolygonDef : public b2ShapeDef
/// @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,
+ b2SegmentCollide TestSegment( const b2XForm& transform,
float32* lambda,
b2Vec2* normal,
const b2Segment& segment,
@@ -68,96 +57,74 @@ class b2PolygonShape : public b2Shape
/// @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;
+ void ComputeMass(b2MassData* massData, float32 density) const;
- /// Get the edge normal vectors. There is one for each vertex.
- const b2Vec2* GetNormals() const;
+ /// @see b2Shape::ComputeSubmergedArea
+ float32 ComputeSubmergedArea( const b2Vec2& normal,
+ float32 offset,
+ const b2XForm& xf,
+ b2Vec2* c) const;
- /// Get the first vertex and apply the supplied transform.
- b2Vec2 GetFirstVertex(const b2XForm& xf) const;
+ /// @see b2Shape::ComputeSweepRadius
+ float32 ComputeSweepRadius(const b2Vec2& pivot) const;
- /// Get the centroid and apply the supplied transform.
- b2Vec2 Centroid(const b2XForm& xf) const;
+ /// Get the supporting vertex index in the given direction.
+ int32 GetSupport(const b2Vec2& d) const;
- /// Get the support point in the given world direction.
- /// Use the supplied transform.
- b2Vec2 Support(const b2XForm& xf, const b2Vec2& d) const;
+ /// Get the supporting vertex in the given direction.
+ const b2Vec2& GetSupportVertex(const b2Vec2& d) const;
-private:
-
- friend class b2Shape;
-
- b2PolygonShape(const b2ShapeDef* def);
+ /// Get the vertex count.
+ int32 GetVertexCount() const { return m_vertexCount; }
- void UpdateSweepRadius(const b2Vec2& center);
+ /// Get a vertex by index.
+ const b2Vec2& GetVertex(int32 index) const;
- // 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
+inline int32 b2PolygonShape::GetSupport(const b2Vec2& d) 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;
-}
+ int32 bestIndex = 0;
+ float32 bestValue = b2Dot(m_vertices[0], d);
+ for (int32 i = 1; i < m_vertexCount; ++i)
+ {
+ float32 value = b2Dot(m_vertices[i], d);
+ if (value > bestValue)
+ {
+ bestIndex = i;
+ bestValue = value;
+ }
+ }
-inline int32 b2PolygonShape::GetVertexCount() const
-{
- return m_vertexCount;
+ return bestIndex;
}
-inline const b2Vec2* b2PolygonShape::GetVertices() const
+inline const b2Vec2& b2PolygonShape::GetSupportVertex(const b2Vec2& d) const
{
- return m_vertices;
-}
+ int32 bestIndex = 0;
+ float32 bestValue = b2Dot(m_vertices[0], d);
+ for (int32 i = 1; i < m_vertexCount; ++i)
+ {
+ float32 value = b2Dot(m_vertices[i], d);
+ if (value > bestValue)
+ {
+ bestIndex = i;
+ bestValue = value;
+ }
+ }
-inline const b2Vec2* b2PolygonShape::GetCoreVertices() const
-{
- return m_coreVertices;
+ return m_vertices[bestIndex];
}
-inline const b2Vec2* b2PolygonShape::GetNormals() const
+inline const b2Vec2& b2PolygonShape::GetVertex(int32 index) const
{
- return m_normals;
+ b2Assert(0 <= index && index < m_vertexCount);
+ return m_vertices[index];
}
#endif
View
150 application/lib/box2d/Collision/Shapes/b2Shape.cpp
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
+* 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
@@ -17,151 +17,3 @@
*/
#include "b2Shape.h"
-#include "b2CircleShape.h"
-#include "b2PolygonShape.h"
-#include "../b2Collision.h"
-#include "../b2BroadPhase.h"
-#include "../../Common/b2BlockAllocator.h"
-
-#include <new>
-
-b2Shape* b2Shape::Create(const b2ShapeDef* def, b2BlockAllocator* allocator)
-{
- switch (def->type)
- {
- case e_circleShape:
- {
- void* mem = allocator->Allocate(sizeof(b2CircleShape));
- return new (mem) b2CircleShape(def);
- }
-
- case e_polygonShape:
- {
- void* mem = allocator->Allocate(sizeof(b2PolygonShape));
- return new (mem) b2PolygonShape(def);
- }
-
- default:
- b2Assert(false);
- return NULL;
- }
-}
-
-void b2Shape::Destroy(b2Shape* s, b2BlockAllocator* allocator)
-{
- switch (s->GetType())
- {
- case e_circleShape:
- s->~b2Shape();
- allocator->Free(s, sizeof(b2CircleShape));
- break;
-
- case e_polygonShape:
- s->~b2Shape();
- allocator->Free(s, sizeof(b2PolygonShape));
- break;
-
- default:
- b2Assert(false);
- }
-}
-
-b2Shape::b2Shape(const b2ShapeDef* def)
-{
- m_userData = def->userData;
- m_friction = def->friction;
- m_restitution = def->restitution;
- m_density = def->density;
- m_body = NULL;
- m_sweepRadius = 0.0f;
-
- m_next = NULL;
-
- m_proxyId = b2_nullProxy;
-
- m_filter = def->filter;
-
- m_isSensor = def->isSensor;
-}
-
-b2Shape::~b2Shape()
-{
- b2Assert(m_proxyId == b2_nullProxy);
-}
-
-void b2Shape::CreateProxy(b2BroadPhase* broadPhase, const b2XForm& transform)
-{
- b2Assert(m_proxyId == b2_nullProxy);
-
- b2AABB aabb;
- ComputeAABB(&aabb, transform);
-
- bool inRange = broadPhase->InRange(aabb);
-
- // You are creating a shape outside the world box.
- b2Assert(inRange);
-
- if (inRange)
- {
- m_proxyId = broadPhase->CreateProxy(aabb, this);
- }
- else
- {
- m_proxyId = b2_nullProxy;
- }
-}
-
-void b2Shape::DestroyProxy(b2BroadPhase* broadPhase)
-{
- if (m_proxyId != b2_nullProxy)
- {
- broadPhase->DestroyProxy(m_proxyId);
- m_proxyId = b2_nullProxy;
- }
-}
-
-bool b2Shape::Synchronize(b2BroadPhase* broadPhase, const b2XForm& transform1, const b2XForm& transform2)
-{
- if (m_proxyId == b2_nullProxy)
- {
- return false;
- }
-
- // Compute an AABB that covers the swept shape (may miss some rotation effect).
- b2AABB aabb;
- ComputeSweptAABB(&aabb, transform1, transform2);
-
- if (broadPhase->InRange(aabb))
- {
- broadPhase->MoveProxy(m_proxyId, aabb);
- return true;
- }
- else
- {
- return false;
- }
-}
-
-void b2Shape::RefilterProxy(b2BroadPhase* broadPhase, const b2XForm& transform)
-{
- if (m_proxyId == b2_nullProxy)
- {
- return;
- }
-
- broadPhase->DestroyProxy(m_proxyId);
-
- b2AABB aabb;
- ComputeAABB(&aabb, transform);
-
- bool inRange = broadPhase->InRange(aabb);
-
- if (inRange)
- {
- m_proxyId = broadPhase->CreateProxy(aabb, this);
- }
- else
- {
- m_proxyId = b2_nullProxy;
- }
-}
View
245 application/lib/box2d/Collision/Shapes/b2Shape.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
+* 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
@@ -22,10 +22,6 @@
#include "../../Common/b2Math.h"
#include "../b2Collision.h"
-class b2BlockAllocator;
-class b2Body;
-class b2BroadPhase;
-
/// This holds the mass data computed for a shape.
struct b2MassData
{
@@ -39,110 +35,38 @@ struct b2MassData
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,
+ b2_unknownShape = -1,
+ b2_circleShape,
+ b2_polygonShape,
+ b2_edgeShape,
+ b2_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
+/// Return codes from TestSegment
+enum b2SegmentCollide
{
- /// 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;
+ b2_startsInsideCollide = -1,
+ b2_missCollide = 0,
+ b2_hitCollide = 1
};
-/// 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.
+/// A shape is used for collision detection. You can create a shape however you like.
+/// Shapes used for simulation in b2World are created automatically when a b2Fixture
+/// is created.
class b2Shape
{
public:
+
+ b2Shape() { m_type = b2_unknownShape; }
+ virtual ~b2Shape() {}
+
/// 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.
@@ -156,75 +80,42 @@ class b2Shape
/// 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;
+ virtual b2SegmentCollide 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;
+ /// @param density the density in kilograms per meter squared.
+ virtual void ComputeMass(b2MassData* massData, float32 density) const = 0;
+
+ /// Compute the volume and centroid of this shape intersected with a half plane
+ /// @param normal the surface normal
+ /// @param offset the surface offset along normal
+ /// @param xf the shape transform
+ /// @param c returns the centroid
+ /// @return the total volume less than offset along normal
+ virtual float32 ComputeSubmergedArea( const b2Vec2& normal,
+ float32 offset,
+ const b2XForm& xf,
+ b2Vec2* c) const = 0;
+
+ /// Compute the sweep radius. This is used for conservative advancement (continuous
+ /// collision detection).
+ /// @param pivot is the pivot point for rotation.
+ /// @return the distance of the furthest point from the pivot.
+ virtual float32 ComputeSweepRadius(const b2Vec2& pivot) const = 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;
+ float32 m_radius;
};
inline b2ShapeType b2Shape::GetType() const
@@ -232,54 +123,4 @@ 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
View
277 application/lib/box2d/Collision/b2BroadPhase.cpp
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
+* 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
@@ -19,6 +19,8 @@
#include "b2BroadPhase.h"
#include <algorithm>
+#include <cstring>
+
// Notes:
// - we use bound arrays instead of linked lists for cache coherence.
// - we use quantized integral values for fast compares.
@@ -139,8 +141,8 @@ bool b2BroadPhase::TestOverlap(const b2BoundValues& b, b2Proxy* p)
void b2BroadPhase::ComputeBounds(uint16* lowerValues, uint16* upperValues, const b2AABB& aabb)
{
- b2Assert(aabb.upperBound.x > aabb.lowerBound.x);
- b2Assert(aabb.upperBound.y > aabb.lowerBound.y);
+ b2Assert(aabb.upperBound.x >= aabb.lowerBound.x);
+ b2Assert(aabb.upperBound.y >= aabb.lowerBound.y);
b2Vec2 minVertex = b2Clamp(aabb.lowerBound, m_worldAABB.lowerBound, m_worldAABB.upperBound);
b2Vec2 maxVertex = b2Clamp(aabb.upperBound, m_worldAABB.lowerBound, m_worldAABB.upperBound);
@@ -665,3 +667,272 @@ void b2BroadPhase::Validate()
}
}
}
+
+
+int32 b2BroadPhase::QuerySegment(const b2Segment& segment, void** userData, int32 maxCount, SortKeyFunc sortKey)
+{
+ float32 maxLambda = 1;
+
+ float32 dx = (segment.p2.x-segment.p1.x)*m_quantizationFactor.x;
+ float32 dy = (segment.p2.y-segment.p1.y)*m_quantizationFactor.y;
+
+ int32 sx = dx<-B2_FLT_EPSILON ? -1 : (dx>B2_FLT_EPSILON ? 1 : 0);
+ int32 sy = dy<-B2_FLT_EPSILON ? -1 : (dy>B2_FLT_EPSILON ? 1 : 0);
+
+ b2Assert(sx!=0||sy!=0);
+
+ float32 p1x = (segment.p1.x-m_worldAABB.lowerBound.x)*m_quantizationFactor.x;
+ float32 p1y = (segment.p1.y-m_worldAABB.lowerBound.y)*m_quantizationFactor.y;
+
+ uint16 startValues[2];
+ uint16 startValues2[2];
+
+ int32 xIndex;
+ int32 yIndex;
+
+ uint16 proxyId;
+ b2Proxy* proxy;
+
+ // TODO_ERIN implement fast float to uint16 conversion.
+ startValues[0] = (uint16)(p1x) & (B2BROADPHASE_MAX - 1);
+ startValues2[0] = (uint16)(p1x) | 1;
+
+ startValues[1] = (uint16)(p1y) & (B2BROADPHASE_MAX - 1);
+ startValues2[1] = (uint16)(p1y) | 1;
+
+ //First deal with all the proxies that contain segment.p1
+ int32 lowerIndex;
+ int32 upperIndex;
+ Query(&lowerIndex,&upperIndex,startValues[0],startValues2[0],m_bounds[0],2*m_proxyCount,0);
+ if(sx>=0) xIndex = upperIndex-1;
+ else xIndex = lowerIndex;
+ Query(&lowerIndex,&upperIndex,startValues[1],startValues2[1],m_bounds[1],2*m_proxyCount,1);
+ if(sy>=0) yIndex = upperIndex-1;
+ else yIndex = lowerIndex;
+
+ //If we are using sortKey, then sort what we have so far, filtering negative keys
+ if(sortKey)
+ {
+ //Fill keys
+ for(int32 i=0;i<m_queryResultCount;i++)
+ {
+ m_querySortKeys[i] = sortKey(m_proxyPool[m_queryResults[i]].userData);
+ }
+ //Bubble sort keys
+ //Sorting negative values to the top, so we can easily remove them
+ int32 i = 0;
+ while(i<m_queryResultCount-1)
+ {
+ float32 a = m_querySortKeys[i];
+ float32 b = m_querySortKeys[i+1];
+ if((a<0)?(b>=0):(a>b&&b>=0))
+ {
+ m_querySortKeys[i+1] = a;
+ m_querySortKeys[i] = b;
+ uint16 tempValue = m_queryResults[i+1];
+ m_queryResults[i+1] = m_queryResults[i];
+ m_queryResults[i] = tempValue;
+ i--;
+ if(i==-1) i=1;
+ }
+ else
+ {
+ i++;
+ }
+ }
+ //Skim off negative values
+ while(m_queryResultCount>0 && m_querySortKeys[m_queryResultCount-1]<0)
+ m_queryResultCount--;
+ }
+
+ //Now work through the rest of the segment
+ for (;;)
+ {
+ float32 xProgress = 0;
+ float32 yProgress = 0;
+ //Move on to the next bound
+ xIndex += sx>=0?1:-1;
+ if(xIndex<0||xIndex>=m_proxyCount*2)
+ break;
+ if(sx!=0)
+ xProgress = ((float32)m_bounds[0][xIndex].value-p1x)/dx;
+ //Move on to the next bound
+ yIndex += sy>=0?1:-1;
+ if(yIndex<0||yIndex>=m_proxyCount*2)
+ break;
+ if(sy!=0)
+ yProgress = ((float32)m_bounds[1][yIndex].value-p1y)/dy;
+ for(;;)
+ {
+ if(sy==0||(sx!=0&&xProgress<yProgress))
+ {
+ if(xProgress>maxLambda)
+ break;
+
+ //Check that we are entering a proxy, not leaving
+ if(sx>0?m_bounds[0][xIndex].IsLower():m_bounds[0][xIndex].IsUpper()){
+ //Check the other axis of the proxy
+ proxyId = m_bounds[0][xIndex].proxyId;
+ proxy = m_proxyPool+proxyId;
+ if(sy>=0)
+ {
+ if(proxy->lowerBounds[1]<=yIndex-1&&proxy->upperBounds[1]>=yIndex)
+ {
+ //Add the proxy
+ if(sortKey)
+ {
+ AddProxyResult(proxyId,proxy,maxCount,sortKey);
+ }
+ else
+ {
+ m_queryResults[m_queryResultCount] = proxyId;
+ ++m_queryResultCount;
+ }
+ }
+ }
+ else
+ {
+ if(proxy->lowerBounds[1]<=yIndex&&proxy->upperBounds[1]>=yIndex+1)
+ {
+ //Add the proxy
+ if(sortKey)
+ {
+ AddProxyResult(proxyId,proxy,maxCount,sortKey);
+ }
+ else
+ {
+ m_queryResults[m_queryResultCount] = proxyId;
+ ++m_queryResultCount;
+ }
+ }
+ }
+ }
+
+ //Early out
+ if(sortKey && m_queryResultCount==maxCount && m_queryResultCount>0 && xProgress>m_querySortKeys[m_queryResultCount-1])
+ break;
+
+ //Move on to the next bound
+ if(sx>0)
+ {
+ xIndex++;
+ if(xIndex==m_proxyCount*2)
+ break;
+ }
+ else
+ {
+ xIndex--;
+ if(xIndex<0)
+ break;
+ }
+ xProgress = ((float32)m_bounds[0][xIndex].value - p1x) / dx;
+ }
+ else
+ {
+ if(yProgress>maxLambda)
+ break;
+
+ //Check that we are entering a proxy, not leaving
+ if(sy>0?m_bounds[1][yIndex].IsLower():m_bounds[1][yIndex].IsUpper()){
+ //Check the other axis of the proxy
+ proxyId = m_bounds[1][yIndex].proxyId;
+ proxy = m_proxyPool+proxyId;
+ if(sx>=0)
+ {
+ if(proxy->lowerBounds[0]<=xIndex-1&&proxy->upperBounds[0]>=xIndex)
+ {
+ //Add the proxy
+ if(sortKey)
+ {
+ AddProxyResult(proxyId,proxy,maxCount,sortKey);
+ }
+ else
+ {
+ m_queryResults[m_queryResultCount] = proxyId;
+ ++m_queryResultCount;
+ }
+ }
+ }
+ else
+ {
+ if(proxy->lowerBounds[0]<=xIndex&&proxy->upperBounds[0]>=xIndex+1)
+ {
+ //Add the proxy
+ if(sortKey)
+ {
+ AddProxyResult(proxyId,proxy,maxCount,sortKey);
+ }
+ else
+ {
+ m_queryResults[m_queryResultCount] = proxyId;
+ ++m_queryResultCount;
+ }
+ }
+ }
+ }
+
+ //Early out
+ if(sortKey && m_queryResultCount==maxCount && m_queryResultCount>0 && yProgress>m_querySortKeys[m_queryResultCount-1])
+ break;
+
+ //Move on to the next bound
+ if(sy>0)
+ {
+ yIndex++;
+ if(yIndex==m_proxyCount*2)
+ break;
+ }
+ else
+ {
+ yIndex--;
+ if(yIndex<0)
+ break;
+ }
+ yProgress = ((float32)m_bounds[1][yIndex].value - p1y) / dy;
+ }
+ }
+
+ break;
+ }
+
+ int32 count = 0;
+ for(int32 i=0;i < m_queryResultCount && count<maxCount; ++i, ++count)
+ {
+ b2Assert(m_queryResults[i] < b2_maxProxies);
+ b2Proxy* proxy = m_proxyPool + m_queryResults[i];
+ b2Assert(proxy->IsValid());
+ userData[i] = proxy->userData;
+ }
+
+ // Prepare for next query.
+ m_queryResultCount = 0;
+ IncrementTimeStamp();
+
+ return count;
+
+}
+void b2BroadPhase::AddProxyResult(uint16 proxyId, b2Proxy* proxy, int32 maxCount, SortKeyFunc sortKey)
+{
+ float32 key = sortKey(proxy->userData);
+ //Filter proxies on positive keys
+ if(key<0)
+ return;
+ //Merge the new key into the sorted list.
+ //float32* p = std::lower_bound(m_querySortKeys,m_querySortKeys+m_queryResultCount,key);
+ float32* p = m_querySortKeys;
+ while(*p<key&&p<m_querySortKeys+m_queryResultCount)
+ p++;
+ int32 i = (int32)(p-m_querySortKeys);
+ if(maxCount==m_queryResultCount&&i==m_queryResultCount)
+ return;
+ if(maxCount==m_queryResultCount)
+ m_queryResultCount--;
+ //std::copy_backward
+ for(int32 j=m_queryResultCount+1;j>i;--j){
+ m_querySortKeys[j] = m_querySortKeys[j-1];
+ m_queryResults[j] = m_queryResults[j-1];
+ }
+ m_querySortKeys[i] = key;
+ m_queryResults[i] = proxyId;
+ m_queryResultCount++;
+}
View
14 application/lib/box2d/Collision/b2BroadPhase.h
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
+* 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
@@ -64,6 +64,8 @@ struct b2Proxy
void* userData;
};
+typedef float32 (*SortKeyFunc)(void* shape);
+
class b2BroadPhase
{
public:
@@ -91,6 +93,14 @@ class b2BroadPhase
// the count, up to the supplied maximum count.
int32 Query(const b2AABB& aabb, void** userData, int32 maxCount);
+ // Query a segment for overlapping proxies, returns the user data and
+ // the count, up to the supplied maximum count.
+ // If sortKey is provided, then it is a function mapping from proxy userDatas to distances along the segment (between 0 & 1)
+ // Then the returned proxies are sorted on that, before being truncated to maxCount
+ // The sortKey of a proxy is assumed to be larger than the closest point inside the proxy along the segment, this allows for early exits
+ // Proxies with a negative sortKey are discarded
+ int32 QuerySegment(const b2Segment& segment, void** userData, int32 maxCount, SortKeyFunc sortKey);
+
void Validate();
void ValidatePairs();
@@ -104,6 +114,7 @@ class b2BroadPhase
b2Bound* bounds, int32 boundCount, int32 axis);
void IncrementOverlapCount(int32 proxyId);
void IncrementTimeStamp();
+ void AddProxyResult(uint16 proxyId, b2Proxy* proxy, int32 maxCount, SortKeyFunc sortKey);
public:
friend class b2PairManager;
@@ -116,6 +127,7 @@ class b2BroadPhase
b2Bound m_bounds[2][2*b2_maxProxies];
uint16 m_queryResults[b2_maxProxies];
+ float32 m_querySortKeys[b2_maxProxies];
int32 m_queryResultCount;
b2AABB m_worldAABB;
View
34 application/lib/box2d/Collision/b2CollideCircle.cpp
@@ -1,5 +1,5 @@
/*
-* Copyright (c) 2007 Erin Catto http://www.gphysics.com
+* Copyright (c) 2007-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
@@ -27,13 +27,13 @@ void b2CollideCircles(
{
manifold->pointCount = 0;
- b2Vec2 p1 = b2Mul(xf1, circle1->GetLocalPosition());
- b2Vec2 p2 = b2Mul(xf2, circle2->GetLocalPosition());
+ b2Vec2 p1 = b2Mul(xf1, circle1->m_p);
+ b2Vec2 p2 = b2Mul(xf2, circle2->m_p);
b2Vec2 d = p2 - p1;
float32 distSqr = b2Dot(d, d);
- float32 r1 = circle1->GetRadius();
- float32 r2 = circle2->GetRadius();
+ float32 r1 = circle1->m_radius;
+ float32 r2 = circle2->m_radius;
float32 radiusSum = r1 + r2;
if (distSqr > radiusSum * radiusSum)
{
@@ -64,8 +64,8 @@ void b2CollideCircles(
b2Vec2 p = 0.5f * (p1 + p2);
- manifold->points[0].localPoint1 = b2MulT(xf1, p);
- manifold->points[0].localPoint2 = b2MulT(xf2, p);
+ manifold->points[0].localPointA = b2MulT(xf1, p);
+ manifold->points[0].localPointB = b2MulT(xf2, p);
}
void b2CollidePolygonAndCircle(
@@ -76,16 +76,16 @@ void b2CollidePolygonAndCircle(
manifold->pointCount = 0;
// Compute circle position in the frame of the polygon.
- b2Vec2 c = b2Mul(xf2, circle->GetLocalPosition());
+ b2Vec2 c = b2Mul(xf2, circle->m_p);
b2Vec2 cLocal = b2MulT(xf1, c);
// Find the min separating edge.
int32 normalIndex = 0;
float32 separation = -B2_FLT_MAX;
- float32 radius = circle->GetRadius();
- int32 vertexCount = polygon->GetVertexCount();
- const b2Vec2* vertices = polygon->GetVertices();
- const b2Vec2* normals = polygon->GetNormals();
+ float32 radius = polygon->m_radius + circle->m_radius;
+ int32 vertexCount = polygon->m_vertexCount;
+ const b2Vec2* vertices = polygon->m_vertices;
+ const b2Vec2* normals = polygon->m_normals;
for (int32 i = 0; i < vertexCount; ++i)
{
@@ -114,8 +114,8 @@ void b2CollidePolygonAndCircle(
manifold->points[0].id.features.referenceEdge = 0;
manifold->points[0].id.features.flip = 0;
b2Vec2 position = c - radius * manifold->normal;
- manifold->points[0].localPoint1 = b2MulT(xf1, position);
- manifold->points[0].localPoint2 = b2MulT(xf2, position);
+ manifold->points[0].localPointA = b2MulT(xf1, position);
+ manifold->points[0].localPointB = b2MulT(xf2, position);
manifold->points[0].separation = separation - radius;
return;
}
@@ -147,7 +147,7 @@ void b2CollidePolygonAndCircle(
{
p = vertices[vertIndex1] + u * e;
manifold->points[0].id.features.incidentEdge = (uint8)normalIndex;
- manifold->points[0].id.features.incidentVertex = 0;
+ manifold->points[0].id.features.incidentVertex = b2_nullFeature;
}
b2Vec2 d = cLocal - p;
@@ -160,8 +160,8 @@ void b2CollidePolygonAndCircle(
manifold->pointCount = 1;
manifold->normal = b2Mul(xf1.R, d);
b2Vec2 position = c - radius * manifold->normal;
- manifold->points[0].localPoint1 = b2MulT(xf1, position);
- manifold->points[0].localPoint2 = b2MulT(xf2, position);
+ manifold->points[0].localPointA = b2MulT(xf1, position);
+ manifold->points[0].localPointB = b2MulT(xf2, position);
manifold->points[0].separation = dist - radius;
manifold->points[0].id.features.referenceEdge = 0;
manifold->points[0].id.features.flip = 0;
View
363 application/lib/box2d/Collision/b2CollideEdge.cpp
@@ -0,0 +1,363 @@
+/*
+* Copyright (c) 2007-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 "b2Collision.h"
+#include "Shapes/b2CircleShape.h"
+#include "Shapes/b2EdgeShape.h"
+#include "Shapes/b2PolygonShape.h"
+
+void b2CollideEdgeAndCircle(b2Manifold* manifold,
+ const b2EdgeShape* edge,
+ const b2XForm& transformA,
+ const b2CircleShape* circle,
+ const b2XForm& transformB)
+{
+ manifold->pointCount = 0;
+ b2Vec2 d;
+ b2Vec2 c = b2Mul(transformB, circle->m_p);
+ b2Vec2 cLocal = b2MulT(transformA, c);
+ b2Vec2 n = edge->GetNormalVector();
+ b2Vec2 v1 = edge->GetVertex1();
+ b2Vec2 v2 = edge->GetVertex2();
+ float32 radius = edge->m_radius + circle->m_radius;
+ float32 separation;
+
+ float32 dirDist = b2Dot((cLocal - v1), edge->GetDirectionVector());
+
+ if (dirDist <= 0.0f)
+ {
+ // Behind v1
+ d = cLocal - v1;
+ if (b2Dot(d, edge->GetCorner1Vector()) < 0.0f)
+ {
+ // Contact handled by previous edge
+ return;
+ }
+ d = c - b2Mul(transformA, v1);
+ }
+ else if (dirDist >= edge->GetLength())
+ {
+ // Ahead of v2
+ d = cLocal - v2;
+ if (b2Dot(d, edge->GetCorner2Vector()) > 0.0f)
+ {
+ // Contact handled by next edge
+ return;
+ }
+ d = c - b2Mul(transformA, v2);
+ }
+ else
+ {
+ separation = b2Dot(cLocal - v1, n);
+ if (separation > radius || separation < -radius)
+ {
+ return;
+ }
+ separation -= radius;
+ manifold->normal = b2Mul(transformA.R, n);
+ manifold->pointCount = 1;
+ manifold->points[0].id.key = 0;
+ manifold->points[0].separation = separation;
+ c = c - radius * manifold->normal;
+ manifold->points[0].localPointA = b2MulT(transformA, c);
+ manifold->points[0].localPointB = b2MulT(transformB, c);
+ return;
+ }
+
+ float32 distSqr = d.LengthSquared();
+ if (distSqr > radius * radius)
+ {
+ return;
+ }
+
+ if (distSqr < B2_FLT_EPSILON)
+ {
+ separation = -radius;
+ manifold->normal = b2Mul(transformA.R, n);
+ }
+ else
+ {
+ separation = d.Normalize() - radius;
+ manifold->normal = d;
+ }
+
+ manifold->pointCount = 1;
+ manifold->points[0].id.key = 0;
+ manifold->points[0].separation = separation;
+ c = c - radius * manifold->normal;
+ manifold->points[0].localPointA = b2MulT(transformA, c);
+ manifold->points[0].localPointB = b2MulT(transformB, c);
+}
+
+void b2CollidePolyAndEdge(b2Manifold* manifold,
+ const b2PolygonShape* polygon,
+ const b2XForm& transformA,
+ const b2EdgeShape* edge,
+ const b2XForm& transformB)
+{
+ manifold->pointCount = 0;
+ b2Vec2 v1 = b2Mul(transformB, edge->GetVertex1());
+ b2Vec2 v2 = b2Mul(transformB, edge->GetVertex2());
+ b2Vec2 n = b2Mul(transformB.R, edge->GetNormalVector());
+ b2Vec2 v1Local = b2MulT(transformA, v1);
+ b2Vec2 v2Local = b2MulT(transformA, v2);
+ b2Vec2 nLocal = b2MulT(transformA.R, n);
+
+ float32 totalRadius = polygon->m_radius + edge->m_radius;
+
+ float32 separation1;
+ int32 separationIndex1 = -1; // which normal on the polygon found the shallowest depth?
+ float32 separationMax1 = -B2_FLT_MAX; // the shallowest depth of edge in polygon