diff --git a/examples/29-debugdraw/debugdraw.cpp b/examples/29-debugdraw/debugdraw.cpp index 529eb522a..3f4756570 100644 --- a/examples/29-debugdraw/debugdraw.cpp +++ b/examples/29-debugdraw/debugdraw.cpp @@ -667,7 +667,8 @@ public: ); constexpr uint32_t kSelected = 0xff80ffff; - constexpr uint32_t kOverlap = 0xff0000ff; + constexpr uint32_t kOverlapA = 0xff0000ff; + constexpr uint32_t kOverlapB = 0xff8080ff; DebugDrawEncoder dde; @@ -883,11 +884,11 @@ public: Sphere sphereB = { { xx+kStepX*0.0f, yy, zz+kStepZ*0.0f }, 0.5f }; olp = overlap(sphereA, sphereB);; - dde.setColor(olp ? kOverlap : 0xffffffff); + dde.setColor(olp ? kOverlapA : 0xffffffff); dde.setWireframe(false); dde.draw(sphereA); - dde.setColor(olp ? kOverlap : 0xffffffff); + dde.setColor(olp ? kOverlapB : 0xffffffff); dde.setWireframe(true); dde.draw(sphereB); } @@ -898,11 +899,11 @@ public: toAabb(aabbB, { xx+kStepX*1.0f, yy, zz+kStepZ*0.0f }, { 0.5f, 0.5f, 0.5f }); olp = overlap(sphereA, aabbB); - dde.setColor(olp ? kOverlap : 0xffffffff); + dde.setColor(olp ? kOverlapA : 0xffffffff); dde.setWireframe(false); dde.draw(sphereA); - dde.setColor(olp ? kOverlap : 0xffffffff); + dde.setColor(olp ? kOverlapB : 0xffffffff); dde.setWireframe(true); dde.draw(aabbB); } @@ -920,11 +921,11 @@ public: olp = overlap(sphereA, triangleB); - dde.setColor(olp ? kOverlap : 0xffffffff); + dde.setColor(olp ? kOverlapA : 0xffffffff); dde.setWireframe(false); dde.draw(sphereA); - dde.setColor(olp ? kOverlap : 0xffffffff); + dde.setColor(olp ? kOverlapB : 0xffffffff); dde.setWireframe(true); dde.draw(triangleB); } @@ -945,11 +946,11 @@ public: olp = overlap(sphereA, planeB); - dde.setColor(olp ? kOverlap : 0xffffffff); + dde.setColor(olp ? kOverlapA : 0xffffffff); dde.setWireframe(false); dde.draw(sphereA); - dde.setColor(olp ? kOverlap : 0xffffffff); + dde.setColor(olp ? kOverlapB : 0xffffffff); dde.setWireframe(true); dde.drawGrid(planeB.normal, triangleB.v0, 10, 0.3f); } @@ -972,11 +973,11 @@ public: olp = overlap(sphereA, diskB); - dde.setColor(olp ? kOverlap : 0xffffffff); + dde.setColor(olp ? kOverlapA : 0xffffffff); dde.setWireframe(false); dde.draw(sphereA); - dde.setColor(olp ? kOverlap : 0xffffffff); + dde.setColor(olp ? kOverlapB : 0xffffffff); dde.setWireframe(true); dde.draw(diskB); } @@ -999,11 +1000,11 @@ public: olp = overlap(sphereA, obbB); - dde.setColor(olp ? kOverlap : 0xffffffff); + dde.setColor(olp ? kOverlapA : 0xffffffff); dde.setWireframe(false); dde.draw(sphereA); - dde.setColor(olp ? kOverlap : 0xffffffff); + dde.setColor(olp ? kOverlapB : 0xffffffff); dde.setWireframe(true); dde.draw(obbB); } @@ -1020,11 +1021,11 @@ public: olp = overlap(sphereA, capsuleB); - dde.setColor(olp ? kOverlap : 0xffffffff); + dde.setColor(olp ? kOverlapA : 0xffffffff); dde.setWireframe(false); dde.draw(sphereA); - dde.setColor(olp ? kOverlap : 0xffffffff); + dde.setColor(olp ? kOverlapB : 0xffffffff); dde.setWireframe(true); dde.draw(capsuleB); } @@ -1041,11 +1042,11 @@ public: olp = overlap(sphereA, cylinderB); - dde.setColor(olp ? kOverlap : 0xffffffff); + dde.setColor(olp ? kOverlapA : 0xffffffff); dde.setWireframe(false); dde.draw(sphereA); - dde.setColor(olp ? kOverlap : 0xffffffff); + dde.setColor(olp ? kOverlapB : 0xffffffff); dde.setWireframe(true); dde.draw(cylinderB); } @@ -1062,11 +1063,11 @@ public: olp = overlap(sphereA, coneB); - dde.setColor(olp ? kOverlap : 0xffffffff); + dde.setColor(olp ? kOverlapA : 0xffffffff); dde.setWireframe(false); dde.draw(sphereA); - dde.setColor(olp ? kOverlap : 0xffffffff); + dde.setColor(olp ? kOverlapB : 0xffffffff); dde.setWireframe(true); dde.draw(coneB); } @@ -1078,11 +1079,11 @@ public: toAabb(aabbB, { xx+kStepX*1.0f, yy, zz+kStepZ*1.0f }, { 0.5f, 0.5f, 0.5f }); olp = overlap(aabbA, aabbB); - dde.setColor(olp ? kOverlap : 0xffffffff); + dde.setColor(olp ? kOverlapA : 0xffffffff); dde.setWireframe(false); dde.draw(aabbA); - dde.setColor(olp ? kOverlap : 0xffffffff); + dde.setColor(olp ? kOverlapB : 0xffffffff); dde.setWireframe(true); dde.draw(aabbB); } @@ -1101,11 +1102,11 @@ public: olp = overlap(aabbA, triangleB); - dde.setColor(olp ? kOverlap : 0xffffffff); + dde.setColor(olp ? kOverlapA : 0xffffffff); dde.setWireframe(false); dde.draw(aabbA); - dde.setColor(olp ? kOverlap : 0xffffffff); + dde.setColor(olp ? kOverlapB : 0xffffffff); dde.setWireframe(true); dde.draw(triangleB); } @@ -1127,11 +1128,11 @@ public: olp = overlap(aabbA, planeB); - dde.setColor(olp ? kOverlap : 0xffffffff); + dde.setColor(olp ? kOverlapA : 0xffffffff); dde.setWireframe(false); dde.draw(aabbA); - dde.setColor(olp ? kOverlap : 0xffffffff); + dde.setColor(olp ? kOverlapB : 0xffffffff); dde.setWireframe(true); dde.drawGrid(planeB.normal, triangleB.v0, 10, 0.3f); } @@ -1155,11 +1156,11 @@ public: olp = overlap(aabbA, diskB); - dde.setColor(olp ? kOverlap : 0xffffffff); + dde.setColor(olp ? kOverlapA : 0xffffffff); dde.setWireframe(false); dde.draw(aabbA); - dde.setColor(olp ? kOverlap : 0xffffffff); + dde.setColor(olp ? kOverlapB : 0xffffffff); dde.setWireframe(true); dde.draw(diskB); } @@ -1186,11 +1187,11 @@ public: olp = overlap(triangleA, triangleB); - dde.setColor(olp ? kOverlap : 0xffffffff); + dde.setColor(olp ? kOverlapA : 0xffffffff); dde.setWireframe(false); dde.draw(triangleA); - dde.setColor(olp ? kOverlap : 0xffffffff); + dde.setColor(olp ? kOverlapB : 0xffffffff); dde.setWireframe(true); dde.draw(triangleB); } @@ -1219,11 +1220,11 @@ public: olp = overlap(triangleA, planeB); - dde.setColor(olp ? kOverlap : 0xffffffff); + dde.setColor(olp ? kOverlapA : 0xffffffff); dde.setWireframe(false); dde.draw(triangleA); - dde.setColor(olp ? kOverlap : 0xffffffff); + dde.setColor(olp ? kOverlapB : 0xffffffff); dde.setWireframe(true); dde.drawGrid(planeB.normal, triangleB.v0, 10, 0.3f); } @@ -1254,14 +1255,41 @@ public: olp = overlap(triangleA, diskB); - dde.setColor(olp ? kOverlap : 0xffffffff); + dde.setColor(olp ? kOverlapA : 0xffffffff); dde.setWireframe(false); dde.draw(triangleA); - dde.setColor(olp ? kOverlap : 0xffffffff); + dde.setColor(olp ? kOverlapB : 0xffffffff); dde.setWireframe(true); dde.draw(diskB); } + + // Capsule --- + { + Capsule capsuleA = + { + { px+kStepX*6.0f, py-1.0f, pz+kStepZ*3.0f }, + { px+kStepX*6.0f, py+1.0f, pz+kStepZ*3.0f }, + 0.5f, + }; + + Capsule capsuleB = + { + { xx+kStepX*5.9f, yy-1.0f, zz+kStepZ*3.0f+0.1f }, + { xx+kStepX*6.0f, yy+1.0f, zz+kStepZ*3.0f }, + 0.2f, + }; + + olp = overlap(capsuleA, capsuleB); + + dde.setColor(olp ? kOverlapA : 0xffffffff); + dde.setWireframe(false); + dde.draw(capsuleA); + + dde.setColor(olp ? kOverlapB : 0xffffffff); + dde.setWireframe(true); + dde.draw(capsuleB); + } } dde.pop(); diff --git a/examples/common/bounds.cpp b/examples/common/bounds.cpp index 470916b2d..6acbc1e8d 100644 --- a/examples/common/bounds.cpp +++ b/examples/common/bounds.cpp @@ -3,7 +3,6 @@ * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause */ -#include #include #include #include "bounds.h" @@ -1024,6 +1023,58 @@ struct LineSegment Vec3 end; }; +bool nearZero(float _v) +{ + return bx::abs(_v) < 0.0001f; +} + +bool nearZero(const Vec3& _v) +{ + return nearZero(dot(_v, _v) ); +} + +bool intersect(float& _outTa, float& _outTb, const LineSegment& _a, const LineSegment _b) +{ + // Reference(s): + // + // - The shortest line between two lines in 3D + // https://web.archive.org/web/20120309093234/http://paulbourke.net/geometry/lineline3d/ + + const Vec3 bd = sub(_b.end, _b.pos); + if (nearZero(bd) ) + { + return false; + } + + const Vec3 ad = sub(_a.end, _a.pos); + if (nearZero(ad) ) + { + return false; + } + + const Vec3 ab = sub(_a.pos, _b.pos); + + const float d0 = projectToAxis(ab, bd); + const float d1 = projectToAxis(ad, bd); + const float d2 = projectToAxis(ab, ad); + const float d3 = projectToAxis(bd, bd); + const float d4 = projectToAxis(ad, ad); + + const float denom = d4*d3 - square(d1); + + float ta = 0.0f; + + if (!nearZero(denom) ) + { + ta = (d0*d1 - d2*d3)/denom; + } + + _outTa = ta; + _outTb = (d0+d1*ta)/d3; + + return true; +} + Vec3 closestPoint(const LineSegment& _line, const Vec3& _point, float& _outT) { const Vec3 axis = sub(_line.end, _line.pos); @@ -1320,6 +1371,128 @@ bool overlap(const Aabb& _aabb, const Obb& _obb) return false; } +bool overlap(const Capsule& _capsule, const bx::Vec3& _pos) +{ + const Vec3 pos = closestPoint(LineSegment{_capsule.pos, _capsule.end}, _pos); + return overlap(Sphere{pos, _capsule.radius}, _pos); +} + +bool overlap(const Capsule& _capsule, const Sphere& _sphere) +{ + return overlap(_sphere, _capsule); +} + +bool overlap(const Capsule& _capsule, const Aabb& _aabb) +{ + return overlap(_aabb, _capsule); +} + +bool overlap(const Capsule& _capsule, const bx::Plane& _plane) +{ + BX_UNUSED(_capsule, _plane); + return false; +} + +bool overlap(const Capsule& _capsule, const Triangle& _triangle) +{ + return overlap(_triangle, _capsule); +} + +bool overlap(const Capsule& _capsule, const Cylinder& _cylinder) +{ + BX_UNUSED(_capsule, _cylinder); + return false; +} + +bool overlap(const Capsule& _capsuleA, const Capsule& _capsuleB) +{ + float ta, tb; + if (!intersect(ta, tb, {_capsuleA.pos, _capsuleA.end}, {_capsuleB.pos, _capsuleB.end}) ) + { + return false; + } + + if (0.0f <= ta + && 1.0f >= ta + && 0.0f <= tb + && 1.0f >= tb) + { + const Vec3 ad = sub(_capsuleA.end, _capsuleA.pos); + const Vec3 bd = sub(_capsuleB.end, _capsuleB.pos); + + return overlap( + Sphere{mad(ad, ta, _capsuleA.pos), _capsuleA.radius} + , Sphere{mad(bd, tb, _capsuleB.pos), _capsuleB.radius} + ); + } + + if (0.0f <= ta + && 1.0f >= ta) + { + Sphere sphereB; + sphereB.radius = _capsuleB.radius; + + if (0.0f >= tb) + { + sphereB.center = _capsuleB.pos; + } + else + { + sphereB.center = _capsuleB.end; + } + + return overlap(_capsuleA, sphereB); + } + + if (0.0f <= tb + && 1.0f >= tb) + { + Sphere sphereA; + sphereA.radius = _capsuleA.radius; + + if (0.0f >= ta) + { + sphereA.center = _capsuleA.pos; + } + else + { + sphereA.center = _capsuleA.end; + } + + return overlap(_capsuleB, sphereA); + } + + const Vec3 pa = 0.0f > ta ? _capsuleA.pos : _capsuleA.end; + const Vec3 pb = 0.0f > tb ? _capsuleB.pos : _capsuleB.end; + const Vec3 closestA = closestPoint(LineSegment{_capsuleA.pos, _capsuleA.end}, pb); + const Vec3 closestB = closestPoint(LineSegment{_capsuleB.pos, _capsuleB.end}, pa); + + if (dot(closestA, pb) <= dot(closestB, pa) ) + { + return overlap(_capsuleA, Sphere{closestB, _capsuleB.radius}); + } + + return overlap(_capsuleB, Sphere{closestA, _capsuleA.radius}); +} + +bool overlap(const Capsule& _capsule, const Cone& _cone) +{ + BX_UNUSED(_capsule, _cone); + return false; +} + +bool overlap(const Capsule& _capsule, const Disk& _disk) +{ + BX_UNUSED(_capsule, _disk); + return false; +} + +bool overlap(const Capsule& _capsule, const Obb& _obb) +{ + BX_UNUSED(_capsule, _obb); + return false; +} + bool overlap(const Triangle& _triangle, const Vec3& _pos) { const Vec3 uvw = barycentric(_triangle, _pos); diff --git a/examples/common/bounds.h b/examples/common/bounds.h index e1a83f433..338ab41e7 100644 --- a/examples/common/bounds.h +++ b/examples/common/bounds.h @@ -225,6 +225,36 @@ bool overlap(const Aabb& _aabb, const Disk& _disk); /// bool overlap(const Aabb& _aabb, const Obb& _obb); +/// +bool overlap(const Capsule& _capsule, const bx::Vec3& _pos); + +/// +bool overlap(const Capsule& _capsule, const Sphere& _sphere); + +/// +bool overlap(const Capsule& _capsule, const Aabb& _aabb); + +/// +bool overlap(const Capsule& _capsule, const bx::Plane& _plane); + +/// +bool overlap(const Capsule& _capsule, const Triangle& _triangle); + +/// +bool overlap(const Capsule& _capsule, const Cylinder& _cylinder); + +/// +bool overlap(const Capsule& _capsuleA, const Capsule& _capsuleB); + +/// +bool overlap(const Capsule& _capsule, const Cone& _cone); + +/// +bool overlap(const Capsule& _capsule, const Disk& _disk); + +/// +bool overlap(const Capsule& _capsule, const Obb& _obb); + /// bool overlap(const Triangle& _triangle, const bx::Vec3& _pos); diff --git a/examples/common/debugdraw/debugdraw.cpp b/examples/common/debugdraw/debugdraw.cpp index df20a4652..976216aca 100644 --- a/examples/common/debugdraw/debugdraw.cpp +++ b/examples/common/debugdraw/debugdraw.cpp @@ -2578,3 +2578,14 @@ void DebugDrawEncoder::drawOrb(float _x, float _y, float _z, float _radius, Axis { DEBUG_DRAW_ENCODER(drawOrb(_x, _y, _z, _radius, _highlight) ); } + +DebugDrawEncoderScopePush::DebugDrawEncoderScopePush(DebugDrawEncoder& _dde) + : m_dde(_dde) +{ + m_dde.push(); +} + +DebugDrawEncoderScopePush::~DebugDrawEncoderScopePush() +{ + m_dde.pop(); +} diff --git a/examples/common/debugdraw/debugdraw.h b/examples/common/debugdraw/debugdraw.h index 27e2e5575..2b98374f3 100644 --- a/examples/common/debugdraw/debugdraw.h +++ b/examples/common/debugdraw/debugdraw.h @@ -7,6 +7,7 @@ #define DEBUGDRAW_H_HEADER_GUARD #include +#include #include "../bounds.h" struct Axis @@ -50,7 +51,7 @@ GeometryHandle ddCreateGeometry(uint32_t _numVertices, const DdVertex* _vertices /// void ddDestroy(GeometryHandle _handle); - +/// struct DebugDrawEncoder { /// @@ -197,4 +198,18 @@ struct DebugDrawEncoder BX_ALIGN_DECL_CACHE_LINE(uint8_t) m_internal[50<<10]; }; +/// +class DebugDrawEncoderScopePush +{ +public: + /// + DebugDrawEncoderScopePush(DebugDrawEncoder& _dde); + + /// + ~DebugDrawEncoderScopePush(); + +private: + DebugDrawEncoder& m_dde; +}; + #endif // DEBUGDRAW_H_HEADER_GUARD