1 /*! \file btGImpactShape.h
2 \author Francisco Len N�jera
3 */
4 /*
5 This source file is part of GIMPACT Library.
6 
7 For the latest info, see http://gimpact.sourceforge.net/
8 
9 Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
10 email: projectileman@yahoo.com
11 
12 
13 This software is provided 'as-is', without any express or implied warranty.
14 In no event will the authors be held liable for any damages arising from the use of this software.
15 Permission is granted to anyone to use this software for any purpose,
16 including commercial applications, and to alter it and redistribute it freely,
17 subject to the following restrictions:
18 
19 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.
20 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
21 3. This notice may not be removed or altered from any source distribution.
22 */
23 
24 #ifndef GIMPACT_SHAPE_H
25 #define GIMPACT_SHAPE_H
26 
27 #include "BulletCollision/CollisionShapes/btCollisionShape.h"
28 #include "BulletCollision/CollisionShapes/btTriangleShape.h"
29 #include "BulletCollision/CollisionShapes/btStridingMeshInterface.h"
30 #include "BulletCollision/CollisionShapes/btCollisionMargin.h"
31 #include "BulletCollision/CollisionDispatch/btCollisionWorld.h"
32 #include "BulletCollision/CollisionShapes/btConcaveShape.h"
33 #include "BulletCollision/CollisionShapes/btTetrahedronShape.h"
34 #include "LinearMath/btVector3.h"
35 #include "LinearMath/btTransform.h"
36 #include "LinearMath/btMatrix3x3.h"
37 #include "LinearMath/btAlignedObjectArray.h"
38 
39 #include "btGImpactQuantizedBvh.h"  // box tree class
40 
41 //! declare Quantized trees, (you can change to float based trees)
42 typedef btGImpactQuantizedBvh btGImpactBoxSet;
43 
44 enum eGIMPACT_SHAPE_TYPE
45 {
46 	CONST_GIMPACT_COMPOUND_SHAPE = 0,
47 	CONST_GIMPACT_TRIMESH_SHAPE_PART,
48 	CONST_GIMPACT_TRIMESH_SHAPE
49 };
50 
51 //! Helper class for tetrahedrons
52 class btTetrahedronShapeEx : public btBU_Simplex1to4
53 {
54 public:
btTetrahedronShapeEx()55 	btTetrahedronShapeEx()
56 	{
57 		m_numVertices = 4;
58 	}
59 
setVertices(const btVector3 & v0,const btVector3 & v1,const btVector3 & v2,const btVector3 & v3)60 	SIMD_FORCE_INLINE void setVertices(
61 		const btVector3& v0, const btVector3& v1,
62 		const btVector3& v2, const btVector3& v3)
63 	{
64 		m_vertices[0] = v0;
65 		m_vertices[1] = v1;
66 		m_vertices[2] = v2;
67 		m_vertices[3] = v3;
68 		recalcLocalAabb();
69 	}
70 };
71 
72 //! Base class for gimpact shapes
73 class btGImpactShapeInterface : public btConcaveShape
74 {
75 protected:
76 	btAABB m_localAABB;
77 	bool m_needs_update;
78 	btVector3 localScaling;
79 	btGImpactBoxSet m_box_set;  // optionally boxset
80 
81 	//! use this function for perfofm refit in bounding boxes
82 	//! use this function for perfofm refit in bounding boxes
calcLocalAABB()83 	virtual void calcLocalAABB()
84 	{
85 		lockChildShapes();
86 		if (m_box_set.getNodeCount() == 0)
87 		{
88 			m_box_set.buildSet();
89 		}
90 		else
91 		{
92 			m_box_set.update();
93 		}
94 		unlockChildShapes();
95 
96 		m_localAABB = m_box_set.getGlobalBox();
97 	}
98 
99 public:
btGImpactShapeInterface()100 	btGImpactShapeInterface()
101 	{
102 		m_shapeType = GIMPACT_SHAPE_PROXYTYPE;
103 		m_localAABB.invalidate();
104 		m_needs_update = true;
105 		localScaling.setValue(1.f, 1.f, 1.f);
106 	}
107 
108 	//! performs refit operation
109 	/*!
110 	Updates the entire Box set of this shape.
111 	\pre postUpdate() must be called for attemps to calculating the box set, else this function
112 		will does nothing.
113 	\post if m_needs_update == true, then it calls calcLocalAABB();
114 	*/
updateBound()115 	SIMD_FORCE_INLINE void updateBound()
116 	{
117 		if (!m_needs_update) return;
118 		calcLocalAABB();
119 		m_needs_update = false;
120 	}
121 
122 	//! If the Bounding box is not updated, then this class attemps to calculate it.
123 	/*!
124     \post Calls updateBound() for update the box set.
125     */
getAabb(const btTransform & t,btVector3 & aabbMin,btVector3 & aabbMax)126 	void getAabb(const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
127 	{
128 		btAABB transformedbox = m_localAABB;
129 		transformedbox.appy_transform(t);
130 		aabbMin = transformedbox.m_min;
131 		aabbMax = transformedbox.m_max;
132 	}
133 
134 	//! Tells to this object that is needed to refit the box set
postUpdate()135 	virtual void postUpdate()
136 	{
137 		m_needs_update = true;
138 	}
139 
140 	//! Obtains the local box, which is the global calculated box of the total of subshapes
getLocalBox()141 	SIMD_FORCE_INLINE const btAABB& getLocalBox()
142 	{
143 		return m_localAABB;
144 	}
145 
getShapeType()146 	virtual int getShapeType() const
147 	{
148 		return GIMPACT_SHAPE_PROXYTYPE;
149 	}
150 
151 	/*!
152 	\post You must call updateBound() for update the box set.
153 	*/
setLocalScaling(const btVector3 & scaling)154 	virtual void setLocalScaling(const btVector3& scaling)
155 	{
156 		localScaling = scaling;
157 		postUpdate();
158 	}
159 
getLocalScaling()160 	virtual const btVector3& getLocalScaling() const
161 	{
162 		return localScaling;
163 	}
164 
setMargin(btScalar margin)165 	virtual void setMargin(btScalar margin)
166 	{
167 		m_collisionMargin = margin;
168 		int i = getNumChildShapes();
169 		while (i--)
170 		{
171 			btCollisionShape* child = getChildShape(i);
172 			child->setMargin(margin);
173 		}
174 
175 		m_needs_update = true;
176 	}
177 
178 	//! Subshape member functions
179 	//!@{
180 
181 	//! Base method for determinig which kind of GIMPACT shape we get
182 	virtual eGIMPACT_SHAPE_TYPE getGImpactShapeType() const = 0;
183 
184 	//! gets boxset
getBoxSet()185 	SIMD_FORCE_INLINE const btGImpactBoxSet* getBoxSet() const
186 	{
187 		return &m_box_set;
188 	}
189 
190 	//! Determines if this class has a hierarchy structure for sorting its primitives
hasBoxSet()191 	SIMD_FORCE_INLINE bool hasBoxSet() const
192 	{
193 		if (m_box_set.getNodeCount() == 0) return false;
194 		return true;
195 	}
196 
197 	//! Obtains the primitive manager
198 	virtual const btPrimitiveManagerBase* getPrimitiveManager() const = 0;
199 
200 	//! Gets the number of children
201 	virtual int getNumChildShapes() const = 0;
202 
203 	//! if true, then its children must get transforms.
204 	virtual bool childrenHasTransform() const = 0;
205 
206 	//! Determines if this shape has triangles
207 	virtual bool needsRetrieveTriangles() const = 0;
208 
209 	//! Determines if this shape has tetrahedrons
210 	virtual bool needsRetrieveTetrahedrons() const = 0;
211 
212 	virtual void getBulletTriangle(int prim_index, btTriangleShapeEx& triangle) const = 0;
213 
214 	virtual void getBulletTetrahedron(int prim_index, btTetrahedronShapeEx& tetrahedron) const = 0;
215 
216 	//! call when reading child shapes
lockChildShapes()217 	virtual void lockChildShapes() const
218 	{
219 	}
220 
unlockChildShapes()221 	virtual void unlockChildShapes() const
222 	{
223 	}
224 
225 	//! if this trimesh
getPrimitiveTriangle(int index,btPrimitiveTriangle & triangle)226 	SIMD_FORCE_INLINE void getPrimitiveTriangle(int index, btPrimitiveTriangle& triangle) const
227 	{
228 		getPrimitiveManager()->get_primitive_triangle(index, triangle);
229 	}
230 
231 	//! Retrieves the bound from a child
232 	/*!
233     */
getChildAabb(int child_index,const btTransform & t,btVector3 & aabbMin,btVector3 & aabbMax)234 	virtual void getChildAabb(int child_index, const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
235 	{
236 		btAABB child_aabb;
237 		getPrimitiveManager()->get_primitive_box(child_index, child_aabb);
238 		child_aabb.appy_transform(t);
239 		aabbMin = child_aabb.m_min;
240 		aabbMax = child_aabb.m_max;
241 	}
242 
243 	//! Gets the children
244 	virtual btCollisionShape* getChildShape(int index) = 0;
245 
246 	//! Gets the child
247 	virtual const btCollisionShape* getChildShape(int index) const = 0;
248 
249 	//! Gets the children transform
250 	virtual btTransform getChildTransform(int index) const = 0;
251 
252 	//! Sets the children transform
253 	/*!
254 	\post You must call updateBound() for update the box set.
255 	*/
256 	virtual void setChildTransform(int index, const btTransform& transform) = 0;
257 
258 	//!@}
259 
260 	//! virtual method for ray collision
rayTest(const btVector3 & rayFrom,const btVector3 & rayTo,btCollisionWorld::RayResultCallback & resultCallback)261 	virtual void rayTest(const btVector3& rayFrom, const btVector3& rayTo, btCollisionWorld::RayResultCallback& resultCallback) const
262 	{
263 		(void)rayFrom;
264 		(void)rayTo;
265 		(void)resultCallback;
266 	}
267 
268 	//! Function for retrieve triangles.
269 	/*!
270 	It gives the triangles in local space
271 	*/
processAllTriangles(btTriangleCallback * callback,const btVector3 & aabbMin,const btVector3 & aabbMax)272 	virtual void processAllTriangles(btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax) const
273 	{
274 		(void)callback;
275 		(void)aabbMin;
276 		(void)aabbMax;
277 	}
278 
279 	//! Function for retrieve triangles.
280 	/*!
281 	It gives the triangles in local space
282 	*/
processAllTrianglesRay(btTriangleCallback *,const btVector3 &,const btVector3 &)283 	virtual void processAllTrianglesRay(btTriangleCallback* /*callback*/, const btVector3& /*rayFrom*/, const btVector3& /*rayTo*/) const
284 	{
285 	}
286 
287 	//!@}
288 };
289 
290 //! btGImpactCompoundShape allows to handle multiple btCollisionShape objects at once
291 /*!
292 This class only can manage Convex subshapes
293 */
294 class btGImpactCompoundShape : public btGImpactShapeInterface
295 {
296 public:
297 	//! compound primitive manager
298 	class CompoundPrimitiveManager : public btPrimitiveManagerBase
299 	{
300 	public:
~CompoundPrimitiveManager()301 		virtual ~CompoundPrimitiveManager() {}
302 		btGImpactCompoundShape* m_compoundShape;
303 
CompoundPrimitiveManager(const CompoundPrimitiveManager & compound)304 		CompoundPrimitiveManager(const CompoundPrimitiveManager& compound)
305 			: btPrimitiveManagerBase()
306 		{
307 			m_compoundShape = compound.m_compoundShape;
308 		}
309 
CompoundPrimitiveManager(btGImpactCompoundShape * compoundShape)310 		CompoundPrimitiveManager(btGImpactCompoundShape* compoundShape)
311 		{
312 			m_compoundShape = compoundShape;
313 		}
314 
CompoundPrimitiveManager()315 		CompoundPrimitiveManager()
316 		{
317 			m_compoundShape = NULL;
318 		}
319 
is_trimesh()320 		virtual bool is_trimesh() const
321 		{
322 			return false;
323 		}
324 
get_primitive_count()325 		virtual int get_primitive_count() const
326 		{
327 			return (int)m_compoundShape->getNumChildShapes();
328 		}
329 
get_primitive_box(int prim_index,btAABB & primbox)330 		virtual void get_primitive_box(int prim_index, btAABB& primbox) const
331 		{
332 			btTransform prim_trans;
333 			if (m_compoundShape->childrenHasTransform())
334 			{
335 				prim_trans = m_compoundShape->getChildTransform(prim_index);
336 			}
337 			else
338 			{
339 				prim_trans.setIdentity();
340 			}
341 			const btCollisionShape* shape = m_compoundShape->getChildShape(prim_index);
342 			shape->getAabb(prim_trans, primbox.m_min, primbox.m_max);
343 		}
344 
get_primitive_triangle(int prim_index,btPrimitiveTriangle & triangle)345 		virtual void get_primitive_triangle(int prim_index, btPrimitiveTriangle& triangle) const
346 		{
347 			btAssert(0);
348 			(void)prim_index;
349 			(void)triangle;
350 		}
351 	};
352 
353 protected:
354 	CompoundPrimitiveManager m_primitive_manager;
355 	btAlignedObjectArray<btTransform> m_childTransforms;
356 	btAlignedObjectArray<btCollisionShape*> m_childShapes;
357 
358 public:
359 	btGImpactCompoundShape(bool children_has_transform = true)
360 	{
361 		(void)children_has_transform;
362 		m_primitive_manager.m_compoundShape = this;
363 		m_box_set.setPrimitiveManager(&m_primitive_manager);
364 	}
365 
~btGImpactCompoundShape()366 	virtual ~btGImpactCompoundShape()
367 	{
368 	}
369 
370 	//! if true, then its children must get transforms.
childrenHasTransform()371 	virtual bool childrenHasTransform() const
372 	{
373 		if (m_childTransforms.size() == 0) return false;
374 		return true;
375 	}
376 
377 	//! Obtains the primitive manager
getPrimitiveManager()378 	virtual const btPrimitiveManagerBase* getPrimitiveManager() const
379 	{
380 		return &m_primitive_manager;
381 	}
382 
383 	//! Obtains the compopund primitive manager
getCompoundPrimitiveManager()384 	SIMD_FORCE_INLINE CompoundPrimitiveManager* getCompoundPrimitiveManager()
385 	{
386 		return &m_primitive_manager;
387 	}
388 
389 	//! Gets the number of children
getNumChildShapes()390 	virtual int getNumChildShapes() const
391 	{
392 		return m_childShapes.size();
393 	}
394 
395 	//! Use this method for adding children. Only Convex shapes are allowed.
addChildShape(const btTransform & localTransform,btCollisionShape * shape)396 	void addChildShape(const btTransform& localTransform, btCollisionShape* shape)
397 	{
398 		btAssert(shape->isConvex());
399 		m_childTransforms.push_back(localTransform);
400 		m_childShapes.push_back(shape);
401 	}
402 
403 	//! Use this method for adding children. Only Convex shapes are allowed.
addChildShape(btCollisionShape * shape)404 	void addChildShape(btCollisionShape* shape)
405 	{
406 		btAssert(shape->isConvex());
407 		m_childShapes.push_back(shape);
408 	}
409 
410 	//! Gets the children
getChildShape(int index)411 	virtual btCollisionShape* getChildShape(int index)
412 	{
413 		return m_childShapes[index];
414 	}
415 
416 	//! Gets the children
getChildShape(int index)417 	virtual const btCollisionShape* getChildShape(int index) const
418 	{
419 		return m_childShapes[index];
420 	}
421 
422 	//! Retrieves the bound from a child
423 	/*!
424     */
getChildAabb(int child_index,const btTransform & t,btVector3 & aabbMin,btVector3 & aabbMax)425 	virtual void getChildAabb(int child_index, const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
426 	{
427 		if (childrenHasTransform())
428 		{
429 			m_childShapes[child_index]->getAabb(t * m_childTransforms[child_index], aabbMin, aabbMax);
430 		}
431 		else
432 		{
433 			m_childShapes[child_index]->getAabb(t, aabbMin, aabbMax);
434 		}
435 	}
436 
437 	//! Gets the children transform
getChildTransform(int index)438 	virtual btTransform getChildTransform(int index) const
439 	{
440 		btAssert(m_childTransforms.size() == m_childShapes.size());
441 		return m_childTransforms[index];
442 	}
443 
444 	//! Sets the children transform
445 	/*!
446 	\post You must call updateBound() for update the box set.
447 	*/
setChildTransform(int index,const btTransform & transform)448 	virtual void setChildTransform(int index, const btTransform& transform)
449 	{
450 		btAssert(m_childTransforms.size() == m_childShapes.size());
451 		m_childTransforms[index] = transform;
452 		postUpdate();
453 	}
454 
455 	//! Determines if this shape has triangles
needsRetrieveTriangles()456 	virtual bool needsRetrieveTriangles() const
457 	{
458 		return false;
459 	}
460 
461 	//! Determines if this shape has tetrahedrons
needsRetrieveTetrahedrons()462 	virtual bool needsRetrieveTetrahedrons() const
463 	{
464 		return false;
465 	}
466 
getBulletTriangle(int prim_index,btTriangleShapeEx & triangle)467 	virtual void getBulletTriangle(int prim_index, btTriangleShapeEx& triangle) const
468 	{
469 		(void)prim_index;
470 		(void)triangle;
471 		btAssert(0);
472 	}
473 
getBulletTetrahedron(int prim_index,btTetrahedronShapeEx & tetrahedron)474 	virtual void getBulletTetrahedron(int prim_index, btTetrahedronShapeEx& tetrahedron) const
475 	{
476 		(void)prim_index;
477 		(void)tetrahedron;
478 		btAssert(0);
479 	}
480 
481 	//! Calculates the exact inertia tensor for this shape
482 	virtual void calculateLocalInertia(btScalar mass, btVector3& inertia) const;
483 
getName()484 	virtual const char* getName() const
485 	{
486 		return "GImpactCompound";
487 	}
488 
getGImpactShapeType()489 	virtual eGIMPACT_SHAPE_TYPE getGImpactShapeType() const
490 	{
491 		return CONST_GIMPACT_COMPOUND_SHAPE;
492 	}
493 };
494 
495 //! This class manages a sub part of a mesh supplied by the btStridingMeshInterface interface.
496 /*!
497 - Simply create this shape by passing the btStridingMeshInterface to the constructor btGImpactMeshShapePart, then you must call updateBound() after creating the mesh
498 - When making operations with this shape, you must call <b>lock</b> before accessing to the trimesh primitives, and then call <b>unlock</b>
499 - You can handle deformable meshes with this shape, by calling postUpdate() every time when changing the mesh vertices.
500 
501 */
502 class btGImpactMeshShapePart : public btGImpactShapeInterface
503 {
504 public:
505 	//! Trimesh primitive manager
506 	/*!
507 	Manages the info from btStridingMeshInterface object and controls the Lock/Unlock mechanism
508 	*/
509 	class TrimeshPrimitiveManager : public btPrimitiveManagerBase
510 	{
511 	public:
512 		btScalar m_margin;
513 		btStridingMeshInterface* m_meshInterface;
514 		btVector3 m_scale;
515 		int m_part;
516 		int m_lock_count;
517 		const unsigned char* vertexbase;
518 		int numverts;
519 		PHY_ScalarType type;
520 		int stride;
521 		const unsigned char* indexbase;
522 		int indexstride;
523 		int numfaces;
524 		PHY_ScalarType indicestype;
525 
TrimeshPrimitiveManager()526 		TrimeshPrimitiveManager()
527 		{
528 			m_meshInterface = NULL;
529 			m_part = 0;
530 			m_margin = 0.01f;
531 			m_scale = btVector3(1.f, 1.f, 1.f);
532 			m_lock_count = 0;
533 			vertexbase = 0;
534 			numverts = 0;
535 			stride = 0;
536 			indexbase = 0;
537 			indexstride = 0;
538 			numfaces = 0;
539 		}
540 
TrimeshPrimitiveManager(const TrimeshPrimitiveManager & manager)541 		TrimeshPrimitiveManager(const TrimeshPrimitiveManager& manager)
542 			: btPrimitiveManagerBase()
543 		{
544 			m_meshInterface = manager.m_meshInterface;
545 			m_part = manager.m_part;
546 			m_margin = manager.m_margin;
547 			m_scale = manager.m_scale;
548 			m_lock_count = 0;
549 			vertexbase = 0;
550 			numverts = 0;
551 			stride = 0;
552 			indexbase = 0;
553 			indexstride = 0;
554 			numfaces = 0;
555 		}
556 
TrimeshPrimitiveManager(btStridingMeshInterface * meshInterface,int part)557 		TrimeshPrimitiveManager(
558 			btStridingMeshInterface* meshInterface, int part)
559 		{
560 			m_meshInterface = meshInterface;
561 			m_part = part;
562 			m_scale = m_meshInterface->getScaling();
563 			m_margin = 0.1f;
564 			m_lock_count = 0;
565 			vertexbase = 0;
566 			numverts = 0;
567 			stride = 0;
568 			indexbase = 0;
569 			indexstride = 0;
570 			numfaces = 0;
571 		}
572 
~TrimeshPrimitiveManager()573 		virtual ~TrimeshPrimitiveManager() {}
574 
lock()575 		void lock()
576 		{
577 			if (m_lock_count > 0)
578 			{
579 				m_lock_count++;
580 				return;
581 			}
582 			m_meshInterface->getLockedReadOnlyVertexIndexBase(
583 				&vertexbase, numverts,
584 				type, stride, &indexbase, indexstride, numfaces, indicestype, m_part);
585 
586 			m_lock_count = 1;
587 		}
588 
unlock()589 		void unlock()
590 		{
591 			if (m_lock_count == 0) return;
592 			if (m_lock_count > 1)
593 			{
594 				--m_lock_count;
595 				return;
596 			}
597 			m_meshInterface->unLockReadOnlyVertexBase(m_part);
598 			vertexbase = NULL;
599 			m_lock_count = 0;
600 		}
601 
is_trimesh()602 		virtual bool is_trimesh() const
603 		{
604 			return true;
605 		}
606 
get_primitive_count()607 		virtual int get_primitive_count() const
608 		{
609 			return (int)numfaces;
610 		}
611 
get_vertex_count()612 		SIMD_FORCE_INLINE int get_vertex_count() const
613 		{
614 			return (int)numverts;
615 		}
616 
get_indices(int face_index,unsigned int & i0,unsigned int & i1,unsigned int & i2)617 		SIMD_FORCE_INLINE void get_indices(int face_index, unsigned int& i0, unsigned int& i1, unsigned int& i2) const
618 		{
619 			if (indicestype == PHY_SHORT)
620 			{
621 				unsigned short* s_indices = (unsigned short*)(indexbase + face_index * indexstride);
622 				i0 = s_indices[0];
623 				i1 = s_indices[1];
624 				i2 = s_indices[2];
625 			}
626 			else
627 			{
628 				unsigned int* i_indices = (unsigned int*)(indexbase + face_index * indexstride);
629 				i0 = i_indices[0];
630 				i1 = i_indices[1];
631 				i2 = i_indices[2];
632 			}
633 		}
634 
get_vertex(unsigned int vertex_index,btVector3 & vertex)635 		SIMD_FORCE_INLINE void get_vertex(unsigned int vertex_index, btVector3& vertex) const
636 		{
637 			if (type == PHY_DOUBLE)
638 			{
639 				double* dvertices = (double*)(vertexbase + vertex_index * stride);
640 				vertex[0] = btScalar(dvertices[0] * m_scale[0]);
641 				vertex[1] = btScalar(dvertices[1] * m_scale[1]);
642 				vertex[2] = btScalar(dvertices[2] * m_scale[2]);
643 			}
644 			else
645 			{
646 				float* svertices = (float*)(vertexbase + vertex_index * stride);
647 				vertex[0] = svertices[0] * m_scale[0];
648 				vertex[1] = svertices[1] * m_scale[1];
649 				vertex[2] = svertices[2] * m_scale[2];
650 			}
651 		}
652 
get_primitive_box(int prim_index,btAABB & primbox)653 		virtual void get_primitive_box(int prim_index, btAABB& primbox) const
654 		{
655 			btPrimitiveTriangle triangle;
656 			get_primitive_triangle(prim_index, triangle);
657 			primbox.calc_from_triangle_margin(
658 				triangle.m_vertices[0],
659 				triangle.m_vertices[1], triangle.m_vertices[2], triangle.m_margin);
660 		}
661 
get_primitive_triangle(int prim_index,btPrimitiveTriangle & triangle)662 		virtual void get_primitive_triangle(int prim_index, btPrimitiveTriangle& triangle) const
663 		{
664 			unsigned int indices[3];
665 			get_indices(prim_index, indices[0], indices[1], indices[2]);
666 			get_vertex(indices[0], triangle.m_vertices[0]);
667 			get_vertex(indices[1], triangle.m_vertices[1]);
668 			get_vertex(indices[2], triangle.m_vertices[2]);
669 			triangle.m_margin = m_margin;
670 		}
671 
get_bullet_triangle(int prim_index,btTriangleShapeEx & triangle)672 		SIMD_FORCE_INLINE void get_bullet_triangle(int prim_index, btTriangleShapeEx& triangle) const
673 		{
674 			unsigned int indices[3];
675 			get_indices(prim_index, indices[0], indices[1], indices[2]);
676 			get_vertex(indices[0], triangle.m_vertices1[0]);
677 			get_vertex(indices[1], triangle.m_vertices1[1]);
678 			get_vertex(indices[2], triangle.m_vertices1[2]);
679 			triangle.setMargin(m_margin);
680 		}
681 	};
682 
683 protected:
684 	TrimeshPrimitiveManager m_primitive_manager;
685 
686 public:
btGImpactMeshShapePart()687 	btGImpactMeshShapePart()
688 	{
689 		m_box_set.setPrimitiveManager(&m_primitive_manager);
690 	}
691 
692 	btGImpactMeshShapePart(btStridingMeshInterface* meshInterface, int part);
693 	virtual ~btGImpactMeshShapePart();
694 
695 	//! if true, then its children must get transforms.
childrenHasTransform()696 	virtual bool childrenHasTransform() const
697 	{
698 		return false;
699 	}
700 
701 	//! call when reading child shapes
702 	virtual void lockChildShapes() const;
703 	virtual void unlockChildShapes() const;
704 
705 	//! Gets the number of children
getNumChildShapes()706 	virtual int getNumChildShapes() const
707 	{
708 		return m_primitive_manager.get_primitive_count();
709 	}
710 
711 	//! Gets the children
getChildShape(int index)712 	virtual btCollisionShape* getChildShape(int index)
713 	{
714 		(void)index;
715 		btAssert(0);
716 		return NULL;
717 	}
718 
719 	//! Gets the child
getChildShape(int index)720 	virtual const btCollisionShape* getChildShape(int index) const
721 	{
722 		(void)index;
723 		btAssert(0);
724 		return NULL;
725 	}
726 
727 	//! Gets the children transform
getChildTransform(int index)728 	virtual btTransform getChildTransform(int index) const
729 	{
730 		(void)index;
731 		btAssert(0);
732 		return btTransform();
733 	}
734 
735 	//! Sets the children transform
736 	/*!
737 	\post You must call updateBound() for update the box set.
738 	*/
setChildTransform(int index,const btTransform & transform)739 	virtual void setChildTransform(int index, const btTransform& transform)
740 	{
741 		(void)index;
742 		(void)transform;
743 		btAssert(0);
744 	}
745 
746 	//! Obtains the primitive manager
getPrimitiveManager()747 	virtual const btPrimitiveManagerBase* getPrimitiveManager() const
748 	{
749 		return &m_primitive_manager;
750 	}
751 
getTrimeshPrimitiveManager()752 	SIMD_FORCE_INLINE TrimeshPrimitiveManager* getTrimeshPrimitiveManager()
753 	{
754 		return &m_primitive_manager;
755 	}
756 
757 	virtual void calculateLocalInertia(btScalar mass, btVector3& inertia) const;
758 
getName()759 	virtual const char* getName() const
760 	{
761 		return "GImpactMeshShapePart";
762 	}
763 
getGImpactShapeType()764 	virtual eGIMPACT_SHAPE_TYPE getGImpactShapeType() const
765 	{
766 		return CONST_GIMPACT_TRIMESH_SHAPE_PART;
767 	}
768 
769 	//! Determines if this shape has triangles
needsRetrieveTriangles()770 	virtual bool needsRetrieveTriangles() const
771 	{
772 		return true;
773 	}
774 
775 	//! Determines if this shape has tetrahedrons
needsRetrieveTetrahedrons()776 	virtual bool needsRetrieveTetrahedrons() const
777 	{
778 		return false;
779 	}
780 
getBulletTriangle(int prim_index,btTriangleShapeEx & triangle)781 	virtual void getBulletTriangle(int prim_index, btTriangleShapeEx& triangle) const
782 	{
783 		m_primitive_manager.get_bullet_triangle(prim_index, triangle);
784 	}
785 
getBulletTetrahedron(int prim_index,btTetrahedronShapeEx & tetrahedron)786 	virtual void getBulletTetrahedron(int prim_index, btTetrahedronShapeEx& tetrahedron) const
787 	{
788 		(void)prim_index;
789 		(void)tetrahedron;
790 		btAssert(0);
791 	}
792 
getVertexCount()793 	SIMD_FORCE_INLINE int getVertexCount() const
794 	{
795 		return m_primitive_manager.get_vertex_count();
796 	}
797 
getVertex(int vertex_index,btVector3 & vertex)798 	SIMD_FORCE_INLINE void getVertex(int vertex_index, btVector3& vertex) const
799 	{
800 		m_primitive_manager.get_vertex(vertex_index, vertex);
801 	}
802 
setMargin(btScalar margin)803 	SIMD_FORCE_INLINE void setMargin(btScalar margin)
804 	{
805 		m_primitive_manager.m_margin = margin;
806 		postUpdate();
807 	}
808 
getMargin()809 	SIMD_FORCE_INLINE btScalar getMargin() const
810 	{
811 		return m_primitive_manager.m_margin;
812 	}
813 
setLocalScaling(const btVector3 & scaling)814 	virtual void setLocalScaling(const btVector3& scaling)
815 	{
816 		m_primitive_manager.m_scale = scaling;
817 		postUpdate();
818 	}
819 
getLocalScaling()820 	virtual const btVector3& getLocalScaling() const
821 	{
822 		return m_primitive_manager.m_scale;
823 	}
824 
getPart()825 	SIMD_FORCE_INLINE int getPart() const
826 	{
827 		return (int)m_primitive_manager.m_part;
828 	}
829 
830 	virtual void processAllTriangles(btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax) const;
831 	virtual void processAllTrianglesRay(btTriangleCallback* callback, const btVector3& rayFrom, const btVector3& rayTo) const;
832 };
833 
834 //! This class manages a mesh supplied by the btStridingMeshInterface interface.
835 /*!
836 Set of btGImpactMeshShapePart parts
837 - Simply create this shape by passing the btStridingMeshInterface to the constructor btGImpactMeshShape, then you must call updateBound() after creating the mesh
838 
839 - You can handle deformable meshes with this shape, by calling postUpdate() every time when changing the mesh vertices.
840 
841 */
842 class btGImpactMeshShape : public btGImpactShapeInterface
843 {
844 	btStridingMeshInterface* m_meshInterface;
845 
846 protected:
847 	btAlignedObjectArray<btGImpactMeshShapePart*> m_mesh_parts;
buildMeshParts(btStridingMeshInterface * meshInterface)848 	void buildMeshParts(btStridingMeshInterface* meshInterface)
849 	{
850 		for (int i = 0; i < meshInterface->getNumSubParts(); ++i)
851 		{
852 			btGImpactMeshShapePart* newpart = new btGImpactMeshShapePart(meshInterface, i);
853 			m_mesh_parts.push_back(newpart);
854 		}
855 	}
856 
857 	//! use this function for perfofm refit in bounding boxes
calcLocalAABB()858 	virtual void calcLocalAABB()
859 	{
860 		m_localAABB.invalidate();
861 		int i = m_mesh_parts.size();
862 		while (i--)
863 		{
864 			m_mesh_parts[i]->updateBound();
865 			m_localAABB.merge(m_mesh_parts[i]->getLocalBox());
866 		}
867 	}
868 
869 public:
btGImpactMeshShape(btStridingMeshInterface * meshInterface)870 	btGImpactMeshShape(btStridingMeshInterface* meshInterface)
871 	{
872 		m_meshInterface = meshInterface;
873 		buildMeshParts(meshInterface);
874 	}
875 
~btGImpactMeshShape()876 	virtual ~btGImpactMeshShape()
877 	{
878 		int i = m_mesh_parts.size();
879 		while (i--)
880 		{
881 			btGImpactMeshShapePart* part = m_mesh_parts[i];
882 			delete part;
883 		}
884 		m_mesh_parts.clear();
885 	}
886 
getMeshInterface()887 	btStridingMeshInterface* getMeshInterface()
888 	{
889 		return m_meshInterface;
890 	}
891 
getMeshInterface()892 	const btStridingMeshInterface* getMeshInterface() const
893 	{
894 		return m_meshInterface;
895 	}
896 
getMeshPartCount()897 	int getMeshPartCount() const
898 	{
899 		return m_mesh_parts.size();
900 	}
901 
getMeshPart(int index)902 	btGImpactMeshShapePart* getMeshPart(int index)
903 	{
904 		return m_mesh_parts[index];
905 	}
906 
getMeshPart(int index)907 	const btGImpactMeshShapePart* getMeshPart(int index) const
908 	{
909 		return m_mesh_parts[index];
910 	}
911 
setLocalScaling(const btVector3 & scaling)912 	virtual void setLocalScaling(const btVector3& scaling)
913 	{
914 		localScaling = scaling;
915 
916 		int i = m_mesh_parts.size();
917 		while (i--)
918 		{
919 			btGImpactMeshShapePart* part = m_mesh_parts[i];
920 			part->setLocalScaling(scaling);
921 		}
922 
923 		m_needs_update = true;
924 	}
925 
setMargin(btScalar margin)926 	virtual void setMargin(btScalar margin)
927 	{
928 		m_collisionMargin = margin;
929 
930 		int i = m_mesh_parts.size();
931 		while (i--)
932 		{
933 			btGImpactMeshShapePart* part = m_mesh_parts[i];
934 			part->setMargin(margin);
935 		}
936 
937 		m_needs_update = true;
938 	}
939 
940 	//! Tells to this object that is needed to refit all the meshes
postUpdate()941 	virtual void postUpdate()
942 	{
943 		int i = m_mesh_parts.size();
944 		while (i--)
945 		{
946 			btGImpactMeshShapePart* part = m_mesh_parts[i];
947 			part->postUpdate();
948 		}
949 
950 		m_needs_update = true;
951 	}
952 
953 	virtual void calculateLocalInertia(btScalar mass, btVector3& inertia) const;
954 
955 	//! Obtains the primitive manager
getPrimitiveManager()956 	virtual const btPrimitiveManagerBase* getPrimitiveManager() const
957 	{
958 		btAssert(0);
959 		return NULL;
960 	}
961 
962 	//! Gets the number of children
getNumChildShapes()963 	virtual int getNumChildShapes() const
964 	{
965 		btAssert(0);
966 		return 0;
967 	}
968 
969 	//! if true, then its children must get transforms.
childrenHasTransform()970 	virtual bool childrenHasTransform() const
971 	{
972 		btAssert(0);
973 		return false;
974 	}
975 
976 	//! Determines if this shape has triangles
needsRetrieveTriangles()977 	virtual bool needsRetrieveTriangles() const
978 	{
979 		btAssert(0);
980 		return false;
981 	}
982 
983 	//! Determines if this shape has tetrahedrons
needsRetrieveTetrahedrons()984 	virtual bool needsRetrieveTetrahedrons() const
985 	{
986 		btAssert(0);
987 		return false;
988 	}
989 
getBulletTriangle(int prim_index,btTriangleShapeEx & triangle)990 	virtual void getBulletTriangle(int prim_index, btTriangleShapeEx& triangle) const
991 	{
992 		(void)prim_index;
993 		(void)triangle;
994 		btAssert(0);
995 	}
996 
getBulletTetrahedron(int prim_index,btTetrahedronShapeEx & tetrahedron)997 	virtual void getBulletTetrahedron(int prim_index, btTetrahedronShapeEx& tetrahedron) const
998 	{
999 		(void)prim_index;
1000 		(void)tetrahedron;
1001 		btAssert(0);
1002 	}
1003 
1004 	//! call when reading child shapes
lockChildShapes()1005 	virtual void lockChildShapes() const
1006 	{
1007 		btAssert(0);
1008 	}
1009 
unlockChildShapes()1010 	virtual void unlockChildShapes() const
1011 	{
1012 		btAssert(0);
1013 	}
1014 
1015 	//! Retrieves the bound from a child
1016 	/*!
1017     */
getChildAabb(int child_index,const btTransform & t,btVector3 & aabbMin,btVector3 & aabbMax)1018 	virtual void getChildAabb(int child_index, const btTransform& t, btVector3& aabbMin, btVector3& aabbMax) const
1019 	{
1020 		(void)child_index;
1021 		(void)t;
1022 		(void)aabbMin;
1023 		(void)aabbMax;
1024 		btAssert(0);
1025 	}
1026 
1027 	//! Gets the children
getChildShape(int index)1028 	virtual btCollisionShape* getChildShape(int index)
1029 	{
1030 		(void)index;
1031 		btAssert(0);
1032 		return NULL;
1033 	}
1034 
1035 	//! Gets the child
getChildShape(int index)1036 	virtual const btCollisionShape* getChildShape(int index) const
1037 	{
1038 		(void)index;
1039 		btAssert(0);
1040 		return NULL;
1041 	}
1042 
1043 	//! Gets the children transform
getChildTransform(int index)1044 	virtual btTransform getChildTransform(int index) const
1045 	{
1046 		(void)index;
1047 		btAssert(0);
1048 		return btTransform();
1049 	}
1050 
1051 	//! Sets the children transform
1052 	/*!
1053 	\post You must call updateBound() for update the box set.
1054 	*/
setChildTransform(int index,const btTransform & transform)1055 	virtual void setChildTransform(int index, const btTransform& transform)
1056 	{
1057 		(void)index;
1058 		(void)transform;
1059 		btAssert(0);
1060 	}
1061 
getGImpactShapeType()1062 	virtual eGIMPACT_SHAPE_TYPE getGImpactShapeType() const
1063 	{
1064 		return CONST_GIMPACT_TRIMESH_SHAPE;
1065 	}
1066 
getName()1067 	virtual const char* getName() const
1068 	{
1069 		return "GImpactMesh";
1070 	}
1071 
1072 	virtual void rayTest(const btVector3& rayFrom, const btVector3& rayTo, btCollisionWorld::RayResultCallback& resultCallback) const;
1073 
1074 	//! Function for retrieve triangles.
1075 	/*!
1076 	It gives the triangles in local space
1077 	*/
1078 	virtual void processAllTriangles(btTriangleCallback* callback, const btVector3& aabbMin, const btVector3& aabbMax) const;
1079 
1080 	virtual void processAllTrianglesRay(btTriangleCallback* callback, const btVector3& rayFrom, const btVector3& rayTo) const;
1081 
1082 	virtual int calculateSerializeBufferSize() const;
1083 
1084 	///fills the dataBuffer and returns the struct name (and 0 on failure)
1085 	virtual const char* serialize(void* dataBuffer, btSerializer* serializer) const;
1086 };
1087 
1088 ///do not change those serialization structures, it requires an updated sBulletDNAstr/sBulletDNAstr64
1089 struct btGImpactMeshShapeData
1090 {
1091 	btCollisionShapeData m_collisionShapeData;
1092 
1093 	btStridingMeshInterfaceData m_meshInterface;
1094 
1095 	btVector3FloatData m_localScaling;
1096 
1097 	float m_collisionMargin;
1098 
1099 	int m_gimpactSubType;
1100 };
1101 
calculateSerializeBufferSize()1102 SIMD_FORCE_INLINE int btGImpactMeshShape::calculateSerializeBufferSize() const
1103 {
1104 	return sizeof(btGImpactMeshShapeData);
1105 }
1106 
1107 #endif  //GIMPACT_MESH_SHAPE_H
1108