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