Home | History | Annotate | Download | only in CollisionShapes
      1 /*
      2 Bullet Continuous Collision Detection and Physics Library
      3 Copyright (c) 2003-2009 Erwin Coumans  http://bulletphysics.org
      4 
      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:
     10 
     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.
     14 */
     15 
     16 #include "btConvexTriangleMeshShape.h"
     17 #include "BulletCollision/CollisionShapes/btCollisionMargin.h"
     18 
     19 #include "LinearMath/btQuaternion.h"
     20 #include "BulletCollision/CollisionShapes/btStridingMeshInterface.h"
     21 
     22 
     23 btConvexTriangleMeshShape ::btConvexTriangleMeshShape (btStridingMeshInterface* meshInterface, bool calcAabb)
     24 : btPolyhedralConvexAabbCachingShape(), m_stridingMesh(meshInterface)
     25 {
     26 	m_shapeType = CONVEX_TRIANGLEMESH_SHAPE_PROXYTYPE;
     27 	if ( calcAabb )
     28 		recalcLocalAabb();
     29 }
     30 
     31 
     32 
     33 
     34 ///It's not nice to have all this virtual function overhead, so perhaps we can also gather the points once
     35 ///but then we are duplicating
     36 class LocalSupportVertexCallback: public btInternalTriangleIndexCallback
     37 {
     38 
     39 	btVector3 m_supportVertexLocal;
     40 public:
     41 
     42 	btScalar m_maxDot;
     43 	btVector3 m_supportVecLocal;
     44 
     45 	LocalSupportVertexCallback(const btVector3& supportVecLocal)
     46 		: m_supportVertexLocal(btScalar(0.),btScalar(0.),btScalar(0.)),
     47 		m_maxDot(btScalar(-BT_LARGE_FLOAT)),
     48                 m_supportVecLocal(supportVecLocal)
     49 	{
     50 	}
     51 
     52 	virtual void internalProcessTriangleIndex(btVector3* triangle,int partId,int  triangleIndex)
     53 	{
     54 		(void)triangleIndex;
     55 		(void)partId;
     56 
     57 		for (int i=0;i<3;i++)
     58 		{
     59 			btScalar dot = m_supportVecLocal.dot(triangle[i]);
     60 			if (dot > m_maxDot)
     61 			{
     62 				m_maxDot = dot;
     63 				m_supportVertexLocal = triangle[i];
     64 			}
     65 		}
     66 	}
     67 
     68 	btVector3	GetSupportVertexLocal()
     69 	{
     70 		return m_supportVertexLocal;
     71 	}
     72 
     73 };
     74 
     75 
     76 
     77 
     78 
     79 btVector3	btConvexTriangleMeshShape::localGetSupportingVertexWithoutMargin(const btVector3& vec0)const
     80 {
     81 	btVector3 supVec(btScalar(0.),btScalar(0.),btScalar(0.));
     82 
     83 	btVector3 vec = vec0;
     84 	btScalar lenSqr = vec.length2();
     85 	if (lenSqr < btScalar(0.0001))
     86 	{
     87 		vec.setValue(1,0,0);
     88 	} else
     89 	{
     90 		btScalar rlen = btScalar(1.) / btSqrt(lenSqr );
     91 		vec *= rlen;
     92 	}
     93 
     94 	LocalSupportVertexCallback	supportCallback(vec);
     95 	btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
     96 	m_stridingMesh->InternalProcessAllTriangles(&supportCallback,-aabbMax,aabbMax);
     97 	supVec = supportCallback.GetSupportVertexLocal();
     98 
     99 	return supVec;
    100 }
    101 
    102 void	btConvexTriangleMeshShape::batchedUnitVectorGetSupportingVertexWithoutMargin(const btVector3* vectors,btVector3* supportVerticesOut,int numVectors) const
    103 {
    104 	//use 'w' component of supportVerticesOut?
    105 	{
    106 		for (int i=0;i<numVectors;i++)
    107 		{
    108 			supportVerticesOut[i][3] = btScalar(-BT_LARGE_FLOAT);
    109 		}
    110 	}
    111 
    112 	///@todo: could do the batch inside the callback!
    113 
    114 
    115 	for (int j=0;j<numVectors;j++)
    116 	{
    117 		const btVector3& vec = vectors[j];
    118 		LocalSupportVertexCallback	supportCallback(vec);
    119 		btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
    120 		m_stridingMesh->InternalProcessAllTriangles(&supportCallback,-aabbMax,aabbMax);
    121 		supportVerticesOut[j] = supportCallback.GetSupportVertexLocal();
    122 	}
    123 
    124 }
    125 
    126 
    127 
    128 btVector3	btConvexTriangleMeshShape::localGetSupportingVertex(const btVector3& vec)const
    129 {
    130 	btVector3 supVertex = localGetSupportingVertexWithoutMargin(vec);
    131 
    132 	if ( getMargin()!=btScalar(0.) )
    133 	{
    134 		btVector3 vecnorm = vec;
    135 		if (vecnorm .length2() < (SIMD_EPSILON*SIMD_EPSILON))
    136 		{
    137 			vecnorm.setValue(btScalar(-1.),btScalar(-1.),btScalar(-1.));
    138 		}
    139 		vecnorm.normalize();
    140 		supVertex+= getMargin() * vecnorm;
    141 	}
    142 	return supVertex;
    143 }
    144 
    145 
    146 
    147 
    148 
    149 
    150 
    151 
    152 
    153 //currently just for debugging (drawing), perhaps future support for algebraic continuous collision detection
    154 //Please note that you can debug-draw btConvexTriangleMeshShape with the Raytracer Demo
    155 int	btConvexTriangleMeshShape::getNumVertices() const
    156 {
    157 	//cache this?
    158 	return 0;
    159 
    160 }
    161 
    162 int btConvexTriangleMeshShape::getNumEdges() const
    163 {
    164 	return 0;
    165 }
    166 
    167 void btConvexTriangleMeshShape::getEdge(int ,btVector3& ,btVector3& ) const
    168 {
    169 	btAssert(0);
    170 }
    171 
    172 void btConvexTriangleMeshShape::getVertex(int ,btVector3& ) const
    173 {
    174 	btAssert(0);
    175 }
    176 
    177 int	btConvexTriangleMeshShape::getNumPlanes() const
    178 {
    179 	return 0;
    180 }
    181 
    182 void btConvexTriangleMeshShape::getPlane(btVector3& ,btVector3& ,int  ) const
    183 {
    184 	btAssert(0);
    185 }
    186 
    187 //not yet
    188 bool btConvexTriangleMeshShape::isInside(const btVector3& ,btScalar ) const
    189 {
    190 	btAssert(0);
    191 	return false;
    192 }
    193 
    194 
    195 
    196 void	btConvexTriangleMeshShape::setLocalScaling(const btVector3& scaling)
    197 {
    198 	m_stridingMesh->setScaling(scaling);
    199 
    200 	recalcLocalAabb();
    201 
    202 }
    203 
    204 
    205 const btVector3& btConvexTriangleMeshShape::getLocalScaling() const
    206 {
    207 	return m_stridingMesh->getScaling();
    208 }
    209 
    210 void btConvexTriangleMeshShape::calculatePrincipalAxisTransform(btTransform& principal, btVector3& inertia, btScalar& volume) const
    211 {
    212    class CenterCallback: public btInternalTriangleIndexCallback
    213    {
    214       bool first;
    215       btVector3 ref;
    216       btVector3 sum;
    217       btScalar volume;
    218 
    219    public:
    220 
    221       CenterCallback() : first(true), ref(0, 0, 0), sum(0, 0, 0), volume(0)
    222       {
    223       }
    224 
    225       virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex)
    226       {
    227          (void) triangleIndex;
    228          (void) partId;
    229          if (first)
    230          {
    231             ref = triangle[0];
    232             first = false;
    233          }
    234          else
    235          {
    236             btScalar vol = btFabs((triangle[0] - ref).triple(triangle[1] - ref, triangle[2] - ref));
    237             sum += (btScalar(0.25) * vol) * ((triangle[0] + triangle[1] + triangle[2] + ref));
    238             volume += vol;
    239          }
    240       }
    241 
    242       btVector3 getCenter()
    243       {
    244          return (volume > 0) ? sum / volume : ref;
    245       }
    246 
    247       btScalar getVolume()
    248       {
    249          return volume * btScalar(1. / 6);
    250       }
    251 
    252    };
    253 
    254    class InertiaCallback: public btInternalTriangleIndexCallback
    255    {
    256       btMatrix3x3 sum;
    257       btVector3 center;
    258 
    259    public:
    260 
    261       InertiaCallback(btVector3& center) : sum(0, 0, 0, 0, 0, 0, 0, 0, 0), center(center)
    262       {
    263       }
    264 
    265       virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex)
    266       {
    267          (void) triangleIndex;
    268          (void) partId;
    269          btMatrix3x3 i;
    270          btVector3 a = triangle[0] - center;
    271          btVector3 b = triangle[1] - center;
    272          btVector3 c = triangle[2] - center;
    273          btScalar volNeg = -btFabs(a.triple(b, c)) * btScalar(1. / 6);
    274          for (int j = 0; j < 3; j++)
    275          {
    276             for (int k = 0; k <= j; k++)
    277             {
    278                i[j][k] = i[k][j] = volNeg * (btScalar(0.1) * (a[j] * a[k] + b[j] * b[k] + c[j] * c[k])
    279                   + 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]));
    280             }
    281          }
    282          btScalar i00 = -i[0][0];
    283          btScalar i11 = -i[1][1];
    284          btScalar i22 = -i[2][2];
    285          i[0][0] = i11 + i22;
    286          i[1][1] = i22 + i00;
    287          i[2][2] = i00 + i11;
    288          sum[0] += i[0];
    289          sum[1] += i[1];
    290          sum[2] += i[2];
    291       }
    292 
    293       btMatrix3x3& getInertia()
    294       {
    295          return sum;
    296       }
    297 
    298    };
    299 
    300    CenterCallback centerCallback;
    301    btVector3 aabbMax(btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT),btScalar(BT_LARGE_FLOAT));
    302    m_stridingMesh->InternalProcessAllTriangles(&centerCallback, -aabbMax, aabbMax);
    303    btVector3 center = centerCallback.getCenter();
    304    principal.setOrigin(center);
    305    volume = centerCallback.getVolume();
    306 
    307    InertiaCallback inertiaCallback(center);
    308    m_stridingMesh->InternalProcessAllTriangles(&inertiaCallback, -aabbMax, aabbMax);
    309 
    310    btMatrix3x3& i = inertiaCallback.getInertia();
    311    i.diagonalize(principal.getBasis(), btScalar(0.00001), 20);
    312    inertia.setValue(i[0][0], i[1][1], i[2][2]);
    313    inertia /= volume;
    314 }
    315 
    316