2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2009 Erwin Coumans 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 #include "btConvexTriangleMeshShape.h"
17 #include "BulletCollision/CollisionShapes/btCollisionMargin.h"
19 #include "LinearMath/btQuaternion.h"
20 #include "BulletCollision/CollisionShapes/btStridingMeshInterface.h"
22 btConvexTriangleMeshShape ::btConvexTriangleMeshShape(btStridingMeshInterface* meshInterface, bool calcAabb)
23 : btPolyhedralConvexAabbCachingShape(), m_stridingMesh(meshInterface)
25 m_shapeType = CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE;
30 ///It's not nice to have all this virtual function overhead, so perhaps we can also gather the points once
31 ///but then we are duplicating
32 class LocalSupportVertexCallback : public btInternalTriangleIndexCallback
34 btVector3 m_supportVertexLocal;
38 btVector3 m_supportVecLocal;
40 LocalSupportVertexCallback(const btVector3& supportVecLocal)
41 : m_supportVertexLocal(btScalar(0.), btScalar(0.), btScalar(0.)),
42 m_maxDot(btScalar(-BT_LARGE_FLOAT)),
43 m_supportVecLocal(supportVecLocal)
47 virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex)
52 for (int i = 0; i < 3; i++)
54 btScalar dot = m_supportVecLocal.dot(triangle[i]);
58 m_supportVertexLocal = triangle[i];
63 btVector3 GetSupportVertexLocal()
65 return m_supportVertexLocal;
69 btVector3 btConvexTriangleMeshShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0) const
71 btVector3 supVec(btScalar(0.), btScalar(0.), btScalar(0.));
74 btScalar lenSqr = vec.length2();
75 if (lenSqr < btScalar(0.0001))
77 vec.setValue(1, 0, 0);
81 btScalar rlen = btScalar(1.) / btSqrt(lenSqr);
85 LocalSupportVertexCallback supportCallback(vec);
86 btVector3 aabbMax(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
87 m_stridingMesh->InternalProcessAllTriangles(&supportCallback, -aabbMax, aabbMax);
88 supVec = supportCallback.GetSupportVertexLocal();
93 void btConvexTriangleMeshShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors, btVector3* supportVerticesOut, int numVectors) const
95 //use 'w' component of supportVerticesOut?
97 for (int i = 0; i < numVectors; i++)
99 supportVerticesOut[i][3] = btScalar(-BT_LARGE_FLOAT);
103 ///@todo: could do the batch inside the callback!
105 for (int j = 0; j < numVectors; j++)
107 const btVector3& vec = vectors[j];
108 LocalSupportVertexCallback supportCallback(vec);
109 btVector3 aabbMax(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
110 m_stridingMesh->InternalProcessAllTriangles(&supportCallback, -aabbMax, aabbMax);
111 supportVerticesOut[j] = supportCallback.GetSupportVertexLocal();
115 btVector3 btConvexTriangleMeshShape::localGetSupportingVertex(const btVector3& vec) const
117 btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec);
119 if (getMargin() != btScalar(0.))
121 btVector3 vecnorm = vec;
122 if (vecnorm.length2() < (SIMD_EPSILON * SIMD_EPSILON))
124 vecnorm.setValue(btScalar(-1.), btScalar(-1.), btScalar(-1.));
127 supVertex += getMargin() * vecnorm;
132 //currently just for debugging (drawing), perhaps future support for algebraic continuous collision detection
133 //Please note that you can debug-draw btConvexTriangleMeshShape with the Raytracer Demo
134 int btConvexTriangleMeshShape::getNumVertices() const
140 int btConvexTriangleMeshShape::getNumEdges() const
145 void btConvexTriangleMeshShape::getEdge(int, btVector3&, btVector3&) const
150 void btConvexTriangleMeshShape::getVertex(int, btVector3&) const
155 int btConvexTriangleMeshShape::getNumPlanes() const
160 void btConvexTriangleMeshShape::getPlane(btVector3&, btVector3&, int) const
166 bool btConvexTriangleMeshShape::isInside(const btVector3&, btScalar) const
172 void btConvexTriangleMeshShape::setLocalScaling(const btVector3& scaling)
174 m_stridingMesh->setScaling(scaling);
179 const btVector3& btConvexTriangleMeshShape::getLocalScaling() const
181 return m_stridingMesh->getScaling();
184 void btConvexTriangleMeshShape::calculatePrincipalAxisTransform(btTransform& principal, btVector3& inertia, btScalar& volume) const
186 class CenterCallback : public btInternalTriangleIndexCallback
194 CenterCallback() : first(true), ref(0, 0, 0), sum(0, 0, 0), volume(0)
198 virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex)
209 btScalar vol = btFabs((triangle[0] - ref).triple(triangle[1] - ref, triangle[2] - ref));
210 sum += (btScalar(0.25) * vol) * ((triangle[0] + triangle[1] + triangle[2] + ref));
215 btVector3 getCenter()
217 return (volume > 0) ? sum / volume : ref;
222 return volume * btScalar(1. / 6);
226 class InertiaCallback : public btInternalTriangleIndexCallback
232 InertiaCallback(btVector3& center) : sum(0, 0, 0, 0, 0, 0, 0, 0, 0), center(center)
236 virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex)
241 btVector3 a = triangle[0] - center;
242 btVector3 b = triangle[1] - center;
243 btVector3 c = triangle[2] - center;
244 btScalar volNeg = -btFabs(a.triple(b, c)) * btScalar(1. / 6);
245 for (int j = 0; j < 3; j++)
247 for (int k = 0; k <= j; k++)
249 i[j][k] = i[k][j] = volNeg * (btScalar(0.1) * (a[j] * a[k] + b[j] * b[k] + c[j] * c[k]) + btScalar(0.05) * (a[j] * b[k] + a[k] * b[j] + a[j] * c[k] + a[k] * c[j] + b[j] * c[k] + b[k] * c[j]));
252 btScalar i00 = -i[0][0];
253 btScalar i11 = -i[1][1];
254 btScalar i22 = -i[2][2];
263 btMatrix3x3& getInertia()
269 CenterCallback centerCallback;
270 btVector3 aabbMax(btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT), btScalar(BT_LARGE_FLOAT));
271 m_stridingMesh->InternalProcessAllTriangles(¢erCallback, -aabbMax, aabbMax);
272 btVector3 center = centerCallback.getCenter();
273 principal.setOrigin(center);
274 volume = centerCallback.getVolume();
276 InertiaCallback inertiaCallback(center);
277 m_stridingMesh->InternalProcessAllTriangles(&inertiaCallback, -aabbMax, aabbMax);
279 btMatrix3x3& i = inertiaCallback.getInertia();
280 i.diagonalize(principal.getBasis(), btScalar(0.00001), 20);
281 inertia.setValue(i[0][0], i[1][1], i[2][2]);