#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