perform GrahamScanConvexHull2D around an arbitrary oriented 2D plane in 3D, to fix some convex hull face merging problems
add compound shape support to BulletXmlWorldImporter and fix some compile issue under Debian (hopefully) object picking change in the demos: create a ball-socket picking constraint when holding shift while mouse dragging, otherwise a fixed (6dof) constraint add assert in constraint solver, when both objects have their inertia tensor rows set to zero btPolyhedralContactClipping: add edge-edge contact point in findSeparatingAxis (similar to the default GJK case)
This commit is contained in:
@@ -201,13 +201,11 @@ const char* btConvexHullShape::serialize(void* dataBuffer, btSerializer* seriali
|
||||
return "btConvexHullShapeData";
|
||||
}
|
||||
|
||||
void btConvexHullShape::project(const btTransform& trans, const btVector3& dir, btScalar& min, btScalar& max) const
|
||||
void btConvexHullShape::project(const btTransform& trans, const btVector3& dir, btScalar& minProj, btScalar& maxProj, btVector3& witnesPtMin,btVector3& witnesPtMax) const
|
||||
{
|
||||
#if 1
|
||||
min = FLT_MAX;
|
||||
max = -FLT_MAX;
|
||||
btVector3 witnesPtMin;
|
||||
btVector3 witnesPtMax;
|
||||
minProj = FLT_MAX;
|
||||
maxProj = -FLT_MAX;
|
||||
|
||||
int numVerts = m_unscaledPoints.size();
|
||||
for(int i=0;i<numVerts;i++)
|
||||
@@ -215,31 +213,30 @@ void btConvexHullShape::project(const btTransform& trans, const btVector3& dir,
|
||||
btVector3 vtx = m_unscaledPoints[i] * m_localScaling;
|
||||
btVector3 pt = trans * vtx;
|
||||
btScalar dp = pt.dot(dir);
|
||||
if(dp < min)
|
||||
if(dp < minProj)
|
||||
{
|
||||
min = dp;
|
||||
minProj = dp;
|
||||
witnesPtMin = pt;
|
||||
}
|
||||
if(dp > max)
|
||||
if(dp > maxProj)
|
||||
{
|
||||
max = dp;
|
||||
maxProj = dp;
|
||||
witnesPtMax=pt;
|
||||
}
|
||||
}
|
||||
#else
|
||||
btVector3 localAxis = dir*trans.getBasis();
|
||||
btVector3 vtx1 = trans(localGetSupportingVertex(localAxis));
|
||||
btVector3 vtx2 = trans(localGetSupportingVertex(-localAxis));
|
||||
witnesPtMin = trans(localGetSupportingVertex(localAxis));
|
||||
witnesPtMax = trans(localGetSupportingVertex(-localAxis));
|
||||
|
||||
min = vtx1.dot(dir);
|
||||
max = vtx2.dot(dir);
|
||||
minProj = witnesPtMin.dot(dir);
|
||||
maxProj = witnesPtMax.dot(dir);
|
||||
#endif
|
||||
|
||||
if(min>max)
|
||||
if(minProj>maxProj)
|
||||
{
|
||||
btScalar tmp = min;
|
||||
min = max;
|
||||
max = tmp;
|
||||
btSwap(minProj,maxProj);
|
||||
btSwap(witnesPtMin,witnesPtMax);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ public:
|
||||
virtual void batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const;
|
||||
|
||||
|
||||
virtual void project(const btTransform& trans, const btVector3& dir, btScalar& min, btScalar& max) const;
|
||||
virtual void project(const btTransform& trans, const btVector3& dir, btScalar& minProj, btScalar& maxProj, btVector3& witnesPtMin,btVector3& witnesPtMax) const;
|
||||
|
||||
|
||||
//debugging
|
||||
|
||||
@@ -274,23 +274,29 @@ void btConvexPolyhedron::initialize()
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void btConvexPolyhedron::project(const btTransform& trans, const btVector3& dir, btScalar& min, btScalar& max) const
|
||||
void btConvexPolyhedron::project(const btTransform& trans, const btVector3& dir, btScalar& minProj, btScalar& maxProj, btVector3& witnesPtMin,btVector3& witnesPtMax) const
|
||||
{
|
||||
min = FLT_MAX;
|
||||
max = -FLT_MAX;
|
||||
minProj = FLT_MAX;
|
||||
maxProj = -FLT_MAX;
|
||||
int numVerts = m_vertices.size();
|
||||
for(int i=0;i<numVerts;i++)
|
||||
{
|
||||
btVector3 pt = trans * m_vertices[i];
|
||||
btScalar dp = pt.dot(dir);
|
||||
if(dp < min) min = dp;
|
||||
if(dp > max) max = dp;
|
||||
if(dp < minProj)
|
||||
{
|
||||
minProj = dp;
|
||||
witnesPtMin = pt;
|
||||
}
|
||||
if(dp > maxProj)
|
||||
{
|
||||
maxProj = dp;
|
||||
witnesPtMax = pt;
|
||||
}
|
||||
}
|
||||
if(min>max)
|
||||
if(minProj>maxProj)
|
||||
{
|
||||
btScalar tmp = min;
|
||||
min = max;
|
||||
max = tmp;
|
||||
btSwap(minProj,maxProj);
|
||||
btSwap(witnesPtMin,witnesPtMax);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ ATTRIBUTE_ALIGNED16(class) btConvexPolyhedron
|
||||
void initialize();
|
||||
bool testContainment() const;
|
||||
|
||||
void project(const btTransform& trans, const btVector3& dir, btScalar& min, btScalar& max) const;
|
||||
void project(const btTransform& trans, const btVector3& dir, btScalar& minProj, btScalar& maxProj, btVector3& witnesPtMin,btVector3& witnesPtMax) const;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ btPolyhedralConvexShape::~btPolyhedralConvexShape()
|
||||
}
|
||||
|
||||
|
||||
bool btPolyhedralConvexShape::initializePolyhedralFeatures()
|
||||
bool btPolyhedralConvexShape::initializePolyhedralFeatures(int shiftVerticesByMargin)
|
||||
{
|
||||
|
||||
if (m_polyhedron)
|
||||
@@ -56,31 +56,34 @@ bool btPolyhedralConvexShape::initializePolyhedralFeatures()
|
||||
btVector3& newVertex = orgVertices.expand();
|
||||
getVertex(i,newVertex);
|
||||
}
|
||||
|
||||
#if 0
|
||||
btAlignedObjectArray<btVector3> planeEquations;
|
||||
btGeometryUtil::getPlaneEquationsFromVertices(orgVertices,planeEquations);
|
||||
|
||||
btAlignedObjectArray<btVector3> shiftedPlaneEquations;
|
||||
for (int p=0;p<planeEquations.size();p++)
|
||||
|
||||
btConvexHullComputer conv;
|
||||
|
||||
if (shiftVerticesByMargin)
|
||||
{
|
||||
btVector3 plane = planeEquations[p];
|
||||
plane[3] -= getMargin();
|
||||
shiftedPlaneEquations.push_back(plane);
|
||||
btAlignedObjectArray<btVector3> planeEquations;
|
||||
btGeometryUtil::getPlaneEquationsFromVertices(orgVertices,planeEquations);
|
||||
|
||||
btAlignedObjectArray<btVector3> shiftedPlaneEquations;
|
||||
for (int p=0;p<planeEquations.size();p++)
|
||||
{
|
||||
btVector3 plane = planeEquations[p];
|
||||
btScalar margin = getMargin();
|
||||
plane[3] -= getMargin();
|
||||
shiftedPlaneEquations.push_back(plane);
|
||||
}
|
||||
|
||||
btAlignedObjectArray<btVector3> tmpVertices;
|
||||
|
||||
btGeometryUtil::getVerticesFromPlaneEquations(shiftedPlaneEquations,tmpVertices);
|
||||
|
||||
conv.compute(&tmpVertices[0].getX(), sizeof(btVector3),tmpVertices.size(),0.f,0.f);
|
||||
} else
|
||||
{
|
||||
|
||||
conv.compute(&orgVertices[0].getX(), sizeof(btVector3),orgVertices.size(),0.f,0.f);
|
||||
}
|
||||
|
||||
btAlignedObjectArray<btVector3> tmpVertices;
|
||||
|
||||
btGeometryUtil::getVerticesFromPlaneEquations(shiftedPlaneEquations,tmpVertices);
|
||||
btConvexHullComputer conv;
|
||||
conv.compute(&tmpVertices[0].getX(), sizeof(btVector3),tmpVertices.size(),0.f,0.f);
|
||||
|
||||
#else
|
||||
btConvexHullComputer conv;
|
||||
conv.compute(&orgVertices[0].getX(), sizeof(btVector3),orgVertices.size(),0.f,0.f);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
btAlignedObjectArray<btVector3> faceNormals;
|
||||
@@ -193,7 +196,8 @@ bool btPolyhedralConvexShape::initializePolyhedralFeatures()
|
||||
{
|
||||
//do the merge: use Graham Scan 2d convex hull
|
||||
|
||||
btAlignedObjectArray<GrahamVector2> orgpoints;
|
||||
btAlignedObjectArray<GrahamVector3> orgpoints;
|
||||
btVector3 averageFaceNormal(0,0,0);
|
||||
|
||||
for (int i=0;i<coplanarFaceGroup.size();i++)
|
||||
{
|
||||
@@ -201,16 +205,12 @@ bool btPolyhedralConvexShape::initializePolyhedralFeatures()
|
||||
|
||||
btFace& face = tmpFaces[coplanarFaceGroup[i]];
|
||||
btVector3 faceNormal(face.m_plane[0],face.m_plane[1],face.m_plane[2]);
|
||||
btVector3 xyPlaneNormal(0,0,1);
|
||||
|
||||
btQuaternion rotationArc = shortestArcQuat(faceNormal,xyPlaneNormal);
|
||||
|
||||
averageFaceNormal+=faceNormal;
|
||||
for (int f=0;f<face.m_indices.size();f++)
|
||||
{
|
||||
int orgIndex = face.m_indices[f];
|
||||
btVector3 pt = m_polyhedron->m_vertices[orgIndex];
|
||||
btVector3 rotatedPt = quatRotate(rotationArc,pt);
|
||||
rotatedPt.setZ(0);
|
||||
|
||||
bool found = false;
|
||||
|
||||
for (int i=0;i<orgpoints.size();i++)
|
||||
@@ -223,34 +223,45 @@ bool btPolyhedralConvexShape::initializePolyhedralFeatures()
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
orgpoints.push_back(GrahamVector2(rotatedPt,orgIndex));
|
||||
orgpoints.push_back(GrahamVector3(pt,orgIndex));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
btFace combinedFace;
|
||||
for (int i=0;i<4;i++)
|
||||
combinedFace.m_plane[i] = tmpFaces[coplanarFaceGroup[0]].m_plane[i];
|
||||
|
||||
btAlignedObjectArray<GrahamVector2> hull;
|
||||
GrahamScanConvexHull2D(orgpoints,hull);
|
||||
btAlignedObjectArray<GrahamVector3> hull;
|
||||
|
||||
averageFaceNormal.normalize();
|
||||
GrahamScanConvexHull2D(orgpoints,hull,averageFaceNormal);
|
||||
|
||||
for (int i=0;i<hull.size();i++)
|
||||
{
|
||||
combinedFace.m_indices.push_back(hull[i].m_orgIndex);
|
||||
for(int k = 0; k < orgpoints.size(); k++) {
|
||||
if(orgpoints[k].m_orgIndex == hull[i].m_orgIndex) {
|
||||
for(int k = 0; k < orgpoints.size(); k++)
|
||||
{
|
||||
if(orgpoints[k].m_orgIndex == hull[i].m_orgIndex)
|
||||
{
|
||||
orgpoints[k].m_orgIndex = -1; // invalidate...
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// are there rejected vertices?
|
||||
bool reject_merge = false;
|
||||
|
||||
|
||||
|
||||
for(int i = 0; i < orgpoints.size(); i++) {
|
||||
if(orgpoints[i].m_orgIndex == -1)
|
||||
continue; // this is in the hull...
|
||||
// this vertex is rejected -- is anybody else using this vertex?
|
||||
for(int j = 0; j < tmpFaces.size(); j++) {
|
||||
|
||||
btFace& face = tmpFaces[j];
|
||||
// is this a face of the current coplanar group?
|
||||
bool is_in_current_group = false;
|
||||
@@ -276,20 +287,23 @@ bool btPolyhedralConvexShape::initializePolyhedralFeatures()
|
||||
if(reject_merge)
|
||||
break;
|
||||
}
|
||||
if(!reject_merge) {
|
||||
|
||||
if (!reject_merge)
|
||||
{
|
||||
// do this merge!
|
||||
did_merge = true;
|
||||
m_polyhedron->m_faces.push_back(combinedFace);
|
||||
m_polyhedron->m_faces.push_back(combinedFace);
|
||||
}
|
||||
}
|
||||
if(!did_merge)
|
||||
{
|
||||
for (int i=0;i<coplanarFaceGroup.size();i++)
|
||||
{
|
||||
m_polyhedron->m_faces.push_back(tmpFaces[coplanarFaceGroup[i]]);
|
||||
btFace face = tmpFaces[coplanarFaceGroup[i]];
|
||||
m_polyhedron->m_faces.push_back(face);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -40,7 +40,8 @@ public:
|
||||
virtual ~btPolyhedralConvexShape();
|
||||
|
||||
///optional method mainly used to generate multiple contact points by clipping polyhedral features (faces/edges)
|
||||
virtual bool initializePolyhedralFeatures();
|
||||
///experimental/work-in-progress
|
||||
virtual bool initializePolyhedralFeatures(int shiftVerticesByMargin=0);
|
||||
|
||||
const btConvexPolyhedron* getConvexPolyhedron() const
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user