Upgrade bounce
This commit is contained in:
@@ -41,7 +41,7 @@ public:
|
||||
~b3BroadPhase();
|
||||
|
||||
// Create a proxy and return a index to it.
|
||||
u32 CreateProxy(const b3AABB3& aabb, void* userData);
|
||||
u32 CreateProxy(const b3AABB& aabb, void* userData);
|
||||
|
||||
// Destroy a given proxy and remove it from the broadphase.
|
||||
void DestroyProxy(u32 proxyId);
|
||||
@@ -49,13 +49,13 @@ public:
|
||||
// Update an existing proxy AABB with a given AABB and a displacement.
|
||||
// displacement = dt * velocity
|
||||
// Return true if the proxy has moved.
|
||||
bool MoveProxy(u32 proxyId, const b3AABB3& aabb, const b3Vec3& displacement);
|
||||
bool MoveProxy(u32 proxyId, const b3AABB& aabb, const b3Vec3& displacement);
|
||||
|
||||
// Force move the proxy
|
||||
void TouchProxy(u32 proxyId);
|
||||
|
||||
// Get the AABB of a given proxy.
|
||||
const b3AABB3& GetAABB(u32 proxyId) const;
|
||||
const b3AABB& GetAABB(u32 proxyId) const;
|
||||
|
||||
// Get the user data attached to a proxy.
|
||||
void* GetUserData(u32 proxyId) const;
|
||||
@@ -68,7 +68,7 @@ public:
|
||||
|
||||
// Notify the client callback the AABBs that are overlapping with the passed AABB.
|
||||
template<class T>
|
||||
void QueryAABB(T* callback, const b3AABB3& aabb) const;
|
||||
void QueryAABB(T* callback, const b3AABB& aabb) const;
|
||||
|
||||
// Notify the client callback the AABBs that are overlapping the
|
||||
// passed ray.
|
||||
@@ -114,7 +114,7 @@ private :
|
||||
u32 m_pairCount;
|
||||
};
|
||||
|
||||
inline const b3AABB3& b3BroadPhase::GetAABB(u32 proxyId) const
|
||||
inline const b3AABB& b3BroadPhase::GetAABB(u32 proxyId) const
|
||||
{
|
||||
return m_tree.GetAABB(proxyId);
|
||||
}
|
||||
@@ -130,7 +130,7 @@ inline u32 b3BroadPhase::GetProxyCount() const
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline void b3BroadPhase::QueryAABB(T* callback, const b3AABB3& aabb) const
|
||||
inline void b3BroadPhase::QueryAABB(T* callback, const b3AABB& aabb) const
|
||||
{
|
||||
return m_tree.QueryAABB(callback, aabb);
|
||||
}
|
||||
@@ -174,7 +174,7 @@ inline void b3BroadPhase::FindPairs(T* callback)
|
||||
continue;
|
||||
}
|
||||
|
||||
const b3AABB3& aabb = m_tree.GetAABB(m_queryProxyId);
|
||||
const b3AABB& aabb = m_tree.GetAABB(m_queryProxyId);
|
||||
m_tree.QueryAABB(this, aabb);
|
||||
}
|
||||
|
||||
|
@@ -19,25 +19,24 @@
|
||||
#ifndef B3_COLLISION_H
|
||||
#define B3_COLLISION_H
|
||||
|
||||
#include <bounce/common/geometry.h>
|
||||
#include <bounce/collision/shapes/aabb3.h>
|
||||
#include <bounce/common/math/vec3.h>
|
||||
|
||||
// Input for a ray cast.
|
||||
struct b3RayCastInput
|
||||
{
|
||||
b3Vec3 p1; // first point on segment
|
||||
b3Vec3 p2; // second point on segment
|
||||
float32 maxFraction; // maximum intersection
|
||||
scalar maxFraction; // maximum intersection
|
||||
};
|
||||
|
||||
// Output of a ray cast.
|
||||
struct b3RayCastOutput
|
||||
{
|
||||
float32 fraction; // time of intersection on ray-segment
|
||||
scalar fraction; // time of intersection on ray-segment
|
||||
b3Vec3 normal; // surface normal of intersection
|
||||
};
|
||||
|
||||
// Perform a ray-cast on a triangle.
|
||||
// Perform a ray-cast against a triangle.
|
||||
bool b3RayCast(b3RayCastOutput* output, const b3RayCastInput* input,
|
||||
const b3Vec3& v1, const b3Vec3& v2, const b3Vec3& v3);
|
||||
|
||||
|
@@ -31,7 +31,7 @@ struct b3SimplexVertex
|
||||
b3Vec3 point1; // support vertex on proxy 1
|
||||
b3Vec3 point2; // support vertex on proxy 2
|
||||
b3Vec3 point; // minkowski vertex
|
||||
float32 weight; // barycentric coordinate for point
|
||||
scalar weight; // barycentric coordinate for point
|
||||
u32 index1; // support 1 vertex index
|
||||
u32 index2; // support 2 vertex index
|
||||
};
|
||||
@@ -56,7 +56,7 @@ struct b3Simplex
|
||||
|
||||
void WriteCache(b3SimplexCache* cache) const;
|
||||
|
||||
float32 GetMetric() const;
|
||||
scalar GetMetric() const;
|
||||
};
|
||||
|
||||
// The output of the GJK algorithm.
|
||||
@@ -67,13 +67,13 @@ struct b3GJKOutput
|
||||
{
|
||||
b3Vec3 point1; // closest point on proxy 1
|
||||
b3Vec3 point2; // closest point on proxy 2
|
||||
float32 distance; // euclidean distance between the closest points
|
||||
scalar distance; // euclidean distance between the closest points
|
||||
u32 iterations; // number of GJK iterations
|
||||
};
|
||||
|
||||
// Find the closest points and distance between two proxies.
|
||||
b3GJKOutput b3GJK(const b3Transform& xf1, const b3GJKProxy& proxy1,
|
||||
const b3Transform& xf2, const b3GJKProxy& proxy2);
|
||||
const b3Transform& xf2, const b3GJKProxy& proxy2, bool applyRadius);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -84,7 +84,7 @@ b3GJKOutput b3GJK(const b3Transform& xf1, const b3GJKProxy& proxy1,
|
||||
// for the first time.
|
||||
struct b3SimplexCache
|
||||
{
|
||||
float32 metric; // distance or area or volume
|
||||
scalar metric; // lenght or area or volume
|
||||
u32 iterations; // number of GJK iterations
|
||||
u16 count; // number of support vertices
|
||||
u8 index1[4]; // support vertices on proxy 1
|
||||
@@ -114,18 +114,4 @@ b3GJKOutput b3GJK(const b3Transform& xf1, const b3GJKProxy& proxy1,
|
||||
const b3Transform& xf2, const b3GJKProxy& proxy2,
|
||||
bool applyRadius, b3SimplexCache* cache);
|
||||
|
||||
// The output of the GJK-based shape cast algorithm.
|
||||
struct b3GJKShapeCastOutput
|
||||
{
|
||||
float32 t; // time of impact
|
||||
b3Vec3 point; // contact point at t
|
||||
b3Vec3 normal; // contact normal at t
|
||||
u32 iterations; // number of iterations
|
||||
};
|
||||
|
||||
// Find the time of impact between two proxies given the relative target translation vector.
|
||||
bool b3GJKShapeCast(b3GJKShapeCastOutput* output,
|
||||
const b3Transform& xf1, const b3GJKProxy& proxy1,
|
||||
const b3Transform& xf2, const b3GJKProxy& proxy2, const b3Vec3& translation2);
|
||||
|
||||
#endif
|
@@ -26,7 +26,7 @@ struct b3GJKProxy
|
||||
{
|
||||
const b3Vec3* vertices; // vertices in this proxy
|
||||
u32 vertexCount; // number of vertices
|
||||
float32 radius; // proxy radius
|
||||
scalar radius; // proxy radius
|
||||
b3Vec3 vertexBuffer[3]; // vertex buffer for convenience
|
||||
|
||||
// Get the number of vertices in this proxy.
|
||||
@@ -57,10 +57,10 @@ inline const b3Vec3& b3GJKProxy::GetVertex(u32 index) const
|
||||
inline u32 b3GJKProxy::GetSupportIndex(const b3Vec3& d) const
|
||||
{
|
||||
u32 maxIndex = 0;
|
||||
float32 maxProjection = b3Dot(d, vertices[maxIndex]);
|
||||
scalar maxProjection = b3Dot(d, vertices[maxIndex]);
|
||||
for (u32 i = 1; i < vertexCount; ++i)
|
||||
{
|
||||
float32 projection = b3Dot(d, vertices[i]);
|
||||
scalar projection = b3Dot(d, vertices[i]);
|
||||
if (projection > maxProjection)
|
||||
{
|
||||
maxIndex = i;
|
||||
|
@@ -28,10 +28,10 @@ struct b3Hull;
|
||||
struct b3FaceQuery
|
||||
{
|
||||
u32 index;
|
||||
float32 separation;
|
||||
scalar separation;
|
||||
};
|
||||
|
||||
float32 b3Project(const b3Hull* hull, const b3Plane& plane);
|
||||
scalar b3Project(const b3Hull* hull, const b3Plane& plane);
|
||||
|
||||
b3FaceQuery b3QueryFaceSeparation(const b3Transform& xf1, const b3Hull* hull1,
|
||||
const b3Transform& xf2, const b3Hull* hull2);
|
||||
@@ -42,12 +42,12 @@ struct b3EdgeQuery
|
||||
{
|
||||
u32 index1;
|
||||
u32 index2;
|
||||
float32 separation;
|
||||
scalar separation;
|
||||
};
|
||||
|
||||
bool b3IsMinkowskiFace(const b3Vec3& A, const b3Vec3& B, const b3Vec3& B_x_A, const b3Vec3& C, const b3Vec3& D, const b3Vec3& D_x_C);
|
||||
|
||||
float32 b3Project(const b3Vec3& P1, const b3Vec3& E1, const b3Vec3& P2, const b3Vec3& E2, const b3Vec3& C1);
|
||||
scalar b3Project(const b3Vec3& P1, const b3Vec3& E1, const b3Vec3& P2, const b3Vec3& E2, const b3Vec3& C1);
|
||||
|
||||
b3EdgeQuery b3QueryEdgeSeparation(const b3Transform& xf1, const b3Hull* hull1,
|
||||
const b3Transform& xf2, const b3Hull* hull2);
|
||||
@@ -94,13 +94,13 @@ struct b3FeatureCache
|
||||
// Read the current state of the cache.
|
||||
// Return e_unkown if neither a separation or penetration was detected.
|
||||
b3SATCacheType ReadState(const b3Transform& xf1, const b3Hull* hull1,
|
||||
const b3Transform& xf2, const b3Hull* hull2, float32 totalRadius);
|
||||
const b3Transform& xf2, const b3Hull* hull2, scalar totalRadius);
|
||||
|
||||
b3SATCacheType ReadEdge(const b3Transform& xf1, const b3Hull* hull1,
|
||||
const b3Transform& xf2, const b3Hull* hull2, float32 totalRadius);
|
||||
const b3Transform& xf2, const b3Hull* hull2, scalar totalRadius);
|
||||
|
||||
b3SATCacheType ReadFace(const b3Transform& xf1, const b3Hull* hull1,
|
||||
const b3Transform& xf2, const b3Hull* hull2, float32 totalRadius);
|
||||
const b3Transform& xf2, const b3Hull* hull2, scalar totalRadius);
|
||||
|
||||
b3SATFeaturePair m_featurePair;
|
||||
};
|
||||
|
@@ -16,8 +16,8 @@
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef B3_EDGE_HULL_SAT_H
|
||||
#define B3_EDGE_HULL_SAT_H
|
||||
#ifndef B3_HULL_AND_EDGE_SAT_H
|
||||
#define B3_HULL_AND_EDGE_SAT_H
|
||||
|
||||
#include <bounce/collision/sat/sat.h>
|
||||
|
||||
@@ -25,16 +25,16 @@ struct b3Capsule;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
float32 b3ProjectEdge(const b3Capsule* hull, const b3Plane& plane);
|
||||
scalar b3ProjectEdge(const b3Capsule* hull, const b3Plane& plane);
|
||||
|
||||
b3FaceQuery b3QueryFaceSeparation(const b3Transform& xf1, const b3Capsule* hull1,
|
||||
const b3Transform& xf2, const b3Hull* hull2);
|
||||
b3FaceQuery b3QueryFaceSeparation(const b3Transform& xf1, const b3Hull* hull1,
|
||||
const b3Transform& xf2, const b3Capsule* hull2);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
float32 b3ProjectEdge(const b3Vec3& P1, const b3Vec3& E1, const b3Vec3& P2, const b3Vec3& E2, const b3Vec3& C2);
|
||||
scalar b3ProjectEdge(const b3Vec3& P1, const b3Vec3& E1, const b3Vec3& P2, const b3Vec3& E2, const b3Vec3& C2);
|
||||
|
||||
b3EdgeQuery b3QueryEdgeSeparation(const b3Transform& xf1, const b3Capsule* hull1,
|
||||
const b3Transform& xf2, const b3Hull* hull2);
|
||||
b3EdgeQuery b3QueryEdgeSeparation(const b3Transform& xf1, const b3Hull* hull1,
|
||||
const b3Transform& xf2, const b3Capsule* hull2);
|
||||
|
||||
#endif
|
@@ -16,8 +16,8 @@
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef B3_VERTEX_HULL_SAT_H
|
||||
#define B3_VERTEX_HULL_SAT_H
|
||||
#ifndef B3_HULL_AND_VERTEX_SAT_H
|
||||
#define B3_HULL_AND_VERTEX_SAT_H
|
||||
|
||||
#include <bounce/collision/sat/sat.h>
|
||||
|
||||
@@ -25,9 +25,9 @@ struct b3Sphere;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
float32 b3ProjectVertex(const b3Sphere* hull, const b3Plane& plane);
|
||||
scalar b3ProjectVertex(const b3Sphere* hull, const b3Plane& plane);
|
||||
|
||||
b3FaceQuery b3QueryFaceSeparation(const b3Transform& xf1, const b3Sphere* hull1,
|
||||
const b3Transform& xf2, const b3Hull* hull2);
|
||||
b3FaceQuery b3QueryFaceSeparation(const b3Transform& xf1, const b3Hull* hull1,
|
||||
const b3Transform& xf2, const b3Sphere* hull2);
|
||||
|
||||
#endif
|
370
include/bounce/collision/shapes/aabb.h
Normal file
370
include/bounce/collision/shapes/aabb.h
Normal file
@@ -0,0 +1,370 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2019 Irlan Robson https://irlanrobson.github.io
|
||||
*
|
||||
* 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 B3_AABB_H
|
||||
#define B3_AABB_H
|
||||
|
||||
#include <bounce/common/math/transform.h>
|
||||
#include <bounce/collision/collision.h>
|
||||
|
||||
// A min-max representation of a three-dimensional AABB.
|
||||
struct b3AABB
|
||||
{
|
||||
// Constructor. Does nothing for performance.
|
||||
b3AABB() { }
|
||||
|
||||
// Get the support vertex in a given direction.
|
||||
b3Vec3 GetSupportVertex(const b3Vec3& direction) const
|
||||
{
|
||||
b3Vec3 support;
|
||||
support.x = direction.x < scalar(0) ? lowerBound.x : upperBound.x;
|
||||
support.y = direction.y < scalar(0) ? lowerBound.y : upperBound.y;
|
||||
support.z = direction.z < scalar(0) ? lowerBound.z : upperBound.z;
|
||||
return support;
|
||||
}
|
||||
|
||||
// Set this AABB from a list of points.
|
||||
void Set(const b3Vec3* points, u32 count)
|
||||
{
|
||||
lowerBound = upperBound = points[0];
|
||||
for (u32 i = 1; i < count; ++i)
|
||||
{
|
||||
lowerBound = b3Min(lowerBound, points[i]);
|
||||
upperBound = b3Max(upperBound, points[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Set this AABB from a list of points and a transform.
|
||||
void Set(const b3Vec3* points, u32 count, const b3Transform& xf)
|
||||
{
|
||||
lowerBound = upperBound = b3Mul(xf, points[0]);
|
||||
for (u32 i = 1; i < count; ++i)
|
||||
{
|
||||
b3Vec3 v = b3Mul(xf, points[i]);
|
||||
lowerBound = b3Min(lowerBound, v);
|
||||
upperBound = b3Max(upperBound, v);
|
||||
}
|
||||
}
|
||||
|
||||
// Set this AABB from a list of points, a local scale, and a transform.
|
||||
void Set(const b3Vec3* points, u32 count, const b3Vec3& scale, const b3Transform& xf)
|
||||
{
|
||||
lowerBound = upperBound = b3Mul(xf, b3MulCW(scale, points[0]));
|
||||
for (u32 i = 1; i < count; ++i)
|
||||
{
|
||||
b3Vec3 v = b3Mul(xf, b3MulCW(scale, points[i]));
|
||||
lowerBound = b3Min(lowerBound, v);
|
||||
upperBound = b3Max(upperBound, v);
|
||||
}
|
||||
}
|
||||
|
||||
// Set this AABB from two points.
|
||||
void SetSegment(const b3Vec3& p1, const b3Vec3& p2)
|
||||
{
|
||||
lowerBound = b3Min(p1, p2);
|
||||
upperBound = b3Max(p1, p2);
|
||||
}
|
||||
|
||||
// Set this AABB from three points.
|
||||
void SetTriangle(const b3Vec3& p1, const b3Vec3& p2, const b3Vec3& p3)
|
||||
{
|
||||
lowerBound = b3Min(p1, b3Min(p2, p3));
|
||||
upperBound = b3Max(p1, b3Max(p2, p3));
|
||||
}
|
||||
|
||||
// Set this AABB from a center point and a radius vector.
|
||||
void Set(const b3Vec3& center, const b3Vec3& r)
|
||||
{
|
||||
lowerBound = center - r;
|
||||
upperBound = center + r;
|
||||
}
|
||||
|
||||
// Set this AABB from a center point and a radius value.
|
||||
void Set(const b3Vec3& center, scalar radius)
|
||||
{
|
||||
b3Vec3 r(radius, radius, radius);
|
||||
Set(center, r);
|
||||
}
|
||||
|
||||
// Extend this AABB by a radius value.
|
||||
void Extend(scalar s)
|
||||
{
|
||||
b3Vec3 r(s, s, s);
|
||||
lowerBound -= r;
|
||||
upperBound += r;
|
||||
}
|
||||
|
||||
// Extend this AABB by a radius vector.
|
||||
void Extend(const b3Vec3& r)
|
||||
{
|
||||
lowerBound -= r;
|
||||
upperBound += r;
|
||||
}
|
||||
|
||||
// Get the center of this AABB.
|
||||
b3Vec3 GetCenter() const
|
||||
{
|
||||
return scalar(0.5) * (lowerBound + upperBound);
|
||||
}
|
||||
|
||||
// Get the half-extents of this AABB.
|
||||
b3Vec3 GetExtents() const
|
||||
{
|
||||
return scalar(0.5) * (upperBound - lowerBound);
|
||||
}
|
||||
|
||||
// Get the width of this AABB.
|
||||
scalar GetWidth() const
|
||||
{
|
||||
return upperBound.x - lowerBound.x;
|
||||
}
|
||||
|
||||
// Get the height of this AABB.
|
||||
scalar GetHeight() const
|
||||
{
|
||||
return upperBound.y - lowerBound.y;
|
||||
}
|
||||
|
||||
// Get the depth of this AABB.
|
||||
scalar GetDepth() const
|
||||
{
|
||||
return upperBound.z - lowerBound.z;
|
||||
}
|
||||
|
||||
// Get the volume of this AABB.
|
||||
scalar GetVolume() const
|
||||
{
|
||||
b3Vec3 d = upperBound - lowerBound;
|
||||
return d.x * d.y * d.z;
|
||||
}
|
||||
|
||||
// Get the surface area of this AABB.
|
||||
scalar GetSurfaceArea() const
|
||||
{
|
||||
b3Vec3 d = upperBound - lowerBound;
|
||||
return scalar(2) * (d.x * d.y + d.y * d.z + d.z * d.x);
|
||||
}
|
||||
|
||||
// Get the index of the longest axis of this AABB.
|
||||
u32 GetLongestAxisIndex() const
|
||||
{
|
||||
b3Vec3 d = upperBound - lowerBound;
|
||||
|
||||
scalar maxValue = d.x;
|
||||
u32 maxIndex = 0;
|
||||
|
||||
if (d.y > maxValue)
|
||||
{
|
||||
maxValue = d.y;
|
||||
maxIndex = 1;
|
||||
}
|
||||
|
||||
if (d.z > maxValue)
|
||||
{
|
||||
maxValue = d.z;
|
||||
maxIndex = 2;
|
||||
}
|
||||
|
||||
return maxIndex;
|
||||
}
|
||||
|
||||
// Test if this AABB contains a point.
|
||||
bool Contains(const b3Vec3& point) const
|
||||
{
|
||||
return lowerBound.x <= point.x && point.x <= upperBound.x &&
|
||||
lowerBound.y <= point.y && point.y <= upperBound.y &&
|
||||
lowerBound.z <= point.z && point.z <= upperBound.z;
|
||||
}
|
||||
|
||||
// Test if this AABB contains another AABB.
|
||||
bool Contains(const b3AABB& aabb) const
|
||||
{
|
||||
return Contains(aabb.lowerBound) && Contains(aabb.upperBound);
|
||||
}
|
||||
|
||||
// Perform a ray-cast against this AABB.
|
||||
bool RayCast(b3RayCastOutput* output, const b3RayCastInput& input) const
|
||||
{
|
||||
b3Vec3 p1 = input.p1;
|
||||
b3Vec3 p2 = input.p2;
|
||||
b3Vec3 d = p2 - p1;
|
||||
|
||||
b3Vec3 normals[6];
|
||||
normals[0].Set(scalar(-1), scalar(0), scalar(0));
|
||||
normals[1].Set(scalar(1), scalar(0), scalar(0));
|
||||
normals[2].Set(scalar(0), scalar(-1), scalar(0));
|
||||
normals[3].Set(scalar(0), scalar(1), scalar(0));
|
||||
normals[4].Set(scalar(0), scalar(0), scalar(-1));
|
||||
normals[5].Set(scalar(0), scalar(0), scalar(1));
|
||||
|
||||
u32 index = B3_MAX_U32;
|
||||
|
||||
scalar lower = scalar(0);
|
||||
scalar upper = input.maxFraction;
|
||||
|
||||
u32 planeIndex = 0;
|
||||
|
||||
for (u32 i = 0; i < 3; ++i)
|
||||
{
|
||||
scalar numerators[2], denominators[2];
|
||||
|
||||
numerators[0] = p1[i] - lowerBound[i];
|
||||
numerators[1] = upperBound[i] - p1[i];
|
||||
|
||||
denominators[0] = -d[i];
|
||||
denominators[1] = d[i];
|
||||
|
||||
for (u32 j = 0; j < 2; ++j)
|
||||
{
|
||||
scalar numerator = numerators[j];
|
||||
scalar denominator = denominators[j];
|
||||
|
||||
if (denominator == scalar(0))
|
||||
{
|
||||
// s is parallel to this half-space.
|
||||
if (numerator < scalar(0))
|
||||
{
|
||||
// s is outside of this half-space.
|
||||
// dot(n, p1) and dot(n, p2) < 0.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (denominator < scalar(0))
|
||||
{
|
||||
// s enters this half-space.
|
||||
if (numerator < lower * denominator)
|
||||
{
|
||||
// Increase lower.
|
||||
lower = numerator / denominator;
|
||||
index = planeIndex;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// s exits the half-space.
|
||||
if (numerator < upper * denominator)
|
||||
{
|
||||
// Decrease upper.
|
||||
upper = numerator / denominator;
|
||||
}
|
||||
}
|
||||
// Exit if intersection becomes empty.
|
||||
if (upper < lower)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
++planeIndex;
|
||||
}
|
||||
}
|
||||
|
||||
B3_ASSERT(lower >= scalar(0) && lower <= input.maxFraction);
|
||||
|
||||
if (index != B3_MAX_U32)
|
||||
{
|
||||
output->fraction = lower;
|
||||
output->normal = normals[index];
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
b3Vec3 lowerBound; // lower vertex
|
||||
b3Vec3 upperBound; // upper vertex
|
||||
};
|
||||
|
||||
// Compute an AABB that encloses two AABBs.
|
||||
inline b3AABB b3Combine(const b3AABB& a, const b3AABB& b)
|
||||
{
|
||||
b3AABB aabb;
|
||||
aabb.lowerBound = b3Min(a.lowerBound, b.lowerBound);
|
||||
aabb.upperBound = b3Max(a.upperBound, b.upperBound);
|
||||
return aabb;
|
||||
}
|
||||
|
||||
// Test if two AABBs are overlapping.
|
||||
inline bool b3TestOverlap(const b3AABB& a, const b3AABB& b)
|
||||
{
|
||||
return (a.lowerBound.x <= b.upperBound.x) && (a.lowerBound.y <= b.upperBound.y) && (a.lowerBound.z <= b.upperBound.z) &&
|
||||
(a.upperBound.x >= b.lowerBound.x) && (a.upperBound.y >= b.lowerBound.y) && (a.upperBound.z >= b.lowerBound.z);
|
||||
}
|
||||
|
||||
// Transform a AABB by a given frame.
|
||||
inline b3AABB b3TransformAABB(const b3AABB& local_aabb, const b3Transform& xf)
|
||||
{
|
||||
b3Vec3 local_center = local_aabb.GetCenter();
|
||||
b3Vec3 local_radius = local_aabb.GetExtents();
|
||||
|
||||
b3Vec3 center = xf * local_center;
|
||||
|
||||
b3Mat33 rotation = b3Abs(b3QuatMat33(xf.rotation));
|
||||
|
||||
b3Vec3 radius;
|
||||
radius.x = b3Dot(local_radius, rotation.x);
|
||||
radius.y = b3Dot(local_radius, rotation.y);
|
||||
radius.z = b3Dot(local_radius, rotation.z);
|
||||
|
||||
b3AABB aabb;
|
||||
aabb.Set(center, radius);
|
||||
|
||||
return aabb;
|
||||
}
|
||||
|
||||
// Transform a AABB given a local scale by a given frame.
|
||||
inline b3AABB b3TransformAABB(const b3AABB& local_aabb, const b3Vec3& local_scale, const b3Transform& xf)
|
||||
{
|
||||
b3Vec3 local_center = local_aabb.GetCenter();
|
||||
b3Vec3 local_radius = b3MulCW(b3Abs(local_scale), local_aabb.GetExtents());
|
||||
|
||||
b3Vec3 center = xf * local_center;
|
||||
|
||||
b3Mat33 rotation = b3Abs(b3QuatMat33(xf.rotation));
|
||||
|
||||
b3Vec3 radius;
|
||||
radius.x = b3Dot(local_radius, rotation.x);
|
||||
radius.y = b3Dot(local_radius, rotation.y);
|
||||
radius.z = b3Dot(local_radius, rotation.z);
|
||||
|
||||
b3AABB aabb;
|
||||
aabb.Set(center, radius);
|
||||
|
||||
return aabb;
|
||||
}
|
||||
|
||||
// Scale an AABB by a scale.
|
||||
// The scale can be non-uniform and negative.
|
||||
inline b3AABB b3ScaleAABB(const b3AABB& aabb, const b3Vec3& scale)
|
||||
{
|
||||
b3AABB scaled_aabb;
|
||||
|
||||
scaled_aabb.lowerBound.x = scale.x > scalar(0) ? scale.x * aabb.lowerBound.x : scale.x * aabb.upperBound.x;
|
||||
scaled_aabb.lowerBound.y = scale.y > scalar(0) ? scale.y * aabb.lowerBound.y : scale.y * aabb.upperBound.y;
|
||||
scaled_aabb.lowerBound.z = scale.z > scalar(0) ? scale.z * aabb.lowerBound.z : scale.z * aabb.upperBound.z;
|
||||
|
||||
scaled_aabb.upperBound.x = scale.x > scalar(0) ? scale.x * aabb.upperBound.x : scale.x * aabb.lowerBound.x;
|
||||
scaled_aabb.upperBound.y = scale.y > scalar(0) ? scale.y * aabb.upperBound.y : scale.y * aabb.lowerBound.y;
|
||||
scaled_aabb.upperBound.z = scale.z > scalar(0) ? scale.z * aabb.upperBound.z : scale.z * aabb.lowerBound.z;
|
||||
|
||||
return scaled_aabb;
|
||||
}
|
||||
|
||||
#endif
|
@@ -1,253 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2019 Irlan Robson https://irlanrobson.github.io
|
||||
*
|
||||
* 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 B3_AABB_3_H
|
||||
#define B3_AABB_3_H
|
||||
|
||||
#include <bounce/common/math/transform.h>
|
||||
|
||||
// A min-max representation of a three-dimensional AABB.
|
||||
struct b3AABB3
|
||||
{
|
||||
b3Vec3 m_lower; // lower vertex
|
||||
b3Vec3 m_upper; // upper vertex
|
||||
|
||||
// Get the support vertex in a given direction.
|
||||
b3Vec3 GetSupportVertex(const b3Vec3& direction) const
|
||||
{
|
||||
b3Vec3 support;
|
||||
support.x = direction.x < 0.0f ? m_lower.x : m_upper.x;
|
||||
support.y = direction.y < 0.0f ? m_lower.y : m_upper.y;
|
||||
support.z = direction.z < 0.0f ? m_lower.z : m_upper.z;
|
||||
return support;
|
||||
}
|
||||
|
||||
// Set this AABB from a list of points.
|
||||
void Set(const b3Vec3* points, u32 count)
|
||||
{
|
||||
m_lower = m_upper = points[0];
|
||||
for (u32 i = 1; i < count; ++i)
|
||||
{
|
||||
m_lower = b3Min(m_lower, points[i]);
|
||||
m_upper = b3Max(m_upper, points[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Set this AABB from a list of points and a transform.
|
||||
void Set(const b3Vec3* points, u32 count, const b3Transform& xf)
|
||||
{
|
||||
m_lower = m_upper = b3Mul(xf, points[0]);
|
||||
for (u32 i = 1; i < count; ++i)
|
||||
{
|
||||
b3Vec3 v = b3Mul(xf, points[i]);
|
||||
m_lower = b3Min(m_lower, v);
|
||||
m_upper = b3Max(m_upper, v);
|
||||
}
|
||||
}
|
||||
|
||||
// Set this AABB from a triangle.
|
||||
void Set(const b3Vec3& v1, const b3Vec3& v2, const b3Vec3& v3)
|
||||
{
|
||||
m_lower = b3Min(v1, b3Min(v2, v3));
|
||||
m_upper = b3Max(v1, b3Max(v2, v3));
|
||||
}
|
||||
|
||||
// Set this AABB from a center point and a radius vector.
|
||||
void Set(const b3Vec3& center, const b3Vec3& r)
|
||||
{
|
||||
m_lower = center - r;
|
||||
m_upper = center + r;
|
||||
}
|
||||
|
||||
// Set this AABB from a center point and a radius value.
|
||||
void Set(const b3Vec3& center, float32 radius)
|
||||
{
|
||||
b3Vec3 r(radius, radius, radius);
|
||||
Set(center, r);
|
||||
}
|
||||
|
||||
// Extend this AABB by a scalar.
|
||||
void Extend(float32 s)
|
||||
{
|
||||
b3Vec3 r(s, s, s);
|
||||
m_lower -= r;
|
||||
m_upper += r;
|
||||
}
|
||||
|
||||
// Extend this AABB by a radius vector.
|
||||
void Extend(const b3Vec3& r)
|
||||
{
|
||||
m_lower -= r;
|
||||
m_upper += r;
|
||||
}
|
||||
|
||||
// Compute the centroid of this AABB.
|
||||
b3Vec3 Centroid() const
|
||||
{
|
||||
return 0.5f * (m_lower + m_upper);
|
||||
}
|
||||
|
||||
// Compute the width of this AABB.
|
||||
float32 Width() const
|
||||
{
|
||||
return m_upper.x - m_lower.x;
|
||||
}
|
||||
|
||||
// Compute the height of this AABB.
|
||||
float32 Height() const
|
||||
{
|
||||
return m_upper.y - m_lower.y;
|
||||
}
|
||||
|
||||
// Compute the depth of this AABB.
|
||||
float32 Depth() const
|
||||
{
|
||||
return m_upper.z - m_lower.z;
|
||||
}
|
||||
|
||||
// Compute the total of cubic units contained in this AABB.
|
||||
float32 Volume() const
|
||||
{
|
||||
return Width() * Height() * Depth();
|
||||
}
|
||||
|
||||
// Compute the surface area of this AABB.
|
||||
float32 SurfaceArea() const
|
||||
{
|
||||
return 2.0f * (Width() * Depth() + Width() * Height() + Depth() * Height());
|
||||
}
|
||||
|
||||
// Read the index of the longest axis of this AABB.
|
||||
u32 GetLongestAxisIndex() const
|
||||
{
|
||||
b3Vec3 c = Centroid();
|
||||
b3Vec3 r = m_upper - c;
|
||||
float32 max = r[0];
|
||||
u32 i = 0;
|
||||
if (r[1] > max)
|
||||
{
|
||||
max = r[1];
|
||||
i = 1;
|
||||
}
|
||||
if (r[2] > max)
|
||||
{
|
||||
max = r[2];
|
||||
i = 2;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
// Test if this AABB contains a point.
|
||||
bool Contains(const b3Vec3& point) const
|
||||
{
|
||||
return m_lower.x <= point.x && point.x <= m_upper.x &&
|
||||
m_lower.y <= point.y && point.y <= m_upper.y &&
|
||||
m_lower.z <= point.z && point.z <= m_upper.z;
|
||||
}
|
||||
|
||||
// Test if this AABB contains another AABB.
|
||||
bool Contains(const b3AABB3& aabb) const
|
||||
{
|
||||
return Contains(aabb.m_lower) && Contains(aabb.m_upper);
|
||||
}
|
||||
|
||||
// Test if a ray intersects this AABB.
|
||||
bool TestRay(float32& minFraction, const b3Vec3& p1, const b3Vec3& p2, float32 maxFraction) const
|
||||
{
|
||||
b3Vec3 d = p2 - p1;
|
||||
|
||||
float32 lower = 0.0f;
|
||||
float32 upper = maxFraction;
|
||||
|
||||
for (u32 i = 0; i < 3; ++i)
|
||||
{
|
||||
float32 numerators[2], denominators[2];
|
||||
|
||||
numerators[0] = p1[i] - m_lower[i];
|
||||
numerators[1] = m_upper[i] - p1[i];
|
||||
|
||||
denominators[0] = -d[i];
|
||||
denominators[1] = d[i];
|
||||
|
||||
for (u32 j = 0; j < 2; ++j)
|
||||
{
|
||||
float32 numerator = numerators[j];
|
||||
float32 denominator = denominators[j];
|
||||
|
||||
if (denominator == 0.0f)
|
||||
{
|
||||
// s is parallel to this half-space.
|
||||
if (numerator < 0.0f)
|
||||
{
|
||||
// s is outside of this half-space.
|
||||
// dot(n, p1) and dot(n, p2) < 0.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (denominator < 0.0f)
|
||||
{
|
||||
// s enters this half-space.
|
||||
if (numerator < lower * denominator)
|
||||
{
|
||||
// Increase lower.
|
||||
lower = numerator / denominator;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// s exits the half-space.
|
||||
if (numerator < upper * denominator)
|
||||
{
|
||||
// Decrease upper.
|
||||
upper = numerator / denominator;
|
||||
}
|
||||
}
|
||||
// Exit if intersection becomes empty.
|
||||
if (upper < lower)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
B3_ASSERT(lower >= 0.0f && lower <= maxFraction);
|
||||
minFraction = lower;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// Compute an AABB that encloses two AABBs.
|
||||
inline b3AABB3 b3Combine(const b3AABB3& a, const b3AABB3& b)
|
||||
{
|
||||
b3AABB3 aabb;
|
||||
aabb.m_lower = b3Min(a.m_lower, b.m_lower);
|
||||
aabb.m_upper = b3Max(a.m_upper, b.m_upper);
|
||||
return aabb;
|
||||
}
|
||||
|
||||
// Test if two AABBs are overlapping.
|
||||
inline bool b3TestOverlap(const b3AABB3& a, const b3AABB3& b)
|
||||
{
|
||||
return (a.m_lower.x <= b.m_upper.x) && (a.m_lower.y <= b.m_upper.y) && (a.m_lower.z <= b.m_upper.z) &&
|
||||
(a.m_upper.x >= b.m_lower.x) && (a.m_upper.y >= b.m_lower.y) && (a.m_upper.z >= b.m_lower.z);
|
||||
}
|
||||
|
||||
#endif
|
@@ -32,140 +32,74 @@ struct b3BoxHull : public b3Hull
|
||||
b3BoxHull() { }
|
||||
|
||||
// Construct this box from three extents and centered at the origin.
|
||||
b3BoxHull(float32 ex, float32 ey, float32 ez)
|
||||
b3BoxHull(scalar ex, scalar ey, scalar ez)
|
||||
{
|
||||
Set(ex, ey, ez);
|
||||
SetExtents(ex, ey, ez);
|
||||
}
|
||||
|
||||
|
||||
// Set this box to the unit box centered at the origin.
|
||||
void SetIdentity()
|
||||
{
|
||||
boxVertices[0] = b3Vec3(1.0f, 1.0f, -1.0f);
|
||||
boxVertices[1] = b3Vec3(-1.0f, 1.0f, -1.0f);
|
||||
boxVertices[2] = b3Vec3(-1.0f, -1.0f, -1.0f);
|
||||
boxVertices[3] = b3Vec3(1.0f, -1.0f, -1.0f);
|
||||
boxVertices[4] = b3Vec3(1.0f, 1.0f, 1.0f);
|
||||
boxVertices[5] = b3Vec3(-1.0f, 1.0f, 1.0f);
|
||||
boxVertices[6] = b3Vec3(-1.0f, -1.0f, 1.0f);
|
||||
boxVertices[7] = b3Vec3(1.0f, -1.0f, 1.0f);
|
||||
boxVertices[0] = b3Vec3(-1, -1, 1);
|
||||
boxVertices[1] = b3Vec3(1, -1, -1);
|
||||
boxVertices[2] = b3Vec3(1, 1, 1);
|
||||
boxVertices[3] = b3Vec3(-1, 1, -1);
|
||||
boxVertices[4] = b3Vec3(1, 1, -1);
|
||||
boxVertices[5] = b3Vec3(-1, 1, 1);
|
||||
boxVertices[6] = b3Vec3(1, -1, 1);
|
||||
boxVertices[7] = b3Vec3(-1, -1, -1);
|
||||
|
||||
boxEdges[0] = b3MakeEdge(1, 1, 0, 2);
|
||||
boxEdges[1] = b3MakeEdge(2, 0, 5, 21);
|
||||
boxEdges[2] = b3MakeEdge(2, 3, 0, 4);
|
||||
boxEdges[3] = b3MakeEdge(6, 2, 2, 18);
|
||||
boxEdges[4] = b3MakeEdge(6, 5, 0, 6);
|
||||
boxEdges[5] = b3MakeEdge(5, 4, 4, 17);
|
||||
boxEdges[6] = b3MakeEdge(5, 7, 0, 0);
|
||||
boxEdges[7] = b3MakeEdge(1, 6, 3, 22);
|
||||
boxEdges[8] = b3MakeEdge(4, 9, 1, 10);
|
||||
boxEdges[9] = b3MakeEdge(7, 8, 4, 23);
|
||||
boxEdges[10] = b3MakeEdge(7, 11, 1, 12);
|
||||
boxEdges[11] = b3MakeEdge(3, 10, 2, 16);
|
||||
boxEdges[12] = b3MakeEdge(3, 13, 1, 14);
|
||||
boxEdges[13] = b3MakeEdge(0, 12, 5, 19);
|
||||
boxEdges[14] = b3MakeEdge(0, 15, 1, 8);
|
||||
boxEdges[15] = b3MakeEdge(4, 14, 3, 20);
|
||||
boxEdges[16] = b3MakeEdge(7, 17, 2, 3);
|
||||
boxEdges[17] = b3MakeEdge(6, 16, 4, 9);
|
||||
boxEdges[18] = b3MakeEdge(2, 19, 2, 11);
|
||||
boxEdges[19] = b3MakeEdge(3, 18, 5, 1);
|
||||
boxEdges[20] = b3MakeEdge(0, 21, 3, 7);
|
||||
boxEdges[21] = b3MakeEdge(1, 20, 5, 13);
|
||||
boxEdges[22] = b3MakeEdge(5, 23, 3, 15);
|
||||
boxEdges[23] = b3MakeEdge(4, 22, 4, 5);
|
||||
boxEdges[0] = b3MakeEdge(0, 1, 0, 6, 2);
|
||||
boxEdges[1] = b3MakeEdge(5, 0, 1, 12, 8);
|
||||
boxEdges[2] = b3MakeEdge(5, 3, 0, 0, 4);
|
||||
boxEdges[3] = b3MakeEdge(3, 2, 5, 19, 13);
|
||||
boxEdges[4] = b3MakeEdge(3, 5, 0, 2, 6);
|
||||
boxEdges[5] = b3MakeEdge(7, 4, 3, 15, 18);
|
||||
boxEdges[6] = b3MakeEdge(7, 7, 0, 4, 0);
|
||||
boxEdges[7] = b3MakeEdge(0, 6, 2, 9, 14);
|
||||
boxEdges[8] = b3MakeEdge(0, 9, 1, 1, 10);
|
||||
boxEdges[9] = b3MakeEdge(6, 8, 2, 16, 7);
|
||||
boxEdges[10] = b3MakeEdge(6, 11, 1, 8, 12);
|
||||
boxEdges[11] = b3MakeEdge(2, 10, 4, 22, 17);
|
||||
boxEdges[12] = b3MakeEdge(2, 13, 1, 10, 1);
|
||||
boxEdges[13] = b3MakeEdge(5, 12, 5, 3, 23);
|
||||
boxEdges[14] = b3MakeEdge(7, 15, 2, 7, 16);
|
||||
boxEdges[15] = b3MakeEdge(1, 14, 3, 20, 5);
|
||||
boxEdges[16] = b3MakeEdge(1, 17, 2, 14, 9);
|
||||
boxEdges[17] = b3MakeEdge(6, 16, 4, 11, 21);
|
||||
boxEdges[18] = b3MakeEdge(3, 19, 3, 5, 20);
|
||||
boxEdges[19] = b3MakeEdge(4, 18, 5, 23, 3);
|
||||
boxEdges[20] = b3MakeEdge(4, 21, 3, 18, 15);
|
||||
boxEdges[21] = b3MakeEdge(1, 20, 4, 17, 22);
|
||||
boxEdges[22] = b3MakeEdge(4, 23, 4, 21, 11);
|
||||
boxEdges[23] = b3MakeEdge(2, 22, 5, 13, 19);
|
||||
|
||||
boxFaces[0].edge = 6;
|
||||
boxFaces[1].edge = 14;
|
||||
boxFaces[2].edge = 18;
|
||||
boxFaces[0].edge = 0;
|
||||
boxFaces[1].edge = 8;
|
||||
boxFaces[2].edge = 7;
|
||||
boxFaces[3].edge = 15;
|
||||
boxFaces[4].edge = 9;
|
||||
boxFaces[5].edge = 21;
|
||||
boxFaces[4].edge = 21;
|
||||
boxFaces[5].edge = 23;
|
||||
|
||||
boxPlanes[0] = b3Plane(b3Vec3(-1.0f, 0.0f, 0.0f), boxVertices[1]);
|
||||
boxPlanes[1] = b3Plane(b3Vec3(1.0f, 0.0f, 0.0f), boxVertices[0]);
|
||||
boxPlanes[2] = b3Plane(b3Vec3(0.0f, -1.0f, 0.0f), boxVertices[2]);
|
||||
boxPlanes[3] = b3Plane(b3Vec3(0.0f, 1.0f, 0.0f), boxVertices[1]);
|
||||
boxPlanes[4] = b3Plane(b3Vec3(0.0f, 0.0f, 1.0f), boxVertices[4]);
|
||||
boxPlanes[5] = b3Plane(b3Vec3(0.0f, 0.0f, -1.0f), boxVertices[0]);
|
||||
|
||||
centroid = b3Vec3(0.0f, 0.0f, 0.0f);
|
||||
vertices = boxVertices;
|
||||
vertexCount = 8;
|
||||
edges = boxEdges;
|
||||
edgeCount = 24;
|
||||
faces = boxFaces;
|
||||
planes = boxPlanes;
|
||||
faceCount = 6;
|
||||
boxPlanes[0].normal = b3Vec3(-1, 0, 0);
|
||||
boxPlanes[0].offset = 1;
|
||||
|
||||
Validate();
|
||||
}
|
||||
|
||||
// Set this box from three extents and centered at the origin.
|
||||
void Set(float32 ex, float32 ey, float32 ez)
|
||||
{
|
||||
b3Transform xf;
|
||||
xf.position.SetZero();
|
||||
xf.rotation = b3Diagonal(ex, ey, ez);
|
||||
SetTransform(xf);
|
||||
}
|
||||
boxPlanes[1].normal = b3Vec3(0, 0, 1);
|
||||
boxPlanes[1].offset = 1;
|
||||
|
||||
boxPlanes[2].normal = b3Vec3(0, -1, 0);
|
||||
boxPlanes[2].offset = 1;
|
||||
|
||||
boxPlanes[3].normal = b3Vec3(0, 0, -1);
|
||||
boxPlanes[3].offset = 1;
|
||||
|
||||
boxPlanes[4].normal = b3Vec3(1, 0, 0);
|
||||
boxPlanes[4].offset = 1;
|
||||
|
||||
boxPlanes[5].normal = b3Vec3(0, 1, 0);
|
||||
boxPlanes[5].offset = 1;
|
||||
|
||||
// Set this box to the unit box and transform it.
|
||||
void SetTransform(const b3Transform& T)
|
||||
{
|
||||
boxVertices[0] = b3Vec3(1.0f, 1.0f, -1.0f);
|
||||
boxVertices[1] = b3Vec3(-1.0f, 1.0f, -1.0f);
|
||||
boxVertices[2] = b3Vec3(-1.0f, -1.0f, -1.0f);
|
||||
boxVertices[3] = b3Vec3(1.0f, -1.0f, -1.0f);
|
||||
boxVertices[4] = b3Vec3(1.0f, 1.0f, 1.0f);
|
||||
boxVertices[5] = b3Vec3(-1.0f, 1.0f, 1.0f);
|
||||
boxVertices[6] = b3Vec3(-1.0f, -1.0f, 1.0f);
|
||||
boxVertices[7] = b3Vec3(1.0f, -1.0f, 1.0f);
|
||||
|
||||
for (u32 i = 0; i < 8; ++i)
|
||||
{
|
||||
boxVertices[i] = T * boxVertices[i];
|
||||
}
|
||||
|
||||
boxEdges[0] = b3MakeEdge(1, 1, 0, 2);
|
||||
boxEdges[1] = b3MakeEdge(2, 0, 5, 21);
|
||||
boxEdges[2] = b3MakeEdge(2, 3, 0, 4);
|
||||
boxEdges[3] = b3MakeEdge(6, 2, 2, 18);
|
||||
boxEdges[4] = b3MakeEdge(6, 5, 0, 6);
|
||||
boxEdges[5] = b3MakeEdge(5, 4, 4, 17);
|
||||
boxEdges[6] = b3MakeEdge(5, 7, 0, 0);
|
||||
boxEdges[7] = b3MakeEdge(1, 6, 3, 22);
|
||||
boxEdges[8] = b3MakeEdge(4, 9, 1, 10);
|
||||
boxEdges[9] = b3MakeEdge(7, 8, 4, 23);
|
||||
boxEdges[10] = b3MakeEdge(7, 11, 1, 12);
|
||||
boxEdges[11] = b3MakeEdge(3, 10, 2, 16);
|
||||
boxEdges[12] = b3MakeEdge(3, 13, 1, 14);
|
||||
boxEdges[13] = b3MakeEdge(0, 12, 5, 19);
|
||||
boxEdges[14] = b3MakeEdge(0, 15, 1, 8);
|
||||
boxEdges[15] = b3MakeEdge(4, 14, 3, 20);
|
||||
boxEdges[16] = b3MakeEdge(7, 17, 2, 3);
|
||||
boxEdges[17] = b3MakeEdge(6, 16, 4, 9);
|
||||
boxEdges[18] = b3MakeEdge(2, 19, 2, 11);
|
||||
boxEdges[19] = b3MakeEdge(3, 18, 5, 1);
|
||||
boxEdges[20] = b3MakeEdge(0, 21, 3, 7);
|
||||
boxEdges[21] = b3MakeEdge(1, 20, 5, 13);
|
||||
boxEdges[22] = b3MakeEdge(5, 23, 3, 15);
|
||||
boxEdges[23] = b3MakeEdge(4, 22, 4, 5);
|
||||
|
||||
boxFaces[0].edge = 6;
|
||||
boxFaces[1].edge = 14;
|
||||
boxFaces[2].edge = 18;
|
||||
boxFaces[3].edge = 15;
|
||||
boxFaces[4].edge = 9;
|
||||
boxFaces[5].edge = 21;
|
||||
|
||||
boxPlanes[0] = b3Plane(b3Vec3(-1.0f, 0.0f, 0.0f), boxVertices[1]);
|
||||
boxPlanes[1] = b3Plane(b3Vec3(1.0f, 0.0f, 0.0f), boxVertices[0]);
|
||||
boxPlanes[2] = b3Plane(b3Vec3(0.0f, -1.0f, 0.0f), boxVertices[2]);
|
||||
boxPlanes[3] = b3Plane(b3Vec3(0.0f, 1.0f, 0.0f), boxVertices[1]);
|
||||
boxPlanes[4] = b3Plane(b3Vec3(0.0f, 0.0f, 1.0f), boxVertices[4]);
|
||||
boxPlanes[5] = b3Plane(b3Vec3(0.0f, 0.0f, -1.0f), boxVertices[0]);
|
||||
|
||||
centroid = b3Vec3(0.0f, 0.0f, 0.0f);
|
||||
centroid = b3Vec3(0, 0, 0);
|
||||
vertices = boxVertices;
|
||||
vertexCount = 8;
|
||||
edges = boxEdges;
|
||||
@@ -174,10 +108,17 @@ struct b3BoxHull : public b3Hull
|
||||
planes = boxPlanes;
|
||||
faceCount = 6;
|
||||
|
||||
centroid = T * centroid;
|
||||
|
||||
Validate();
|
||||
}
|
||||
|
||||
// Set this box from three extents and centered and aligned at the origin.
|
||||
void SetExtents(scalar ex, scalar ey, scalar ez)
|
||||
{
|
||||
SetIdentity();
|
||||
|
||||
b3Vec3 scale(ex, ey, ez);
|
||||
Scale(scale);
|
||||
}
|
||||
};
|
||||
|
||||
extern const b3BoxHull b3BoxHull_identity;
|
||||
|
@@ -23,23 +23,18 @@
|
||||
|
||||
struct b3Capsule
|
||||
{
|
||||
//
|
||||
b3Vec3 vertex1, vertex2;
|
||||
scalar radius;
|
||||
|
||||
b3Capsule() { }
|
||||
|
||||
//
|
||||
b3Capsule(const b3Vec3& v1, const b3Vec3& v2, float32 r)
|
||||
b3Capsule(const b3Vec3& v1, const b3Vec3& v2, scalar r)
|
||||
{
|
||||
vertices[0] = v1;
|
||||
vertices[1] = v2;
|
||||
vertex1 = v1;
|
||||
vertex2 = v2;
|
||||
radius = r;
|
||||
}
|
||||
|
||||
//
|
||||
~b3Capsule() { }
|
||||
|
||||
b3Vec3 vertices[2];
|
||||
float32 radius;
|
||||
|
||||
const b3Vec3& GetVertex(u32 index) const;
|
||||
u32 GetSupportVertex(const b3Vec3& direction) const;
|
||||
};
|
||||
@@ -49,12 +44,12 @@ extern const b3Capsule b3Capsule_identity;
|
||||
|
||||
inline const b3Vec3& b3Capsule::GetVertex(u32 index) const
|
||||
{
|
||||
return vertices[index];
|
||||
return (&vertex1)[index];
|
||||
}
|
||||
|
||||
inline u32 b3Capsule::GetSupportVertex(const b3Vec3& d) const
|
||||
{
|
||||
if (b3Dot(d, vertices[0]) > b3Dot(d, vertices[1]))
|
||||
if (b3Dot(d, vertex1) > b3Dot(d, vertex2))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
240
include/bounce/collision/shapes/cone_hull.h
Normal file
240
include/bounce/collision/shapes/cone_hull.h
Normal file
@@ -0,0 +1,240 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2019 Irlan Robson https://irlanrobson.github.io
|
||||
*
|
||||
* 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 B3_CONE_HULL_H
|
||||
#define B3_CONE_HULL_H
|
||||
|
||||
#include <bounce/collision/shapes/hull.h>
|
||||
|
||||
// A cone with 20 segments.
|
||||
struct b3ConeHull : public b3Hull
|
||||
{
|
||||
b3Vec3 coneVertices[21];
|
||||
b3HalfEdge coneEdges[80];
|
||||
b3Face coneFaces[21];
|
||||
b3Plane conePlanes[21];
|
||||
|
||||
// Does nothing for performance.
|
||||
b3ConeHull()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// Construct this cone from radius and y extent centered at the origin.
|
||||
// The cone will have radius and extent set to 1;
|
||||
b3ConeHull(scalar radius, scalar ey)
|
||||
{
|
||||
SetExtents(radius, ey);
|
||||
}
|
||||
|
||||
// Set this cone to the unit cylinder centered at the origin.
|
||||
void SetIdentity()
|
||||
{
|
||||
coneVertices[0] = b3Vec3(-0.95105665922164916992, -1.00000000000000000000, -0.30901667475700378418);
|
||||
coneVertices[1] = b3Vec3(-0.95105648040771484375, -1.00000000000000000000, 0.30901741981506347656);
|
||||
coneVertices[2] = b3Vec3(0.30901747941970825195, -1.00000000000000000000, 0.95105648040771484375);
|
||||
coneVertices[3] = b3Vec3(0.95105648040771484375, -1.00000000000000000000, -0.30901703238487243652);
|
||||
coneVertices[4] = b3Vec3(-0.58778500556945800781, -1.00000000000000000000, 0.80901730060577392578);
|
||||
coneVertices[5] = b3Vec3(-0.30901724100112915039, -1.00000000000000000000, -0.95105648040771484375);
|
||||
coneVertices[6] = b3Vec3(0.30901682376861572266, -1.00000000000000000000, -0.95105654001235961914);
|
||||
coneVertices[7] = b3Vec3(0.80901741981506347656, -1.00000000000000000000, 0.58778494596481323242);
|
||||
coneVertices[8] = b3Vec3(-0.80901724100112915039, -1.00000000000000000000, -0.58778500556945800781);
|
||||
coneVertices[9] = b3Vec3(0.95105683803558349609, -1.00000000000000000000, 0.30901655554771423340);
|
||||
coneVertices[10] = b3Vec3(-0.30901664495468139648, -1.00000000000000000000, 0.95105671882629394531);
|
||||
coneVertices[11] = b3Vec3(0.80901694297790527344, -1.00000000000000000000, -0.58778530359268188477);
|
||||
coneVertices[12] = b3Vec3(0.58778578042984008789, -1.00000000000000000000, 0.80901682376861572266);
|
||||
coneVertices[13] = b3Vec3(0.58778512477874755859, -1.00000000000000000000, -0.80901706218719482422);
|
||||
coneVertices[14] = b3Vec3(-0.80901682376861572266, -1.00000000000000000000, 0.58778566122055053711);
|
||||
coneVertices[15] = b3Vec3(-0.58778554201126098633, -1.00000000000000000000, -0.80901688337326049805);
|
||||
coneVertices[16] = b3Vec3(0.00000044982880353928, -1.00000000000000000000, 1.00000011920928955078);
|
||||
coneVertices[17] = b3Vec3(-0.00000022072345018387, -1.00000000000000000000, -1.00000000000000000000);
|
||||
coneVertices[18] = b3Vec3(-1.00000011920928955078, -1.00000000000000000000, 0.00000039115548133850);
|
||||
coneVertices[19] = b3Vec3(0.00000000000000000000, 1.00000000000000000000, 0.00000000000000000000);
|
||||
coneVertices[20] = b3Vec3(1.00000000000000000000, -1.00000000000000000000, 0.00000000000000000000);
|
||||
|
||||
coneEdges[0] = b3MakeEdge(0, 1, 0, 4, 2);
|
||||
coneEdges[1] = b3MakeEdge(19, 0, 1, 8, 6);
|
||||
coneEdges[2] = b3MakeEdge(19, 3, 0, 0, 4);
|
||||
coneEdges[3] = b3MakeEdge(8, 2, 17, 11, 71);
|
||||
coneEdges[4] = b3MakeEdge(8, 5, 0, 2, 0);
|
||||
coneEdges[5] = b3MakeEdge(0, 4, 2, 7, 10);
|
||||
coneEdges[6] = b3MakeEdge(0, 7, 1, 1, 8);
|
||||
coneEdges[7] = b3MakeEdge(18, 6, 2, 44, 5);
|
||||
coneEdges[8] = b3MakeEdge(18, 9, 1, 6, 1);
|
||||
coneEdges[9] = b3MakeEdge(19, 8, 3, 46, 45);
|
||||
coneEdges[10] = b3MakeEdge(8, 11, 2, 5, 12);
|
||||
coneEdges[11] = b3MakeEdge(15, 10, 17, 71, 3);
|
||||
coneEdges[12] = b3MakeEdge(15, 13, 2, 10, 14);
|
||||
coneEdges[13] = b3MakeEdge(5, 12, 12, 67, 70);
|
||||
coneEdges[14] = b3MakeEdge(5, 15, 2, 12, 16);
|
||||
coneEdges[15] = b3MakeEdge(17, 14, 11, 68, 66);
|
||||
coneEdges[16] = b3MakeEdge(17, 17, 2, 14, 18);
|
||||
coneEdges[17] = b3MakeEdge(6, 16, 14, 73, 69);
|
||||
coneEdges[18] = b3MakeEdge(6, 19, 2, 16, 20);
|
||||
coneEdges[19] = b3MakeEdge(13, 18, 13, 74, 72);
|
||||
coneEdges[20] = b3MakeEdge(13, 21, 2, 18, 22);
|
||||
coneEdges[21] = b3MakeEdge(11, 20, 20, 61, 75);
|
||||
coneEdges[22] = b3MakeEdge(11, 23, 2, 20, 24);
|
||||
coneEdges[23] = b3MakeEdge(3, 22, 8, 57, 60);
|
||||
coneEdges[24] = b3MakeEdge(3, 25, 2, 22, 26);
|
||||
coneEdges[25] = b3MakeEdge(20, 24, 7, 58, 56);
|
||||
coneEdges[26] = b3MakeEdge(20, 27, 2, 24, 28);
|
||||
coneEdges[27] = b3MakeEdge(9, 26, 18, 79, 59);
|
||||
coneEdges[28] = b3MakeEdge(9, 29, 2, 26, 30);
|
||||
coneEdges[29] = b3MakeEdge(7, 28, 16, 77, 78);
|
||||
coneEdges[30] = b3MakeEdge(7, 31, 2, 28, 32);
|
||||
coneEdges[31] = b3MakeEdge(12, 30, 15, 55, 76);
|
||||
coneEdges[32] = b3MakeEdge(12, 33, 2, 30, 34);
|
||||
coneEdges[33] = b3MakeEdge(2, 32, 6, 51, 54);
|
||||
coneEdges[34] = b3MakeEdge(2, 35, 2, 32, 36);
|
||||
coneEdges[35] = b3MakeEdge(16, 34, 5, 52, 50);
|
||||
coneEdges[36] = b3MakeEdge(16, 37, 2, 34, 38);
|
||||
coneEdges[37] = b3MakeEdge(10, 36, 19, 65, 53);
|
||||
coneEdges[38] = b3MakeEdge(10, 39, 2, 36, 40);
|
||||
coneEdges[39] = b3MakeEdge(4, 38, 10, 63, 64);
|
||||
coneEdges[40] = b3MakeEdge(4, 41, 2, 38, 42);
|
||||
coneEdges[41] = b3MakeEdge(14, 40, 9, 49, 62);
|
||||
coneEdges[42] = b3MakeEdge(14, 43, 2, 40, 44);
|
||||
coneEdges[43] = b3MakeEdge(1, 42, 4, 47, 48);
|
||||
coneEdges[44] = b3MakeEdge(1, 45, 2, 42, 7);
|
||||
coneEdges[45] = b3MakeEdge(18, 44, 3, 9, 46);
|
||||
coneEdges[46] = b3MakeEdge(1, 47, 3, 45, 9);
|
||||
coneEdges[47] = b3MakeEdge(19, 46, 4, 48, 43);
|
||||
coneEdges[48] = b3MakeEdge(14, 49, 4, 43, 47);
|
||||
coneEdges[49] = b3MakeEdge(19, 48, 9, 62, 41);
|
||||
coneEdges[50] = b3MakeEdge(2, 51, 5, 35, 52);
|
||||
coneEdges[51] = b3MakeEdge(19, 50, 6, 54, 33);
|
||||
coneEdges[52] = b3MakeEdge(19, 53, 5, 50, 35);
|
||||
coneEdges[53] = b3MakeEdge(16, 52, 19, 37, 65);
|
||||
coneEdges[54] = b3MakeEdge(12, 55, 6, 33, 51);
|
||||
coneEdges[55] = b3MakeEdge(19, 54, 15, 76, 31);
|
||||
coneEdges[56] = b3MakeEdge(3, 57, 7, 25, 58);
|
||||
coneEdges[57] = b3MakeEdge(19, 56, 8, 60, 23);
|
||||
coneEdges[58] = b3MakeEdge(19, 59, 7, 56, 25);
|
||||
coneEdges[59] = b3MakeEdge(20, 58, 18, 27, 79);
|
||||
coneEdges[60] = b3MakeEdge(11, 61, 8, 23, 57);
|
||||
coneEdges[61] = b3MakeEdge(19, 60, 20, 75, 21);
|
||||
coneEdges[62] = b3MakeEdge(4, 63, 9, 41, 49);
|
||||
coneEdges[63] = b3MakeEdge(19, 62, 10, 64, 39);
|
||||
coneEdges[64] = b3MakeEdge(10, 65, 10, 39, 63);
|
||||
coneEdges[65] = b3MakeEdge(19, 64, 19, 53, 37);
|
||||
coneEdges[66] = b3MakeEdge(5, 67, 11, 15, 68);
|
||||
coneEdges[67] = b3MakeEdge(19, 66, 12, 70, 13);
|
||||
coneEdges[68] = b3MakeEdge(19, 69, 11, 66, 15);
|
||||
coneEdges[69] = b3MakeEdge(17, 68, 14, 17, 73);
|
||||
coneEdges[70] = b3MakeEdge(15, 71, 12, 13, 67);
|
||||
coneEdges[71] = b3MakeEdge(19, 70, 17, 3, 11);
|
||||
coneEdges[72] = b3MakeEdge(6, 73, 13, 19, 74);
|
||||
coneEdges[73] = b3MakeEdge(19, 72, 14, 69, 17);
|
||||
coneEdges[74] = b3MakeEdge(19, 75, 13, 72, 19);
|
||||
coneEdges[75] = b3MakeEdge(13, 74, 20, 21, 61);
|
||||
coneEdges[76] = b3MakeEdge(7, 77, 15, 31, 55);
|
||||
coneEdges[77] = b3MakeEdge(19, 76, 16, 78, 29);
|
||||
coneEdges[78] = b3MakeEdge(9, 79, 16, 29, 77);
|
||||
coneEdges[79] = b3MakeEdge(19, 78, 18, 59, 27);
|
||||
|
||||
coneFaces[0].edge = 0;
|
||||
coneFaces[1].edge = 6;
|
||||
coneFaces[2].edge = 5;
|
||||
coneFaces[3].edge = 46;
|
||||
coneFaces[4].edge = 43;
|
||||
coneFaces[5].edge = 50;
|
||||
coneFaces[6].edge = 33;
|
||||
coneFaces[7].edge = 56;
|
||||
coneFaces[8].edge = 23;
|
||||
coneFaces[9].edge = 62;
|
||||
coneFaces[10].edge = 39;
|
||||
coneFaces[11].edge = 66;
|
||||
coneFaces[12].edge = 13;
|
||||
coneFaces[13].edge = 72;
|
||||
coneFaces[14].edge = 17;
|
||||
coneFaces[15].edge = 76;
|
||||
coneFaces[16].edge = 29;
|
||||
coneFaces[17].edge = 3;
|
||||
coneFaces[18].edge = 27;
|
||||
coneFaces[19].edge = 37;
|
||||
coneFaces[20].edge = 21;
|
||||
|
||||
conePlanes[0].normal = b3Vec3(-0.79889804124832153320, 0.44279259443283081055, -0.40705847740173339844);
|
||||
conePlanes[0].offset = 0.44279259443283081055;
|
||||
conePlanes[1].normal = b3Vec3(-0.88558518886566162109, 0.44279265403747558594, -0.14026281237602233887);
|
||||
conePlanes[1].offset = 0.44279262423515319824;
|
||||
conePlanes[2].normal = b3Vec3(0.00000000000000000000, -1.00000000000000000000, 0.00000000000000000000);
|
||||
conePlanes[2].offset = 1.00000000000000000000;
|
||||
conePlanes[3].normal = b3Vec3(-0.88558501005172729492, 0.44279259443283081055, 0.14026330411434173584);
|
||||
conePlanes[3].offset = 0.44279262423515319824;
|
||||
conePlanes[4].normal = b3Vec3(-0.79889774322509765625, 0.44279259443283081055, 0.40705913305282592773);
|
||||
conePlanes[4].offset = 0.44279265403747558594;
|
||||
conePlanes[5].normal = b3Vec3(0.14026331901550292969, 0.44279259443283081055, 0.88558501005172729492);
|
||||
conePlanes[5].offset = 0.44279265403747558594;
|
||||
conePlanes[6].normal = b3Vec3(0.40705907344818115234, 0.44279259443283081055, 0.79889774322509765625);
|
||||
conePlanes[6].offset = 0.44279265403747558594;
|
||||
conePlanes[7].normal = b3Vec3(0.88558512926101684570, 0.44279256463050842285, -0.14026297628879547119);
|
||||
conePlanes[7].offset = 0.44279259443283081055;
|
||||
conePlanes[8].normal = b3Vec3(0.79889786243438720703, 0.44279253482818603516, -0.40705886483192443848);
|
||||
conePlanes[8].offset = 0.44279256463050842285;
|
||||
conePlanes[9].normal = b3Vec3(-0.63400870561599731445, 0.44279262423515319824, 0.63400918245315551758);
|
||||
conePlanes[9].offset = 0.44279256463050842285;
|
||||
conePlanes[10].normal = b3Vec3(-0.40705844759941101074, 0.44279259443283081055, 0.79889804124832153320);
|
||||
conePlanes[10].offset = 0.44279265403747558594;
|
||||
conePlanes[11].normal = b3Vec3(-0.14026300609111785889, 0.44279259443283081055, -0.88558506965637207031);
|
||||
conePlanes[11].offset = 0.44279253482818603516;
|
||||
conePlanes[12].normal = b3Vec3(-0.40705892443656921387, 0.44279259443283081055, -0.79889780282974243164);
|
||||
conePlanes[12].offset = 0.44279259443283081055;
|
||||
conePlanes[13].normal = b3Vec3(0.40705865621566772461, 0.44279253482818603516, -0.79889798164367675781);
|
||||
conePlanes[13].offset = 0.44279259443283081055;
|
||||
conePlanes[14].normal = b3Vec3(0.14026281237602233887, 0.44279256463050842285, -0.88558518886566162109);
|
||||
conePlanes[14].offset = 0.44279259443283081055;
|
||||
conePlanes[15].normal = b3Vec3(0.63400930166244506836, 0.44279262423515319824, 0.63400864601135253906);
|
||||
conePlanes[15].offset = 0.44279265403747558594;
|
||||
conePlanes[16].normal = b3Vec3(0.79889810085296630859, 0.44279265403747558594, 0.40705841779708862305);
|
||||
conePlanes[16].offset = 0.44279265403747558594;
|
||||
conePlanes[17].normal = b3Vec3(-0.63400924205780029297, 0.44279265403747558594, -0.63400876522064208984);
|
||||
conePlanes[17].offset = 0.44279265403747558594;
|
||||
conePlanes[18].normal = b3Vec3(0.88558530807495117188, 0.44279265403747558594, 0.14026220142841339111);
|
||||
conePlanes[18].offset = 0.44279268383979797363;
|
||||
conePlanes[19].normal = b3Vec3(-0.14026261866092681885, 0.44279259443283081055, 0.88558512926101684570);
|
||||
conePlanes[19].offset = 0.44279259443283081055;
|
||||
conePlanes[20].normal = b3Vec3(0.63400888442993164063, 0.44279256463050842285, -0.63400906324386596680);
|
||||
conePlanes[20].offset = 0.44279259443283081055;
|
||||
|
||||
centroid = b3Vec3(-0.00000003081002830641, -0.50000011920928955078, 0.00000003992893837790);
|
||||
vertices = coneVertices;
|
||||
vertexCount = 21;
|
||||
edges = coneEdges;
|
||||
edgeCount = 80;
|
||||
faces = coneFaces;
|
||||
planes = conePlanes;
|
||||
faceCount = 21;
|
||||
|
||||
Validate();
|
||||
}
|
||||
|
||||
// Construct this cylinder from radius and y extent centered at the origin.
|
||||
void SetExtents(scalar radius, scalar ey)
|
||||
{
|
||||
SetIdentity();
|
||||
|
||||
b3Vec3 scale(radius, ey, radius);
|
||||
Scale(scale);
|
||||
}
|
||||
};
|
||||
|
||||
extern const b3ConeHull b3ConeHull_identity;
|
||||
|
||||
#endif
|
322
include/bounce/collision/shapes/cylinder_hull.h
Normal file
322
include/bounce/collision/shapes/cylinder_hull.h
Normal file
@@ -0,0 +1,322 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2019 Irlan Robson https://irlanrobson.github.io
|
||||
*
|
||||
* 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 B3_CYLINDER_HULL_H
|
||||
#define B3_CYLINDER_HULL_H
|
||||
|
||||
#include <bounce/collision/shapes/hull.h>
|
||||
|
||||
// A cylinder with 20 segments.
|
||||
struct b3CylinderHull : public b3Hull
|
||||
{
|
||||
b3Vec3 cylinderVertices[40];
|
||||
b3HalfEdge cylinderEdges[120];
|
||||
b3Face cylinderFaces[22];
|
||||
b3Plane cylinderPlanes[22];
|
||||
|
||||
// Does nothing for performance.
|
||||
b3CylinderHull()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// Construct this cylinder from radius and y extent centered at the origin.
|
||||
b3CylinderHull(scalar radius, scalar ey)
|
||||
{
|
||||
SetExtents(radius, ey);
|
||||
}
|
||||
|
||||
// Set this cylinder to the unit cylinder centered at the origin.
|
||||
void SetIdentity()
|
||||
{
|
||||
cylinderVertices[0] = b3Vec3(0.80901741981506347656, 1, 0.58778494596481323242);
|
||||
cylinderVertices[1] = b3Vec3(-0.80901724100112915039, -1, -0.58778500556945800781);
|
||||
cylinderVertices[2] = b3Vec3(-0.30901724100112915039, 1, -0.95105648040771484375);
|
||||
cylinderVertices[3] = b3Vec3(0.30901747941970825195, 1, 0.95105648040771484375);
|
||||
cylinderVertices[4] = b3Vec3(0.95105648040771484375, 1, -0.30901703238487243652);
|
||||
cylinderVertices[5] = b3Vec3(-0.95105648040771484375, -1, 0.30901741981506347656);
|
||||
cylinderVertices[6] = b3Vec3(0.58778512477874755859, -1, -0.80901706218719482422);
|
||||
cylinderVertices[7] = b3Vec3(0.95105683803558349609, -1, 0.30901655554771423340);
|
||||
cylinderVertices[8] = b3Vec3(-0.58778500556945800781, 1, 0.80901730060577392578);
|
||||
cylinderVertices[9] = b3Vec3(0.30901747941970825195, -1, 0.95105648040771484375);
|
||||
cylinderVertices[10] = b3Vec3(-0.30901724100112915039, -1, -0.95105648040771484375);
|
||||
cylinderVertices[11] = b3Vec3(-0.95105648040771484375, 1, 0.30901741981506347656);
|
||||
cylinderVertices[12] = b3Vec3(0.95105648040771484375, -1, -0.30901703238487243652);
|
||||
cylinderVertices[13] = b3Vec3(0.58778512477874755859, 1, -0.80901706218719482422);
|
||||
cylinderVertices[14] = b3Vec3(-0.80901724100112915039, 1, -0.58778500556945800781);
|
||||
cylinderVertices[15] = b3Vec3(-0.58778500556945800781, -1, 0.80901730060577392578);
|
||||
cylinderVertices[16] = b3Vec3(-0.30901664495468139648, -1, 0.95105671882629394531);
|
||||
cylinderVertices[17] = b3Vec3(0.95105683803558349609, 1, 0.30901655554771423340);
|
||||
cylinderVertices[18] = b3Vec3(-0.95105665922164916992, 1, -0.30901667475700378418);
|
||||
cylinderVertices[19] = b3Vec3(0.30901682376861572266, 1, -0.95105654001235961914);
|
||||
cylinderVertices[20] = b3Vec3(-0.95105665922164916992, -1, -0.30901667475700378418);
|
||||
cylinderVertices[21] = b3Vec3(0.30901682376861572266, -1, -0.95105654001235961914);
|
||||
cylinderVertices[22] = b3Vec3(0.80901741981506347656, -1, 0.58778494596481323242);
|
||||
cylinderVertices[23] = b3Vec3(-0.30901664495468139648, 1, 0.95105671882629394531);
|
||||
cylinderVertices[24] = b3Vec3(-0.80901682376861572266, 1, 0.58778566122055053711);
|
||||
cylinderVertices[25] = b3Vec3(0.80901694297790527344, -1, -0.58778530359268188477);
|
||||
cylinderVertices[26] = b3Vec3(-0.58778554201126098633, -1, -0.80901688337326049805);
|
||||
cylinderVertices[27] = b3Vec3(0.58778578042984008789, -1, 0.80901682376861572266);
|
||||
cylinderVertices[28] = b3Vec3(0.58778578042984008789, 1, 0.80901682376861572266);
|
||||
cylinderVertices[29] = b3Vec3(-0.80901682376861572266, -1, 0.58778566122055053711);
|
||||
cylinderVertices[30] = b3Vec3(0.80901694297790527344, 1, -0.58778530359268188477);
|
||||
cylinderVertices[31] = b3Vec3(-0.58778554201126098633, 1, -0.80901688337326049805);
|
||||
cylinderVertices[32] = b3Vec3(1, 1, 0);
|
||||
cylinderVertices[33] = b3Vec3(0.00000044982880353928, -1, 1.00000011920928955078);
|
||||
cylinderVertices[34] = b3Vec3(-1.00000011920928955078, 1, 0.00000039115548133850);
|
||||
cylinderVertices[35] = b3Vec3(-0.00000022072345018387, -1, -1);
|
||||
cylinderVertices[36] = b3Vec3(0.00000044982880353928, 1, 1.00000011920928955078);
|
||||
cylinderVertices[37] = b3Vec3(-0.00000022072345018387, 1, -1);
|
||||
cylinderVertices[38] = b3Vec3(1, -1, 0);
|
||||
cylinderVertices[39] = b3Vec3(-1.00000011920928955078, -1, 0.00000039115548133850);
|
||||
|
||||
cylinderEdges[0] = b3MakeEdge(0, 1, 0, 6, 2);
|
||||
cylinderEdges[1] = b3MakeEdge(22, 0, 1, 12, 8);
|
||||
cylinderEdges[2] = b3MakeEdge(22, 3, 0, 0, 4);
|
||||
cylinderEdges[3] = b3MakeEdge(7, 2, 4, 72, 13);
|
||||
cylinderEdges[4] = b3MakeEdge(7, 5, 0, 2, 6);
|
||||
cylinderEdges[5] = b3MakeEdge(17, 4, 16, 15, 73);
|
||||
cylinderEdges[6] = b3MakeEdge(17, 7, 0, 4, 0);
|
||||
cylinderEdges[7] = b3MakeEdge(0, 6, 2, 9, 14);
|
||||
cylinderEdges[8] = b3MakeEdge(0, 9, 1, 1, 10);
|
||||
cylinderEdges[9] = b3MakeEdge(28, 8, 2, 48, 7);
|
||||
cylinderEdges[10] = b3MakeEdge(28, 11, 1, 8, 12);
|
||||
cylinderEdges[11] = b3MakeEdge(27, 10, 9, 75, 49);
|
||||
cylinderEdges[12] = b3MakeEdge(27, 13, 1, 10, 1);
|
||||
cylinderEdges[13] = b3MakeEdge(22, 12, 4, 3, 74);
|
||||
cylinderEdges[14] = b3MakeEdge(17, 15, 2, 7, 16);
|
||||
cylinderEdges[15] = b3MakeEdge(32, 14, 16, 101, 5);
|
||||
cylinderEdges[16] = b3MakeEdge(32, 17, 2, 14, 18);
|
||||
cylinderEdges[17] = b3MakeEdge(4, 16, 10, 102, 100);
|
||||
cylinderEdges[18] = b3MakeEdge(4, 19, 2, 16, 20);
|
||||
cylinderEdges[19] = b3MakeEdge(30, 18, 11, 104, 103);
|
||||
cylinderEdges[20] = b3MakeEdge(30, 21, 2, 18, 22);
|
||||
cylinderEdges[21] = b3MakeEdge(13, 20, 15, 115, 105);
|
||||
cylinderEdges[22] = b3MakeEdge(13, 23, 2, 20, 24);
|
||||
cylinderEdges[23] = b3MakeEdge(19, 22, 14, 112, 114);
|
||||
cylinderEdges[24] = b3MakeEdge(19, 25, 2, 22, 26);
|
||||
cylinderEdges[25] = b3MakeEdge(37, 24, 21, 93, 113);
|
||||
cylinderEdges[26] = b3MakeEdge(37, 27, 2, 24, 28);
|
||||
cylinderEdges[27] = b3MakeEdge(2, 26, 6, 94, 92);
|
||||
cylinderEdges[28] = b3MakeEdge(2, 29, 2, 26, 30);
|
||||
cylinderEdges[29] = b3MakeEdge(31, 28, 7, 91, 95);
|
||||
cylinderEdges[30] = b3MakeEdge(31, 31, 2, 28, 32);
|
||||
cylinderEdges[31] = b3MakeEdge(14, 30, 5, 55, 90);
|
||||
cylinderEdges[32] = b3MakeEdge(14, 33, 2, 30, 34);
|
||||
cylinderEdges[33] = b3MakeEdge(18, 32, 3, 52, 54);
|
||||
cylinderEdges[34] = b3MakeEdge(18, 35, 2, 32, 36);
|
||||
cylinderEdges[35] = b3MakeEdge(34, 34, 20, 111, 53);
|
||||
cylinderEdges[36] = b3MakeEdge(34, 37, 2, 34, 38);
|
||||
cylinderEdges[37] = b3MakeEdge(11, 36, 13, 109, 110);
|
||||
cylinderEdges[38] = b3MakeEdge(11, 39, 2, 36, 40);
|
||||
cylinderEdges[39] = b3MakeEdge(24, 38, 12, 106, 108);
|
||||
cylinderEdges[40] = b3MakeEdge(24, 41, 2, 38, 42);
|
||||
cylinderEdges[41] = b3MakeEdge(8, 40, 17, 116, 107);
|
||||
cylinderEdges[42] = b3MakeEdge(8, 43, 2, 40, 44);
|
||||
cylinderEdges[43] = b3MakeEdge(23, 42, 18, 118, 117);
|
||||
cylinderEdges[44] = b3MakeEdge(23, 45, 2, 42, 46);
|
||||
cylinderEdges[45] = b3MakeEdge(36, 44, 19, 97, 119);
|
||||
cylinderEdges[46] = b3MakeEdge(36, 47, 2, 44, 48);
|
||||
cylinderEdges[47] = b3MakeEdge(3, 46, 8, 98, 96);
|
||||
cylinderEdges[48] = b3MakeEdge(3, 49, 2, 46, 9);
|
||||
cylinderEdges[49] = b3MakeEdge(28, 48, 9, 11, 99);
|
||||
cylinderEdges[50] = b3MakeEdge(1, 51, 3, 54, 52);
|
||||
cylinderEdges[51] = b3MakeEdge(20, 50, 4, 88, 56);
|
||||
cylinderEdges[52] = b3MakeEdge(20, 53, 3, 50, 33);
|
||||
cylinderEdges[53] = b3MakeEdge(18, 52, 20, 35, 89);
|
||||
cylinderEdges[54] = b3MakeEdge(14, 55, 3, 33, 50);
|
||||
cylinderEdges[55] = b3MakeEdge(1, 54, 5, 57, 31);
|
||||
cylinderEdges[56] = b3MakeEdge(1, 57, 4, 51, 58);
|
||||
cylinderEdges[57] = b3MakeEdge(26, 56, 5, 90, 55);
|
||||
cylinderEdges[58] = b3MakeEdge(26, 59, 4, 56, 60);
|
||||
cylinderEdges[59] = b3MakeEdge(10, 58, 7, 95, 91);
|
||||
cylinderEdges[60] = b3MakeEdge(10, 61, 4, 58, 62);
|
||||
cylinderEdges[61] = b3MakeEdge(35, 60, 6, 92, 94);
|
||||
cylinderEdges[62] = b3MakeEdge(35, 63, 4, 60, 64);
|
||||
cylinderEdges[63] = b3MakeEdge(21, 62, 21, 113, 93);
|
||||
cylinderEdges[64] = b3MakeEdge(21, 65, 4, 62, 66);
|
||||
cylinderEdges[65] = b3MakeEdge(6, 64, 14, 114, 112);
|
||||
cylinderEdges[66] = b3MakeEdge(6, 67, 4, 64, 68);
|
||||
cylinderEdges[67] = b3MakeEdge(25, 66, 15, 105, 115);
|
||||
cylinderEdges[68] = b3MakeEdge(25, 69, 4, 66, 70);
|
||||
cylinderEdges[69] = b3MakeEdge(12, 68, 11, 103, 104);
|
||||
cylinderEdges[70] = b3MakeEdge(12, 71, 4, 68, 72);
|
||||
cylinderEdges[71] = b3MakeEdge(38, 70, 10, 100, 102);
|
||||
cylinderEdges[72] = b3MakeEdge(38, 73, 4, 70, 3);
|
||||
cylinderEdges[73] = b3MakeEdge(7, 72, 16, 5, 101);
|
||||
cylinderEdges[74] = b3MakeEdge(27, 75, 4, 13, 76);
|
||||
cylinderEdges[75] = b3MakeEdge(9, 74, 9, 99, 11);
|
||||
cylinderEdges[76] = b3MakeEdge(9, 77, 4, 74, 78);
|
||||
cylinderEdges[77] = b3MakeEdge(33, 76, 8, 96, 98);
|
||||
cylinderEdges[78] = b3MakeEdge(33, 79, 4, 76, 80);
|
||||
cylinderEdges[79] = b3MakeEdge(16, 78, 19, 119, 97);
|
||||
cylinderEdges[80] = b3MakeEdge(16, 81, 4, 78, 82);
|
||||
cylinderEdges[81] = b3MakeEdge(15, 80, 18, 117, 118);
|
||||
cylinderEdges[82] = b3MakeEdge(15, 83, 4, 80, 84);
|
||||
cylinderEdges[83] = b3MakeEdge(29, 82, 17, 107, 116);
|
||||
cylinderEdges[84] = b3MakeEdge(29, 85, 4, 82, 86);
|
||||
cylinderEdges[85] = b3MakeEdge(5, 84, 12, 108, 106);
|
||||
cylinderEdges[86] = b3MakeEdge(5, 87, 4, 84, 88);
|
||||
cylinderEdges[87] = b3MakeEdge(39, 86, 13, 110, 109);
|
||||
cylinderEdges[88] = b3MakeEdge(39, 89, 4, 86, 51);
|
||||
cylinderEdges[89] = b3MakeEdge(20, 88, 20, 53, 111);
|
||||
cylinderEdges[90] = b3MakeEdge(31, 91, 5, 31, 57);
|
||||
cylinderEdges[91] = b3MakeEdge(26, 90, 7, 59, 29);
|
||||
cylinderEdges[92] = b3MakeEdge(37, 93, 6, 27, 61);
|
||||
cylinderEdges[93] = b3MakeEdge(35, 92, 21, 63, 25);
|
||||
cylinderEdges[94] = b3MakeEdge(10, 95, 6, 61, 27);
|
||||
cylinderEdges[95] = b3MakeEdge(2, 94, 7, 29, 59);
|
||||
cylinderEdges[96] = b3MakeEdge(36, 97, 8, 47, 77);
|
||||
cylinderEdges[97] = b3MakeEdge(33, 96, 19, 79, 45);
|
||||
cylinderEdges[98] = b3MakeEdge(9, 99, 8, 77, 47);
|
||||
cylinderEdges[99] = b3MakeEdge(3, 98, 9, 49, 75);
|
||||
cylinderEdges[100] = b3MakeEdge(32, 101, 10, 17, 71);
|
||||
cylinderEdges[101] = b3MakeEdge(38, 100, 16, 73, 15);
|
||||
cylinderEdges[102] = b3MakeEdge(12, 103, 10, 71, 17);
|
||||
cylinderEdges[103] = b3MakeEdge(4, 102, 11, 19, 69);
|
||||
cylinderEdges[104] = b3MakeEdge(25, 105, 11, 69, 19);
|
||||
cylinderEdges[105] = b3MakeEdge(30, 104, 15, 21, 67);
|
||||
cylinderEdges[106] = b3MakeEdge(29, 107, 12, 85, 39);
|
||||
cylinderEdges[107] = b3MakeEdge(24, 106, 17, 41, 83);
|
||||
cylinderEdges[108] = b3MakeEdge(11, 109, 12, 39, 85);
|
||||
cylinderEdges[109] = b3MakeEdge(5, 108, 13, 87, 37);
|
||||
cylinderEdges[110] = b3MakeEdge(34, 111, 13, 37, 87);
|
||||
cylinderEdges[111] = b3MakeEdge(39, 110, 20, 89, 35);
|
||||
cylinderEdges[112] = b3MakeEdge(21, 113, 14, 65, 23);
|
||||
cylinderEdges[113] = b3MakeEdge(19, 112, 21, 25, 63);
|
||||
cylinderEdges[114] = b3MakeEdge(13, 115, 14, 23, 65);
|
||||
cylinderEdges[115] = b3MakeEdge(6, 114, 15, 67, 21);
|
||||
cylinderEdges[116] = b3MakeEdge(15, 117, 17, 83, 41);
|
||||
cylinderEdges[117] = b3MakeEdge(8, 116, 18, 43, 81);
|
||||
cylinderEdges[118] = b3MakeEdge(16, 119, 18, 81, 43);
|
||||
cylinderEdges[119] = b3MakeEdge(23, 118, 19, 45, 79);
|
||||
|
||||
cylinderFaces[0].edge = 0;
|
||||
cylinderFaces[1].edge = 8;
|
||||
cylinderFaces[2].edge = 7;
|
||||
cylinderFaces[3].edge = 50;
|
||||
cylinderFaces[4].edge = 56;
|
||||
cylinderFaces[5].edge = 55;
|
||||
cylinderFaces[6].edge = 27;
|
||||
cylinderFaces[7].edge = 95;
|
||||
cylinderFaces[8].edge = 47;
|
||||
cylinderFaces[9].edge = 99;
|
||||
cylinderFaces[10].edge = 17;
|
||||
cylinderFaces[11].edge = 103;
|
||||
cylinderFaces[12].edge = 85;
|
||||
cylinderFaces[13].edge = 109;
|
||||
cylinderFaces[14].edge = 65;
|
||||
cylinderFaces[15].edge = 115;
|
||||
cylinderFaces[16].edge = 73;
|
||||
cylinderFaces[17].edge = 41;
|
||||
cylinderFaces[18].edge = 117;
|
||||
cylinderFaces[19].edge = 79;
|
||||
cylinderFaces[20].edge = 53;
|
||||
cylinderFaces[21].edge = 113;
|
||||
|
||||
cylinderPlanes[0].normal = b3Vec3(0.89100682735443115234, 0, 0.45399010181427001953);
|
||||
cylinderPlanes[0].offset = 0.98768866062164306641;
|
||||
|
||||
cylinderPlanes[1].normal = b3Vec3(0.70710718631744384766, 0, 0.70710641145706176758);
|
||||
cylinderPlanes[1].offset = 0.98768854141235351563;
|
||||
|
||||
cylinderPlanes[2].normal = b3Vec3(0, 1, 0);
|
||||
cylinderPlanes[2].offset = 1;
|
||||
|
||||
cylinderPlanes[3].normal = b3Vec3(-0.89100670814514160156, 0, -0.45399013161659240723);
|
||||
cylinderPlanes[3].offset = 0.98768842220306396484;
|
||||
|
||||
cylinderPlanes[4].normal = b3Vec3(0, -1, 0);
|
||||
cylinderPlanes[4].offset = 1;
|
||||
|
||||
cylinderPlanes[5].normal = b3Vec3(-0.70710712671279907227, 0, -0.70710653066635131836);
|
||||
cylinderPlanes[5].offset = 0.98768848180770874023;
|
||||
|
||||
cylinderPlanes[6].normal = b3Vec3(-0.15643458068370819092, 0, -0.98768836259841918945);
|
||||
cylinderPlanes[6].offset = 0.98768842220306396484;
|
||||
|
||||
cylinderPlanes[7].normal = b3Vec3(-0.45399063825607299805, 0, -0.89100646972656250000);
|
||||
cylinderPlanes[7].offset = 0.98768842220306396484;
|
||||
|
||||
cylinderPlanes[8].normal = b3Vec3(0.15643493831157684326, 0, 0.98768830299377441406);
|
||||
cylinderPlanes[8].offset = 0.98768848180770874023;
|
||||
|
||||
cylinderPlanes[9].normal = b3Vec3(0.45399075746536254883, 0, 0.89100635051727294922);
|
||||
cylinderPlanes[9].offset = 0.98768836259841918945;
|
||||
|
||||
cylinderPlanes[10].normal = b3Vec3(0.98768830299377441406, 0, -0.15643455088138580322);
|
||||
cylinderPlanes[10].offset = 0.98768830299377441406;
|
||||
|
||||
cylinderPlanes[11].normal = b3Vec3(0.89100646972656250000, 0, -0.45399051904678344727);
|
||||
cylinderPlanes[11].offset = 0.98768830299377441406;
|
||||
|
||||
cylinderPlanes[12].normal = b3Vec3(-0.89100635051727294922, 0, 0.45399084687232971191);
|
||||
cylinderPlanes[12].offset = 0.98768842220306396484;
|
||||
|
||||
cylinderPlanes[13].normal = b3Vec3(-0.98768830299377441406, 0, 0.15643493831157684326);
|
||||
cylinderPlanes[13].offset = 0.98768842220306396484;
|
||||
|
||||
cylinderPlanes[14].normal = b3Vec3(0.45399031043052673340, 0, -0.89100658893585205078);
|
||||
cylinderPlanes[14].offset = 0.98768830299377441406;
|
||||
|
||||
cylinderPlanes[15].normal = b3Vec3(0.70710670948028564453, 0, -0.70710688829421997070);
|
||||
cylinderPlanes[15].offset = 0.98768830299377441406;
|
||||
|
||||
cylinderPlanes[16].normal = b3Vec3(0.98768848180770874023, 0, 0.15643368661403656006);
|
||||
cylinderPlanes[16].offset = 0.98768854141235351563;
|
||||
|
||||
cylinderPlanes[17].normal = b3Vec3(-0.70710653066635131836, 0, 0.70710712671279907227);
|
||||
cylinderPlanes[17].offset = 0.98768854141235351563;
|
||||
|
||||
cylinderPlanes[18].normal = b3Vec3(-0.45399010181427001953, 0, 0.89100670814514160156);
|
||||
cylinderPlanes[18].offset = 0.98768842220306396484;
|
||||
|
||||
cylinderPlanes[19].normal = b3Vec3(-0.15643416345119476318, 0, 0.98768842220306396484);
|
||||
cylinderPlanes[19].offset = 0.98768848180770874023;
|
||||
|
||||
cylinderPlanes[20].normal = b3Vec3(-0.98768842220306396484, 0, -0.15643437206745147705);
|
||||
cylinderPlanes[20].offset = 0.98768848180770874023;
|
||||
|
||||
cylinderPlanes[21].normal = b3Vec3(0.15643437206745147705, 0, -0.98768842220306396484);
|
||||
cylinderPlanes[21].offset = 0.98768836259841918945;
|
||||
|
||||
centroid = b3Vec3(0, 0, 0);
|
||||
vertices = cylinderVertices;
|
||||
vertexCount = 40;
|
||||
edges = cylinderEdges;
|
||||
edgeCount = 120;
|
||||
faces = cylinderFaces;
|
||||
planes = cylinderPlanes;
|
||||
faceCount = 22;
|
||||
|
||||
Validate();
|
||||
}
|
||||
|
||||
// Construct this cylinder from radius and y extent centered at the origin.
|
||||
void SetExtents(scalar radius, scalar ey)
|
||||
{
|
||||
SetIdentity();
|
||||
|
||||
b3Vec3 scale(radius, ey, radius);
|
||||
Scale(scale);
|
||||
}
|
||||
};
|
||||
|
||||
extern const b3CylinderHull b3CylinderHull_identity;
|
||||
|
||||
#endif
|
@@ -26,28 +26,30 @@
|
||||
template<u32 H = 1, u32 W = 1>
|
||||
struct b3GridMesh : public b3Mesh
|
||||
{
|
||||
b3Vec3 gridVertices[ (H + 1) * (W + 1) ];
|
||||
b3Triangle gridTriangles[2 * H * W];
|
||||
b3Vec3 gridVertices[(H + 1) * (W + 1)];
|
||||
b3MeshTriangle gridTriangles[2 * H * W];
|
||||
|
||||
// Set this grid to a W (width) per H (height) dimensioned grid centered at the origin and aligned
|
||||
// with the world x-z axes.
|
||||
b3GridMesh()
|
||||
{
|
||||
vertexCount = 0;
|
||||
for (u32 i = 0; i <= H; ++i)
|
||||
for (u32 j = 0; j <= W; ++j)
|
||||
{
|
||||
for (u32 j = 0; j <= W; ++j)
|
||||
for (u32 i = 0; i <= H; ++i)
|
||||
{
|
||||
gridVertices[vertexCount++].Set(float32(j), 0.0f, float32(i));
|
||||
u32 vertex = GetVertex(i, j);
|
||||
gridVertices[vertex].Set(scalar(j), 0, scalar(i));
|
||||
++vertexCount;
|
||||
}
|
||||
}
|
||||
|
||||
B3_ASSERT(vertexCount == (H + 1) * (W + 1));
|
||||
|
||||
b3Vec3 translation;
|
||||
translation.x = -0.5f * float32(W);
|
||||
translation.y = 0.0f;
|
||||
translation.z = -0.5f * float32(H);
|
||||
translation.x = scalar(-0.5) * scalar(W);
|
||||
translation.y = 0;
|
||||
translation.z = scalar(-0.5) * scalar(H);
|
||||
|
||||
for (u32 i = 0; i < vertexCount; ++i)
|
||||
{
|
||||
@@ -59,20 +61,23 @@ struct b3GridMesh : public b3Mesh
|
||||
{
|
||||
for (u32 j = 0; j < W; ++j)
|
||||
{
|
||||
u32 v1 = i * (W + 1) + j;
|
||||
u32 v2 = (i + 1) * (W + 1) + j;
|
||||
u32 v3 = (i + 1) * (W + 1) + (j + 1);
|
||||
u32 v4 = i * (W + 1) + (j + 1);
|
||||
// 1*|----|*4
|
||||
// |----|
|
||||
// 2*|----|*3
|
||||
u32 v1 = GetVertex(i, j);
|
||||
u32 v2 = GetVertex(i + 1, j);
|
||||
u32 v3 = GetVertex(i + 1, j + 1);
|
||||
u32 v4 = GetVertex(i, j + 1);
|
||||
|
||||
b3Triangle* t1 = gridTriangles + triangleCount++;
|
||||
t1->v1 = v3;
|
||||
b3MeshTriangle* t1 = gridTriangles + triangleCount++;
|
||||
t1->v1 = v1;
|
||||
t1->v2 = v2;
|
||||
t1->v3 = v1;
|
||||
t1->v3 = v3;
|
||||
|
||||
b3Triangle* t2 = gridTriangles + triangleCount++;
|
||||
t2->v1 = v1;
|
||||
b3MeshTriangle* t2 = gridTriangles + triangleCount++;
|
||||
t2->v1 = v3;
|
||||
t2->v2 = v4;
|
||||
t2->v3 = v3;
|
||||
t2->v3 = v1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,6 +86,13 @@ struct b3GridMesh : public b3Mesh
|
||||
vertices = gridVertices;
|
||||
triangles = gridTriangles;
|
||||
}
|
||||
|
||||
u32 GetVertex(u32 i, u32 j)
|
||||
{
|
||||
B3_ASSERT(i < H + 1);
|
||||
B3_ASSERT(j < W + 1);
|
||||
return i * (W + 1) + j;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
@@ -31,6 +31,7 @@ struct b3HalfEdge
|
||||
u32 origin;
|
||||
u32 twin;
|
||||
u32 face;
|
||||
u32 prev;
|
||||
u32 next;
|
||||
};
|
||||
|
||||
@@ -61,6 +62,15 @@ struct b3Hull
|
||||
void Validate() const;
|
||||
void Validate(const b3Face* face) const;
|
||||
void Validate(const b3HalfEdge* edge) const;
|
||||
|
||||
void Dump() const;
|
||||
|
||||
void Scale(const b3Vec3& scale);
|
||||
void Rotate(const b3Quat& rotation);
|
||||
void Translate(const b3Vec3& translation);
|
||||
|
||||
// Scale -> Rotate -> Translate
|
||||
void Transform(const b3Transform& xf, const b3Vec3& scale);
|
||||
};
|
||||
|
||||
#include <bounce/collision/shapes/hull.inl>
|
||||
|
@@ -1,9 +1,10 @@
|
||||
inline b3HalfEdge b3MakeEdge(u32 origin, u32 twin, u32 face, u32 next)
|
||||
inline b3HalfEdge b3MakeEdge(u32 origin, u32 twin, u32 face, u32 prev, u32 next)
|
||||
{
|
||||
b3HalfEdge edge;
|
||||
edge.origin = origin;
|
||||
edge.twin = twin;
|
||||
edge.face = face;
|
||||
edge.prev = prev;
|
||||
edge.next = next;
|
||||
return edge;
|
||||
}
|
||||
@@ -31,10 +32,10 @@ inline const b3Plane& b3Hull::GetPlane(u32 index) const
|
||||
inline u32 b3Hull::GetSupportVertex(const b3Vec3& direction) const
|
||||
{
|
||||
u32 maxIndex = 0;
|
||||
float32 maxProjection = b3Dot(direction, vertices[maxIndex]);
|
||||
scalar maxProjection = b3Dot(direction, vertices[maxIndex]);
|
||||
for (u32 i = 1; i < vertexCount; ++i)
|
||||
{
|
||||
float32 projection = b3Dot(direction, vertices[i]);
|
||||
scalar projection = b3Dot(direction, vertices[i]);
|
||||
if (projection > maxProjection)
|
||||
{
|
||||
maxIndex = i;
|
||||
@@ -47,10 +48,10 @@ inline u32 b3Hull::GetSupportVertex(const b3Vec3& direction) const
|
||||
inline u32 b3Hull::GetSupportFace(const b3Vec3& direction) const
|
||||
{
|
||||
u32 maxIndex = 0;
|
||||
float32 maxProjection = b3Dot(direction, planes[maxIndex].normal);
|
||||
scalar maxProjection = b3Dot(direction, planes[maxIndex].normal);
|
||||
for (u32 i = 1; i < faceCount; ++i)
|
||||
{
|
||||
float32 projection = b3Dot(direction, planes[i].normal);
|
||||
scalar projection = b3Dot(direction, planes[i].normal);
|
||||
if (projection > maxProjection)
|
||||
{
|
||||
maxIndex = i;
|
||||
|
@@ -19,40 +19,72 @@
|
||||
#ifndef B3_MESH_H
|
||||
#define B3_MESH_H
|
||||
|
||||
#include <bounce/common/geometry.h>
|
||||
#include <bounce/collision/trees/static_tree.h>
|
||||
|
||||
struct b3Triangle
|
||||
#define B3_NULL_VERTEX B3_MAX_U32
|
||||
|
||||
// Mesh triangle.
|
||||
struct b3MeshTriangle
|
||||
{
|
||||
// Test if this triangle contains a given vertex.
|
||||
bool TestVertex(u32 v) const
|
||||
{
|
||||
return v == v1 || v == v2 || v == v3;
|
||||
}
|
||||
// Write an indexed vertex to this triangle.
|
||||
u32& GetVertex(u32 i) { return (&v1)[i]; }
|
||||
|
||||
// Test if this triangle contains two vertices.
|
||||
bool TestEdge(u32 _v1, u32 _v2) const
|
||||
{
|
||||
return TestVertex(_v1) && TestVertex(_v2);
|
||||
}
|
||||
// Read an indexed vertex from this triangle.
|
||||
u32 GetVertex(u32 i) const { return (&v1)[i]; }
|
||||
|
||||
// The triangle vertices in the mesh.
|
||||
u32 v1, v2, v3;
|
||||
};
|
||||
|
||||
// Mesh triangle adjacency.
|
||||
// This is used for smooth edge collision.
|
||||
struct b3MeshTriangleWings
|
||||
{
|
||||
// Write an indexed edge wing vertex to this triangle.
|
||||
u32& GetVertex(u32 i) { return (&u1)[i]; }
|
||||
|
||||
// Read an indexed edge wing vertex from this triangle.
|
||||
u32 GetVertex(u32 i) const { return (&u1)[i]; }
|
||||
|
||||
// The wing vertex of each edge in this triangle.
|
||||
// An edge is a boundary if its wing vertex is set to B3_NULL_VERTEX.
|
||||
u32 u1, u2, u3;
|
||||
};
|
||||
|
||||
struct b3Mesh
|
||||
{
|
||||
u32 vertexCount;
|
||||
b3Vec3* vertices;
|
||||
u32 triangleCount;
|
||||
b3Triangle* triangles;
|
||||
b3MeshTriangle* triangles;
|
||||
b3MeshTriangleWings* triangleWings;
|
||||
|
||||
b3StaticTree tree;
|
||||
|
||||
b3Mesh();
|
||||
~b3Mesh();
|
||||
|
||||
// Build the static AABB tree.
|
||||
void BuildTree();
|
||||
|
||||
// Build mesh adjacency.
|
||||
// This won't work properly if there are non-manifold edges.
|
||||
void BuildAdjacency();
|
||||
|
||||
const b3Vec3& GetVertex(u32 index) const;
|
||||
const b3Triangle& GetTriangle(u32 index) const;
|
||||
const b3MeshTriangle* GetTriangle(u32 index) const;
|
||||
const b3MeshTriangleWings* GetTriangleWings(u32 index) const;
|
||||
b3AABB GetTriangleAABB(u32 index) const;
|
||||
|
||||
u32 GetSize() const;
|
||||
|
||||
b3AABB3 GetTriangleAABB(u32 index) const;
|
||||
void Scale(const b3Vec3& scale);
|
||||
void Rotate(const b3Quat& rotation);
|
||||
void Translate(const b3Vec3& translation);
|
||||
|
||||
void BuildTree();
|
||||
// Scale -> Rotate -> Translate
|
||||
void Transform(const b3Transform& xf, const b3Vec3& scale);
|
||||
};
|
||||
|
||||
inline const b3Vec3& b3Mesh::GetVertex(u32 index) const
|
||||
@@ -60,9 +92,24 @@ inline const b3Vec3& b3Mesh::GetVertex(u32 index) const
|
||||
return vertices[index];
|
||||
}
|
||||
|
||||
inline const b3Triangle& b3Mesh::GetTriangle(u32 index) const
|
||||
inline const b3MeshTriangle* b3Mesh::GetTriangle(u32 index) const
|
||||
{
|
||||
return triangles[index];
|
||||
return triangles + index;
|
||||
}
|
||||
|
||||
inline const b3MeshTriangleWings* b3Mesh::GetTriangleWings(u32 index) const
|
||||
{
|
||||
return triangleWings + index;
|
||||
}
|
||||
|
||||
inline b3AABB b3Mesh::GetTriangleAABB(u32 index) const
|
||||
{
|
||||
const b3MeshTriangle* triangle = triangles + index;
|
||||
|
||||
b3AABB aabb;
|
||||
aabb.SetTriangle(vertices[triangle->v1], vertices[triangle->v2], vertices[triangle->v3]);
|
||||
|
||||
return aabb;
|
||||
}
|
||||
|
||||
inline u32 b3Mesh::GetSize() const
|
||||
@@ -70,32 +117,10 @@ inline u32 b3Mesh::GetSize() const
|
||||
u32 size = 0;
|
||||
size += sizeof(b3Mesh);
|
||||
size += sizeof(b3Vec3) * vertexCount;
|
||||
size += sizeof(b3Triangle) * triangleCount;
|
||||
size += sizeof(b3MeshTriangle) * triangleCount;
|
||||
size += sizeof(b3MeshTriangleWings) * triangleCount;
|
||||
size += tree.GetSize();
|
||||
return size;
|
||||
}
|
||||
|
||||
inline b3AABB3 b3Mesh::GetTriangleAABB(u32 index) const
|
||||
{
|
||||
const b3Triangle* triangle = triangles + index;
|
||||
|
||||
b3AABB3 aabb;
|
||||
aabb.Set(vertices[triangle->v1], vertices[triangle->v2], vertices[triangle->v3]);
|
||||
|
||||
return aabb;
|
||||
}
|
||||
|
||||
inline void b3Mesh::BuildTree()
|
||||
{
|
||||
b3AABB3* aabbs = (b3AABB3*)b3Alloc(triangleCount * sizeof(b3AABB3));
|
||||
for (u32 i = 0; i < triangleCount; ++i)
|
||||
{
|
||||
aabbs[i] = GetTriangleAABB(i);
|
||||
}
|
||||
|
||||
tree.Build(aabbs, triangleCount);
|
||||
|
||||
b3Free(aabbs);
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
@@ -52,15 +52,15 @@ struct b3QHull : public b3Hull
|
||||
|
||||
// Set this hull as a sphere located at the origin
|
||||
// given the radius.
|
||||
void SetAsSphere(float32 radius = 1.0f);
|
||||
void SetAsSphere(scalar radius = 1, u32 subdivisions = 0);
|
||||
|
||||
// Set this hull as a cylinder located at the origin
|
||||
// given the radius and extent along the y axis.
|
||||
void SetAsCylinder(float32 radius = 1.0f, float32 ey = 1.0f);
|
||||
// given the radius, extent along the y axis, and number of segments.
|
||||
void SetAsCylinder(scalar radius = 1, scalar ey = 1, u32 segments = 20);
|
||||
|
||||
// Set this hull as a cone located at the origin
|
||||
// given the radius and extent along the y axis.
|
||||
void SetAsCone(float32 radius = 1.0f, float32 ey = 1.0f);
|
||||
// given the radius, extent along the y axis, and number of segments.
|
||||
void SetAsCone(scalar radius = 1, scalar ey = 1, u32 segments = 20);
|
||||
};
|
||||
|
||||
#endif
|
168
include/bounce/collision/shapes/sdf.h
Normal file
168
include/bounce/collision/shapes/sdf.h
Normal file
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2019 Irlan Robson https://irlanrobson.github.io
|
||||
*
|
||||
* 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 B3_SDF_H
|
||||
#define B3_SDF_H
|
||||
|
||||
#include <bounce/collision/shapes/aabb.h>
|
||||
|
||||
struct b3MultiIndex
|
||||
{
|
||||
unsigned int& operator[](unsigned int i)
|
||||
{
|
||||
return v[i];
|
||||
}
|
||||
|
||||
const unsigned int& operator[](unsigned int i) const
|
||||
{
|
||||
return v[i];
|
||||
}
|
||||
|
||||
unsigned int v[3];
|
||||
};
|
||||
|
||||
struct b3Cell32
|
||||
{
|
||||
unsigned int v[32];
|
||||
};
|
||||
|
||||
// This class stores a discretized signed distance function (SDF)
|
||||
// generated by Discregrid.
|
||||
// Discregrid is available at https://github.com/InteractiveComputerGraphics/Discregrid
|
||||
// Inside Discregrid, there is a tool called GenerateSDF that can
|
||||
// generate an SDF of a triangle mesh stored in .obj file format.
|
||||
// You may call this tool from a command line.
|
||||
// For example, the following command will generate an SDF for a given .obj mesh.
|
||||
// GenerateSDF -r "32 32 32" -d "-5 -5 -5 5 5 5" teapot.obj
|
||||
// The parameters are:
|
||||
// 1. r - resolution
|
||||
// 2. d - domain (an AABB)
|
||||
// 3. input filename
|
||||
// You will need to set a reasonable large domain depending on the radius of
|
||||
// the vertices that can collide against the SDF because the SDF
|
||||
// can only return valid output values for points that are inside the domain.
|
||||
// Therefore, its a good idea to set the domain to the AABB containing the
|
||||
// associated object extended by twice the largest vertex radius that can collide against this SDF.
|
||||
// Generally, the greater the SDF resolution the more accurate is the result of the signed distance function.
|
||||
class b3SDF
|
||||
{
|
||||
public:
|
||||
// Construct this SDF
|
||||
b3SDF();
|
||||
|
||||
// Destruct this SDF
|
||||
~b3SDF();
|
||||
|
||||
// Read this SDF from a .cdf (binary) file given the filename.
|
||||
// Returns true if this SDF was loaded sucessfuly and false otherwise.
|
||||
bool Load(const char* filename);
|
||||
|
||||
// Return the domain (AABB) of this SDF.
|
||||
const b3AABB& GetDomain() const
|
||||
{
|
||||
return m_domain;
|
||||
}
|
||||
|
||||
// Evaluate the signed distance function for a point if the point is inside the domain of this SDF.
|
||||
// Optionally output the normal at the SDF boundary.
|
||||
// Return true if the output values are valid and false otherwise.
|
||||
bool Evaluate(const b3Vec3& point, double& distance, b3Vec3* normal = nullptr) const
|
||||
{
|
||||
return interpolate(0, distance, point, normal);
|
||||
}
|
||||
private:
|
||||
bool interpolate(unsigned int field_id, double& dist, b3Vec3 const& x, b3Vec3* gradient = nullptr) const;
|
||||
|
||||
b3MultiIndex singleToMultiIndex(unsigned int i) const;
|
||||
unsigned int multiToSingleIndex(b3MultiIndex const& ijk) const;
|
||||
|
||||
b3AABB subdomain(b3MultiIndex const& ijk) const;
|
||||
b3AABB subdomain(unsigned int l) const;
|
||||
|
||||
b3AABB m_domain;
|
||||
unsigned int m_resolution[3];
|
||||
b3Vec3 m_cell_size;
|
||||
b3Vec3 m_inv_cell_size;
|
||||
std::size_t m_n_cells;
|
||||
std::size_t m_n_fields;
|
||||
|
||||
struct b3SDFNodeArray
|
||||
{
|
||||
double& operator[](u32 i)
|
||||
{
|
||||
B3_ASSERT(i < count);
|
||||
return values[i];
|
||||
}
|
||||
|
||||
const double& operator[](u32 i) const
|
||||
{
|
||||
B3_ASSERT(i < count);
|
||||
return values[i];
|
||||
}
|
||||
|
||||
u32 count;
|
||||
double* values;
|
||||
};
|
||||
|
||||
struct b3SDFCellArray
|
||||
{
|
||||
b3Cell32& operator[](u32 i)
|
||||
{
|
||||
B3_ASSERT(i < count);
|
||||
return values[i];
|
||||
}
|
||||
|
||||
const b3Cell32& operator[](u32 i) const
|
||||
{
|
||||
B3_ASSERT(i < count);
|
||||
return values[i];
|
||||
}
|
||||
|
||||
u32 count;
|
||||
b3Cell32* values;
|
||||
};
|
||||
|
||||
struct b3SDFCellMapArray
|
||||
{
|
||||
unsigned int& operator[](u32 i)
|
||||
{
|
||||
B3_ASSERT(i < count);
|
||||
return values[i];
|
||||
}
|
||||
|
||||
const unsigned int& operator[](u32 i) const
|
||||
{
|
||||
B3_ASSERT(i < count);
|
||||
return values[i];
|
||||
}
|
||||
|
||||
u32 count;
|
||||
unsigned int* values;
|
||||
};
|
||||
|
||||
u32 m_nodeCount;
|
||||
b3SDFNodeArray* m_nodes;
|
||||
|
||||
u32 m_cellCount;
|
||||
b3SDFCellArray* m_cells;
|
||||
|
||||
u32 m_cellMapCount;
|
||||
b3SDFCellMapArray* m_cell_map;
|
||||
};
|
||||
|
||||
#endif
|
@@ -27,7 +27,7 @@ struct b3Sphere
|
||||
b3Sphere() { }
|
||||
|
||||
//
|
||||
b3Sphere(const b3Vec3& v, float32 r)
|
||||
b3Sphere(const b3Vec3& v, scalar r)
|
||||
{
|
||||
vertex = v;
|
||||
radius = r;
|
||||
@@ -37,7 +37,7 @@ struct b3Sphere
|
||||
~b3Sphere() { }
|
||||
|
||||
b3Vec3 vertex;
|
||||
float32 radius;
|
||||
scalar radius;
|
||||
|
||||
const b3Vec3& GetVertex(u32 index) const;
|
||||
u32 GetSupportVertex(const b3Vec3& direction) const;
|
||||
|
@@ -37,20 +37,20 @@ struct b3TriangleHull : public b3Hull
|
||||
|
||||
void Set(const b3Vec3& A, const b3Vec3& B, const b3Vec3& C)
|
||||
{
|
||||
centroid = (A + B + C) / 3.0f;
|
||||
centroid = (A + B + C) / scalar(3);
|
||||
|
||||
triangleVertices[0] = A;
|
||||
triangleVertices[1] = B;
|
||||
triangleVertices[2] = C;
|
||||
|
||||
// Each edge must be followed by its twin.
|
||||
triangleEdges[0] = b3MakeEdge(0, 1, 0, 2); // Face 0 - Edge 0
|
||||
triangleEdges[2] = b3MakeEdge(1, 3, 0, 4); // Face 0 - Edge 1
|
||||
triangleEdges[4] = b3MakeEdge(2, 5, 0, 0); // Face 0 - Edge 2
|
||||
triangleEdges[0] = b3MakeEdge(0, 1, 0, 4, 2); // Face 0 - Edge 0
|
||||
triangleEdges[2] = b3MakeEdge(1, 3, 0, 0, 4); // Face 0 - Edge 1
|
||||
triangleEdges[4] = b3MakeEdge(2, 5, 0, 2, 0); // Face 0 - Edge 2
|
||||
|
||||
triangleEdges[1] = b3MakeEdge(1, 0, 1, 3); // Face 1 - Edge 0
|
||||
triangleEdges[3] = b3MakeEdge(2, 2, 1, 5); // Face 1 - Edge 1
|
||||
triangleEdges[5] = b3MakeEdge(0, 4, 1, 1); // Face 1 - Edge 2
|
||||
triangleEdges[1] = b3MakeEdge(1, 0, 1, 3, 5); // Face 1 - Edge 0
|
||||
triangleEdges[3] = b3MakeEdge(2, 2, 1, 5, 1); // Face 1 - Edge 1
|
||||
triangleEdges[5] = b3MakeEdge(0, 4, 1, 1, 3); // Face 1 - Edge 2
|
||||
|
||||
triangleFaces[0].edge = 0;
|
||||
triangleFaces[1].edge = 1;
|
||||
|
71
include/bounce/collision/time_of_impact.h
Normal file
71
include/bounce/collision/time_of_impact.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2019 Irlan Robson https://irlanrobson.github.io
|
||||
*
|
||||
* 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 B3_TIME_OF_IMPACT_H
|
||||
#define B3_TIME_OF_IMPACT_H
|
||||
|
||||
#include <bounce/collision/gjk/gjk_proxy.h>
|
||||
#include <bounce/collision/shapes/aabb.h>
|
||||
#include <bounce/common/math/transform.h>
|
||||
|
||||
// Input parameters for b3TimeOfImpact
|
||||
struct b3TOIInput
|
||||
{
|
||||
b3GJKProxy proxyA;
|
||||
b3GJKProxy proxyB;
|
||||
b3Sweep sweepA;
|
||||
b3Sweep sweepB;
|
||||
scalar tMax; // sweep interval in [0, 1]
|
||||
};
|
||||
|
||||
// Output parameters of b3TimeOfImpact
|
||||
struct b3TOIOutput
|
||||
{
|
||||
enum State
|
||||
{
|
||||
e_unknown,
|
||||
e_failed,
|
||||
e_overlapped,
|
||||
e_touching,
|
||||
e_separated
|
||||
};
|
||||
|
||||
State state;
|
||||
scalar t;
|
||||
u32 iterations;
|
||||
};
|
||||
|
||||
// Compute the time of impact between two shapes.
|
||||
// This is represented as a fraction between [0, tMax].
|
||||
// Use b3GJK to compute the contact point and normal at the time of impact.
|
||||
b3TOIOutput b3TimeOfImpact(const b3TOIInput& input);
|
||||
|
||||
// Compute the time of impact between two shapes.
|
||||
// This is represented as a fraction between [0, 1].
|
||||
// You must supply the linear displacements of each shape.
|
||||
// Use b3GJK to compute the contact point and normal at the time of impact.
|
||||
b3TOIOutput b3TimeOfImpact(const b3Transform& xf1, const b3GJKProxy& proxy1, const b3Vec3& d1,
|
||||
const b3Transform& xf2, const b3GJKProxy& proxy2, const b3Vec3& d2,
|
||||
u32 maxIterations = 20);
|
||||
|
||||
// Compute the time of impact between two AABBs.
|
||||
// This is represented as a fraction between [0, 1].
|
||||
// You must supply the linear displacements of each AABB center.
|
||||
b3TOIOutput b3TimeOfImpact(const b3AABB& aabb1, const b3Vec3& d1, const b3AABB& aabb2, const b3Vec3& d2);
|
||||
|
||||
#endif
|
@@ -20,29 +20,29 @@
|
||||
#define B3_DYNAMIC_TREE_H
|
||||
|
||||
#include <bounce/common/template/stack.h>
|
||||
#include <bounce/collision/shapes/aabb3.h>
|
||||
#include <bounce/collision/shapes/aabb.h>
|
||||
#include <bounce/collision/collision.h>
|
||||
|
||||
#define B3_NULL_NODE_D (0xFFFFFFFF)
|
||||
|
||||
// AABB tree for dynamic AABBs.
|
||||
class b3DynamicTree
|
||||
class b3DynamicTree
|
||||
{
|
||||
public :
|
||||
public:
|
||||
b3DynamicTree();
|
||||
~b3DynamicTree();
|
||||
|
||||
// Insert a node into the tree and return its ID.
|
||||
u32 InsertNode(const b3AABB3& aabb, void* userData);
|
||||
|
||||
u32 InsertNode(const b3AABB& aabb, void* userData);
|
||||
|
||||
// Remove a node from the tree.
|
||||
void RemoveNode(u32 proxyId);
|
||||
|
||||
// Update a node AABB.
|
||||
void UpdateNode(u32 proxyId, const b3AABB3& aabb);
|
||||
void UpdateNode(u32 proxyId, const b3AABB& aabb);
|
||||
|
||||
// Get the (fat) AABB of a given proxy.
|
||||
const b3AABB3& GetAABB(u32 proxyId) const;
|
||||
const b3AABB& GetAABB(u32 proxyId) const;
|
||||
|
||||
// Get the data associated with a given proxy.
|
||||
void* GetUserData(u32 proxyId) const;
|
||||
@@ -53,8 +53,8 @@ public :
|
||||
// Keep reporting the client callback the AABBs that are overlapping with
|
||||
// the given AABB. The client callback must return true if the query
|
||||
// must be stopped or false to continue looking for more overlapping pairs.
|
||||
template<class T>
|
||||
void QueryAABB(T* callback, const b3AABB3& aabb) const;
|
||||
template<class T>
|
||||
void QueryAABB(T* callback, const b3AABB& aabb) const;
|
||||
|
||||
// Keep reporting the client callback all AABBs that are overlapping with
|
||||
// the given ray. The client callback must return the new intersection fraction.
|
||||
@@ -67,23 +67,23 @@ public :
|
||||
|
||||
// Draw this tree.
|
||||
void Draw() const;
|
||||
private :
|
||||
struct b3Node
|
||||
private:
|
||||
struct b3Node
|
||||
{
|
||||
// Is this node a leaf?
|
||||
bool IsLeaf() const
|
||||
bool IsLeaf() const
|
||||
{
|
||||
//A node is a leaf if child 2 == B3_NULL_NODE_D or height == 0.
|
||||
return child1 == B3_NULL_NODE_D;
|
||||
}
|
||||
|
||||
// The fattened node AABB.
|
||||
b3AABB3 aabb;
|
||||
b3AABB aabb;
|
||||
|
||||
// The associated user data.
|
||||
void* userData;
|
||||
|
||||
union
|
||||
union
|
||||
{
|
||||
u32 parent;
|
||||
u32 next;
|
||||
@@ -96,18 +96,18 @@ private :
|
||||
// leaf if 0, free node if -1
|
||||
i32 height;
|
||||
};
|
||||
|
||||
|
||||
// Insert a node into the tree.
|
||||
void InsertLeaf(u32 node);
|
||||
|
||||
|
||||
// Remove a node from the tree.
|
||||
void RemoveLeaf(u32 node);
|
||||
|
||||
// Rebuild the hierarchy starting from the given node.
|
||||
void WalkBackNodeAndCombineVolumes(u32 node);
|
||||
|
||||
// Find the best node that can be merged with a given AABB.
|
||||
u32 FindBest(const b3AABB3& aabb) const;
|
||||
void Refit(u32 node);
|
||||
|
||||
// Pick the best node that can be merged with a given AABB.
|
||||
u32 PickBest(const b3AABB& aabb) const;
|
||||
|
||||
// Peel a node from the free list and insert into the node array.
|
||||
// Allocate a new node if necessary. The function returns the new node index.
|
||||
@@ -129,7 +129,7 @@ private :
|
||||
u32 m_freeList;
|
||||
};
|
||||
|
||||
inline const b3AABB3& b3DynamicTree::GetAABB(u32 proxyId) const
|
||||
inline const b3AABB& b3DynamicTree::GetAABB(u32 proxyId) const
|
||||
{
|
||||
B3_ASSERT(proxyId != B3_NULL_NODE_D && proxyId < m_nodeCapacity);
|
||||
return m_nodes[proxyId].aabb;
|
||||
@@ -149,12 +149,12 @@ inline bool b3DynamicTree::TestOverlap(u32 proxy1, u32 proxy2) const
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline void b3DynamicTree::QueryAABB(T* callback, const b3AABB3& aabb) const
|
||||
inline void b3DynamicTree::QueryAABB(T* callback, const b3AABB& aabb) const
|
||||
{
|
||||
b3Stack<u32, 256> stack;
|
||||
stack.Push(m_root);
|
||||
|
||||
while (stack.IsEmpty() == false)
|
||||
while (stack.IsEmpty() == false)
|
||||
{
|
||||
u32 nodeIndex = stack.Top();
|
||||
stack.Pop();
|
||||
@@ -166,16 +166,16 @@ inline void b3DynamicTree::QueryAABB(T* callback, const b3AABB3& aabb) const
|
||||
|
||||
const b3Node* node = m_nodes + nodeIndex;
|
||||
|
||||
if (b3TestOverlap(node->aabb, aabb) == true)
|
||||
if (b3TestOverlap(node->aabb, aabb) == true)
|
||||
{
|
||||
if (node->IsLeaf() == true)
|
||||
if (node->IsLeaf() == true)
|
||||
{
|
||||
if (callback->Report(nodeIndex) == false)
|
||||
if (callback->Report(nodeIndex) == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
stack.Push(node->child1);
|
||||
stack.Push(node->child2);
|
||||
@@ -185,55 +185,142 @@ inline void b3DynamicTree::QueryAABB(T* callback, const b3AABB3& aabb) const
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline void b3DynamicTree::RayCast(T* callback, const b3RayCastInput& input) const
|
||||
inline void b3DynamicTree::RayCast(T* callback, const b3RayCastInput& input) const
|
||||
{
|
||||
b3Vec3 p1 = input.p1;
|
||||
b3Vec3 p2 = input.p2;
|
||||
b3Vec3 d = p2 - p1;
|
||||
float32 maxFraction = input.maxFraction;
|
||||
b3Vec3 r = p2 - p1;
|
||||
B3_ASSERT(b3LengthSquared(r) > scalar(0));
|
||||
r.Normalize();
|
||||
|
||||
scalar maxFraction = input.maxFraction;
|
||||
|
||||
// Build an AABB for the segment.
|
||||
b3Vec3 q2;
|
||||
b3AABB segmentAABB;
|
||||
{
|
||||
q2 = p1 + maxFraction * (p2 - p1);
|
||||
segmentAABB.lowerBound = b3Min(p1, q2);
|
||||
segmentAABB.upperBound = b3Max(p1, q2);
|
||||
}
|
||||
|
||||
// Ensure non-degenerate segment.
|
||||
B3_ASSERT(b3Dot(d, d) > B3_EPSILON * B3_EPSILON);
|
||||
b3Vec3 e1 = b3Vec3_x;
|
||||
b3Vec3 e2 = b3Vec3_y;
|
||||
b3Vec3 e3 = b3Vec3_z;
|
||||
|
||||
b3Stack<u32, 256> stack;
|
||||
stack.Push(m_root);
|
||||
|
||||
while (stack.IsEmpty() == false)
|
||||
while (stack.IsEmpty() == false)
|
||||
{
|
||||
u32 nodeIndex = stack.Top();
|
||||
|
||||
|
||||
stack.Pop();
|
||||
|
||||
if (nodeIndex == B3_NULL_NODE_D)
|
||||
if (nodeIndex == B3_NULL_NODE_D)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const b3Node* node = m_nodes + nodeIndex;
|
||||
|
||||
float32 minFraction;
|
||||
if (node->aabb.TestRay(minFraction, p1, p2, maxFraction) == true)
|
||||
if (b3TestOverlap(segmentAABB, node->aabb) == false)
|
||||
{
|
||||
if (node->IsLeaf() == true)
|
||||
{
|
||||
b3RayCastInput subInput;
|
||||
subInput.p1 = input.p1;
|
||||
subInput.p2 = input.p2;
|
||||
subInput.maxFraction = maxFraction;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Separating axis for segment (Gino, p80).
|
||||
b3Vec3 c = node->aabb.GetCenter();
|
||||
b3Vec3 h = node->aabb.GetExtents();
|
||||
|
||||
float32 newFraction = callback->Report(subInput, nodeIndex);
|
||||
b3Vec3 s = p1 - c;
|
||||
b3Vec3 t = q2 - c;
|
||||
|
||||
if (newFraction == 0.0f)
|
||||
{
|
||||
// The client has stopped the query.
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
// |sigma + tau| > |sigma - tau| + 2 * eta
|
||||
scalar sigma_1 = s.x;
|
||||
scalar tau_1 = t.x;
|
||||
scalar eta_1 = h.x;
|
||||
|
||||
scalar s1 = b3Abs(sigma_1 + tau_1) - (b3Abs(sigma_1 - tau_1) + scalar(2) * eta_1);
|
||||
if (s1 > scalar(0))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
scalar sigma_2 = s.y;
|
||||
scalar tau_2 = t.y;
|
||||
scalar eta_2 = h.y;
|
||||
|
||||
scalar s2 = b3Abs(sigma_2 + tau_2) - (b3Abs(sigma_2 - tau_2) + scalar(2) * eta_2);
|
||||
if (s2 > scalar(0))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
scalar sigma_3 = s.z;
|
||||
scalar tau_3 = t.z;
|
||||
scalar eta_3 = h.z;
|
||||
|
||||
scalar s3 = b3Abs(sigma_3 + tau_3) - (b3Abs(sigma_3 - tau_3) + scalar(2) * eta_3);
|
||||
if (s3 > scalar(0))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// v = cross(ei, r)
|
||||
// |dot(v, s)| > dot(|v|, h)
|
||||
b3Vec3 v1 = b3Cross(e1, r);
|
||||
b3Vec3 abs_v1 = b3Abs(v1);
|
||||
scalar s4 = b3Abs(b3Dot(v1, s)) - b3Dot(abs_v1, h);
|
||||
if (s4 > scalar(0))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
b3Vec3 v2 = b3Cross(e2, r);
|
||||
b3Vec3 abs_v2 = b3Abs(v2);
|
||||
scalar s5 = b3Abs(b3Dot(v2, s)) - b3Dot(abs_v2, h);
|
||||
if (s5 > scalar(0))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
b3Vec3 v3 = b3Cross(e3, r);
|
||||
b3Vec3 abs_v3 = b3Abs(v3);
|
||||
scalar s6 = b3Abs(b3Dot(v3, s)) - b3Dot(abs_v3, h);
|
||||
if (s6 > scalar(0))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (node->IsLeaf() == true)
|
||||
{
|
||||
b3RayCastInput subInput;
|
||||
subInput.p1 = input.p1;
|
||||
subInput.p2 = input.p2;
|
||||
subInput.maxFraction = maxFraction;
|
||||
|
||||
scalar newMaxFraction = callback->Report(subInput, nodeIndex);
|
||||
|
||||
if (newMaxFraction == scalar(0))
|
||||
{
|
||||
stack.Push(node->child1);
|
||||
stack.Push(node->child2);
|
||||
// The client has stopped the query.
|
||||
return;
|
||||
}
|
||||
|
||||
if (newMaxFraction > scalar(0))
|
||||
{
|
||||
// Update the segment AABB.
|
||||
maxFraction = newMaxFraction;
|
||||
q2 = p1 + maxFraction * (p2 - p1);
|
||||
segmentAABB.lowerBound = b3Min(p1, q2);
|
||||
segmentAABB.upperBound = b3Max(p1, q2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
stack.Push(node->child1);
|
||||
stack.Push(node->child2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -20,7 +20,7 @@
|
||||
#define B3_STATIC_TREE_H
|
||||
|
||||
#include <bounce/common/template/stack.h>
|
||||
#include <bounce/collision/shapes/aabb3.h>
|
||||
#include <bounce/collision/shapes/aabb.h>
|
||||
#include <bounce/collision/collision.h>
|
||||
|
||||
#define B3_NULL_NODE_S (0xFFFFFFFF)
|
||||
@@ -33,10 +33,10 @@ public:
|
||||
~b3StaticTree();
|
||||
|
||||
// Build this tree from a list of AABBs.
|
||||
void Build(const b3AABB3* aabbs, u32 count);
|
||||
void Build(const b3AABB* aabbs, u32 count);
|
||||
|
||||
// Get the AABB of a given proxy.
|
||||
const b3AABB3& GetAABB(u32 proxyId) const;
|
||||
const b3AABB& GetAABB(u32 proxyId) const;
|
||||
|
||||
// Get the user data associated with a given proxy.
|
||||
u32 GetUserData(u32 proxyId) const;
|
||||
@@ -45,7 +45,7 @@ public:
|
||||
// the given AABB. The client callback must return true if the query
|
||||
// must be stopped or false to continue looking for more overlapping pairs.
|
||||
template<class T>
|
||||
void QueryAABB(T* callback, const b3AABB3& aabb) const;
|
||||
void QueryAABB(T* callback, const b3AABB& aabb) const;
|
||||
|
||||
// Report the client callback all AABBs that are overlapping with
|
||||
// the given ray. The client callback must return the new intersection fraction
|
||||
@@ -56,12 +56,13 @@ public:
|
||||
// Draw this tree.
|
||||
void Draw() const;
|
||||
|
||||
// Get the size in bytes of this tree.
|
||||
u32 GetSize() const;
|
||||
private :
|
||||
// A node in a static tree.
|
||||
struct b3Node
|
||||
{
|
||||
b3AABB3 aabb;
|
||||
b3AABB aabb;
|
||||
u32 child1;
|
||||
union
|
||||
{
|
||||
@@ -76,15 +77,18 @@ private :
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
void Build(const b3AABB3* set, b3Node* node, u32* indices, u32 count, u32 minObjectsPerLeaf, u32 nodeCapacity, u32& leafCount, u32& internalCount);
|
||||
// Build this tree recursively.
|
||||
void RecurseBuild(const b3AABB* set, b3Node* node, u32* indices, u32 count, u32 minObjectsPerLeaf, u32 nodeCapacity, u32& leafCount, u32& internalCount);
|
||||
|
||||
// The root of this tree.
|
||||
u32 m_root;
|
||||
|
||||
// The nodes of this tree stored in an array.
|
||||
u32 m_nodeCount;
|
||||
b3Node* m_nodes;
|
||||
};
|
||||
|
||||
inline const b3AABB3& b3StaticTree::GetAABB(u32 proxyId) const
|
||||
inline const b3AABB& b3StaticTree::GetAABB(u32 proxyId) const
|
||||
{
|
||||
B3_ASSERT(proxyId < m_nodeCount);
|
||||
return m_nodes[proxyId].aabb;
|
||||
@@ -98,17 +102,15 @@ inline u32 b3StaticTree::GetUserData(u32 proxyId) const
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline void b3StaticTree::QueryAABB(T* callback, const b3AABB3& aabb) const
|
||||
inline void b3StaticTree::QueryAABB(T* callback, const b3AABB& aabb) const
|
||||
{
|
||||
if (m_nodeCount == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
u32 root = 0;
|
||||
|
||||
b3Stack<u32, 256> stack;
|
||||
stack.Push(root);
|
||||
stack.Push(m_root);
|
||||
|
||||
while (stack.IsEmpty() == false)
|
||||
{
|
||||
@@ -151,20 +153,32 @@ inline void b3StaticTree::RayCast(T* callback, const b3RayCastInput& input) cons
|
||||
|
||||
b3Vec3 p1 = input.p1;
|
||||
b3Vec3 p2 = input.p2;
|
||||
b3Vec3 d = p2 - p1;
|
||||
float32 maxFraction = input.maxFraction;
|
||||
b3Vec3 r = p2 - p1;
|
||||
B3_ASSERT(b3LengthSquared(r) > scalar(0));
|
||||
r.Normalize();
|
||||
|
||||
// Ensure non-degenerate segment.
|
||||
B3_ASSERT(b3Dot(d, d) > B3_EPSILON * B3_EPSILON);
|
||||
scalar maxFraction = input.maxFraction;
|
||||
|
||||
u32 root = 0;
|
||||
// Build an AABB for the segment.
|
||||
b3Vec3 q2;
|
||||
b3AABB segmentAABB;
|
||||
{
|
||||
q2 = p1 + maxFraction * (p2 - p1);
|
||||
segmentAABB.lowerBound = b3Min(p1, q2);
|
||||
segmentAABB.upperBound = b3Max(p1, q2);
|
||||
}
|
||||
|
||||
b3Vec3 e1 = b3Vec3_x;
|
||||
b3Vec3 e2 = b3Vec3_y;
|
||||
b3Vec3 e3 = b3Vec3_z;
|
||||
|
||||
b3Stack<u32, 256> stack;
|
||||
stack.Push(root);
|
||||
|
||||
while (stack.IsEmpty() == false)
|
||||
stack.Push(m_root);
|
||||
|
||||
while (stack.IsEmpty() == false)
|
||||
{
|
||||
u32 nodeIndex = stack.Top();
|
||||
u32 nodeIndex = stack.Top();
|
||||
|
||||
stack.Pop();
|
||||
|
||||
if (nodeIndex == B3_NULL_NODE_S)
|
||||
@@ -174,29 +188,103 @@ inline void b3StaticTree::RayCast(T* callback, const b3RayCastInput& input) cons
|
||||
|
||||
const b3Node* node = m_nodes + nodeIndex;
|
||||
|
||||
float32 minFraction;
|
||||
if (node->aabb.TestRay(minFraction, p1, p2, maxFraction) == true)
|
||||
if (b3TestOverlap(segmentAABB, node->aabb) == false)
|
||||
{
|
||||
if (node->IsLeaf() == true)
|
||||
{
|
||||
b3RayCastInput subInput;
|
||||
subInput.p1 = input.p1;
|
||||
subInput.p2 = input.p2;
|
||||
subInput.maxFraction = maxFraction;
|
||||
continue;
|
||||
}
|
||||
|
||||
float32 newFraction = callback->Report(subInput, nodeIndex);
|
||||
// Separating axis for segment (Gino, p80).
|
||||
b3Vec3 c = node->aabb.GetCenter();
|
||||
b3Vec3 h = node->aabb.GetExtents();
|
||||
|
||||
if (newFraction == 0.0f)
|
||||
{
|
||||
// The client has stopped the query.
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
b3Vec3 s = p1 - c;
|
||||
b3Vec3 t = q2 - c;
|
||||
|
||||
// |sigma + tau| > |sigma - tau| + 2 * eta
|
||||
scalar sigma_1 = s.x;
|
||||
scalar tau_1 = t.x;
|
||||
scalar eta_1 = h.x;
|
||||
|
||||
scalar s1 = b3Abs(sigma_1 + tau_1) - (b3Abs(sigma_1 - tau_1) + scalar(2) * eta_1);
|
||||
if (s1 > scalar(0))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
scalar sigma_2 = s.y;
|
||||
scalar tau_2 = t.y;
|
||||
scalar eta_2 = h.y;
|
||||
|
||||
scalar s2 = b3Abs(sigma_2 + tau_2) - (b3Abs(sigma_2 - tau_2) + scalar(2) * eta_2);
|
||||
if (s2 > scalar(0))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
scalar sigma_3 = s.z;
|
||||
scalar tau_3 = t.z;
|
||||
scalar eta_3 = h.z;
|
||||
|
||||
scalar s3 = b3Abs(sigma_3 + tau_3) - (b3Abs(sigma_3 - tau_3) + scalar(2) * eta_3);
|
||||
if (s3 > scalar(0))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// v = cross(ei, r)
|
||||
// |dot(v, s)| > dot(|v|, h)
|
||||
b3Vec3 v1 = b3Cross(e1, r);
|
||||
b3Vec3 abs_v1 = b3Abs(v1);
|
||||
scalar s4 = b3Abs(b3Dot(v1, s)) - b3Dot(abs_v1, h);
|
||||
if (s4 > scalar(0))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
b3Vec3 v2 = b3Cross(e2, r);
|
||||
b3Vec3 abs_v2 = b3Abs(v2);
|
||||
scalar s5 = b3Abs(b3Dot(v2, s)) - b3Dot(abs_v2, h);
|
||||
if (s5 > scalar(0))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
b3Vec3 v3 = b3Cross(e3, r);
|
||||
b3Vec3 abs_v3 = b3Abs(v3);
|
||||
scalar s6 = b3Abs(b3Dot(v3, s)) - b3Dot(abs_v3, h);
|
||||
if (s6 > scalar(0))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (node->IsLeaf() == true)
|
||||
{
|
||||
b3RayCastInput subInput;
|
||||
subInput.p1 = input.p1;
|
||||
subInput.p2 = input.p2;
|
||||
subInput.maxFraction = maxFraction;
|
||||
|
||||
scalar newMaxFraction = callback->Report(subInput, nodeIndex);
|
||||
|
||||
if (newMaxFraction == scalar(0))
|
||||
{
|
||||
stack.Push(node->child1);
|
||||
stack.Push(node->child2);
|
||||
// The client has stopped the query.
|
||||
return;
|
||||
}
|
||||
|
||||
if (newMaxFraction > scalar(0))
|
||||
{
|
||||
// Update the segment AABB.
|
||||
maxFraction = newMaxFraction;
|
||||
q2 = p1 + maxFraction * (p2 - p1);
|
||||
segmentAABB.lowerBound = b3Min(p1, q2);
|
||||
segmentAABB.upperBound = b3Max(p1, q2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
stack.Push(node->child1);
|
||||
stack.Push(node->child2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user