generate contact when body type changes at runtime, decoupling, add first ray cast hit query to world query (more to add later such as sphere/box/convex casts), hotfix

This commit is contained in:
Irlan Robson
2017-01-13 17:17:02 -02:00
parent caa9d703b5
commit 7d0f06fea2
18 changed files with 209 additions and 174 deletions

View File

@@ -335,6 +335,41 @@ bool b3Body::ShouldCollide(const b3Body* other) const
return true;
}
void b3Body::SetType(b3BodyType type)
{
if (m_type == type)
{
return;
}
m_type = type;
ResetMass();
m_force.SetZero();
m_torque.SetZero();
if (m_type == e_staticBody)
{
m_linearVelocity.SetZero();
m_angularVelocity.SetZero();
m_sweep.worldCenter0 = m_sweep.worldCenter;
m_sweep.orientation0 = m_sweep.orientation;
SynchronizeShapes();
}
SetAwake(true);
DestroyContacts();
// Move the shape proxies so new contacts can be created.
b3BroadPhase* phase = &m_world->m_contactMan.m_broadPhase;
for (b3Shape* s = m_shapeList.m_head; s; s = s->m_next)
{
phase->BufferMove(s->m_broadPhaseID);
}
}
void b3Body::Dump() const
{
i32 bodyIndex = m_islandID;

View File

@@ -79,7 +79,7 @@ void b3CollideCapsuleAndCapsule(b3Manifold& manifold,
float32 d1 = b3Distance(clipEdgeA[0].position, cp1);
float32 d2 = b3Distance(clipEdgeA[1].position, cp2);
if (d1 <= totalRadius && d2 <= totalRadius)
if (d1 > B3_EPSILON && d1 <= totalRadius && d2 > B3_EPSILON && d2 <= totalRadius)
{
b3Vec3 n1 = (cp1 - clipEdgeA[0].position) / d1;
b3Vec3 n2 = (cp2 - clipEdgeA[1].position) / d2;
@@ -123,7 +123,7 @@ void b3CollideCapsuleAndCapsule(b3Manifold& manifold,
float32 distance = b3Distance(pointA, pointB);
if (distance > 0.0f)
if (distance > B3_EPSILON)
{
b3Vec3 normal = (pointB - pointA) / distance;
b3Vec3 center = 0.5f * (pointA + hullA.radius * normal + pointB - hullB.radius * normal);

View File

@@ -17,6 +17,7 @@
*/
#include <bounce/dynamics/shapes/capsule_shape.h>
#include <bounce/dynamics/time_step.h>
b3CapsuleShape::b3CapsuleShape()
{

View File

@@ -17,6 +17,7 @@
*/
#include <bounce/dynamics/shapes/sphere_shape.h>
#include <bounce/dynamics/time_step.h>
b3SphereShape::b3SphereShape()
{

View File

@@ -377,6 +377,68 @@ void b3World::RayCast(b3RayCastListener* listener, const b3Vec3& p1, const b3Vec
m_contactMan.m_broadPhase.RayCast(&callback, input);
}
struct b3RayCastFirstCallback
{
float32 Report(const b3RayCastInput& input, i32 proxyId)
{
// Get shape associated with the proxy.
void* userData = broadPhase->GetUserData(proxyId);
b3Shape* shape = (b3Shape*)userData;
// Get map from shape local space to world space.
b3Transform xf = shape->GetBody()->GetTransform();
b3RayCastOutput output;
bool hit = shape->RayCast(&output, input, xf);
if (hit)
{
// Track minimum time of impact to require less memory.
if (output.fraction < output0.fraction)
{
shape0 = shape;
output0 = output;
}
}
// Continue the search from where we stopped.
return input.maxFraction;
}
b3Shape* shape0;
b3RayCastOutput output0;
const b3BroadPhase* broadPhase;
};
void b3World::RayCastFirst(b3RayCastListener* listener, const b3Vec3& p1, const b3Vec3& p2) const
{
b3RayCastInput input;
input.p1 = p1;
input.p2 = p2;
input.maxFraction = 1.0f;
b3RayCastFirstCallback callback;
callback.shape0 = NULL;
callback.output0.fraction = B3_MAX_FLOAT;
callback.broadPhase = &m_contactMan.m_broadPhase;
// Perform the ray cast.
m_contactMan.m_broadPhase.RayCast(&callback, input);
if (callback.shape0)
{
// 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 normal = callback.output0.normal;
// Report the intersection to the user.
listener->ReportShape(callback.shape0, point, normal, fraction);
}
}
struct b3QueryAABBCallback
{
bool Report(i32 proxyID)