summaryrefslogtreecommitdiff
path: root/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/bullet/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp')
-rw-r--r--thirdparty/bullet/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp303
1 files changed, 303 insertions, 0 deletions
diff --git a/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp b/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp
new file mode 100644
index 0000000000..4f45319a83
--- /dev/null
+++ b/thirdparty/bullet/BulletCollision/CollisionShapes/btConvexPolyhedron.cpp
@@ -0,0 +1,303 @@
+/*
+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.
+*/
+
+
+///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
+
+#include "btConvexPolyhedron.h"
+#include "LinearMath/btHashMap.h"
+
+
+btConvexPolyhedron::btConvexPolyhedron()
+{
+
+}
+btConvexPolyhedron::~btConvexPolyhedron()
+{
+
+}
+
+
+inline bool IsAlmostZero(const btVector3& v)
+{
+ if(btFabs(v.x())>1e-6 || btFabs(v.y())>1e-6 || btFabs(v.z())>1e-6) return false;
+ return true;
+}
+
+struct btInternalVertexPair
+{
+ btInternalVertexPair(short int v0,short int v1)
+ :m_v0(v0),
+ m_v1(v1)
+ {
+ if (m_v1>m_v0)
+ btSwap(m_v0,m_v1);
+ }
+ short int m_v0;
+ short int m_v1;
+ int getHash() const
+ {
+ return m_v0+(m_v1<<16);
+ }
+ bool equals(const btInternalVertexPair& other) const
+ {
+ return m_v0==other.m_v0 && m_v1==other.m_v1;
+ }
+};
+
+struct btInternalEdge
+{
+ btInternalEdge()
+ :m_face0(-1),
+ m_face1(-1)
+ {
+ }
+ short int m_face0;
+ short int m_face1;
+};
+
+//
+
+#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;
+
+ btScalar TotalArea = 0.0f;
+
+ m_localCenter.setValue(0, 0, 0);
+ for(int i=0;i<m_faces.size();i++)
+ {
+ int numVertices = m_faces[i].m_indices.size();
+ int NbTris = numVertices;
+ for(int j=0;j<NbTris;j++)
+ {
+ int k = (j+1)%numVertices;
+ btInternalVertexPair vp(m_faces[i].m_indices[j],m_faces[i].m_indices[k]);
+ btInternalEdge* edptr = edges.find(vp);
+ btVector3 edge = m_vertices[vp.m_v1]-m_vertices[vp.m_v0];
+ edge.normalize();
+
+ bool found = false;
+
+ for (int p=0;p<m_uniqueEdges.size();p++)
+ {
+
+ if (IsAlmostZero(m_uniqueEdges[p]-edge) ||
+ IsAlmostZero(m_uniqueEdges[p]+edge))
+ {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found)
+ {
+ m_uniqueEdges.push_back(edge);
+ }
+
+ if (edptr)
+ {
+ btAssert(edptr->m_face0>=0);
+ btAssert(edptr->m_face1<0);
+ edptr->m_face1 = i;
+ } else
+ {
+ btInternalEdge ed;
+ ed.m_face0 = i;
+ edges.insert(vp,ed);
+ }
+ }
+ }
+
+#ifdef USE_CONNECTED_FACES
+ for(int i=0;i<m_faces.size();i++)
+ {
+ int numVertices = m_faces[i].m_indices.size();
+ m_faces[i].m_connectedFaces.resize(numVertices);
+
+ for(int j=0;j<numVertices;j++)
+ {
+ int k = (j+1)%numVertices;
+ btInternalVertexPair vp(m_faces[i].m_indices[j],m_faces[i].m_indices[k]);
+ btInternalEdge* edptr = edges.find(vp);
+ btAssert(edptr);
+ btAssert(edptr->m_face0>=0);
+ btAssert(edptr->m_face1>=0);
+
+ int connectedFace = (edptr->m_face0==i)?edptr->m_face1:edptr->m_face0;
+ m_faces[i].m_connectedFaces[j] = connectedFace;
+ }
+ }
+#endif//USE_CONNECTED_FACES
+
+ for(int i=0;i<m_faces.size();i++)
+ {
+ int numVertices = m_faces[i].m_indices.size();
+ int NbTris = numVertices-2;
+
+ const btVector3& p0 = m_vertices[m_faces[i].m_indices[0]];
+ for(int j=1;j<=NbTris;j++)
+ {
+ 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]];
+ btScalar Area = ((p0 - p1).cross(p0 - p2)).length() * 0.5f;
+ btVector3 Center = (p0+p1+p2)/3.0f;
+ m_localCenter += Area * Center;
+ TotalArea += Area;
+ }
+ }
+ 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, btScalar& minProj, btScalar& maxProj, btVector3& witnesPtMin,btVector3& witnesPtMax) const
+{
+ 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 < minProj)
+ {
+ minProj = dp;
+ witnesPtMin = pt;
+ }
+ if(dp > maxProj)
+ {
+ maxProj = dp;
+ witnesPtMax = pt;
+ }
+ }
+ if(minProj>maxProj)
+ {
+ btSwap(minProj,maxProj);
+ btSwap(witnesPtMin,witnesPtMax);
+ }
+}