improve segment vs segment collision, small fixes
This commit is contained in:
parent
a346a1472d
commit
012460f6b0
@ -32,6 +32,15 @@ struct b3Color
|
||||
float32 r, g, b, a;
|
||||
};
|
||||
|
||||
// Color pallete commonly used by the debug draw interface.
|
||||
extern const b3Color b3Color_black;
|
||||
extern const b3Color b3Color_white;
|
||||
extern const b3Color b3Color_red;
|
||||
extern const b3Color b3Color_green;
|
||||
extern const b3Color b3Color_blue;
|
||||
extern const b3Color b3Color_yellow;
|
||||
extern const b3Color b3Color_pink;
|
||||
|
||||
// Implement this interface and set to a world so it can draw the physics entities.
|
||||
class b3Draw
|
||||
{
|
||||
|
@ -34,6 +34,14 @@ class b3ContactListener;
|
||||
class b3ContactFilter;
|
||||
class b3Draw;
|
||||
|
||||
struct b3RayCastSingleOutput
|
||||
{
|
||||
b3Shape* shape; // shape
|
||||
b3Vec3 point; // intersection point on surface
|
||||
b3Vec3 normal; // surface normal of intersection
|
||||
float32 fraction; // time of intersection on segment
|
||||
};
|
||||
|
||||
// Use a physics world to create/destroy rigid bodies, execute ray cast and volume queries.
|
||||
class b3World
|
||||
{
|
||||
@ -83,6 +91,13 @@ public:
|
||||
// and the number of constraint solver iterations.
|
||||
void Step(float32 dt, u32 velocityIterations, u32 positionIterations);
|
||||
|
||||
// Perform a ray cast with the world.
|
||||
// If the ray doesn't intersect with a shape in the world then return false.
|
||||
// The ray cast output is the intercepted shape, the intersection
|
||||
// point in world space, the face normal on the shape associated with the point,
|
||||
// and the intersection fraction.
|
||||
bool RayCastSingle(b3RayCastSingleOutput* output, const b3Vec3& p1, const b3Vec3& p2) const;
|
||||
|
||||
// Perform a ray cast with the world.
|
||||
// The given ray cast listener will be notified when a ray intersects a shape
|
||||
// in the world.
|
||||
@ -91,13 +106,6 @@ public:
|
||||
// and the intersection fraction.
|
||||
void RayCast(b3RayCastListener* listener, const b3Vec3& p1, const b3Vec3& p2) const;
|
||||
|
||||
// Convenience function.
|
||||
// Perform a ray cast with the world.
|
||||
// If there is an intersection then the given ray cast listener will be notified once with
|
||||
// the shape closest to the ray origin and the associated ray cast output.
|
||||
// @todo Centralize all queries to a common scene query class?
|
||||
void RayCastFirst(b3RayCastListener* listener, const b3Vec3& p1, const b3Vec3& p2) const;
|
||||
|
||||
// Perform a AABB cast with the world.
|
||||
// The query listener will be notified when two shape AABBs are overlapping.
|
||||
// If the listener returns false then the query is stopped immediately.
|
||||
|
@ -106,7 +106,7 @@ public:
|
||||
|
||||
void Draw(const b3World& world);
|
||||
|
||||
void Draw();
|
||||
void Submit();
|
||||
private:
|
||||
friend struct DrawShapes;
|
||||
|
||||
|
@ -204,18 +204,12 @@ public:
|
||||
|
||||
void CastRay(const b3Vec3 p1, const b3Vec3 p2) const
|
||||
{
|
||||
// Perform the ray cast
|
||||
RayCastListener listener;
|
||||
listener.hit.shape = NULL;
|
||||
m_world.RayCastFirst(&listener, p1, p2);
|
||||
|
||||
RayCastHit hit = listener.hit;
|
||||
if (hit.shape)
|
||||
b3RayCastSingleOutput out;
|
||||
if (m_world.RayCastSingle(&out, p1, p2))
|
||||
{
|
||||
// Replace current hit
|
||||
g_debugDraw->DrawSegment(p1, hit.point, b3Color(0.0f, 1.0f, 0.0f));
|
||||
g_debugDraw->DrawPoint(hit.point, 4.0f, b3Color(1.0f, 0.0f, 0.0f));
|
||||
g_debugDraw->DrawSegment(hit.point, hit.point + hit.normal, b3Color(1.0f, 1.0f, 1.0f));
|
||||
g_debugDraw->DrawSegment(p1, out.point, b3Color(0.0f, 1.0f, 0.0f));
|
||||
g_debugDraw->DrawPoint(out.point, 4.0f, b3Color(1.0f, 0.0f, 0.0f));
|
||||
g_debugDraw->DrawSegment(out.point, out.point + out.normal, b3Color(1.0f, 1.0f, 1.0f));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -88,14 +88,6 @@ struct TestEntry
|
||||
|
||||
extern TestEntry g_tests[];
|
||||
|
||||
struct RayCastHit
|
||||
{
|
||||
b3Shape* shape;
|
||||
b3Vec3 point;
|
||||
b3Vec3 normal;
|
||||
float32 fraction;
|
||||
};
|
||||
|
||||
class RayCastListener : public b3RayCastListener
|
||||
{
|
||||
public:
|
||||
@ -108,7 +100,7 @@ public:
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
RayCastHit hit;
|
||||
b3RayCastSingleOutput hit;
|
||||
};
|
||||
|
||||
class Test : public b3ContactListener
|
||||
@ -142,7 +134,7 @@ public:
|
||||
b3Profile m_profile;
|
||||
b3Profile m_maxProfile;
|
||||
|
||||
RayCastHit m_rayHit;
|
||||
b3RayCastSingleOutput m_rayHit;
|
||||
b3BoxHull m_groundHull;
|
||||
b3BoxHull m_boxHull;
|
||||
b3BoxHull m_tallHull;
|
||||
|
@ -178,7 +178,7 @@ solution (solution_name)
|
||||
links { "glfw", "glad", "imgui", "bounce" }
|
||||
|
||||
configuration { "windows" }
|
||||
links { "glu32", "opengl32", "winmm" }
|
||||
links { "opengl32", "winmm" }
|
||||
|
||||
configuration { "not windows", "not macosx" }
|
||||
links
|
||||
|
@ -157,32 +157,41 @@ void b3ClosestPointsOnNormalizedLines(b3Vec3* C1, b3Vec3* C2,
|
||||
const b3Vec3& P1, const b3Vec3& N1,
|
||||
const b3Vec3& P2, const b3Vec3& N2)
|
||||
{
|
||||
float32 a12 = -b3Dot(N1, N2);
|
||||
float32 a21 = -a12;
|
||||
// sin^2 = 1 - cos^2
|
||||
// or
|
||||
// sin = norm( cross(n1, n2) )
|
||||
const float32 kTol = 0.0f;
|
||||
|
||||
float32 det = -1.0f - a12 * a21;
|
||||
if (det == 0.0f)
|
||||
float32 c = b3Dot(N1, N2);
|
||||
float32 den = 1.0f - c * c;
|
||||
if (den < kTol * kTol)
|
||||
{
|
||||
// Nearly paralell lines.
|
||||
*C1 = P1;
|
||||
*C2 = P2;
|
||||
return;
|
||||
}
|
||||
|
||||
det = 1.0f / det;
|
||||
den = 1.0f / den;
|
||||
|
||||
// a = dot(n1, e3)
|
||||
// b = dot(n2, e3)
|
||||
// c = dot(n1, n2)
|
||||
|
||||
// s - c * t = -dot(n1, e3)
|
||||
// c * s - t = -dot(n2, e3)
|
||||
|
||||
// s = ( c * dot(n2, e3) - dot(n1, e3) ) / den
|
||||
// t = ( dot(n2, e3) - c * dot(n1, e3) ) / den
|
||||
b3Vec3 E3 = P1 - P2;
|
||||
|
||||
b3Vec2 b;
|
||||
b.x = -b3Dot(N1, E3);
|
||||
b.y = -b3Dot(N2, E3);
|
||||
float32 a = b3Dot(N2, E3);
|
||||
float32 b = b3Dot(N1, E3);
|
||||
|
||||
float32 s = den * (c * a - b);
|
||||
float32 t = den * (a - c - b);
|
||||
|
||||
b3Vec2 x;
|
||||
x.x = det * (-b.x - a12 * b.y);
|
||||
x.y = det * (b.y - a21 * b.x);
|
||||
|
||||
*C1 = P1 + x.x * N1;
|
||||
*C2 = P2 + x.y * N2;
|
||||
*C1 = P1 + s * N1;
|
||||
*C2 = P2 + t * N2;
|
||||
}
|
||||
|
||||
void b3ClosestPointsOnSegments(b3Vec3* C1, b3Vec3* C2,
|
||||
@ -191,45 +200,72 @@ void b3ClosestPointsOnSegments(b3Vec3* C1, b3Vec3* C2,
|
||||
{
|
||||
b3Vec3 E1 = Q1 - P1;
|
||||
float32 L1 = b3Length(E1);
|
||||
|
||||
|
||||
b3Vec3 E2 = Q2 - P2;
|
||||
float32 L2 = b3Length(E2);
|
||||
|
||||
if (L1 < B3_LINEAR_SLOP && L2 < B3_LINEAR_SLOP)
|
||||
if (L1 < 0.0f && L2 < 0.0f)
|
||||
{
|
||||
*C1 = P1;
|
||||
*C2 = P2;
|
||||
return;
|
||||
}
|
||||
|
||||
if (L1 < B3_LINEAR_SLOP)
|
||||
if (L1 < 0.0f)
|
||||
{
|
||||
*C1 = P1;
|
||||
*C2 = b3ClosestPointOnSegment(P1, P2, Q2);
|
||||
return;
|
||||
}
|
||||
|
||||
if (L2 < B3_LINEAR_SLOP)
|
||||
if (L2 < 0.0f)
|
||||
{
|
||||
*C1 = b3ClosestPointOnSegment(P2, P1, Q1);
|
||||
*C2 = P2;
|
||||
return;
|
||||
}
|
||||
|
||||
// |e1xe2| = sin(theta) * |e1| * |e2|
|
||||
b3Vec3 E1_x_E2 = b3Cross(E1, E2);
|
||||
float32 L = b3Length(E1_x_E2);
|
||||
const float32 kTolerance = 0.005f;
|
||||
if (L < kTolerance * L1 * L2)
|
||||
// Here and in 3D we need to start "GJK" with the closest points between the two edges
|
||||
// since the cross product between their direction is a possible separating axis.
|
||||
b3Vec3 N1 = (1.0f / L1) * E1;
|
||||
b3Vec3 N2 = (1.0f / L2) * E2;
|
||||
|
||||
// sin = norm( cross(n1, n2) )
|
||||
// or
|
||||
// sin^2 = 1 - cos^2
|
||||
|
||||
// Zero parallelism tolerance used because the colinearity tolerance above is also zero.
|
||||
const float32 kTol = 0.0f;
|
||||
|
||||
float32 c = b3Dot(N1, N2);
|
||||
float32 den = 1.0f - c * c;
|
||||
if (den < kTol * kTol)
|
||||
{
|
||||
*C1 = P1;
|
||||
*C2 = P2;
|
||||
}
|
||||
else
|
||||
{
|
||||
b3Vec3 N1 = (1.0f / L1) * E1;
|
||||
b3Vec3 N2 = (1.0f / L2) * E2;
|
||||
b3ClosestPointsOnNormalizedLines(C1, C2, P1, N1, P2, N2);
|
||||
// a = dot(n1, e3)
|
||||
// b = dot(n2, e3)
|
||||
// c = dot(n1, n2)
|
||||
|
||||
// s - c * t = -dot(n1, e3)
|
||||
// c * s - t = -dot(n2, e3)
|
||||
|
||||
// s = ( c * dot(n2, e3) - dot(n1, e3) ) / den
|
||||
// t = ( dot(n2, e3) - c * dot(n1, e3) ) / den
|
||||
b3Vec3 E3 = P1 - P2;
|
||||
|
||||
float32 a = b3Dot(N2, E3);
|
||||
float32 b = b3Dot(N1, E3);
|
||||
float32 inv_den = 1.0f / den;
|
||||
|
||||
float32 s = inv_den * (c * a - b);
|
||||
float32 t = inv_den * (a - c - b);
|
||||
|
||||
*C1 = P1 + s * N1;
|
||||
*C2 = P2 + t * N2;
|
||||
}
|
||||
|
||||
*C1 = b3ClosestPointOnSegment(*C1, P1, Q1);
|
||||
|
@ -42,47 +42,29 @@ void b3BuildEdgeContact(b3Manifold& manifold,
|
||||
b3Vec3 E2 = Q2 - P2;
|
||||
b3Vec3 N2 = b3Normalize(E2);
|
||||
|
||||
b3Vec3 E3 = P1 - P2;
|
||||
|
||||
b3Vec2 b;
|
||||
b.x = -b3Dot(N1, E3);
|
||||
b.y = -b3Dot(N2, E3);
|
||||
|
||||
float32 a12 = -b3Dot(N1, N2), a21 = -a12;
|
||||
|
||||
float32 det = -1.0f - a12 * a21;
|
||||
if (det != 0.0f)
|
||||
b3Vec3 N = b3Cross(E1, E2);
|
||||
N.Normalize();
|
||||
if (b3Dot(N, P2 - C2) > 0.0f)
|
||||
{
|
||||
det = 1.0f / det;
|
||||
N = -N;
|
||||
}
|
||||
|
||||
b3Vec2 x;
|
||||
x.x = det * (-b.x - a12 * b.y);
|
||||
x.y = det * (b.y - a21 * b.x);
|
||||
|
||||
b3Vec3 point1 = P1 + x.x * N1;
|
||||
b3Vec3 point2 = P2 + x.y * N2;
|
||||
|
||||
b3Vec3 axis = b3Cross(E1, E2);
|
||||
b3Vec3 normal = b3Normalize(axis);
|
||||
if (b3Dot(normal, P2 - C2) > 0.0f)
|
||||
{
|
||||
normal = -normal;
|
||||
}
|
||||
b3Vec3 PA, PB;
|
||||
b3ClosestPointsOnNormalizedLines(&PA, &PB, P1, E1, P2, E2);
|
||||
|
||||
b3FeaturePair pair = b3MakePair(0, 1, index2, index2 + 1);
|
||||
|
||||
manifold.pointCount = 1;
|
||||
manifold.points[0].triangleKey = B3_NULL_TRIANGLE;
|
||||
manifold.points[0].key = b3MakeKey(pair);
|
||||
manifold.points[0].localNormal = b3MulT(xf1.rotation, normal);
|
||||
manifold.points[0].localPoint = b3MulT(xf1, point1);
|
||||
manifold.points[0].localPoint2 = b3MulT(xf2, point2);
|
||||
manifold.points[0].localNormal = b3MulT(xf1.rotation, N);
|
||||
manifold.points[0].localPoint = b3MulT(xf1, PA);
|
||||
manifold.points[0].localPoint2 = b3MulT(xf2, PB);
|
||||
|
||||
manifold.center = 0.5f * (point1 + hull1->radius * normal + point2 - B3_HULL_RADIUS * normal);
|
||||
manifold.normal = normal;
|
||||
manifold.tangent1 = b3Perp(normal);
|
||||
manifold.tangent2 = b3Cross(manifold.tangent1, normal);
|
||||
manifold.center = 0.5f * (PA + hull1->radius * N + PB - B3_HULL_RADIUS * N);
|
||||
manifold.normal = N;
|
||||
manifold.tangent1 = b3Perp(N);
|
||||
manifold.tangent2 = b3Cross(manifold.tangent1, N);
|
||||
}
|
||||
|
||||
void b3BuildFaceContact(b3Manifold& manifold,
|
||||
@ -207,7 +189,7 @@ void b3CollideCapsuleAndHull(b3Manifold& manifold,
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
b3FaceQuery faceQueryB = b3QueryFaceSeparation(xfA, &hullA, xfB, hullB);
|
||||
if (faceQueryB.separation > totalRadius)
|
||||
{
|
||||
|
@ -40,20 +40,20 @@
|
||||
#include <bounce/collision/shapes/hull.h>
|
||||
#include <bounce/collision/shapes/mesh.h>
|
||||
|
||||
const b3Color b3Color_black(0.0f, 0.0f, 0.0f);
|
||||
const b3Color b3Color_white(1.0f, 1.0f, 1.0f);
|
||||
const b3Color b3Color_red(1.0f, 0.0f, 0.0f);
|
||||
const b3Color b3Color_green(0.0f, 1.0f, 0.0f);
|
||||
const b3Color b3Color_blue(0.0f, 0.0f, 1.0f);
|
||||
const b3Color b3Color_yellow(1.0f, 1.0f, 0.0f);
|
||||
const b3Color b3Color_pink(1.0f, 0.0f, 1.0f);
|
||||
|
||||
void b3World::DebugDraw() const
|
||||
{
|
||||
B3_ASSERT(m_debugDraw);
|
||||
|
||||
u32 flags = m_debugDraw->m_flags;
|
||||
|
||||
b3Color black(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
b3Color white(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
b3Color red(1.0f, 0.0f, 0.0f, 1.0f);
|
||||
b3Color green(0.0f, 1.0f, 0.0f, 1.0f);
|
||||
b3Color blue(0.0f, 0.0f, 1.0f, 1.0f);
|
||||
b3Color yellow(1.0f, 1.0f, 0.0f, 1.0f);
|
||||
b3Color purple(1.0f, 0.0f, 1.0f, 1.0f);
|
||||
|
||||
if (flags & b3Draw::e_centerOfMassesFlag)
|
||||
{
|
||||
for (b3Body* b = m_bodyList.m_head; b; b = b->m_next)
|
||||
@ -83,7 +83,7 @@ void b3World::DebugDraw() const
|
||||
for (b3Shape* s = b->m_shapeList.m_head; s; s = s->m_next)
|
||||
{
|
||||
const b3AABB3& aabb = m_contactMan.m_broadPhase.GetAABB(s->m_broadPhaseID);
|
||||
m_debugDraw->DrawAABB(aabb, purple);
|
||||
m_debugDraw->DrawAABB(aabb, b3Color_pink);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -122,18 +122,18 @@ void b3World::DebugDraw() const
|
||||
|
||||
if (flags & b3Draw::e_contactPointsFlag)
|
||||
{
|
||||
m_debugDraw->DrawPoint(p, 4.0f, yellow);
|
||||
m_debugDraw->DrawPoint(p, 4.0f, b3Color_yellow);
|
||||
}
|
||||
|
||||
if (flags & b3Draw::e_contactNormalsFlag)
|
||||
{
|
||||
m_debugDraw->DrawSegment(p, p + n, yellow);
|
||||
m_debugDraw->DrawSegment(p, p + n, b3Color_yellow);
|
||||
}
|
||||
|
||||
if (flags & b3Draw::e_contactTangentsFlag)
|
||||
{
|
||||
m_debugDraw->DrawSegment(p, p + t1, yellow);
|
||||
m_debugDraw->DrawSegment(p, p + t2, yellow);
|
||||
m_debugDraw->DrawSegment(p, p + t1, b3Color_yellow);
|
||||
m_debugDraw->DrawSegment(p, p + t2, b3Color_yellow);
|
||||
}
|
||||
}
|
||||
|
||||
@ -152,18 +152,18 @@ void b3World::DebugDraw() const
|
||||
|
||||
if (flags & b3Draw::e_contactPointsFlag)
|
||||
{
|
||||
m_debugDraw->DrawPoint(p, 4.0f, mp->persisting ? green : red);
|
||||
m_debugDraw->DrawPoint(p, 4.0f, mp->persisting ? b3Color_green : b3Color_red);
|
||||
}
|
||||
|
||||
if (flags & b3Draw::e_contactNormalsFlag)
|
||||
{
|
||||
m_debugDraw->DrawSegment(p, p + n, white);
|
||||
m_debugDraw->DrawSegment(p, p + n, b3Color_white);
|
||||
}
|
||||
|
||||
if (flags & b3Draw::e_contactTangentsFlag)
|
||||
{
|
||||
m_debugDraw->DrawSegment(p, p + t1, yellow);
|
||||
m_debugDraw->DrawSegment(p, p + t2, yellow);
|
||||
m_debugDraw->DrawSegment(p, p + t1, b3Color_yellow);
|
||||
m_debugDraw->DrawSegment(p, p + t2, b3Color_yellow);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -109,14 +109,10 @@ void b3MouseJoint::SetTarget(const b3Vec3& target)
|
||||
|
||||
void b3MouseJoint::Draw(b3Draw* draw) const
|
||||
{
|
||||
b3Color red(1.0f, 0.0f, 0.0f);
|
||||
b3Color green(0.0f, 1.0f, 0.0f);
|
||||
b3Color yellow(1.0f, 1.0f, 0.0f);
|
||||
|
||||
b3Vec3 a = GetAnchorA();
|
||||
b3Vec3 b = GetAnchorB();
|
||||
|
||||
draw->DrawPoint(a, 4.0f, green);
|
||||
draw->DrawPoint(b, 4.0f, red);
|
||||
draw->DrawSegment(a, b, yellow);
|
||||
draw->DrawPoint(a, 4.0f, b3Color_green);
|
||||
draw->DrawPoint(b, 4.0f, b3Color_red);
|
||||
draw->DrawSegment(a, b, b3Color_yellow);
|
||||
}
|
@ -162,7 +162,7 @@ void b3SphereJoint::Draw(b3Draw* draw) const
|
||||
b3Vec3 a = GetAnchorA();
|
||||
b3Vec3 b = GetAnchorB();
|
||||
|
||||
draw->DrawPoint(a, 4.0f, b3Color(1.0f, 0.0f, 0.0f));
|
||||
draw->DrawPoint(b, 4.0f, b3Color(0.0f, 1.0f, 0.0f));
|
||||
draw->DrawSegment(a, b, b3Color(1.0f, 1.0f, 0.0f));
|
||||
draw->DrawPoint(a, 4.0f, b3Color_red);
|
||||
draw->DrawPoint(b, 4.0f, b3Color_green);
|
||||
draw->DrawSegment(a, b, b3Color_yellow);
|
||||
}
|
||||
|
@ -254,14 +254,10 @@ bool b3SpringJoint::SolvePositionConstraints(const b3SolverData* data)
|
||||
|
||||
void b3SpringJoint::Draw(b3Draw* draw) const
|
||||
{
|
||||
b3Color red = b3Color(1.0f, 0.0f, 0.0f, 1.0f);
|
||||
b3Color green = b3Color(0.0f, 1.0f, 0.0f, 1.0f);
|
||||
b3Color blue = b3Color(0.0f, 0.0f, 1.0f, 1.0f);
|
||||
|
||||
b3Vec3 a = GetBodyA()->GetWorldPoint(m_localAnchorA);
|
||||
b3Vec3 b = GetBodyB()->GetWorldPoint(m_localAnchorB);
|
||||
|
||||
draw->DrawPoint(a, 4.0f, red);
|
||||
draw->DrawPoint(b, 4.0f, green);
|
||||
draw->DrawSegment(a, b, blue);
|
||||
draw->DrawPoint(a, 4.0f, b3Color_red);
|
||||
draw->DrawPoint(b, 4.0f, b3Color_green);
|
||||
draw->DrawSegment(a, b, b3Color_yellow);
|
||||
}
|
||||
|
@ -377,7 +377,7 @@ void b3World::RayCast(b3RayCastListener* listener, const b3Vec3& p1, const b3Vec
|
||||
m_contactMan.m_broadPhase.RayCast(&callback, input);
|
||||
}
|
||||
|
||||
struct b3RayCastFirstCallback
|
||||
struct b3RayCastSingleCallback
|
||||
{
|
||||
float32 Report(const b3RayCastInput& input, i32 proxyId)
|
||||
{
|
||||
@ -409,14 +409,14 @@ struct b3RayCastFirstCallback
|
||||
const b3BroadPhase* broadPhase;
|
||||
};
|
||||
|
||||
void b3World::RayCastFirst(b3RayCastListener* listener, const b3Vec3& p1, const b3Vec3& p2) const
|
||||
bool b3World::RayCastSingle(b3RayCastSingleOutput* output, const b3Vec3& p1, const b3Vec3& p2) const
|
||||
{
|
||||
b3RayCastInput input;
|
||||
input.p1 = p1;
|
||||
input.p2 = p2;
|
||||
input.maxFraction = 1.0f;
|
||||
|
||||
b3RayCastFirstCallback callback;
|
||||
b3RayCastSingleCallback callback;
|
||||
callback.shape0 = NULL;
|
||||
callback.output0.fraction = B3_MAX_FLOAT;
|
||||
callback.broadPhase = &m_contactMan.m_broadPhase;
|
||||
@ -428,15 +428,18 @@ void b3World::RayCastFirst(b3RayCastListener* listener, const b3Vec3& p1, const
|
||||
{
|
||||
// Ray hits closest shape.
|
||||
float32 fraction = callback.output0.fraction;
|
||||
float32 w1 = 1.0f - fraction;
|
||||
float32 w2 = fraction;
|
||||
|
||||
b3Vec3 point = w1 * input.p1 + w2 * input.p2;
|
||||
b3Vec3 point = (1.0f - fraction) * input.p1 + fraction * input.p2;
|
||||
b3Vec3 normal = callback.output0.normal;
|
||||
|
||||
// Report the intersection to the user.
|
||||
listener->ReportShape(callback.shape0, point, normal, fraction);
|
||||
output->shape = callback.shape0;
|
||||
output->point = point;
|
||||
output->normal = normal;
|
||||
output->fraction = fraction;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
struct b3QueryAABBCallback
|
||||
|
@ -1115,6 +1115,9 @@ void DebugDraw::DrawSolidTriangle(const b3Vec3& normal, const b3Vec3& p1, const
|
||||
m_triangles->Vertex(p1, color, normal);
|
||||
m_triangles->Vertex(p2, color, normal);
|
||||
m_triangles->Vertex(p3, color, normal);
|
||||
|
||||
b3Color edgeColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
DrawTriangle(p2, p3, p3, edgeColor);
|
||||
}
|
||||
|
||||
void DebugDraw::DrawPolygon(const b3Vec3* vertices, u32 count, const b3Color& color)
|
||||
@ -1124,7 +1127,8 @@ void DebugDraw::DrawPolygon(const b3Vec3* vertices, u32 count, const b3Color& co
|
||||
{
|
||||
b3Vec3 p2 = vertices[i];
|
||||
|
||||
DrawSegment(p1, p2, color);
|
||||
m_lines->Vertex(p1, color);
|
||||
m_lines->Vertex(p2, color);
|
||||
|
||||
p1 = p2;
|
||||
}
|
||||
@ -1132,7 +1136,7 @@ void DebugDraw::DrawPolygon(const b3Vec3* vertices, u32 count, const b3Color& co
|
||||
|
||||
void DebugDraw::DrawSolidPolygon(const b3Vec3& normal, const b3Vec3* vertices, u32 count, const b3Color& color)
|
||||
{
|
||||
b3Color fillColor(color.r, color.g, color.b, 0.5f);
|
||||
b3Color fillColor(color.r, color.g, color.b, color.a);
|
||||
|
||||
b3Vec3 p1 = vertices[0];
|
||||
for (u32 i = 1; i < count - 1; ++i)
|
||||
@ -1165,8 +1169,9 @@ void DebugDraw::DrawCircle(const b3Vec3& normal, const b3Vec3& center, float32 r
|
||||
b3Vec3 n2 = cosInc * n1 + sinInc * b3Cross(normal, n1) + tInc * b3Dot(normal, n1) * normal;
|
||||
b3Vec3 v2 = center + radius * n2;
|
||||
|
||||
DrawSegment(v1, v2, color);
|
||||
|
||||
m_lines->Vertex(v1, color);
|
||||
m_lines->Vertex(v2, color);
|
||||
|
||||
n1 = n2;
|
||||
v1 = v2;
|
||||
}
|
||||
@ -1367,12 +1372,18 @@ void DebugDraw::DrawMesh(const b3MeshShape* s, const b3Color& c, const b3Transfo
|
||||
b3Vec3 p2 = xf * mesh->vertices[t->v2];
|
||||
b3Vec3 p3 = xf * mesh->vertices[t->v3];
|
||||
|
||||
b3Vec3 n = b3Cross(p2 - p1, p3 - p1);
|
||||
n.Normalize();
|
||||
b3Vec3 n1 = b3Cross(p2 - p1, p3 - p1);
|
||||
n1.Normalize();
|
||||
|
||||
m_triangles->Vertex(p1, c, n);
|
||||
m_triangles->Vertex(p2, c, n);
|
||||
m_triangles->Vertex(p3, c, n);
|
||||
m_triangles->Vertex(p1, c, n1);
|
||||
m_triangles->Vertex(p2, c, n1);
|
||||
m_triangles->Vertex(p3, c, n1);
|
||||
|
||||
b3Vec3 n2 = -n1;
|
||||
|
||||
m_triangles->Vertex(p1, c, n2);
|
||||
m_triangles->Vertex(p3, c, n2);
|
||||
m_triangles->Vertex(p2, c, n2);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1436,10 +1447,10 @@ void DebugDraw::Draw(const b3World& world)
|
||||
}
|
||||
}
|
||||
|
||||
g_debugDraw->Draw();
|
||||
g_debugDraw->Submit();
|
||||
}
|
||||
|
||||
void DebugDraw::Draw()
|
||||
void DebugDraw::Submit()
|
||||
{
|
||||
m_triangles->Submit();
|
||||
m_lines->Submit();
|
||||
|
@ -339,7 +339,7 @@ void Step()
|
||||
}
|
||||
|
||||
g_test->Step();
|
||||
g_debugDraw->Draw();
|
||||
g_debugDraw->Submit();
|
||||
}
|
||||
|
||||
void Run()
|
||||
|
@ -376,7 +376,7 @@ void Test::Step()
|
||||
|
||||
g_debugDraw->SetFlags(drawFlags);
|
||||
m_world.DebugDraw();
|
||||
g_debugDraw->Draw();
|
||||
g_debugDraw->Submit();
|
||||
|
||||
if (g_settings.drawFaces)
|
||||
{
|
||||
@ -459,12 +459,10 @@ void Test::MouseLeftDown(const Ray3& pw)
|
||||
listener.hit.shape = NULL;
|
||||
|
||||
// Perform the ray cast
|
||||
m_world.RayCastFirst(&listener, p1, p2);
|
||||
|
||||
if (listener.hit.shape)
|
||||
b3RayCastSingleOutput out;
|
||||
if (m_world.RayCastSingle(&out, p1, p2))
|
||||
{
|
||||
m_rayHit = listener.hit;
|
||||
|
||||
m_rayHit = out;
|
||||
RayHit();
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user