Added Pierre Terdiman's 'internal object' optimization to improve performance for separating axis tests.
Make the winding consistent in btConvexHullComputer (and related fixes in btPolyhedralConvexShape), thanks to Ole! Some fixes in the btPolyhedralContactClipping implementation (never report a penetration deeper than GJK/EPA found, to avoid issues due to its approximate contact normal directions) Properly visualize btPolyhedralConvexHullShape that have a btConvexPolyhedron (by calling initializePolyhedralFeatures() method)
This commit is contained in:
@@ -208,4 +208,48 @@ const char* btConvexHullShape::serialize(void* dataBuffer, btSerializer* seriali
|
||||
return "btConvexHullShapeData";
|
||||
}
|
||||
|
||||
void btConvexHullShape::project(const btTransform& trans, const btVector3& dir, float& min, float& max) const
|
||||
{
|
||||
#if 1
|
||||
min = FLT_MAX;
|
||||
max = -FLT_MAX;
|
||||
btVector3 witnesPtMin;
|
||||
btVector3 witnesPtMax;
|
||||
|
||||
int numVerts = m_unscaledPoints.size();
|
||||
for(int i=0;i<numVerts;i++)
|
||||
{
|
||||
btVector3 vtx = m_unscaledPoints[i] * m_localScaling;
|
||||
btVector3 pt = trans * vtx;
|
||||
float dp = pt.dot(dir);
|
||||
if(dp < min)
|
||||
{
|
||||
min = dp;
|
||||
witnesPtMin = pt;
|
||||
}
|
||||
if(dp > max)
|
||||
{
|
||||
max = dp;
|
||||
witnesPtMax=pt;
|
||||
}
|
||||
}
|
||||
#else
|
||||
btVector3 localAxis = dir*trans.getBasis();
|
||||
btVector3 vtx1 = trans(localGetSupportingVertex(localAxis));
|
||||
btVector3 vtx2 = trans(localGetSupportingVertex(-localAxis));
|
||||
|
||||
min = vtx1.dot(dir);
|
||||
max = vtx2.dot(dir);
|
||||
#endif
|
||||
|
||||
if(min>max)
|
||||
{
|
||||
float tmp = min;
|
||||
min = max;
|
||||
max = tmp;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -73,6 +73,8 @@ public:
|
||||
virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
|
||||
|
||||
|
||||
virtual void project(const btTransform& trans, const btVector3& dir, float& min, float& max) const;
|
||||
|
||||
|
||||
//debugging
|
||||
virtual const char* getName()const {return "Convex";}
|
||||
|
||||
@@ -17,7 +17,7 @@ subject to the following restrictions:
|
||||
///This file was written by Erwin Coumans
|
||||
///Separating axis rest based on work from Pierre Terdiman, see
|
||||
///And contact clipping based on work from Simon Hobbs
|
||||
|
||||
#define TEST_INTERNAL_OBJECTS 1
|
||||
|
||||
#include "btConvexPolyhedron.h"
|
||||
#include "LinearMath/btHashMap.h"
|
||||
@@ -72,11 +72,39 @@ struct btInternalEdge
|
||||
|
||||
//
|
||||
|
||||
#ifdef TEST_INTERNAL_OBJECTS
|
||||
bool btConvexPolyhedron::testContainment() const
|
||||
{
|
||||
for(int p=0;p<8;p++)
|
||||
{
|
||||
btVector3 LocalPt;
|
||||
if(p==0) LocalPt = m_localCenter + btVector3(m_extents[0], m_extents[1], m_extents[2]);
|
||||
else if(p==1) LocalPt = m_localCenter + btVector3(m_extents[0], m_extents[1], -m_extents[2]);
|
||||
else if(p==2) LocalPt = m_localCenter + btVector3(m_extents[0], -m_extents[1], m_extents[2]);
|
||||
else if(p==3) LocalPt = m_localCenter + btVector3(m_extents[0], -m_extents[1], -m_extents[2]);
|
||||
else if(p==4) LocalPt = m_localCenter + btVector3(-m_extents[0], m_extents[1], m_extents[2]);
|
||||
else if(p==5) LocalPt = m_localCenter + btVector3(-m_extents[0], m_extents[1], -m_extents[2]);
|
||||
else if(p==6) LocalPt = m_localCenter + btVector3(-m_extents[0], -m_extents[1], m_extents[2]);
|
||||
else if(p==7) LocalPt = m_localCenter + btVector3(-m_extents[0], -m_extents[1], -m_extents[2]);
|
||||
|
||||
for(int i=0;i<m_faces.size();i++)
|
||||
{
|
||||
const btVector3 Normal(m_faces[i].m_plane[0], m_faces[i].m_plane[1], m_faces[i].m_plane[2]);
|
||||
const btScalar d = LocalPt.dot(Normal) + m_faces[i].m_plane[3];
|
||||
if(d>0.0f)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
void btConvexPolyhedron::initialize()
|
||||
{
|
||||
|
||||
btHashMap<btInternalVertexPair,btInternalEdge> edges;
|
||||
|
||||
float TotalArea = 0.0f;
|
||||
btScalar TotalArea = 0.0f;
|
||||
|
||||
m_localCenter.setValue(0, 0, 0);
|
||||
for(int i=0;i<m_faces.size();i++)
|
||||
@@ -153,7 +181,7 @@ void btConvexPolyhedron::initialize()
|
||||
int k = (j+1)%numVertices;
|
||||
const btVector3& p1 = m_vertices[m_faces[i].m_indices[j]];
|
||||
const btVector3& p2 = m_vertices[m_faces[i].m_indices[k]];
|
||||
float Area = ((p0 - p1).cross(p0 - p2)).length() * 0.5f;
|
||||
btScalar Area = ((p0 - p1).cross(p0 - p2)).length() * 0.5f;
|
||||
btVector3 Center = (p0+p1+p2)/3.0f;
|
||||
m_localCenter += Area * Center;
|
||||
TotalArea += Area;
|
||||
@@ -161,10 +189,92 @@ void btConvexPolyhedron::initialize()
|
||||
}
|
||||
m_localCenter /= TotalArea;
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef TEST_INTERNAL_OBJECTS
|
||||
if(1)
|
||||
{
|
||||
m_radius = FLT_MAX;
|
||||
for(int i=0;i<m_faces.size();i++)
|
||||
{
|
||||
const btVector3 Normal(m_faces[i].m_plane[0], m_faces[i].m_plane[1], m_faces[i].m_plane[2]);
|
||||
const btScalar dist = btFabs(m_localCenter.dot(Normal) + m_faces[i].m_plane[3]);
|
||||
if(dist<m_radius)
|
||||
m_radius = dist;
|
||||
}
|
||||
|
||||
|
||||
btScalar MinX = FLT_MAX;
|
||||
btScalar MinY = FLT_MAX;
|
||||
btScalar MinZ = FLT_MAX;
|
||||
btScalar MaxX = -FLT_MAX;
|
||||
btScalar MaxY = -FLT_MAX;
|
||||
btScalar MaxZ = -FLT_MAX;
|
||||
for(int i=0; i<m_vertices.size(); i++)
|
||||
{
|
||||
const btVector3& pt = m_vertices[i];
|
||||
if(pt.x()<MinX) MinX = pt.x();
|
||||
if(pt.x()>MaxX) MaxX = pt.x();
|
||||
if(pt.y()<MinY) MinY = pt.y();
|
||||
if(pt.y()>MaxY) MaxY = pt.y();
|
||||
if(pt.z()<MinZ) MinZ = pt.z();
|
||||
if(pt.z()>MaxZ) MaxZ = pt.z();
|
||||
}
|
||||
mC.setValue(MaxX+MinX, MaxY+MinY, MaxZ+MinZ);
|
||||
mE.setValue(MaxX-MinX, MaxY-MinY, MaxZ-MinZ);
|
||||
|
||||
|
||||
|
||||
// const btScalar r = m_radius / sqrtf(2.0f);
|
||||
const btScalar r = m_radius / sqrtf(3.0f);
|
||||
const int LargestExtent = mE.maxAxis();
|
||||
const btScalar Step = (mE[LargestExtent]*0.5f - r)/1024.0f;
|
||||
m_extents[0] = m_extents[1] = m_extents[2] = r;
|
||||
m_extents[LargestExtent] = mE[LargestExtent]*0.5f;
|
||||
bool FoundBox = false;
|
||||
for(int j=0;j<1024;j++)
|
||||
{
|
||||
if(testContainment())
|
||||
{
|
||||
FoundBox = true;
|
||||
break;
|
||||
}
|
||||
|
||||
m_extents[LargestExtent] -= Step;
|
||||
}
|
||||
if(!FoundBox)
|
||||
{
|
||||
m_extents[0] = m_extents[1] = m_extents[2] = r;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Refine the box
|
||||
const btScalar Step = (m_radius - r)/1024.0f;
|
||||
const int e0 = (1<<LargestExtent) & 3;
|
||||
const int e1 = (1<<e0) & 3;
|
||||
|
||||
for(int j=0;j<1024;j++)
|
||||
{
|
||||
const btScalar Saved0 = m_extents[e0];
|
||||
const btScalar Saved1 = m_extents[e1];
|
||||
m_extents[e0] += Step;
|
||||
m_extents[e1] += Step;
|
||||
|
||||
if(!testContainment())
|
||||
{
|
||||
m_extents[e0] = Saved0;
|
||||
m_extents[e1] = Saved1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void btConvexPolyhedron::project(const btTransform& trans, const btVector3& dir, float& min, float& max) const
|
||||
void btConvexPolyhedron::project(const btTransform& trans, const btVector3& dir, btScalar& min, btScalar& max) const
|
||||
{
|
||||
min = FLT_MAX;
|
||||
max = -FLT_MAX;
|
||||
@@ -172,13 +282,13 @@ void btConvexPolyhedron::project(const btTransform& trans, const btVector3& dir,
|
||||
for(int i=0;i<numVerts;i++)
|
||||
{
|
||||
btVector3 pt = trans * m_vertices[i];
|
||||
float dp = pt.dot(dir);
|
||||
btScalar dp = pt.dot(dir);
|
||||
if(dp < min) min = dp;
|
||||
if(dp > max) max = dp;
|
||||
}
|
||||
if(min>max)
|
||||
{
|
||||
float tmp = min;
|
||||
btScalar tmp = min;
|
||||
min = max;
|
||||
max = tmp;
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ struct btFace
|
||||
{
|
||||
btAlignedObjectArray<int> m_indices;
|
||||
btAlignedObjectArray<int> m_connectedFaces;
|
||||
float m_plane[4];
|
||||
btScalar m_plane[4];
|
||||
};
|
||||
|
||||
|
||||
@@ -41,11 +41,17 @@ class btConvexPolyhedron
|
||||
btAlignedObjectArray<btVector3> m_vertices;
|
||||
btAlignedObjectArray<btFace> m_faces;
|
||||
btAlignedObjectArray<btVector3> m_uniqueEdges;
|
||||
|
||||
btVector3 m_localCenter;
|
||||
btVector3 m_extents;
|
||||
btScalar m_radius;
|
||||
btVector3 mC;
|
||||
btVector3 mE;
|
||||
|
||||
void initialize();
|
||||
bool testContainment() const;
|
||||
|
||||
void project(const btTransform& trans, const btVector3& dir, float& min, float& max) const;
|
||||
void project(const btTransform& trans, const btVector3& dir, btScalar& min, btScalar& max) const;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -43,6 +43,23 @@ btConvexShape::~btConvexShape()
|
||||
}
|
||||
|
||||
|
||||
void btConvexShape::project(const btTransform& trans, const btVector3& dir, float& min, float& max) const
|
||||
{
|
||||
btVector3 localAxis = dir*trans.getBasis();
|
||||
btVector3 vtx1 = trans(localGetSupportingVertex(localAxis));
|
||||
btVector3 vtx2 = trans(localGetSupportingVertex(-localAxis));
|
||||
|
||||
min = vtx1.dot(dir);
|
||||
max = vtx2.dot(dir);
|
||||
|
||||
if(min>max)
|
||||
{
|
||||
float tmp = min;
|
||||
min = max;
|
||||
max = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static btVector3 convexHullSupport (const btVector3& localDirOrg, const btVector3* points, int numPoints, const btVector3& localScaling)
|
||||
{
|
||||
|
||||
@@ -52,6 +52,8 @@ public:
|
||||
btScalar getMarginNonVirtual () const;
|
||||
void getAabbNonVirtual (const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const;
|
||||
|
||||
virtual void project(const btTransform& trans, const btVector3& dir, float& min, float& max) const;
|
||||
|
||||
|
||||
//notice that the vectors should be unit length
|
||||
virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const= 0;
|
||||
|
||||
@@ -105,9 +105,9 @@ bool btPolyhedralConvexShape::initializePolyhedralFeatures()
|
||||
{
|
||||
faceNormals[i] = edges[0].cross(edges[1]);
|
||||
faceNormals[i].normalize();
|
||||
m_polyhedron->m_faces[i].m_plane[0] = -faceNormals[i].getX();
|
||||
m_polyhedron->m_faces[i].m_plane[1] = -faceNormals[i].getY();
|
||||
m_polyhedron->m_faces[i].m_plane[2] = -faceNormals[i].getZ();
|
||||
m_polyhedron->m_faces[i].m_plane[0] = faceNormals[i].getX();
|
||||
m_polyhedron->m_faces[i].m_plane[1] = faceNormals[i].getY();
|
||||
m_polyhedron->m_faces[i].m_plane[2] = faceNormals[i].getZ();
|
||||
m_polyhedron->m_faces[i].m_plane[3] = planeEq;
|
||||
|
||||
}
|
||||
@@ -125,35 +125,11 @@ bool btPolyhedralConvexShape::initializePolyhedralFeatures()
|
||||
planeEq=eq;
|
||||
}
|
||||
}
|
||||
m_polyhedron->m_faces[i].m_plane[3] = planeEq;
|
||||
m_polyhedron->m_faces[i].m_plane[3] = -planeEq;
|
||||
}
|
||||
|
||||
|
||||
if (m_polyhedron->m_faces.size() && conv.vertices.size())
|
||||
{
|
||||
|
||||
for (int f=0;f<m_polyhedron->m_faces.size();f++)
|
||||
{
|
||||
|
||||
btVector3 planeNormal(m_polyhedron->m_faces[f].m_plane[0],m_polyhedron->m_faces[f].m_plane[1],m_polyhedron->m_faces[f].m_plane[2]);
|
||||
btScalar planeEq = m_polyhedron->m_faces[f].m_plane[3];
|
||||
|
||||
btVector3 supVec = localGetSupportingVertex(-planeNormal);
|
||||
|
||||
if (supVec.dot(planeNormal)<planeEq)
|
||||
{
|
||||
m_polyhedron->m_faces[f].m_plane[0] *= -1;
|
||||
m_polyhedron->m_faces[f].m_plane[1] *= -1;
|
||||
m_polyhedron->m_faces[f].m_plane[2] *= -1;
|
||||
m_polyhedron->m_faces[f].m_plane[3] *= -1;
|
||||
int numVerts = m_polyhedron->m_faces[f].m_indices.size();
|
||||
for (int v=0;v<numVerts/2;v++)
|
||||
{
|
||||
btSwap(m_polyhedron->m_faces[f].m_indices[v],m_polyhedron->m_faces[f].m_indices[numVerts-1-v]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user