diff --git a/Demos/OpenGL/DemoApplication.cpp b/Demos/OpenGL/DemoApplication.cpp index 7129bf763..712574989 100644 --- a/Demos/OpenGL/DemoApplication.cpp +++ b/Demos/OpenGL/DemoApplication.cpp @@ -786,7 +786,7 @@ void DemoApplication::mouseFunc(int button, int state, int x, int y) btVector3 pickPos = rayCallback.m_hitPointWorld; - printf("pickPos=%f,%f,%f\n",pickPos.getX(),pickPos.getY(),pickPos.getZ()); + //printf("pickPos=%f,%f,%f\n",pickPos.getX(),pickPos.getY(),pickPos.getZ()); btVector3 localPivot = body->getCenterOfMassTransform().inverse() * pickPos; diff --git a/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp b/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp index dc8829dde..aab53bad2 100644 --- a/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp +++ b/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp @@ -1260,7 +1260,7 @@ void btCollisionWorld::debugDrawObject(const btTransform& worldTransform, const btVector3 normalColor(1,1,0); btVector3 faceNormal(poly->m_faces[i].m_plane[0],poly->m_faces[i].m_plane[1],poly->m_faces[i].m_plane[2]); - getDebugDrawer()->drawLine(worldTransform*centroid,worldTransform*(centroid+faceNormal),normalColor); + //getDebugDrawer()->drawLine(worldTransform*centroid,worldTransform*(centroid+faceNormal),normalColor); } diff --git a/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp b/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp index bb2a7f239..41592afbb 100644 --- a/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp +++ b/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp @@ -47,6 +47,8 @@ void btSimulationIslandManager::findUnions(btDispatcher* /* dispatcher */,btColl { btOverlappingPairCache* pairCachePtr = colWorld->getPairCache(); const int numOverlappingPairs = pairCachePtr->getNumOverlappingPairs(); + if (numOverlappingPairs) + { btBroadphasePair* pairPtr = pairCachePtr->getOverlappingPairArrayPtr(); for (int i=0;igetIslandTag()); } } + } } } diff --git a/src/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp b/src/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp index 2404164eb..c8fe9492d 100644 --- a/src/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp +++ b/src/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp @@ -17,7 +17,6 @@ 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" @@ -151,6 +150,7 @@ void btConvexPolyhedron::initialize() } } +#ifdef USE_CONNECTED_FACES for(int i=0;i m_indices; - btAlignedObjectArray m_connectedFaces; +// btAlignedObjectArray m_connectedFaces; btScalar m_plane[4]; }; diff --git a/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp b/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp index f9043f7d4..a9a887d3e 100644 --- a/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp +++ b/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.cpp @@ -17,6 +17,9 @@ subject to the following restrictions: #include "btConvexPolyhedron.h" #include "LinearMath/btConvexHullComputer.h" #include +#include "LinearMath/btGeometryUtil.h" +#include "LinearMath/btGrahamScan2dConvexHull.h" + btPolyhedralConvexShape::btPolyhedralConvexShape() :btConvexInternalShape(), m_polyhedron(0) @@ -32,34 +35,53 @@ btPolyhedralConvexShape::~btPolyhedralConvexShape() } } + bool btPolyhedralConvexShape::initializePolyhedralFeatures() { + if (m_polyhedron) btAlignedFree(m_polyhedron); void* mem = btAlignedAlloc(sizeof(btConvexPolyhedron),16); m_polyhedron = new (mem) btConvexPolyhedron; - btAlignedObjectArray tmpVertices; + btAlignedObjectArray orgVertices; + for (int i=0;i planeEquations; + btGeometryUtil::getPlaneEquationsFromVertices(orgVertices,planeEquations); + + btAlignedObjectArray shiftedPlaneEquations; + for (int p=0;p tmpVertices; + + btGeometryUtil::getVerticesFromPlaneEquations(shiftedPlaneEquations,tmpVertices); + + btConvexHullComputer conv; conv.compute(&tmpVertices[0].getX(), sizeof(btVector3),tmpVertices.size(),0.f,0.f); - - btAlignedObjectArray faceNormals; int numFaces = conv.faces.size(); faceNormals.resize(numFaces); btConvexHullComputer* convexUtil = &conv; - - m_polyhedron->m_faces.resize(numFaces); + btAlignedObjectArray tmpFaces; + tmpFaces.resize(numFaces); + int numVertices = convexUtil->vertices.size(); m_polyhedron->m_vertices.resize(numVertices); for (int p=0;pm_vertices[p] = convexUtil->vertices[p]; } + for (int i=0;ifaces[i]; @@ -85,7 +108,7 @@ bool btPolyhedralConvexShape::initializePolyhedralFeatures() { int src = edge->getSourceVertex(); - m_polyhedron->m_faces[i].m_indices.push_back(src); + tmpFaces[i].m_indices.push_back(src); int targ = edge->getTargetVertex(); btVector3 wa = convexUtil->vertices[src]; @@ -105,10 +128,10 @@ 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[3] = planeEq; + tmpFaces[i].m_plane[0] = faceNormals[i].getX(); + tmpFaces[i].m_plane[1] = faceNormals[i].getY(); + tmpFaces[i].m_plane[2] = faceNormals[i].getZ(); + tmpFaces[i].m_plane[3] = planeEq; } else @@ -117,22 +140,109 @@ bool btPolyhedralConvexShape::initializePolyhedralFeatures() faceNormals[i].setZero(); } - for (int v=0;vm_faces[i].m_indices.size();v++) + for (int v=0;vm_vertices[m_polyhedron->m_faces[i].m_indices[v]].dot(faceNormals[i]); + btScalar eq = m_polyhedron->m_vertices[tmpFaces[i].m_indices[v]].dot(faceNormals[i]); if (planeEq>eq) { planeEq=eq; } } - m_polyhedron->m_faces[i].m_plane[3] = -planeEq; + tmpFaces[i].m_plane[3] = -planeEq; } + //merge coplanar faces and copy them to m_polyhedron + btScalar faceWeldThreshold= 0.999f; + btAlignedObjectArray todoFaces; + for (int i=0;i coplanarFaceGroup; + int refFace = todoFaces[todoFaces.size()-1]; + + coplanarFaceGroup.push_back(refFace); + btFace& faceA = tmpFaces[refFace]; + todoFaces.pop_back(); + + btVector3 faceNormalA(faceA.m_plane[0],faceA.m_plane[1],faceA.m_plane[2]); + for (int j=todoFaces.size()-1;j>=0;j--) + { + int i = todoFaces[j]; + btFace& faceB = tmpFaces[i]; + btVector3 faceNormalB(faceB.m_plane[0],faceB.m_plane[1],faceB.m_plane[2]); + if (faceNormalA.dot(faceNormalB)>faceWeldThreshold) + { + coplanarFaceGroup.push_back(i); + todoFaces.remove(i); + } + } + + + if (coplanarFaceGroup.size()>1) + { + //do the merge: use Graham Scan 2d convex hull + + btAlignedObjectArray orgpoints; + + for (int i=0;im_faces.push_back(tmpFaces[coplanarFaceGroup[i]]); + + 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); + + for (int f=0;fm_vertices[orgIndex]; + btVector3 rotatedPt = quatRotate(rotationArc,pt); + rotatedPt.setZ(0); + bool found = false; + + for (int i=0;i hull; + GrahamScanConvexHull2D(orgpoints,hull); + + for (int i=0;im_faces.push_back(combinedFace); + } else + { + for (int i=0;im_faces.push_back(tmpFaces[coplanarFaceGroup[i]]); + } + + } + + + + } - - - m_polyhedron->initialize(); return true; diff --git a/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp b/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp index 8aacacc42..61573ddb9 100644 --- a/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp +++ b/src/BulletCollision/NarrowPhaseCollision/btPolyhedralContactClipping.cpp @@ -75,7 +75,6 @@ void btPolyhedralContactClipping::clipFace(const btVertexArray& pVtxIn, btVertex ds = de; } } -#include static bool TestSepAxis(const btConvexPolyhedron& hullA, const btConvexPolyhedron& hullB, const btTransform& transA,const btTransform& transB, const btVector3& sep_axis, btScalar& depth) @@ -106,7 +105,6 @@ inline bool IsAlmostZero(const btVector3& v) return true; } -#define TEST_INTERNAL_OBJECTS 1 #ifdef TEST_INTERNAL_OBJECTS inline void BoxSupport(const btScalar extents[3], const btScalar sv[3], btScalar p[3]) @@ -170,11 +168,11 @@ bool btPolyhedralContactClipping::findSeparatingAxis( const btConvexPolyhedron& { gActualSATPairTests++; -#ifdef TEST_INTERNAL_OBJECTS +//#ifdef TEST_INTERNAL_OBJECTS const btVector3 c0 = transA * hullA.m_localCenter; const btVector3 c1 = transB * hullB.m_localCenter; const btVector3 DeltaC2 = c0 - c1; -#endif +//#endif btScalar dmin = FLT_MAX; int curPlaneTests=0; @@ -185,6 +183,8 @@ bool btPolyhedralContactClipping::findSeparatingAxis( const btConvexPolyhedron& { const btVector3 Normal(hullA.m_faces[i].m_plane[0], hullA.m_faces[i].m_plane[1], hullA.m_faces[i].m_plane[2]); const btVector3 faceANormalWS = transA.getBasis() * Normal; + if (DeltaC2.dot(faceANormalWS)<0) + continue; curPlaneTests++; #ifdef TEST_INTERNAL_OBJECTS @@ -211,6 +211,8 @@ bool btPolyhedralContactClipping::findSeparatingAxis( const btConvexPolyhedron& { const btVector3 Normal(hullB.m_faces[i].m_plane[0], hullB.m_faces[i].m_plane[1], hullB.m_faces[i].m_plane[2]); const btVector3 WorldNormal = transB.getBasis() * Normal; + if (DeltaC2.dot(WorldNormal)<0) + continue; curPlaneTests++; #ifdef TEST_INTERNAL_OBJECTS @@ -249,6 +251,9 @@ bool btPolyhedralContactClipping::findSeparatingAxis( const btConvexPolyhedron& if(!IsAlmostZero(Cross)) { Cross = Cross.normalize(); + if (DeltaC2.dot(Cross)<0) + continue; + #ifdef TEST_INTERNAL_OBJECTS gExpectedNbTests++; @@ -311,18 +316,29 @@ void btPolyhedralContactClipping::clipFaceAgainstHull(const btVector3& separatin int numVerticesA = polyA.m_indices.size(); for(int e0=0;e0 dmax) { @@ -401,28 +422,19 @@ void btPolyhedralContactClipping::clipHullAgainstHull(const btVector3& separatin } } } + btVertexArray worldVertsB1; + { + const btFace& polyB = hullB.m_faces[closestFaceB]; + const int numVertices = polyB.m_indices.size(); + for(int e0=0;e0=0) + clipFaceAgainstHull(separatingNormal, hullA, transA,worldVertsB1, minDist, maxDist,resultOut); } diff --git a/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp b/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp index b08dcf0b8..1eb3e4105 100644 --- a/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp +++ b/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp @@ -675,7 +675,12 @@ void btDiscreteDynamicsWorld::solveConstraints(btContactSolverInfo& solverInfo) { if (m_manifolds.size() + m_constraints.size()>0) { - m_solver->solveGroup( &m_bodies[0],m_bodies.size(), &m_manifolds[0], m_manifolds.size(), &m_constraints[0], m_constraints.size() ,m_solverInfo,m_debugDrawer,m_stackAlloc,m_dispatcher); + + btCollisionObject** bodies = m_bodies.size()? &m_bodies[0]:0; + btPersistentManifold** manifold = m_manifolds.size()?&m_manifolds[0]:0; + btTypedConstraint** constraints = m_constraints.size()?&m_constraints[0]:0; + + m_solver->solveGroup( bodies,m_bodies.size(),manifold, m_manifolds.size(),constraints, m_constraints.size() ,m_solverInfo,m_debugDrawer,m_stackAlloc,m_dispatcher); } m_bodies.resize(0); m_manifolds.resize(0); diff --git a/src/LinearMath/btAlignedObjectArray.h b/src/LinearMath/btAlignedObjectArray.h index 955bb128e..9022a941e 100644 --- a/src/LinearMath/btAlignedObjectArray.h +++ b/src/LinearMath/btAlignedObjectArray.h @@ -140,21 +140,29 @@ class btAlignedObjectArray SIMD_FORCE_INLINE const T& at(int n) const { + btAssert(n>=0); + btAssert(n=0); + btAssert(n=0); + btAssert(n=0); + btAssert(n0); m_size--; m_data[m_size].~T(); } diff --git a/src/LinearMath/btGrahamScan2dConvexHull.h b/src/LinearMath/btGrahamScan2dConvexHull.h new file mode 100644 index 000000000..ee35b78ba --- /dev/null +++ b/src/LinearMath/btGrahamScan2dConvexHull.h @@ -0,0 +1,110 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2011 Advanced Micro Devices, Inc. http://bulletphysics.org + +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 GRAHAM_SCAN_2D_CONVEX_HULL_H +#define GRAHAM_SCAN_2D_CONVEX_HULL_H + + +#include "btVector3.h" +#include "btAlignedObjectArray.h" + +struct GrahamVector2 : public btVector3 +{ + GrahamVector2(const btVector3& org, int orgIndex) + :btVector3(org), + m_orgIndex(orgIndex) + { + } + btScalar m_angle; + int m_orgIndex; +}; + + +struct btAngleCompareFunc { + btVector3 m_anchor; + btAngleCompareFunc(const btVector3& anchor) + : m_anchor(anchor) + { + } + bool operator()(const GrahamVector2& a, const GrahamVector2& b) { + if (a.m_angle != b.m_angle) + return a.m_angle < b.m_angle; + else + { + btScalar al = (a-m_anchor).length2(); + btScalar bl = (b-m_anchor).length2(); + if (al != bl) + return al < bl; + else + { + return a.uid < b.uid; + } + } + } +}; + +inline void GrahamScanConvexHull2D(btAlignedObjectArray& originalPoints, btAlignedObjectArray& hull) +{ + if (originalPoints.size()<=1) + { + for (int i=0;i1) { + btVector3& a = hull[hull.size()-2]; + btVector3& b = hull[hull.size()-1]; + isConvex = btCross(a-b,a-originalPoints[i]).dot(btVector3(0,0,1))> 0; + if (!isConvex) + hull.pop_back(); + else + hull.push_back(originalPoints[i]); + } + } +} + +#endif //GRAHAM_SCAN_2D_CONVEX_HULL_H