#ifndef BT_COMPOUND_FROM_GIMPACT #define BT_COMPOUND_FROM_GIMPACT #include "BulletCollision/CollisionShapes/btCompoundShape.h" #include "btGImpactShape.h" #include "BulletCollision/NarrowPhaseCollision/btRaycastCallback.h" ATTRIBUTE_ALIGNED16(class) btCompoundFromGimpactShape : public btCompoundShape { public: BT_DECLARE_ALIGNED_ALLOCATOR(); virtual ~btCompoundFromGimpactShape() { /*delete all the btBU_Simplex1to4 ChildShapes*/ for (int i = 0; i < m_children.size(); i++) { delete m_children[i].m_childShape; } } }; struct MyCallback : public btTriangleRaycastCallback { int m_ignorePart; int m_ignoreTriangleIndex; MyCallback(const btVector3& from, const btVector3& to, int ignorePart, int ignoreTriangleIndex) : btTriangleRaycastCallback(from, to), m_ignorePart(ignorePart), m_ignoreTriangleIndex(ignoreTriangleIndex) { } virtual btScalar reportHit(const btVector3& hitNormalLocal, btScalar hitFraction, int partId, int triangleIndex) { if (partId != m_ignorePart || triangleIndex != m_ignoreTriangleIndex) { if (hitFraction < m_hitFraction) return hitFraction; } return m_hitFraction; } }; struct MyInternalTriangleIndexCallback : public btInternalTriangleIndexCallback { const btGImpactMeshShape* m_gimpactShape; btCompoundShape* m_colShape; btScalar m_depth; MyInternalTriangleIndexCallback(btCompoundShape* colShape, const btGImpactMeshShape* meshShape, btScalar depth) : m_colShape(colShape), m_gimpactShape(meshShape), m_depth(depth) { } virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex) { btVector3 scale = m_gimpactShape->getLocalScaling(); btVector3 v0 = triangle[0] * scale; btVector3 v1 = triangle[1] * scale; btVector3 v2 = triangle[2] * scale; btVector3 centroid = (v0 + v1 + v2) / 3; btVector3 normal = (v1 - v0).cross(v2 - v0); normal.normalize(); btVector3 rayFrom = centroid; btVector3 rayTo = centroid - normal * m_depth; MyCallback cb(rayFrom, rayTo, partId, triangleIndex); m_gimpactShape->processAllTrianglesRay(&cb, rayFrom, rayTo); if (cb.m_hitFraction < 1) { rayTo.setInterpolate3(cb.m_from, cb.m_to, cb.m_hitFraction); //rayTo = cb.m_from; //rayTo = rayTo.lerp(cb.m_to,cb.m_hitFraction); //gDebugDraw.drawLine(tr(centroid),tr(centroid+normal),btVector3(1,0,0)); } btBU_Simplex1to4* tet = new btBU_Simplex1to4(v0, v1, v2, rayTo); btTransform ident; ident.setIdentity(); m_colShape->addChildShape(ident, tet); } }; btCompoundShape* btCreateCompoundFromGimpactShape(const btGImpactMeshShape* gimpactMesh, btScalar depth) { btCompoundShape* colShape = new btCompoundFromGimpactShape(); btTransform tr; tr.setIdentity(); MyInternalTriangleIndexCallback cb(colShape, gimpactMesh, depth); btVector3 aabbMin, aabbMax; gimpactMesh->getAabb(tr, aabbMin, aabbMax); gimpactMesh->getMeshInterface()->InternalProcessAllTriangles(&cb, aabbMin, aabbMax); return colShape; } #endif //BT_COMPOUND_FROM_GIMPACT