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