summaryrefslogtreecommitdiff
path: root/thirdparty/bullet/BulletCollision/Gimpact/btCompoundFromGimpact.h
blob: 19f7ecddd0e79fff03c5fb0f8731baaa87af8b67 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#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