2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2011 Advanced Micro Devices, Inc. http://bulletphysics.org
5 This software is provided 'as-is', without any express or implied warranty.
6 In no event will the authors be held liable for any damages arising from the use of this software.
7 Permission is granted to anyone to use this software for any purpose,
8 including commercial applications, and to alter it and redistribute it freely,
9 subject to the following restrictions:
11 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.
12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
13 3. This notice may not be removed or altered from any source distribution.
16 ///This file was written by Erwin Coumans
17 ///Separating axis rest based on work from Pierre Terdiman, see
18 ///And contact clipping based on work from Simon Hobbs
20 #include "btConvexPolyhedron.h"
21 #include "LinearMath/btHashMap.h"
23 btConvexPolyhedron::btConvexPolyhedron()
26 btConvexPolyhedron::~btConvexPolyhedron()
30 inline bool IsAlmostZero1(const btVector3& v)
32 if (btFabs(v.x()) > 1e-6 || btFabs(v.y()) > 1e-6 || btFabs(v.z()) > 1e-6) return false;
36 struct btInternalVertexPair
38 btInternalVertexPair(short int v0, short int v1)
49 return m_v0 + (m_v1 << 16);
51 bool equals(const btInternalVertexPair& other) const
53 return m_v0 == other.m_v0 && m_v1 == other.m_v1;
70 #ifdef TEST_INTERNAL_OBJECTS
71 bool btConvexPolyhedron::testContainment() const
73 for (int p = 0; p < 8; p++)
77 LocalPt = m_localCenter + btVector3(m_extents[0], m_extents[1], m_extents[2]);
79 LocalPt = m_localCenter + btVector3(m_extents[0], m_extents[1], -m_extents[2]);
81 LocalPt = m_localCenter + btVector3(m_extents[0], -m_extents[1], m_extents[2]);
83 LocalPt = m_localCenter + btVector3(m_extents[0], -m_extents[1], -m_extents[2]);
85 LocalPt = m_localCenter + btVector3(-m_extents[0], m_extents[1], m_extents[2]);
87 LocalPt = m_localCenter + btVector3(-m_extents[0], m_extents[1], -m_extents[2]);
89 LocalPt = m_localCenter + btVector3(-m_extents[0], -m_extents[1], m_extents[2]);
91 LocalPt = m_localCenter + btVector3(-m_extents[0], -m_extents[1], -m_extents[2]);
93 for (int i = 0; i < m_faces.size(); i++)
95 const btVector3 Normal(m_faces[i].m_plane[0], m_faces[i].m_plane[1], m_faces[i].m_plane[2]);
96 const btScalar d = LocalPt.dot(Normal) + m_faces[i].m_plane[3];
105 void btConvexPolyhedron::initialize()
107 btHashMap<btInternalVertexPair, btInternalEdge> edges;
109 for (int i = 0; i < m_faces.size(); i++)
111 int numVertices = m_faces[i].m_indices.size();
112 int NbTris = numVertices;
113 for (int j = 0; j < NbTris; j++)
115 int k = (j + 1) % numVertices;
116 btInternalVertexPair vp(m_faces[i].m_indices[j], m_faces[i].m_indices[k]);
117 btInternalEdge* edptr = edges.find(vp);
118 btVector3 edge = m_vertices[vp.m_v1] - m_vertices[vp.m_v0];
123 for (int p = 0; p < m_uniqueEdges.size(); p++)
125 if (IsAlmostZero1(m_uniqueEdges[p] - edge) ||
126 IsAlmostZero1(m_uniqueEdges[p] + edge))
135 m_uniqueEdges.push_back(edge);
140 btAssert(edptr->m_face0 >= 0);
141 btAssert(edptr->m_face1 < 0);
148 edges.insert(vp, ed);
153 #ifdef USE_CONNECTED_FACES
154 for (int i = 0; i < m_faces.size(); i++)
156 int numVertices = m_faces[i].m_indices.size();
157 m_faces[i].m_connectedFaces.resize(numVertices);
159 for (int j = 0; j < numVertices; j++)
161 int k = (j + 1) % numVertices;
162 btInternalVertexPair vp(m_faces[i].m_indices[j], m_faces[i].m_indices[k]);
163 btInternalEdge* edptr = edges.find(vp);
165 btAssert(edptr->m_face0 >= 0);
166 btAssert(edptr->m_face1 >= 0);
168 int connectedFace = (edptr->m_face0 == i) ? edptr->m_face1 : edptr->m_face0;
169 m_faces[i].m_connectedFaces[j] = connectedFace;
172 #endif //USE_CONNECTED_FACES
177 void btConvexPolyhedron::initialize2()
179 m_localCenter.setValue(0, 0, 0);
180 btScalar TotalArea = 0.0f;
181 for (int i = 0; i < m_faces.size(); i++)
183 int numVertices = m_faces[i].m_indices.size();
184 int NbTris = numVertices - 2;
186 const btVector3& p0 = m_vertices[m_faces[i].m_indices[0]];
187 for (int j = 1; j <= NbTris; j++)
189 int k = (j + 1) % numVertices;
190 const btVector3& p1 = m_vertices[m_faces[i].m_indices[j]];
191 const btVector3& p2 = m_vertices[m_faces[i].m_indices[k]];
192 btScalar Area = ((p0 - p1).cross(p0 - p2)).length() * 0.5f;
193 btVector3 Center = (p0 + p1 + p2) / 3.0f;
194 m_localCenter += Area * Center;
198 m_localCenter /= TotalArea;
200 #ifdef TEST_INTERNAL_OBJECTS
204 for (int i = 0; i < m_faces.size(); i++)
206 const btVector3 Normal(m_faces[i].m_plane[0], m_faces[i].m_plane[1], m_faces[i].m_plane[2]);
207 const btScalar dist = btFabs(m_localCenter.dot(Normal) + m_faces[i].m_plane[3]);
212 btScalar MinX = FLT_MAX;
213 btScalar MinY = FLT_MAX;
214 btScalar MinZ = FLT_MAX;
215 btScalar MaxX = -FLT_MAX;
216 btScalar MaxY = -FLT_MAX;
217 btScalar MaxZ = -FLT_MAX;
218 for (int i = 0; i < m_vertices.size(); i++)
220 const btVector3& pt = m_vertices[i];
221 if (pt.x() < MinX) MinX = pt.x();
222 if (pt.x() > MaxX) MaxX = pt.x();
223 if (pt.y() < MinY) MinY = pt.y();
224 if (pt.y() > MaxY) MaxY = pt.y();
225 if (pt.z() < MinZ) MinZ = pt.z();
226 if (pt.z() > MaxZ) MaxZ = pt.z();
228 mC.setValue(MaxX + MinX, MaxY + MinY, MaxZ + MinZ);
229 mE.setValue(MaxX - MinX, MaxY - MinY, MaxZ - MinZ);
231 // const btScalar r = m_radius / sqrtf(2.0f);
232 const btScalar r = m_radius / sqrtf(3.0f);
233 const int LargestExtent = mE.maxAxis();
234 const btScalar Step = (mE[LargestExtent] * 0.5f - r) / 1024.0f;
235 m_extents[0] = m_extents[1] = m_extents[2] = r;
236 m_extents[LargestExtent] = mE[LargestExtent] * 0.5f;
237 bool FoundBox = false;
238 for (int j = 0; j < 1024; j++)
240 if (testContainment())
246 m_extents[LargestExtent] -= Step;
250 m_extents[0] = m_extents[1] = m_extents[2] = r;
255 const btScalar Step = (m_radius - r) / 1024.0f;
256 const int e0 = (1 << LargestExtent) & 3;
257 const int e1 = (1 << e0) & 3;
259 for (int j = 0; j < 1024; j++)
261 const btScalar Saved0 = m_extents[e0];
262 const btScalar Saved1 = m_extents[e1];
263 m_extents[e0] += Step;
264 m_extents[e1] += Step;
266 if (!testContainment())
268 m_extents[e0] = Saved0;
269 m_extents[e1] = Saved1;
277 void btConvexPolyhedron::project(const btTransform& trans, const btVector3& dir, btScalar& minProj, btScalar& maxProj, btVector3& witnesPtMin, btVector3& witnesPtMax) const
281 int numVerts = m_vertices.size();
282 for (int i = 0; i < numVerts; i++)
284 btVector3 pt = trans * m_vertices[i];
285 btScalar dp = pt.dot(dir);
297 if (minProj > maxProj)
299 btSwap(minProj, maxProj);
300 btSwap(witnesPtMin, witnesPtMax);