Files
DarkRP2D/external/Box2D-2.3.1/Contributions/Enhancements/Shapes/capsule88.patch
Julian Nießner d175d433a8 Added Box2D
2018-05-06 12:43:20 +02:00

1360 lines
44 KiB
Diff

Index: Box2D/Box2D/Box2D.h
===================================================================
--- Box2D/Box2D/Box2D.h (revision 70)
+++ Box2D/Box2D/Box2D.h (working copy)
@@ -35,6 +35,7 @@
#include <Box2D/Collision/Shapes/b2CircleShape.h>
#include <Box2D/Collision/Shapes/b2PolygonShape.h>
+#include <Box2D/Collision/Shapes/b2CapsuleShape.h>
#include <Box2D/Collision/b2BroadPhase.h>
#include <Box2D/Collision/b2Distance.h>
Index: Box2D/Box2D/CMakeLists.txt
===================================================================
--- Box2D/Box2D/CMakeLists.txt (revision 70)
+++ Box2D/Box2D/CMakeLists.txt (working copy)
@@ -15,10 +15,12 @@
Collision/b2TimeOfImpact.h
)
set(BOX2D_Shapes_SRCS
+ Collision/Shapes/b2CapsuleShape.cpp
Collision/Shapes/b2CircleShape.cpp
Collision/Shapes/b2PolygonShape.cpp
)
set(BOX2D_Shapes_HDRS
+ Collision/Shapes/b2CapsuleShape.h
Collision/Shapes/b2CircleShape.h
Collision/Shapes/b2PolygonShape.h
Collision/Shapes/b2Shape.h
@@ -53,18 +55,24 @@
Dynamics/b2WorldCallbacks.h
)
set(BOX2D_Contacts_SRCS
+ Dynamics/Contacts/b2CapsuleAndCircleContact.cpp
+ Dynamics/Contacts/b2CapsuleContact.cpp
Dynamics/Contacts/b2CircleContact.cpp
Dynamics/Contacts/b2Contact.cpp
Dynamics/Contacts/b2ContactSolver.cpp
+ Dynamics/Contacts/b2PolygonAndCapsuleContact.cpp
Dynamics/Contacts/b2PolygonAndCircleContact.cpp
Dynamics/Contacts/b2PolygonContact.cpp
Dynamics/Contacts/b2TOISolver.cpp
)
set(BOX2D_Contacts_HDRS
+ Dynamics/Contacts/b2CapsuleAndCircleContact.h
+ Dynamics/Contacts/b2CapsuleContact.h
Dynamics/Contacts/b2CircleContact.h
Dynamics/Contacts/b2Contact.h
Dynamics/Contacts/b2ContactSolver.h
Dynamics/Contacts/b2NullContact.h
+ Dynamics/Contacts/b2PolygonAndCapsuleContact.h
Dynamics/Contacts/b2PolygonAndCircleContact.h
Dynamics/Contacts/b2PolygonContact.h
Dynamics/Contacts/b2TOISolver.h
Index: Box2D/Box2D/Collision/b2Collision.cpp
===================================================================
--- Box2D/Box2D/Collision/b2Collision.cpp (revision 70)
+++ Box2D/Box2D/Collision/b2Collision.cpp (working copy)
@@ -248,3 +248,220 @@
return output.distance < 10.0f * b2_epsilon;
}
+
+
+// Collision Detection in Interactive 3D Environments by Gino van den Bergen
+// From Section 3.4.1
+// x = mu1 * p1 + mu2 * p2
+// mu1 + mu2 = 1 && mu1 >= 0 && mu2 >= 0
+// mu1 = 1 - mu2;
+// x = (1 - mu2) * p1 + mu2 * p2
+// = p1 + mu2 * (p2 - p1)
+// x = s + a * r (s := start, r := end - start)
+// s + a * r = p1 + mu2 * d (d := p2 - p1)
+// -a * r + mu2 * d = b (b := s - p1)
+// [-r d] * [a; mu2] = b
+// Cramer's rule:
+// denom = det[-r d]
+// a = det[b d] / denom
+// mu2 = det[-r b] / denom
+bool b2RaycastSegment(b2RayCastOutput* output, const b2RayCastInput& input, const b2Vec2& p1, const b2Vec2& p2)
+{
+ b2Vec2 s = input.p1;
+ b2Vec2 r = input.p2 - s;
+ b2Vec2 d = p2 - p1;
+ b2Vec2 n = b2Cross(d, 1.0f);
+
+ const float32 k_slop = 100.0f * b2_epsilon;
+ float32 denom = -b2Dot(r, n);
+
+ // Cull back facing collision and ignore parallel segments.
+ if (denom > k_slop)
+ {
+ // Does the segment intersect the infinite line associated with this segment?
+ b2Vec2 b = s - p1;
+ float32 a = b2Dot(b, n);
+
+ if (0.0f <= a && a <= input.maxFraction * denom)
+ {
+ float32 mu2 = -r.x * b.y + r.y * b.x;
+
+ // Does the segment intersect this segment?
+ if (-k_slop * denom <= mu2 && mu2 <= denom * (1.0f + k_slop))
+ {
+ a /= denom;
+ n.Normalize();
+ output->normal = n;
+ output->fraction = a;
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+
+static void FindNearestPointOnLineSegment( b2Vec2* nearest, float32* parameter,
+ const b2Vec2& A1, const b2Vec2& L, const b2Vec2& B,
+ bool infinite_line )
+{
+ float32 D = L.LengthSquared();
+ if (D < b2_epsilon * b2_epsilon)
+ {
+ *nearest = A1;
+ return;
+ }
+
+ b2Vec2 AB = B - A1;
+ *parameter = b2Dot(L, AB) / D;
+ if (!infinite_line)
+ {
+ *parameter = b2Clamp(*parameter, 0.0f, 1.0f);
+ }
+ *nearest = A1 + *parameter * L;
+}
+
+// Based on Game Programming Gems 2
+// Fast, Robust Intersection of 3D Line Segments
+// Graham Rhodes, Applied Research Associates
+b2Vec2 b2NearestPointOnLine(const b2Vec2& point, const b2Vec2& p1, const b2Vec2& p2)
+{
+ b2Vec2 result;
+ float32 unused;
+ FindNearestPointOnLineSegment(&result, &unused, p1, p2 - p1, point, false);
+ return result;
+}
+
+static void FindNearestPointOfParallelLineSegments( b2Vec2* x1, b2Vec2* x2,
+ const b2Vec2& A1, const b2Vec2& A2, const b2Vec2& La,
+ const b2Vec2& B1, const b2Vec2& B2, const b2Vec2& Lb)
+{
+ float32 s, t;
+ FindNearestPointOnLineSegment(x1, &s, A1, La, B1, true);
+ FindNearestPointOnLineSegment(x2, &t, A1, La, B2, true);
+
+ if (s < 0.0f && t < 0.0f)
+ {
+ *x1 = A1;
+ if (s < t)
+ *x2 = B2;
+ else
+ *x2 = B1;
+ return;
+ }
+
+ if (s > 1.0f && t > 1.0f)
+ {
+ *x1 = A2;
+ if (s < t)
+ *x2 = B1;
+ else
+ *x2 = B2;
+ return;
+ }
+
+ float32 temp = 0.5f * (b2Clamp(s, 0.0f, 1.0f) + b2Clamp(t, 0.0f, 1.0f));
+ *x1 = A1 + temp * La;
+
+ float32 unused;
+ FindNearestPointOnLineSegment(x2, &unused, B1, Lb, *x1, true);
+}
+
+static void AdjustNearestPoints(b2Vec2* x1, b2Vec2* x2,
+ const b2Vec2& A1, const b2Vec2& A2, const b2Vec2& La,
+ const b2Vec2& B1, const b2Vec2& B2, const b2Vec2& Lb,
+ float32 s, float32 t)
+{
+ if ((s < 0.0f || s > 1.0f) && (t < 0.0f || t > 1.0f))
+ {
+ s = b2Clamp(s, 0.0f, 1.0f);
+ *x1 = A1 + s * La;
+ FindNearestPointOnLineSegment(x2, &t, B1, Lb, *x1, true);
+ if (t < 0.0f || t > 1.0f)
+ {
+ t = b2Clamp(t, 0.0f, 1.0f);
+ *x2 = B1 + t * Lb;
+ FindNearestPointOnLineSegment(x1, &s, A1, La, *x2, false);
+ FindNearestPointOnLineSegment(x2, &t, B1, Lb, *x1, false);
+ }
+ return;
+ }
+ if (s < 0.0f || s > 1.0f)
+ {
+ s = b2Clamp(s, 0.0f, 1.0f);
+ *x1 = A1 + s * La;
+ FindNearestPointOnLineSegment(x2, &t, B1, Lb, *x1, false);
+ return;
+ }
+ b2Assert(t < 0.0f || t > 1.0f);
+ t = b2Clamp(t, 0.0f, 1.0f);
+ *x2 = B1 + t * Lb;
+ FindNearestPointOnLineSegment(x1, &s, A1, La, *x2, false);
+}
+
+static void IntersectLineSegments( b2Vec2* x1, b2Vec2* x2,
+ const b2Vec2& A1, const b2Vec2& A2,
+ const b2Vec2& B1, const b2Vec2& B2)
+{
+ float32 unused;
+
+ b2Vec2 La = A2 - A1;
+ b2Vec2 Lb = B2 - B1;
+ float32 L11 = La.LengthSquared();
+ float32 L22 = Lb.LengthSquared();
+
+ // Check for degenerate parameters
+ if (L11 < b2_epsilon * b2_epsilon)
+ {
+ *x1 = A1;
+ FindNearestPointOnLineSegment(x2, &unused, B1, Lb, A1, false);
+ return;
+ }
+ if (L22 < b2_epsilon * b2_epsilon)
+ {
+ *x2 = B1;
+ FindNearestPointOnLineSegment(x1, &unused, A1, La, B1, false);
+ return;
+ }
+
+ b2Vec2 AB = B1 - A1;
+ float32 L12 = -b2Dot(La, Lb);
+ float32 DetL = L11 * L22 - L12 * L12;
+
+ // parallel segments
+ if (b2Abs(DetL) < b2_epsilon)
+ {
+ FindNearestPointOfParallelLineSegments(x1, x2, A1, A2, La, B1, B2, Lb);
+ return;
+ }
+
+ float32 ra = b2Dot(La, AB);
+ float32 rb = -b2Dot(Lb, AB);
+
+ float32 t = (L11 * rb - ra * L12) / DetL;
+ float32 s = (ra - L12 * t) / L11;
+
+ // These tests can't quite stay within B2_FLT_EPSILON
+ //b2Assert(b2Abs(s * L11 + t * L12 - ra) < .0001f);
+ //b2Assert(b2Abs(s * L12 + t * L22 - rb) < .0001f);
+
+ *x1 = A1 + s * La;
+ *x2 = B1 + t * Lb;
+
+ if (s < 0.0f || s > 1.0f || t < 0.0f || t > 1.0f)
+ {
+ AdjustNearestPoints(x1, x2, A1, A2, La, B1, B2, Lb, s, t);
+ }
+}
+
+// Based on Game Programming Gems 2
+// Fast, Robust Intersection of 3D Line Segments
+// Graham Rhodes, Applied Research Associates
+float32 b2DistanceBetweenLines( b2Vec2* x1, b2Vec2* x2,
+ const b2Vec2& A1, const b2Vec2& A2,
+ const b2Vec2& B1, const b2Vec2& B2)
+{
+ IntersectLineSegments(x1, x2, A1, A2, B1, B2);
+ return (*x2 - *x1).Length();
+}
\ No newline at end of file
Index: Box2D/Box2D/Collision/b2Collision.h
===================================================================
--- Box2D/Box2D/Collision/b2Collision.h (revision 70)
+++ Box2D/Box2D/Collision/b2Collision.h (working copy)
@@ -27,6 +27,7 @@
/// queries, and TOI queries.
class b2Shape;
+class b2CapsuleShape;
class b2CircleShape;
class b2PolygonShape;
@@ -212,6 +213,18 @@
bool b2TestOverlap(const b2Shape* shapeA, const b2Shape* shapeB,
const b2Transform& xfA, const b2Transform& xfB);
+/// Perform a raycast against a given line segment.
+bool b2RaycastSegment(b2RayCastOutput* output, const b2RayCastInput& input, const b2Vec2& p1, const b2Vec2& p2);
+
+/// Find the nearest point on a line.
+b2Vec2 b2NearestPointOnLine(const b2Vec2& point, const b2Vec2& p1, const b2Vec2& p2);
+
+/// Find the nearest points on between two different lines.
+float32 b2DistanceBetweenLines( b2Vec2* x1, b2Vec2* x2,
+ const b2Vec2& A1, const b2Vec2& A2,
+ const b2Vec2& B1, const b2Vec2& B2);
+
+
// ---------------- Inline Functions ------------------------------------------
inline bool b2AABB::IsValid() const
Index: Box2D/Box2D/Collision/b2Distance.cpp
===================================================================
--- Box2D/Box2D/Collision/b2Distance.cpp (revision 70)
+++ Box2D/Box2D/Collision/b2Distance.cpp (working copy)
@@ -17,6 +17,7 @@
*/
#include <Box2D/Collision/b2Distance.h>
+#include <Box2D/Collision/Shapes/b2CapsuleShape.h>
#include <Box2D/Collision/Shapes/b2CircleShape.h>
#include <Box2D/Collision/Shapes/b2PolygonShape.h>
@@ -44,6 +45,15 @@
m_radius = polygon->m_radius;
}
break;
+
+ case b2Shape::e_capsule:
+ {
+ const b2CapsuleShape* capsule = (b2CapsuleShape*)shape;
+ m_vertices = capsule->m_vertices;
+ m_count = 2;
+ m_radius = capsule->m_radius;
+ }
+ break;
default:
b2Assert(false);
Index: Box2D/Box2D/Collision/Shapes/b2CapsuleShape.cpp
===================================================================
--- Box2D/Box2D/Collision/Shapes/b2CapsuleShape.cpp (revision 0)
+++ Box2D/Box2D/Collision/Shapes/b2CapsuleShape.cpp (revision 0)
@@ -0,0 +1,194 @@
+/*
+* Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com
+*
+* This software is provided 'as-is', without any express or implied
+* warranty. In no event will the authors be held liable for any damages
+* arising from the use of this software.
+* Permission is granted to anyone to use this software for any purpose,
+* including commercial applications, and to alter it and redistribute it
+* freely, subject to the following restrictions:
+* 1. The origin of this software must not be misrepresented; you must not
+* claim that you wrote the original software. If you use this software
+* in a product, an acknowledgment in the product documentation would be
+* appreciated but is not required.
+* 2. Altered source versions must be plainly marked as such, and must not be
+* misrepresented as being the original software.
+* 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include <Box2D/Collision/Shapes/b2CapsuleShape.h>
+#include <new>
+
+void b2CapsuleShape::SetByExtentsX(float32 radius, float32 length)
+{
+ m_radius = radius;
+ float32 half = length * 0.5f;
+ m_vertices[0] = b2Vec2(-half, 0.0f);
+ m_vertices[1] = b2Vec2(half, 0.0f);
+}
+
+void b2CapsuleShape::SetByExtentsX(float32 radius, float32 length,
+ const b2Vec2& center, float32 angle)
+{
+ SetByExtentsX(radius, length);
+ b2Transform xf;
+ xf.position = center;
+ xf.R.Set(angle);
+
+ m_vertices[0] = b2Mul(xf, m_vertices[0]);
+ m_vertices[1] = b2Mul(xf, m_vertices[1]);
+}
+
+
+void b2CapsuleShape::SetByExtentsY(float32 radius, float32 height)
+{
+ m_radius = radius;
+ float32 half = height * 0.5f;
+ m_vertices[0] = b2Vec2(0.0f, -half);
+ m_vertices[1] = b2Vec2(0.0f, half);
+}
+
+void b2CapsuleShape::SetByExtentsY(float32 radius, float32 height,
+ const b2Vec2& center, float32 angle)
+{
+ SetByExtentsY(radius, height);
+ b2Transform xf;
+ xf.position = center;
+ xf.R.Set(angle);
+
+ m_vertices[0] = b2Mul(xf, m_vertices[0]);
+ m_vertices[1] = b2Mul(xf, m_vertices[1]);
+}
+
+b2Shape* b2CapsuleShape::Clone(b2BlockAllocator* allocator) const
+{
+ void* mem = allocator->Allocate(sizeof(b2CapsuleShape));
+ b2CapsuleShape* clone = new (mem) b2CapsuleShape;
+ *clone = *this;
+ return clone;
+}
+
+bool b2CapsuleShape::TestPoint(const b2Transform& transform, const b2Vec2& p) const
+{
+ b2Vec2 local = b2MulT(transform, p);
+ b2Vec2 d = b2NearestPointOnLine(local, m_vertices[0], m_vertices[1]) - local;
+ return (d.LengthSquared() <= m_radius * m_radius);
+}
+
+bool b2CapsuleShape::RayCast(b2RayCastOutput* output, const b2RayCastInput& input, const b2Transform& transform) const
+{
+ // Test for starting inside first significantly reduces complexity
+ if (TestPoint(transform, input.p1)) {
+ return false;
+ }
+
+ // Project capsule to world
+ b2Vec2 capsule[2];
+ capsule[0] = b2Mul(transform, m_vertices[0]);
+ capsule[1] = b2Mul(transform, m_vertices[1]);
+ b2Vec2 d = capsule[1] - capsule[0];
+
+ // Consider "cylinder"
+
+ // Figure out signed distance from p1 to infinite capsule line
+ float32 ld = b2Cross(d, capsule[0] - input.p1);
+
+ // Only bother if we don't start inside the infinite "cylinder"
+ if (!(ld * ld <= m_radius * m_radius * d.LengthSquared())) {
+
+ // Find a perpendicular vector to the intersect, with length equal to radius
+ b2Vec2 perp = b2Cross(d, m_radius / d.Length());
+
+ // Push the capsule segment by that vector
+ // Must swap if coming from the other side
+ b2Vec2 boundary[2];
+ if (ld < 0) {
+ boundary[0] = capsule[1] - perp;
+ boundary[1] = capsule[0] - perp;
+ }
+ else {
+ boundary[0] = capsule[0] + perp;
+ boundary[1] = capsule[1] + perp;
+ }
+
+ // Check intersection against the adjusted segments.
+ if (b2RaycastSegment(output, input, boundary[0], boundary[1]))
+ return true;
+ }
+
+ // Consider circular caps
+
+ // Precompute some circle values
+ b2Vec2 r = input.p2 - input.p1;
+ float32 rr = r.LengthSquared();
+
+ // Check for short segment
+ if (rr < b2_epsilon)
+ {
+ return false;
+ }
+
+ // Check the circle caps, starting with closer
+ int startingIndex = 0;
+ if ((capsule[1] - input.p1).LengthSquared() < (capsule[0] - input.p1).LengthSquared()) {
+ startingIndex = 1;
+ }
+ b2Vec2 center = capsule[startingIndex];
+ for (int i = 0; i < 2; ++i)
+ {
+ b2Vec2 s = input.p1 - center;
+ float32 b = b2Dot(s, s) - m_radius * m_radius;
+
+ // Should not start inside
+ b2Assert(!(b < 0.0f));
+
+ // Solve quadratic equation.
+ float32 c = b2Dot(s, r);
+ float32 sigma = c * c - rr * b;
+
+ // Check for negative discriminant.
+ if (!(sigma < 0.0f))
+ {
+ // Find the point of intersection of the line with the circle.
+ float32 a = -(c + b2Sqrt(sigma));
+
+ // Is the intersection point on the segment?
+ if (0.0f <= a && a <= input.maxFraction * rr)
+ {
+ a /= rr;
+ output->fraction = a;
+ output->normal = s + a * r;
+ output->normal.Normalize();
+ return true;
+ }
+ }
+ center = capsule[!startingIndex];
+ }
+
+ return false;
+}
+
+void b2CapsuleShape::ComputeAABB(b2AABB* aabb, const b2Transform& transform) const
+{
+ b2Vec2 p1 = transform.position + b2Mul(transform.R, m_vertices[0]);
+ b2Vec2 p2 = transform.position + b2Mul(transform.R, m_vertices[1]);
+ b2Vec2 min = b2Min(p1, p2);
+ b2Vec2 max = b2Max(p1, p2);
+ aabb->lowerBound.Set(min.x - m_radius, min.y - m_radius);
+ aabb->upperBound.Set(max.x + m_radius, max.y + m_radius);
+}
+
+void b2CapsuleShape::ComputeMass(b2MassData* massData, float32 density) const
+{
+ // Area of rectangle + 2 half circles
+ float32 rectHeight = (m_vertices[1] - m_vertices[0]).Length();
+ float32 rectMass = density * rectHeight * m_radius;
+ float32 circleMass = density * b2_pi * m_radius * m_radius;
+ massData->mass = rectMass + circleMass;
+ massData->center = 0.5f * (m_vertices[0] + m_vertices[1]);
+
+ // inertia about the local origin
+ float32 rectInertia = rectMass * (rectHeight * rectHeight + m_radius * m_radius) / 12.0f;
+ float32 circleInertia = circleMass * (0.5f * m_radius * m_radius + rectHeight * rectHeight * .25f);
+ massData->I = rectInertia + circleInertia + massData->mass * massData->center.LengthSquared();
+}
Index: Box2D/Box2D/Collision/Shapes/b2CapsuleShape.h
===================================================================
--- Box2D/Box2D/Collision/Shapes/b2CapsuleShape.h (revision 0)
+++ Box2D/Box2D/Collision/Shapes/b2CapsuleShape.h (revision 0)
@@ -0,0 +1,103 @@
+/*
+* Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com
+*
+* This software is provided 'as-is', without any express or implied
+* warranty. In no event will the authors be held liable for any damages
+* arising from the use of this software.
+* Permission is granted to anyone to use this software for any purpose,
+* including commercial applications, and to alter it and redistribute it
+* freely, subject to the following restrictions:
+* 1. The origin of this software must not be misrepresented; you must not
+* claim that you wrote the original software. If you use this software
+* in a product, an acknowledgment in the product documentation would be
+* appreciated but is not required.
+* 2. Altered source versions must be plainly marked as such, and must not be
+* misrepresented as being the original software.
+* 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef B2_CAPSULE_SHAPE_H
+#define B2_CAPSULE_SHAPE_H
+
+#include <Box2D/Collision/Shapes/b2Shape.h>
+
+/// A circle shape.
+class b2CapsuleShape : public b2Shape
+{
+public:
+ b2CapsuleShape();
+
+ /// Set to a capsule across the X axis, with given width between focii.
+ void SetByExtentsX(float32 radius, float32 width);
+ /// Set to a capsule across the X axis, rotated and transposed.
+ void SetByExtentsX(float32 radius, float32 width,
+ const b2Vec2& center, float32 angle);
+
+ /// Set to a capsule across the Y axis, with given height between focii.
+ void SetByExtentsY(float32 radius, float32 height);
+ /// Set to a capsule across the Y axis, rotated and transposed.
+ void SetByExtentsY(float32 radius, float32 height,
+ const b2Vec2& center, float32 angle);
+
+ /// Implement b2Shape.
+ b2Shape* Clone(b2BlockAllocator* allocator) const;
+
+ /// Implement b2Shape.
+ bool TestPoint(const b2Transform& transform, const b2Vec2& p) const;
+
+ /// Implement b2Shape.
+ bool RayCast(b2RayCastOutput* output, const b2RayCastInput& input, const b2Transform& transform) const;
+
+ /// @see b2Shape::ComputeAABB
+ void ComputeAABB(b2AABB* aabb, const b2Transform& transform) const;
+
+ /// @see b2Shape::ComputeMass
+ void ComputeMass(b2MassData* massData, float32 density) const;
+
+ /// Get the supporting vertex index in the given direction.
+ int32 GetSupport(const b2Vec2& d) const;
+
+ /// Get the supporting vertex in the given direction.
+ const b2Vec2& GetSupportVertex(const b2Vec2& d) const;
+
+ /// Get the vertex count.
+ int32 GetVertexCount() const { return 2; }
+
+ /// Get a vertex by index. Used by b2Distance.
+ const b2Vec2& GetVertex(int32 index) const;
+
+ /// Position of circle centers
+ b2Vec2 m_vertices[2];
+};
+
+inline b2CapsuleShape::b2CapsuleShape()
+{
+ m_type = e_capsule;
+ m_radius = 0.0f;
+ m_vertices[0].SetZero();
+ m_vertices[1].SetZero();
+}
+
+
+inline int32 b2CapsuleShape::GetSupport(const b2Vec2 &d) const
+{
+ if ((m_vertices[0] - d).LengthSquared() <= (m_vertices[1] - d).LengthSquared()) {
+ return 0;
+ }
+ return 1;
+}
+
+inline const b2Vec2& b2CapsuleShape::GetSupportVertex(const b2Vec2 &d) const
+{
+ return GetVertex(GetSupport(d));
+}
+
+inline const b2Vec2& b2CapsuleShape::GetVertex(int32 index) const
+{
+ b2Assert(index == 0 || index == 1);
+ return m_vertices[index];
+}
+
+
+
+#endif
Index: Box2D/Box2D/Collision/Shapes/b2Shape.h
===================================================================
--- Box2D/Box2D/Collision/Shapes/b2Shape.h (revision 70)
+++ Box2D/Box2D/Collision/Shapes/b2Shape.h (working copy)
@@ -48,7 +48,8 @@
e_unknown= -1,
e_circle = 0,
e_polygon = 1,
- e_typeCount = 2,
+ e_capsule = 2,
+ e_typeCount = 3,
};
b2Shape() { m_type = e_unknown; }
Index: Box2D/Box2D/Dynamics/b2Fixture.cpp
===================================================================
--- Box2D/Box2D/Dynamics/b2Fixture.cpp (revision 70)
+++ Box2D/Box2D/Dynamics/b2Fixture.cpp (working copy)
@@ -18,6 +18,7 @@
#include <Box2D/Dynamics/b2Fixture.h>
#include <Box2D/Dynamics/Contacts/b2Contact.h>
+#include <Box2D/Collision/Shapes/b2CapsuleShape.h>
#include <Box2D/Collision/Shapes/b2CircleShape.h>
#include <Box2D/Collision/Shapes/b2PolygonShape.h>
#include <Box2D/Collision/b2BroadPhase.h>
@@ -82,6 +83,14 @@
allocator->Free(s, sizeof(b2PolygonShape));
}
break;
+
+ case b2Shape::e_capsule:
+ {
+ b2CapsuleShape* s = (b2CapsuleShape*)m_shape;
+ s->~b2CapsuleShape();
+ allocator->Free(s, sizeof(b2CapsuleShape));
+ }
+ break;
default:
b2Assert(false);
Index: Box2D/Box2D/Dynamics/b2World.cpp
===================================================================
--- Box2D/Box2D/Dynamics/b2World.cpp (revision 70)
+++ Box2D/Box2D/Dynamics/b2World.cpp (working copy)
@@ -26,6 +26,7 @@
#include <Box2D/Dynamics/Contacts/b2TOISolver.h>
#include <Box2D/Collision/b2Collision.h>
#include <Box2D/Collision/b2BroadPhase.h>
+#include <Box2D/Collision/Shapes/b2CapsuleShape.h>
#include <Box2D/Collision/Shapes/b2CircleShape.h>
#include <Box2D/Collision/Shapes/b2PolygonShape.h>
#include <Box2D/Collision/b2TimeOfImpact.h>
@@ -907,6 +908,18 @@
m_debugDraw->DrawSolidPolygon(vertices, vertexCount, color);
}
break;
+
+ case b2Shape::e_capsule:
+ {
+ b2CapsuleShape* capsule = (b2CapsuleShape*)fixture->GetShape();
+
+ b2Vec2 p1 = b2Mul(xf, capsule->m_vertices[0]);
+ b2Vec2 p2 = b2Mul(xf, capsule->m_vertices[1]);
+ float32 radius = capsule->m_radius;
+
+ m_debugDraw->DrawSolidCapsule(p1, p2, radius, color);
+ }
+ break;
}
}
Index: Box2D/Box2D/Dynamics/b2WorldCallbacks.h
===================================================================
--- Box2D/Box2D/Dynamics/b2WorldCallbacks.h (revision 70)
+++ Box2D/Box2D/Dynamics/b2WorldCallbacks.h (working copy)
@@ -206,6 +206,12 @@
/// Draw a solid circle.
virtual void DrawSolidCircle(const b2Vec2& center, float32 radius, const b2Vec2& axis, const b2Color& color) = 0;
+ /// Draw a capsule.
+ virtual void DrawCapsule(const b2Vec2& p1, const b2Vec2& p2, float32 radius, const b2Color& color) = 0;
+
+ /// Draw a solid capsule.
+ virtual void DrawSolidCapsule(const b2Vec2& p1, const b2Vec2& p2, float32 radius, const b2Color& color) = 0;
+
/// Draw a line segment.
virtual void DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color) = 0;
Index: Box2D/Box2D/Dynamics/Contacts/b2CapsuleAndCircleContact.cpp
===================================================================
--- Box2D/Box2D/Dynamics/Contacts/b2CapsuleAndCircleContact.cpp (revision 0)
+++ Box2D/Box2D/Dynamics/Contacts/b2CapsuleAndCircleContact.cpp (revision 0)
@@ -0,0 +1,63 @@
+/*
+* Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com
+*
+* This software is provided 'as-is', without any express or implied
+* warranty. In no event will the authors be held liable for any damages
+* arising from the use of this software.
+* Permission is granted to anyone to use this software for any purpose,
+* including commercial applications, and to alter it and redistribute it
+* freely, subject to the following restrictions:
+* 1. The origin of this software must not be misrepresented; you must not
+* claim that you wrote the original software. If you use this software
+* in a product, an acknowledgment in the product documentation would be
+* appreciated but is not required.
+* 2. Altered source versions must be plainly marked as such, and must not be
+* misrepresented as being the original software.
+* 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include <Box2D/Dynamics/Contacts/b2CapsuleAndCircleContact.h>
+#include <Box2D/Dynamics/b2Body.h>
+#include <Box2D/Dynamics/b2Fixture.h>
+#include <Box2D/Dynamics/b2WorldCallbacks.h>
+#include <Box2D/Common/b2BlockAllocator.h>
+#include <Box2D/Collision/b2TimeOfImpact.h>
+#include <Box2D/Collision/Shapes/b2CapsuleShape.h>
+#include <Box2D/Collision/Shapes/b2PolygonShape.h>
+
+#include <new>
+
+b2Contact* b2CapsuleAndCircleContact::Create(b2Fixture* fixtureA, b2Fixture* fixtureB, b2BlockAllocator* allocator)
+{
+ void* mem = allocator->Allocate(sizeof(b2CapsuleAndCircleContact));
+ return new (mem) b2CapsuleAndCircleContact(fixtureA, fixtureB);
+}
+
+void b2CapsuleAndCircleContact::Destroy(b2Contact* contact, b2BlockAllocator* allocator)
+{
+ ((b2CapsuleAndCircleContact*)contact)->~b2CapsuleAndCircleContact();
+ allocator->Free(contact, sizeof(b2CapsuleAndCircleContact));
+}
+
+b2CapsuleAndCircleContact::b2CapsuleAndCircleContact(b2Fixture* fixtureA, b2Fixture* fixtureB)
+ : b2Contact(fixtureA, fixtureB)
+{
+ b2Assert(m_fixtureA->GetType() == b2Shape::e_capsule);
+ b2Assert(m_fixtureB->GetType() == b2Shape::e_circle);
+}
+
+void b2CapsuleAndCircleContact::Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB)
+{
+ b2Body* bodyA = m_fixtureA->GetBody();
+ b2Body* bodyB = m_fixtureB->GetBody();
+
+ b2CapsuleShape* capsule = (b2CapsuleShape*)m_fixtureA->GetShape();
+
+ b2PolygonShape polygon;
+ polygon.SetAsEdge(capsule->m_vertices[0], capsule->m_vertices[1]);
+ polygon.m_radius = capsule->m_radius;
+
+ b2CollidePolygonAndCircle( manifold,
+ &polygon, xfA,
+ (b2CircleShape*)m_fixtureB->GetShape(), xfB);
+}
Index: Box2D/Box2D/Dynamics/Contacts/b2CapsuleAndCircleContact.h
===================================================================
--- Box2D/Box2D/Dynamics/Contacts/b2CapsuleAndCircleContact.h (revision 0)
+++ Box2D/Box2D/Dynamics/Contacts/b2CapsuleAndCircleContact.h (revision 0)
@@ -0,0 +1,38 @@
+/*
+* Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com
+*
+* This software is provided 'as-is', without any express or implied
+* warranty. In no event will the authors be held liable for any damages
+* arising from the use of this software.
+* Permission is granted to anyone to use this software for any purpose,
+* including commercial applications, and to alter it and redistribute it
+* freely, subject to the following restrictions:
+* 1. The origin of this software must not be misrepresented; you must not
+* claim that you wrote the original software. If you use this software
+* in a product, an acknowledgment in the product documentation would be
+* appreciated but is not required.
+* 2. Altered source versions must be plainly marked as such, and must not be
+* misrepresented as being the original software.
+* 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef B2_CAPSULE_AND_CIRCLE_CONTACT_H
+#define B2_CAPSULE_AND_CIRCLE_CONTACT_H
+
+#include <Box2D/Dynamics/Contacts/b2Contact.h>
+
+class b2BlockAllocator;
+
+class b2CapsuleAndCircleContact : public b2Contact
+{
+public:
+ static b2Contact* Create(b2Fixture* fixtureA, b2Fixture* fixtureB, b2BlockAllocator* allocator);
+ static void Destroy(b2Contact* contact, b2BlockAllocator* allocator);
+
+ b2CapsuleAndCircleContact(b2Fixture* fixtureA, b2Fixture* fixtureB);
+ ~b2CapsuleAndCircleContact() {}
+
+ void Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB);
+};
+
+#endif
Index: Box2D/Box2D/Dynamics/Contacts/b2CapsuleContact.cpp
===================================================================
--- Box2D/Box2D/Dynamics/Contacts/b2CapsuleContact.cpp (revision 0)
+++ Box2D/Box2D/Dynamics/Contacts/b2CapsuleContact.cpp (revision 0)
@@ -0,0 +1,66 @@
+/*
+* Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com
+*
+* This software is provided 'as-is', without any express or implied
+* warranty. In no event will the authors be held liable for any damages
+* arising from the use of this software.
+* Permission is granted to anyone to use this software for any purpose,
+* including commercial applications, and to alter it and redistribute it
+* freely, subject to the following restrictions:
+* 1. The origin of this software must not be misrepresented; you must not
+* claim that you wrote the original software. If you use this software
+* in a product, an acknowledgment in the product documentation would be
+* appreciated but is not required.
+* 2. Altered source versions must be plainly marked as such, and must not be
+* misrepresented as being the original software.
+* 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include <Box2D/Dynamics/Contacts/b2CapsuleContact.h>
+#include <Box2D/Dynamics/b2Body.h>
+#include <Box2D/Dynamics/b2Fixture.h>
+#include <Box2D/Dynamics/b2WorldCallbacks.h>
+#include <Box2D/Common/b2BlockAllocator.h>
+#include <Box2D/Collision/b2TimeOfImpact.h>
+#include <Box2D/Collision/Shapes/b2CapsuleShape.h>
+#include <Box2D/Collision/Shapes/b2PolygonShape.h>
+
+#include <new>
+
+b2Contact* b2CapsuleContact::Create(b2Fixture* fixtureA, b2Fixture* fixtureB, b2BlockAllocator* allocator)
+{
+ void* mem = allocator->Allocate(sizeof(b2CapsuleContact));
+ return new (mem) b2CapsuleContact(fixtureA, fixtureB);
+}
+
+void b2CapsuleContact::Destroy(b2Contact* contact, b2BlockAllocator* allocator)
+{
+ ((b2CapsuleContact*)contact)->~b2CapsuleContact();
+ allocator->Free(contact, sizeof(b2CapsuleContact));
+}
+
+b2CapsuleContact::b2CapsuleContact(b2Fixture* fixtureA, b2Fixture* fixtureB)
+ : b2Contact(fixtureA, fixtureB)
+{
+ b2Assert(m_fixtureA->GetType() == b2Shape::e_capsule);
+ b2Assert(m_fixtureB->GetType() == b2Shape::e_capsule);
+}
+
+void b2CapsuleContact::Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB)
+{
+ b2Body* bodyA = m_fixtureA->GetBody();
+ b2Body* bodyB = m_fixtureB->GetBody();
+
+ b2CapsuleShape* capsule1 = (b2CapsuleShape*)m_fixtureA->GetShape();
+ b2CapsuleShape* capsule2 = (b2CapsuleShape*)m_fixtureB->GetShape();
+
+ b2PolygonShape polygon1, polygon2;
+ polygon1.SetAsEdge(capsule1->m_vertices[0], capsule1->m_vertices[1]);
+ polygon2.SetAsEdge(capsule2->m_vertices[0], capsule2->m_vertices[1]);
+ polygon1.m_radius = capsule1->m_radius;
+ polygon2.m_radius = capsule2->m_radius;
+
+ b2CollidePolygons( manifold,
+ &polygon1, xfA,
+ &polygon2, xfB);
+}
Index: Box2D/Box2D/Dynamics/Contacts/b2CapsuleContact.h
===================================================================
--- Box2D/Box2D/Dynamics/Contacts/b2CapsuleContact.h (revision 0)
+++ Box2D/Box2D/Dynamics/Contacts/b2CapsuleContact.h (revision 0)
@@ -0,0 +1,38 @@
+/*
+* Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com
+*
+* This software is provided 'as-is', without any express or implied
+* warranty. In no event will the authors be held liable for any damages
+* arising from the use of this software.
+* Permission is granted to anyone to use this software for any purpose,
+* including commercial applications, and to alter it and redistribute it
+* freely, subject to the following restrictions:
+* 1. The origin of this software must not be misrepresented; you must not
+* claim that you wrote the original software. If you use this software
+* in a product, an acknowledgment in the product documentation would be
+* appreciated but is not required.
+* 2. Altered source versions must be plainly marked as such, and must not be
+* misrepresented as being the original software.
+* 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef B2_CAPSULE_CONTACT_H
+#define B2_CAPSULE_CONTACT_H
+
+#include <Box2D/Dynamics/Contacts/b2Contact.h>
+
+class b2BlockAllocator;
+
+class b2CapsuleContact : public b2Contact
+{
+public:
+ static b2Contact* Create(b2Fixture* fixtureA, b2Fixture* fixtureB, b2BlockAllocator* allocator);
+ static void Destroy(b2Contact* contact, b2BlockAllocator* allocator);
+
+ b2CapsuleContact(b2Fixture* fixtureA, b2Fixture* fixtureB);
+ ~b2CapsuleContact() {}
+
+ void Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB);
+};
+
+#endif
Index: Box2D/Box2D/Dynamics/Contacts/b2Contact.cpp
===================================================================
--- Box2D/Box2D/Dynamics/Contacts/b2Contact.cpp (revision 70)
+++ Box2D/Box2D/Dynamics/Contacts/b2Contact.cpp (working copy)
@@ -17,7 +17,10 @@
*/
#include <Box2D/Dynamics/Contacts/b2Contact.h>
+#include <Box2D/Dynamics/Contacts/b2CapsuleContact.h>
+#include <Box2D/Dynamics/Contacts/b2CapsuleAndCircleContact.h>
#include <Box2D/Dynamics/Contacts/b2CircleContact.h>
+#include <Box2D/Dynamics/Contacts/b2PolygonAndCapsuleContact.h>
#include <Box2D/Dynamics/Contacts/b2PolygonAndCircleContact.h>
#include <Box2D/Dynamics/Contacts/b2PolygonContact.h>
#include <Box2D/Dynamics/Contacts/b2ContactSolver.h>
@@ -38,6 +41,10 @@
AddType(b2CircleContact::Create, b2CircleContact::Destroy, b2Shape::e_circle, b2Shape::e_circle);
AddType(b2PolygonAndCircleContact::Create, b2PolygonAndCircleContact::Destroy, b2Shape::e_polygon, b2Shape::e_circle);
AddType(b2PolygonContact::Create, b2PolygonContact::Destroy, b2Shape::e_polygon, b2Shape::e_polygon);
+
+ AddType(b2CapsuleContact::Create, b2CapsuleContact::Destroy, b2Shape::e_capsule, b2Shape::e_capsule);
+ AddType(b2CapsuleAndCircleContact::Create, b2CapsuleAndCircleContact::Destroy, b2Shape::e_capsule, b2Shape::e_circle);
+ AddType(b2PolygonAndCapsuleContact::Create, b2PolygonAndCapsuleContact::Destroy, b2Shape::e_polygon, b2Shape::e_capsule);
}
void b2Contact::AddType(b2ContactCreateFcn* createFcn, b2ContactDestroyFcn* destoryFcn,
Index: Box2D/Box2D/Dynamics/Contacts/b2PolygonAndCapsuleContact.cpp
===================================================================
--- Box2D/Box2D/Dynamics/Contacts/b2PolygonAndCapsuleContact.cpp (revision 0)
+++ Box2D/Box2D/Dynamics/Contacts/b2PolygonAndCapsuleContact.cpp (revision 0)
@@ -0,0 +1,63 @@
+/*
+* Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com
+*
+* This software is provided 'as-is', without any express or implied
+* warranty. In no event will the authors be held liable for any damages
+* arising from the use of this software.
+* Permission is granted to anyone to use this software for any purpose,
+* including commercial applications, and to alter it and redistribute it
+* freely, subject to the following restrictions:
+* 1. The origin of this software must not be misrepresented; you must not
+* claim that you wrote the original software. If you use this software
+* in a product, an acknowledgment in the product documentation would be
+* appreciated but is not required.
+* 2. Altered source versions must be plainly marked as such, and must not be
+* misrepresented as being the original software.
+* 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include <Box2D/Dynamics/Contacts/b2PolygonAndCapsuleContact.h>
+#include <Box2D/Dynamics/b2Body.h>
+#include <Box2D/Dynamics/b2Fixture.h>
+#include <Box2D/Dynamics/b2WorldCallbacks.h>
+#include <Box2D/Common/b2BlockAllocator.h>
+#include <Box2D/Collision/b2TimeOfImpact.h>
+#include <Box2D/Collision/Shapes/b2CapsuleShape.h>
+#include <Box2D/Collision/Shapes/b2PolygonShape.h>
+
+#include <new>
+
+b2Contact* b2PolygonAndCapsuleContact::Create(b2Fixture* fixtureA, b2Fixture* fixtureB, b2BlockAllocator* allocator)
+{
+ void* mem = allocator->Allocate(sizeof(b2PolygonAndCapsuleContact));
+ return new (mem) b2PolygonAndCapsuleContact(fixtureA, fixtureB);
+}
+
+void b2PolygonAndCapsuleContact::Destroy(b2Contact* contact, b2BlockAllocator* allocator)
+{
+ ((b2PolygonAndCapsuleContact*)contact)->~b2PolygonAndCapsuleContact();
+ allocator->Free(contact, sizeof(b2PolygonAndCapsuleContact));
+}
+
+b2PolygonAndCapsuleContact::b2PolygonAndCapsuleContact(b2Fixture* fixtureA, b2Fixture* fixtureB)
+ : b2Contact(fixtureA, fixtureB)
+{
+ b2Assert(m_fixtureA->GetType() == b2Shape::e_polygon);
+ b2Assert(m_fixtureB->GetType() == b2Shape::e_capsule);
+}
+
+void b2PolygonAndCapsuleContact::Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB)
+{
+ b2Body* bodyA = m_fixtureA->GetBody();
+ b2Body* bodyB = m_fixtureB->GetBody();
+
+ b2CapsuleShape* capsule = (b2CapsuleShape*)m_fixtureB->GetShape();
+
+ b2PolygonShape polygon;
+ polygon.SetAsEdge(capsule->m_vertices[0], capsule->m_vertices[1]);
+ polygon.m_radius = capsule->m_radius;
+
+ b2CollidePolygons( manifold,
+ (b2PolygonShape*)m_fixtureA->GetShape(), xfA,
+ &polygon, xfB);
+}
Index: Box2D/Box2D/Dynamics/Contacts/b2PolygonAndCapsuleContact.h
===================================================================
--- Box2D/Box2D/Dynamics/Contacts/b2PolygonAndCapsuleContact.h (revision 0)
+++ Box2D/Box2D/Dynamics/Contacts/b2PolygonAndCapsuleContact.h (revision 0)
@@ -0,0 +1,38 @@
+/*
+* Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com
+*
+* This software is provided 'as-is', without any express or implied
+* warranty. In no event will the authors be held liable for any damages
+* arising from the use of this software.
+* Permission is granted to anyone to use this software for any purpose,
+* including commercial applications, and to alter it and redistribute it
+* freely, subject to the following restrictions:
+* 1. The origin of this software must not be misrepresented; you must not
+* claim that you wrote the original software. If you use this software
+* in a product, an acknowledgment in the product documentation would be
+* appreciated but is not required.
+* 2. Altered source versions must be plainly marked as such, and must not be
+* misrepresented as being the original software.
+* 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef B2_POLYGON_AND_CAPSULE_CONTACT_H
+#define B2_POLYGON_AND_CAPSULE_CONTACT_H
+
+#include <Box2D/Dynamics/Contacts/b2Contact.h>
+
+class b2BlockAllocator;
+
+class b2PolygonAndCapsuleContact : public b2Contact
+{
+public:
+ static b2Contact* Create(b2Fixture* fixtureA, b2Fixture* fixtureB, b2BlockAllocator* allocator);
+ static void Destroy(b2Contact* contact, b2BlockAllocator* allocator);
+
+ b2PolygonAndCapsuleContact(b2Fixture* fixtureA, b2Fixture* fixtureB);
+ ~b2PolygonAndCapsuleContact() {}
+
+ void Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB);
+};
+
+#endif
Index: Box2D/Testbed/Framework/Render.cpp
===================================================================
--- Box2D/Testbed/Framework/Render.cpp (revision 70)
+++ Box2D/Testbed/Framework/Render.cpp (working copy)
@@ -110,6 +110,83 @@
glEnd();
}
+void DebugDraw::DrawCapsule(const b2Vec2& p1, const b2Vec2& p2, float32 radius, const b2Color& color)
+{
+ b2Vec2 displacement = p2 - p1;
+ displacement.Normalize();
+ float32 startingAngle = atan2f(displacement.y, displacement.x) + b2_pi / 2;
+
+ const float32 k_segments = 8.0f;
+ const float32 k_increment = b2_pi / k_segments;
+ float32 theta = startingAngle;
+ glColor3f(color.r, color.g, color.b);
+ glBegin(GL_LINE_LOOP);
+ for (int32 i = 0; i < k_segments; ++i)
+ {
+ b2Vec2 v = p1 + radius * b2Vec2(cosf(theta), sinf(theta));
+ glVertex2f(v.x, v.y);
+ theta += k_increment;
+ }
+ for (int32 i = 0; i < k_segments; ++i)
+ {
+ b2Vec2 v = p2 + radius * b2Vec2(cosf(theta), sinf(theta));
+ glVertex2f(v.x, v.y);
+ theta += k_increment;
+ }
+ glEnd();
+}
+
+void DebugDraw::DrawSolidCapsule(const b2Vec2& p1, const b2Vec2& p2, float32 radius, const b2Color& color)
+{
+ b2Vec2 displacement = p2 - p1;
+ displacement.Normalize();
+ float32 startingAngle = atan2f(displacement.y, displacement.x) + b2_pi / 2;
+
+ const float32 k_segments = 8.0f;
+ const float32 k_increment = b2_pi / k_segments;
+ float32 theta = startingAngle;
+ glEnable(GL_BLEND);
+ glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glColor4f(0.5f * color.r, 0.5f * color.g, 0.5f * color.b, 0.5f);
+ glBegin(GL_TRIANGLE_FAN);
+ for (int32 i = 0; i < k_segments; ++i)
+ {
+ b2Vec2 v = p1 + radius * b2Vec2(cosf(theta), sinf(theta));
+ glVertex2f(v.x, v.y);
+ theta += k_increment;
+ }
+ for (int32 i = 0; i < k_segments; ++i)
+ {
+ b2Vec2 v = p2 + radius * b2Vec2(cosf(theta), sinf(theta));
+ glVertex2f(v.x, v.y);
+ theta += k_increment;
+ }
+ glEnd();
+ glDisable(GL_BLEND);
+
+ theta = startingAngle;
+ glColor4f(color.r, color.g, color.b, 1.0f);
+ glBegin(GL_LINE_LOOP);
+ for (int32 i = 0; i < k_segments; ++i)
+ {
+ b2Vec2 v = p1 + radius * b2Vec2(cosf(theta), sinf(theta));
+ glVertex2f(v.x, v.y);
+ theta += k_increment;
+ }
+ for (int32 i = 0; i < k_segments; ++i)
+ {
+ b2Vec2 v = p2 + radius * b2Vec2(cosf(theta), sinf(theta));
+ glVertex2f(v.x, v.y);
+ theta += k_increment;
+ }
+ glEnd();
+
+ glBegin(GL_LINES);
+ glVertex2f(p1.x, p1.y);
+ glVertex2f(p2.x, p2.y);
+ glEnd();
+}
+
void DebugDraw::DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color)
{
glColor3f(color.r, color.g, color.b);
Index: Box2D/Testbed/Framework/Render.h
===================================================================
--- Box2D/Testbed/Framework/Render.h (revision 70)
+++ Box2D/Testbed/Framework/Render.h (working copy)
@@ -36,6 +36,10 @@
void DrawSolidCircle(const b2Vec2& center, float32 radius, const b2Vec2& axis, const b2Color& color);
+ void DrawCapsule(const b2Vec2& p1, const b2Vec2& p2, float32 radius, const b2Color& color);
+
+ void DrawSolidCapsule(const b2Vec2& p1, const b2Vec2& p2, float32 radius, const b2Color& color);
+
void DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color);
void DrawTransform(const b2Transform& xf);
Index: Box2D/Testbed/Tests/PolyShapes.h
===================================================================
--- Box2D/Testbed/Tests/PolyShapes.h (revision 70)
+++ Box2D/Testbed/Tests/PolyShapes.h (working copy)
@@ -74,6 +74,19 @@
m_debugDraw->DrawPolygon(vertices, vertexCount, color);
}
break;
+
+ case b2Shape::e_capsule:
+ {
+ b2CapsuleShape* capsule = (b2CapsuleShape*)fixture->GetShape();
+
+ b2Vec2 p1 = b2Mul(xf, capsule->m_vertices[0]);
+ b2Vec2 p2 = b2Mul(xf, capsule->m_vertices[1]);
+ float32 radius = capsule->m_radius;
+
+ m_debugDraw->DrawCapsule(p1, p2, radius, color);
+ }
+ break;
+
}
}
@@ -163,6 +176,14 @@
m_circle.m_radius = 0.5f;
}
+ {
+ m_capsules[0].SetByExtentsX(0.5f, 0.5f);
+ }
+
+ {
+ m_capsules[1].SetByExtentsY(0.1f, 1.8f, b2Vec2(0.0f, 1.0f), 0.0f);
+ }
+
m_bodyIndex = 0;
memset(m_bodies, 0, sizeof(m_bodies));
}
@@ -197,7 +218,7 @@
fd.friction = 0.3f;
m_bodies[m_bodyIndex]->CreateFixture(&fd);
}
- else
+ else if (index == 4)
{
b2FixtureDef fd;
fd.shape = &m_circle;
@@ -206,6 +227,15 @@
m_bodies[m_bodyIndex]->CreateFixture(&fd);
}
+ else
+ {
+ b2FixtureDef fd;
+ fd.shape = m_capsules + (index - 5);
+ fd.density = 1.0f;
+ fd.friction = 0.3f;
+
+ m_bodies[m_bodyIndex]->CreateFixture(&fd);
+ }
m_bodyIndex = (m_bodyIndex + 1) % k_maxBodies;
}
@@ -232,6 +262,8 @@
case '3':
case '4':
case '5':
+ case '6':
+ case '7':
Create(key - '1');
break;
@@ -270,7 +302,7 @@
b2Color color(0.4f, 0.7f, 0.8f);
m_debugDraw.DrawCircle(callback.m_circle.m_p, callback.m_circle.m_radius, color);
- m_debugDraw.DrawString(5, m_textLine, "Press 1-5 to drop stuff");
+ m_debugDraw.DrawString(5, m_textLine, "Press 1-7 to drop stuff");
m_textLine += 15;
m_debugDraw.DrawString(5, m_textLine, "Press 'a' to (de)activate some bodies");
m_textLine += 15;
@@ -287,6 +319,7 @@
b2Body* m_bodies[k_maxBodies];
b2PolygonShape m_polygons[4];
b2CircleShape m_circle;
+ b2CapsuleShape m_capsules[2];
};
#endif
Index: Box2D/Testbed/Tests/RayCast.h
===================================================================
--- Box2D/Testbed/Tests/RayCast.h (revision 70)
+++ Box2D/Testbed/Tests/RayCast.h (working copy)
@@ -211,6 +211,14 @@
m_circle.m_radius = 0.5f;
}
+ {
+ m_capsules[0].SetByExtentsX(0.5f, 0.5f);
+ }
+
+ {
+ m_capsules[1].SetByExtentsY(0.1f, 1.8f, b2Vec2(0.0f, 1.0f), 0.0f);
+ }
+
m_bodyIndex = 0;
memset(m_bodies, 0, sizeof(m_bodies));
@@ -251,7 +259,7 @@
fd.friction = 0.3f;
m_bodies[m_bodyIndex]->CreateFixture(&fd);
}
- else
+ else if (index == 4)
{
b2FixtureDef fd;
fd.shape = &m_circle;
@@ -259,6 +267,14 @@
m_bodies[m_bodyIndex]->CreateFixture(&fd);
}
+ else
+ {
+ b2FixtureDef fd;
+ fd.shape = m_capsules + (index - 5);
+ fd.friction = 0.3f;
+
+ m_bodies[m_bodyIndex]->CreateFixture(&fd);
+ }
m_bodyIndex = (m_bodyIndex + 1) % e_maxBodies;
}
@@ -285,6 +301,8 @@
case '3':
case '4':
case '5':
+ case '6':
+ case '7':
Create(key - '1');
break;
@@ -311,7 +329,7 @@
void Step(Settings* settings)
{
Test::Step(settings);
- m_debugDraw.DrawString(5, m_textLine, "Press 1-5 to drop stuff, m to change the mode");
+ m_debugDraw.DrawString(5, m_textLine, "Press 1-7 to drop stuff, m to change the mode");
m_textLine += 15;
m_debugDraw.DrawString(5, m_textLine, "Mode = %d", m_mode);
m_textLine += 15;
@@ -385,6 +403,7 @@
int32 m_userData[e_maxBodies];
b2PolygonShape m_polygons[4];
b2CircleShape m_circle;
+ b2CapsuleShape m_capsules[2];
float32 m_angle;