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:
@ -49,6 +49,10 @@ public:
|
||||
// Return true if the proxy has moved.
|
||||
bool MoveProxy(i32 proxyId, const b3AABB3& aabb, const b3Vec3& displacement);
|
||||
|
||||
// Add a proxy to the list of moved proxies.
|
||||
// Only moved proxies will be used internally as an AABB query reference object.
|
||||
void BufferMove(i32 proxyId);
|
||||
|
||||
// Get the AABB of a given proxy.
|
||||
const b3AABB3& GetAABB(i32 proxyId) const;
|
||||
|
||||
@ -77,10 +81,6 @@ public:
|
||||
private :
|
||||
friend class b3DynamicTree;
|
||||
|
||||
// Add a proxy to the list of moved proxies.
|
||||
// Only moved proxies will be used as an AABB query reference object.
|
||||
void BufferMove(i32 proxyId);
|
||||
|
||||
// The client callback used to add an overlapping pair
|
||||
// to the overlapping pair buffer.
|
||||
bool Report(i32 proxyId);
|
||||
|
@ -208,34 +208,6 @@ inline b3Mat33 b3Outer(const b3Vec3& a, const b3Vec3& b)
|
||||
return b3Mat33(b.x * a, b.y * a, b.z * a);
|
||||
}
|
||||
|
||||
// Move an inertia tensor from the its current center
|
||||
// to another.
|
||||
inline b3Mat33 b3MoveToCOM(const b3Mat33& inertia, float32 mass, const b3Vec3& center)
|
||||
{
|
||||
// Paralell Axis Theorem
|
||||
// J = I + m * dot(r, r) * E - outer(r, r)
|
||||
// where
|
||||
// I - inertia about the center of mass
|
||||
// m - mass
|
||||
// E - identity 3x3
|
||||
// r - displacement vector from the current com to the new com
|
||||
// J - inertia tensor at the new center of rotation
|
||||
float32 dd = b3Dot(center, center);
|
||||
b3Mat33 A = b3Diagonal(mass * dd);
|
||||
b3Mat33 B = b3Outer(center, center);
|
||||
return inertia + A - B;
|
||||
}
|
||||
|
||||
// Compute the inertia matrix of a body measured in
|
||||
// inertial frame (variable over time) given the
|
||||
// inertia matrix in body-fixed frame (constant)
|
||||
// and a rotation matrix representing the orientation
|
||||
// of the body frame relative to the inertial frame.
|
||||
inline b3Mat33 b3RotateToFrame(const b3Mat33& inertia, const b3Mat33& rotation)
|
||||
{
|
||||
return rotation * inertia * b3Transpose(rotation);
|
||||
}
|
||||
|
||||
// Compute an orthogonal basis given one of its vectors.
|
||||
// The vector must be normalized.
|
||||
inline b3Mat33 b3Basis(const b3Vec3& a)
|
||||
@ -250,6 +222,7 @@ inline b3Mat33 b3Basis(const b3Vec3& a)
|
||||
{
|
||||
A.y.Set(0.0f, a.z, -a.y);
|
||||
}
|
||||
A.x = a;
|
||||
A.y = b3Normalize(A.y);
|
||||
A.z = b3Cross(a, A.y);
|
||||
return A;
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <bounce/common/math/quat.h>
|
||||
#include <bounce/common/math/transform.h>
|
||||
#include <bounce/common/template/list.h>
|
||||
#include <bounce/dynamics/time_step.h>
|
||||
|
||||
class b3World;
|
||||
class b3Shape;
|
||||
@ -328,32 +329,6 @@ inline b3BodyType b3Body::GetType() const
|
||||
return m_type;
|
||||
}
|
||||
|
||||
inline void b3Body::SetType(b3BodyType type)
|
||||
{
|
||||
if (m_type == type)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_type = type;
|
||||
|
||||
ResetMass();
|
||||
|
||||
if (m_type == e_staticBody)
|
||||
{
|
||||
m_linearVelocity.SetZero();
|
||||
m_angularVelocity.SetZero();
|
||||
SynchronizeShapes();
|
||||
}
|
||||
|
||||
SetAwake(true);
|
||||
|
||||
m_force.SetZero();
|
||||
m_torque.SetZero();
|
||||
|
||||
DestroyContacts();
|
||||
}
|
||||
|
||||
inline void* b3Body::GetUserData() const
|
||||
{
|
||||
return m_userData;
|
||||
@ -430,6 +405,11 @@ inline const b3Sweep& b3Body::GetSweep() const
|
||||
return m_sweep;
|
||||
}
|
||||
|
||||
inline bool b3Body::IsAwake() const
|
||||
{
|
||||
return (m_flags & e_awakeFlag) != 0;
|
||||
}
|
||||
|
||||
inline void b3Body::SetAwake(bool flag)
|
||||
{
|
||||
if (flag)
|
||||
@ -451,11 +431,6 @@ inline void b3Body::SetAwake(bool flag)
|
||||
}
|
||||
}
|
||||
|
||||
inline bool b3Body::IsAwake() const
|
||||
{
|
||||
return (m_flags & e_awakeFlag) != 0;
|
||||
}
|
||||
|
||||
inline float32 b3Body::GetGravityScale() const
|
||||
{
|
||||
return m_gravityScale;
|
||||
|
@ -51,6 +51,34 @@ enum b3LimitState
|
||||
e_equalLimits
|
||||
};
|
||||
|
||||
// Move an inertia tensor from the its current center
|
||||
// to another.
|
||||
inline b3Mat33 b3MoveToCOM(const b3Mat33& inertia, float32 mass, const b3Vec3& center)
|
||||
{
|
||||
// Paralell Axis Theorem
|
||||
// J = I + m * dot(r, r) * E - outer(r, r)
|
||||
// where
|
||||
// I - inertia about the center of mass
|
||||
// m - mass
|
||||
// E - identity 3x3
|
||||
// r - displacement vector from the current com to the new com
|
||||
// J - inertia tensor at the new center of rotation
|
||||
float32 dd = b3Dot(center, center);
|
||||
b3Mat33 A = b3Diagonal(mass * dd);
|
||||
b3Mat33 B = b3Outer(center, center);
|
||||
return inertia + A - B;
|
||||
}
|
||||
|
||||
// Compute the inertia matrix of a body measured in
|
||||
// inertial frame (variable over time) given the
|
||||
// inertia matrix in body-fixed frame (constant)
|
||||
// and a rotation matrix representing the orientation
|
||||
// of the body frame relative to the inertial frame.
|
||||
inline b3Mat33 b3RotateToFrame(const b3Mat33& inertia, const b3Mat33& rotation)
|
||||
{
|
||||
return rotation * inertia * b3Transpose(rotation);
|
||||
}
|
||||
|
||||
// Compute the time derivative of an orientation given
|
||||
// the angular velocity of the rotating frame represented by the orientation.
|
||||
inline b3Quat b3Derivative(const b3Quat& orientation, const b3Vec3& velocity)
|
||||
|
@ -85,11 +85,19 @@ public:
|
||||
|
||||
// Perform a ray cast with the world.
|
||||
// The given ray cast listener will be notified when a ray intersects a shape
|
||||
// in the world. The ray cast output is the intercepted shape, the intersection
|
||||
// in the world.
|
||||
// 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.
|
||||
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.
|
||||
|
@ -61,9 +61,9 @@ public:
|
||||
|
||||
void RayHit()
|
||||
{
|
||||
if (m_rayHit.m_shape)
|
||||
if (m_rayHit.shape)
|
||||
{
|
||||
if (m_rayHit.m_shape->GetBody() != m_character)
|
||||
if (m_rayHit.shape->GetBody() != m_character)
|
||||
{
|
||||
Test::RayHit();
|
||||
}
|
||||
@ -72,12 +72,12 @@ public:
|
||||
|
||||
void Step()
|
||||
{
|
||||
if (m_rayHit.m_shape)
|
||||
if (m_rayHit.shape)
|
||||
{
|
||||
if (m_rayHit.m_shape->GetBody() != m_character)
|
||||
if (m_rayHit.shape->GetBody() != m_character)
|
||||
{
|
||||
b3Vec3 point = m_rayHit.m_point;
|
||||
b3Vec3 normal = m_rayHit.m_normal;
|
||||
b3Vec3 point = m_rayHit.point;
|
||||
b3Vec3 normal = m_rayHit.normal;
|
||||
|
||||
const b3Transform& xf = m_character->GetTransform();
|
||||
b3Vec3 n = point - xf.position;
|
||||
|
@ -206,16 +206,16 @@ public:
|
||||
{
|
||||
// Perform the ray cast
|
||||
RayCastListener listener;
|
||||
m_world.RayCast(&listener, p1, p2);
|
||||
listener.hit.shape = NULL;
|
||||
m_world.RayCastFirst(&listener, p1, p2);
|
||||
|
||||
i32 hitId = listener.FindClosestHit();
|
||||
if (hitId >= 0)
|
||||
RayCastHit hit = listener.hit;
|
||||
if (hit.shape)
|
||||
{
|
||||
// Replace current hit
|
||||
RayCastHit hit = listener.m_hits[hitId];
|
||||
g_debugDraw->DrawSegment(p1, hit.m_point, b3Color(0.0f, 1.0f, 0.0f));
|
||||
g_debugDraw->DrawPoint(hit.m_point, b3Color(1.0f, 0.0f, 0.0f));
|
||||
g_debugDraw->DrawSegment(hit.m_point, hit.m_point + hit.m_normal, b3Color(1.0f, 1.0f, 1.0f));
|
||||
g_debugDraw->DrawSegment(p1, hit.point, b3Color(0.0f, 1.0f, 0.0f));
|
||||
g_debugDraw->DrawPoint(hit.point, b3Color(1.0f, 0.0f, 0.0f));
|
||||
g_debugDraw->DrawSegment(hit.point, hit.point + hit.normal, b3Color(1.0f, 1.0f, 1.0f));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -19,10 +19,11 @@
|
||||
#ifndef TEST_H
|
||||
#define TEST_H
|
||||
|
||||
#include <bounce/bounce.h>
|
||||
|
||||
#include <glfw/glfw3.h>
|
||||
#include <imgui/imgui.h>
|
||||
#include "../framework/debug_draw.h"
|
||||
#include <bounce/bounce.h>
|
||||
|
||||
struct Settings
|
||||
{
|
||||
@ -83,53 +84,14 @@ struct TestEntry
|
||||
TestCreate create;
|
||||
};
|
||||
|
||||
enum TestType
|
||||
{
|
||||
// Collision
|
||||
e_QHull,
|
||||
e_Cluster,
|
||||
e_Distance,
|
||||
e_CapsuleDistance,
|
||||
e_CapsuleAndCapsule,
|
||||
e_CapsuleAndHull,
|
||||
e_HullAndHull,
|
||||
// Dynamics
|
||||
// Joints
|
||||
e_NewtonCradle,
|
||||
e_Vehicle,
|
||||
e_Door,
|
||||
e_HingeChain,
|
||||
e_Ragdoll,
|
||||
// Contacts
|
||||
e_Quadric,
|
||||
e_MeshContact,
|
||||
// World
|
||||
e_SphereStack,
|
||||
e_CapsuleStack,
|
||||
e_BoxStack,
|
||||
e_ShapeStack,
|
||||
e_Jenga,
|
||||
e_Thin,
|
||||
e_Pyramid,
|
||||
e_Pyramids,
|
||||
// World Queries
|
||||
e_RayCast,
|
||||
e_SensorTest,
|
||||
e_Character,
|
||||
e_BodyTypes,
|
||||
e_VaryingFriction,
|
||||
e_VaryingRestitution,
|
||||
e_testCount
|
||||
};
|
||||
|
||||
extern TestEntry g_tests[e_testCount];
|
||||
extern TestEntry g_tests[];
|
||||
|
||||
struct RayCastHit
|
||||
{
|
||||
b3Shape* m_shape;
|
||||
b3Vec3 m_point;
|
||||
b3Vec3 m_normal;
|
||||
float32 m_fraction;
|
||||
b3Shape* shape;
|
||||
b3Vec3 point;
|
||||
b3Vec3 normal;
|
||||
float32 fraction;
|
||||
};
|
||||
|
||||
class RayCastListener : public b3RayCastListener
|
||||
@ -137,35 +99,14 @@ class RayCastListener : public b3RayCastListener
|
||||
public:
|
||||
float32 ReportShape(b3Shape* shape, const b3Vec3& point, const b3Vec3& normal, float32 fraction)
|
||||
{
|
||||
RayCastHit hit;
|
||||
hit.m_shape = shape;
|
||||
hit.m_point = point;
|
||||
hit.m_normal = normal;
|
||||
hit.m_fraction = fraction;
|
||||
|
||||
m_hits.PushBack(hit);
|
||||
|
||||
// Continue.
|
||||
hit.shape = shape;
|
||||
hit.point = point;
|
||||
hit.normal = normal;
|
||||
hit.fraction = fraction;
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
int FindClosestHit() const
|
||||
{
|
||||
float32 minFraction = FLT_MAX;
|
||||
int minIndex = -1;
|
||||
for (u32 i = 0; i < m_hits.Count(); ++i)
|
||||
{
|
||||
const RayCastHit* hit = m_hits.Get(i);
|
||||
if (hit->m_fraction < minFraction)
|
||||
{
|
||||
minFraction = hit->m_fraction;
|
||||
minIndex = i;
|
||||
}
|
||||
}
|
||||
return minIndex;
|
||||
}
|
||||
|
||||
b3StackArray<RayCastHit, 256> m_hits;
|
||||
RayCastHit hit;
|
||||
};
|
||||
|
||||
class Test : public b3ContactListener
|
||||
|
Reference in New Issue
Block a user