1 #ifndef BT_BOX_COLLISION_H_INCLUDED
2 #define BT_BOX_COLLISION_H_INCLUDED
3 
4 /*! \file gim_box_collision.h
5 \author Francisco Leon Najera
6 */
7 /*
8 This source file is part of GIMPACT Library.
9 
10 For the latest info, see http://gimpact.sourceforge.net/
11 
12 Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371.
13 email: projectileman@yahoo.com
14 
15 
16 This software is provided 'as-is', without any express or implied warranty.
17 In no event will the authors be held liable for any damages arising from the use of this software.
18 Permission is granted to anyone to use this software for any purpose,
19 including commercial applications, and to alter it and redistribute it freely,
20 subject to the following restrictions:
21 
22 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.
23 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
24 3. This notice may not be removed or altered from any source distribution.
25 */
26 
27 #include "LinearMath/btTransform.h"
28 
29 
30 ///Swap numbers
31 #define BT_SWAP_NUMBERS(a,b){ \
32     a = a+b; \
33     b = a-b; \
34     a = a-b; \
35 }\
36 
37 
38 #define BT_MAX(a,b) (a<b?b:a)
39 #define BT_MIN(a,b) (a>b?b:a)
40 
41 #define BT_GREATER(x, y)	btFabs(x) > (y)
42 
43 #define BT_MAX3(a,b,c) BT_MAX(a,BT_MAX(b,c))
44 #define BT_MIN3(a,b,c) BT_MIN(a,BT_MIN(b,c))
45 
46 
47 
48 
49 
50 
51 enum eBT_PLANE_INTERSECTION_TYPE
52 {
53 	BT_CONST_BACK_PLANE = 0,
54 	BT_CONST_COLLIDE_PLANE,
55 	BT_CONST_FRONT_PLANE
56 };
57 
58 //SIMD_FORCE_INLINE bool test_cross_edge_box(
59 //	const btVector3 & edge,
60 //	const btVector3 & absolute_edge,
61 //	const btVector3 & pointa,
62 //	const btVector3 & pointb, const btVector3 & extend,
63 //	int dir_index0,
64 //	int dir_index1
65 //	int component_index0,
66 //	int component_index1)
67 //{
68 //	// dir coords are -z and y
69 //
70 //	const btScalar dir0 = -edge[dir_index0];
71 //	const btScalar dir1 = edge[dir_index1];
72 //	btScalar pmin = pointa[component_index0]*dir0 + pointa[component_index1]*dir1;
73 //	btScalar pmax = pointb[component_index0]*dir0 + pointb[component_index1]*dir1;
74 //	//find minmax
75 //	if(pmin>pmax)
76 //	{
77 //		BT_SWAP_NUMBERS(pmin,pmax);
78 //	}
79 //	//find extends
80 //	const btScalar rad = extend[component_index0] * absolute_edge[dir_index0] +
81 //					extend[component_index1] * absolute_edge[dir_index1];
82 //
83 //	if(pmin>rad || -rad>pmax) return false;
84 //	return true;
85 //}
86 //
87 //SIMD_FORCE_INLINE bool test_cross_edge_box_X_axis(
88 //	const btVector3 & edge,
89 //	const btVector3 & absolute_edge,
90 //	const btVector3 & pointa,
91 //	const btVector3 & pointb, btVector3 & extend)
92 //{
93 //
94 //	return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,2,1,1,2);
95 //}
96 //
97 //
98 //SIMD_FORCE_INLINE bool test_cross_edge_box_Y_axis(
99 //	const btVector3 & edge,
100 //	const btVector3 & absolute_edge,
101 //	const btVector3 & pointa,
102 //	const btVector3 & pointb, btVector3 & extend)
103 //{
104 //
105 //	return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,0,2,2,0);
106 //}
107 //
108 //SIMD_FORCE_INLINE bool test_cross_edge_box_Z_axis(
109 //	const btVector3 & edge,
110 //	const btVector3 & absolute_edge,
111 //	const btVector3 & pointa,
112 //	const btVector3 & pointb, btVector3 & extend)
113 //{
114 //
115 //	return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,1,0,0,1);
116 //}
117 
118 
119 #define TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,i_dir_0,i_dir_1,i_comp_0,i_comp_1)\
120 {\
121 	const btScalar dir0 = -edge[i_dir_0];\
122 	const btScalar dir1 = edge[i_dir_1];\
123 	btScalar pmin = pointa[i_comp_0]*dir0 + pointa[i_comp_1]*dir1;\
124 	btScalar pmax = pointb[i_comp_0]*dir0 + pointb[i_comp_1]*dir1;\
125 	if(pmin>pmax)\
126 	{\
127 		BT_SWAP_NUMBERS(pmin,pmax); \
128 	}\
129 	const btScalar abs_dir0 = absolute_edge[i_dir_0];\
130 	const btScalar abs_dir1 = absolute_edge[i_dir_1];\
131 	const btScalar rad = _extend[i_comp_0] * abs_dir0 + _extend[i_comp_1] * abs_dir1;\
132 	if(pmin>rad || -rad>pmax) return false;\
133 }\
134 
135 
136 #define TEST_CROSS_EDGE_BOX_X_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\
137 {\
138 	TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,2,1,1,2);\
139 }\
140 
141 #define TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\
142 {\
143 	TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,0,2,2,0);\
144 }\
145 
146 #define TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\
147 {\
148 	TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,1,0,0,1);\
149 }\
150 
151 
152 //! Returns the dot product between a vec3f and the col of a matrix
bt_mat3_dot_col(const btMatrix3x3 & mat,const btVector3 & vec3,int colindex)153 SIMD_FORCE_INLINE btScalar bt_mat3_dot_col(
154 const btMatrix3x3 & mat, const btVector3 & vec3, int colindex)
155 {
156 	return vec3[0]*mat[0][colindex] + vec3[1]*mat[1][colindex] + vec3[2]*mat[2][colindex];
157 }
158 
159 
160 //!  Class for transforming a model1 to the space of model0
ATTRIBUTE_ALIGNED16(class)161 ATTRIBUTE_ALIGNED16	(class) BT_BOX_BOX_TRANSFORM_CACHE
162 {
163 public:
164     btVector3  m_T1to0;//!< Transforms translation of model1 to model 0
165 	btMatrix3x3 m_R1to0;//!< Transforms Rotation of model1 to model 0, equal  to R0' * R1
166 	btMatrix3x3 m_AR;//!< Absolute value of m_R1to0
167 
168 	SIMD_FORCE_INLINE void calc_absolute_matrix()
169 	{
170 //		static const btVector3 vepsi(1e-6f,1e-6f,1e-6f);
171 //		m_AR[0] = vepsi + m_R1to0[0].absolute();
172 //		m_AR[1] = vepsi + m_R1to0[1].absolute();
173 //		m_AR[2] = vepsi + m_R1to0[2].absolute();
174 
175 		int i,j;
176 
177         for(i=0;i<3;i++)
178         {
179             for(j=0;j<3;j++ )
180             {
181             	m_AR[i][j] = 1e-6f + btFabs(m_R1to0[i][j]);
182             }
183         }
184 
185 	}
186 
187 	BT_BOX_BOX_TRANSFORM_CACHE()
188 	{
189 	}
190 
191 
192 
193 	//! Calc the transformation relative  1 to 0. Inverts matrics by transposing
194 	SIMD_FORCE_INLINE void calc_from_homogenic(const btTransform & trans0,const btTransform & trans1)
195 	{
196 
197 		btTransform temp_trans = trans0.inverse();
198 		temp_trans = temp_trans * trans1;
199 
200 		m_T1to0 = temp_trans.getOrigin();
201 		m_R1to0 = temp_trans.getBasis();
202 
203 
204 		calc_absolute_matrix();
205 	}
206 
207 	//! Calcs the full invertion of the matrices. Useful for scaling matrices
208 	SIMD_FORCE_INLINE void calc_from_full_invert(const btTransform & trans0,const btTransform & trans1)
209 	{
210 		m_R1to0 = trans0.getBasis().inverse();
211 		m_T1to0 = m_R1to0 * (-trans0.getOrigin());
212 
213 		m_T1to0 += m_R1to0*trans1.getOrigin();
214 		m_R1to0 *= trans1.getBasis();
215 
216 		calc_absolute_matrix();
217 	}
218 
219 	SIMD_FORCE_INLINE btVector3 transform(const btVector3 & point) const
220 	{
221 		return btVector3(m_R1to0[0].dot(point) + m_T1to0.x(),
222 			m_R1to0[1].dot(point) + m_T1to0.y(),
223 			m_R1to0[2].dot(point) + m_T1to0.z());
224 	}
225 };
226 
227 
228 #define BOX_PLANE_EPSILON 0.000001f
229 
230 //! Axis aligned box
ATTRIBUTE_ALIGNED16(class)231 ATTRIBUTE_ALIGNED16	(class) btAABB
232 {
233 public:
234 	btVector3 m_min;
235 	btVector3 m_max;
236 
237 	btAABB()
238 	{}
239 
240 
241 	btAABB(const btVector3 & V1,
242 			 const btVector3 & V2,
243 			 const btVector3 & V3)
244 	{
245 		m_min[0] = BT_MIN3(V1[0],V2[0],V3[0]);
246 		m_min[1] = BT_MIN3(V1[1],V2[1],V3[1]);
247 		m_min[2] = BT_MIN3(V1[2],V2[2],V3[2]);
248 
249 		m_max[0] = BT_MAX3(V1[0],V2[0],V3[0]);
250 		m_max[1] = BT_MAX3(V1[1],V2[1],V3[1]);
251 		m_max[2] = BT_MAX3(V1[2],V2[2],V3[2]);
252 	}
253 
254 	btAABB(const btVector3 & V1,
255 			 const btVector3 & V2,
256 			 const btVector3 & V3,
257 			 btScalar margin)
258 	{
259 		m_min[0] = BT_MIN3(V1[0],V2[0],V3[0]);
260 		m_min[1] = BT_MIN3(V1[1],V2[1],V3[1]);
261 		m_min[2] = BT_MIN3(V1[2],V2[2],V3[2]);
262 
263 		m_max[0] = BT_MAX3(V1[0],V2[0],V3[0]);
264 		m_max[1] = BT_MAX3(V1[1],V2[1],V3[1]);
265 		m_max[2] = BT_MAX3(V1[2],V2[2],V3[2]);
266 
267 		m_min[0] -= margin;
268 		m_min[1] -= margin;
269 		m_min[2] -= margin;
270 		m_max[0] += margin;
271 		m_max[1] += margin;
272 		m_max[2] += margin;
273 	}
274 
275 	btAABB(const btAABB &other):
276 		m_min(other.m_min),m_max(other.m_max)
277 	{
278 	}
279 
280 	btAABB(const btAABB &other,btScalar margin ):
281 		m_min(other.m_min),m_max(other.m_max)
282 	{
283 		m_min[0] -= margin;
284 		m_min[1] -= margin;
285 		m_min[2] -= margin;
286 		m_max[0] += margin;
287 		m_max[1] += margin;
288 		m_max[2] += margin;
289 	}
290 
291 	SIMD_FORCE_INLINE void invalidate()
292 	{
293 		m_min[0] = SIMD_INFINITY;
294 		m_min[1] = SIMD_INFINITY;
295 		m_min[2] = SIMD_INFINITY;
296 		m_max[0] = -SIMD_INFINITY;
297 		m_max[1] = -SIMD_INFINITY;
298 		m_max[2] = -SIMD_INFINITY;
299 	}
300 
301 	SIMD_FORCE_INLINE void increment_margin(btScalar margin)
302 	{
303 		m_min[0] -= margin;
304 		m_min[1] -= margin;
305 		m_min[2] -= margin;
306 		m_max[0] += margin;
307 		m_max[1] += margin;
308 		m_max[2] += margin;
309 	}
310 
311 	SIMD_FORCE_INLINE void copy_with_margin(const btAABB &other, btScalar margin)
312 	{
313 		m_min[0] = other.m_min[0] - margin;
314 		m_min[1] = other.m_min[1] - margin;
315 		m_min[2] = other.m_min[2] - margin;
316 
317 		m_max[0] = other.m_max[0] + margin;
318 		m_max[1] = other.m_max[1] + margin;
319 		m_max[2] = other.m_max[2] + margin;
320 	}
321 
322 	template<typename CLASS_POINT>
323 	SIMD_FORCE_INLINE void calc_from_triangle(
324 							const CLASS_POINT & V1,
325 							const CLASS_POINT & V2,
326 							const CLASS_POINT & V3)
327 	{
328 		m_min[0] = BT_MIN3(V1[0],V2[0],V3[0]);
329 		m_min[1] = BT_MIN3(V1[1],V2[1],V3[1]);
330 		m_min[2] = BT_MIN3(V1[2],V2[2],V3[2]);
331 
332 		m_max[0] = BT_MAX3(V1[0],V2[0],V3[0]);
333 		m_max[1] = BT_MAX3(V1[1],V2[1],V3[1]);
334 		m_max[2] = BT_MAX3(V1[2],V2[2],V3[2]);
335 	}
336 
337 	template<typename CLASS_POINT>
338 	SIMD_FORCE_INLINE void calc_from_triangle_margin(
339 							const CLASS_POINT & V1,
340 							const CLASS_POINT & V2,
341 							const CLASS_POINT & V3, btScalar margin)
342 	{
343 		m_min[0] = BT_MIN3(V1[0],V2[0],V3[0]);
344 		m_min[1] = BT_MIN3(V1[1],V2[1],V3[1]);
345 		m_min[2] = BT_MIN3(V1[2],V2[2],V3[2]);
346 
347 		m_max[0] = BT_MAX3(V1[0],V2[0],V3[0]);
348 		m_max[1] = BT_MAX3(V1[1],V2[1],V3[1]);
349 		m_max[2] = BT_MAX3(V1[2],V2[2],V3[2]);
350 
351 		m_min[0] -= margin;
352 		m_min[1] -= margin;
353 		m_min[2] -= margin;
354 		m_max[0] += margin;
355 		m_max[1] += margin;
356 		m_max[2] += margin;
357 	}
358 
359 	//! Apply a transform to an AABB
360 	SIMD_FORCE_INLINE void appy_transform(const btTransform & trans)
361 	{
362 		btVector3 center = (m_max+m_min)*0.5f;
363 		btVector3 extends = m_max - center;
364 		// Compute new center
365 		center = trans(center);
366 
367 		btVector3 textends(extends.dot(trans.getBasis().getRow(0).absolute()),
368  				 extends.dot(trans.getBasis().getRow(1).absolute()),
369 				 extends.dot(trans.getBasis().getRow(2).absolute()));
370 
371 		m_min = center - textends;
372 		m_max = center + textends;
373 	}
374 
375 
376 	//! Apply a transform to an AABB
377 	SIMD_FORCE_INLINE void appy_transform_trans_cache(const BT_BOX_BOX_TRANSFORM_CACHE & trans)
378 	{
379 		btVector3 center = (m_max+m_min)*0.5f;
380 		btVector3 extends = m_max - center;
381 		// Compute new center
382 		center = trans.transform(center);
383 
384 		btVector3 textends(extends.dot(trans.m_R1to0.getRow(0).absolute()),
385  				 extends.dot(trans.m_R1to0.getRow(1).absolute()),
386 				 extends.dot(trans.m_R1to0.getRow(2).absolute()));
387 
388 		m_min = center - textends;
389 		m_max = center + textends;
390 	}
391 
392 	//! Merges a Box
393 	SIMD_FORCE_INLINE void merge(const btAABB & box)
394 	{
395 		m_min[0] = BT_MIN(m_min[0],box.m_min[0]);
396 		m_min[1] = BT_MIN(m_min[1],box.m_min[1]);
397 		m_min[2] = BT_MIN(m_min[2],box.m_min[2]);
398 
399 		m_max[0] = BT_MAX(m_max[0],box.m_max[0]);
400 		m_max[1] = BT_MAX(m_max[1],box.m_max[1]);
401 		m_max[2] = BT_MAX(m_max[2],box.m_max[2]);
402 	}
403 
404 	//! Merges a point
405 	template<typename CLASS_POINT>
406 	SIMD_FORCE_INLINE void merge_point(const CLASS_POINT & point)
407 	{
408 		m_min[0] = BT_MIN(m_min[0],point[0]);
409 		m_min[1] = BT_MIN(m_min[1],point[1]);
410 		m_min[2] = BT_MIN(m_min[2],point[2]);
411 
412 		m_max[0] = BT_MAX(m_max[0],point[0]);
413 		m_max[1] = BT_MAX(m_max[1],point[1]);
414 		m_max[2] = BT_MAX(m_max[2],point[2]);
415 	}
416 
417 	//! Gets the extend and center
418 	SIMD_FORCE_INLINE void get_center_extend(btVector3 & center,btVector3 & extend)  const
419 	{
420 		center = (m_max+m_min)*0.5f;
421 		extend = m_max - center;
422 	}
423 
424 	//! Finds the intersecting box between this box and the other.
425 	SIMD_FORCE_INLINE void find_intersection(const btAABB & other, btAABB & intersection)  const
426 	{
427 		intersection.m_min[0] = BT_MAX(other.m_min[0],m_min[0]);
428 		intersection.m_min[1] = BT_MAX(other.m_min[1],m_min[1]);
429 		intersection.m_min[2] = BT_MAX(other.m_min[2],m_min[2]);
430 
431 		intersection.m_max[0] = BT_MIN(other.m_max[0],m_max[0]);
432 		intersection.m_max[1] = BT_MIN(other.m_max[1],m_max[1]);
433 		intersection.m_max[2] = BT_MIN(other.m_max[2],m_max[2]);
434 	}
435 
436 
437 	SIMD_FORCE_INLINE bool has_collision(const btAABB & other) const
438 	{
439 		if(m_min[0] > other.m_max[0] ||
440 		   m_max[0] < other.m_min[0] ||
441 		   m_min[1] > other.m_max[1] ||
442 		   m_max[1] < other.m_min[1] ||
443 		   m_min[2] > other.m_max[2] ||
444 		   m_max[2] < other.m_min[2])
445 		{
446 			return false;
447 		}
448 		return true;
449 	}
450 
451 	/*! \brief Finds the Ray intersection parameter.
452 	\param aabb Aligned box
453 	\param vorigin A vec3f with the origin of the ray
454 	\param vdir A vec3f with the direction of the ray
455 	*/
456 	SIMD_FORCE_INLINE bool collide_ray(const btVector3 & vorigin,const btVector3 & vdir)  const
457 	{
458 		btVector3 extents,center;
459 		this->get_center_extend(center,extents);;
460 
461 		btScalar Dx = vorigin[0] - center[0];
462 		if(BT_GREATER(Dx, extents[0]) && Dx*vdir[0]>=0.0f)	return false;
463 		btScalar Dy = vorigin[1] - center[1];
464 		if(BT_GREATER(Dy, extents[1]) && Dy*vdir[1]>=0.0f)	return false;
465 		btScalar Dz = vorigin[2] - center[2];
466 		if(BT_GREATER(Dz, extents[2]) && Dz*vdir[2]>=0.0f)	return false;
467 
468 
469 		btScalar f = vdir[1] * Dz - vdir[2] * Dy;
470 		if(btFabs(f) > extents[1]*btFabs(vdir[2]) + extents[2]*btFabs(vdir[1])) return false;
471 		f = vdir[2] * Dx - vdir[0] * Dz;
472 		if(btFabs(f) > extents[0]*btFabs(vdir[2]) + extents[2]*btFabs(vdir[0]))return false;
473 		f = vdir[0] * Dy - vdir[1] * Dx;
474 		if(btFabs(f) > extents[0]*btFabs(vdir[1]) + extents[1]*btFabs(vdir[0]))return false;
475 		return true;
476 	}
477 
478 
479 	SIMD_FORCE_INLINE void projection_interval(const btVector3 & direction, btScalar &vmin, btScalar &vmax) const
480 	{
481 		btVector3 center = (m_max+m_min)*0.5f;
482 		btVector3 extend = m_max-center;
483 
484 		btScalar _fOrigin =  direction.dot(center);
485 		btScalar _fMaximumExtent = extend.dot(direction.absolute());
486 		vmin = _fOrigin - _fMaximumExtent;
487 		vmax = _fOrigin + _fMaximumExtent;
488 	}
489 
490 	SIMD_FORCE_INLINE eBT_PLANE_INTERSECTION_TYPE plane_classify(const btVector4 &plane) const
491 	{
492 		btScalar _fmin,_fmax;
493 		this->projection_interval(plane,_fmin,_fmax);
494 
495 		if(plane[3] > _fmax + BOX_PLANE_EPSILON)
496 		{
497 			return BT_CONST_BACK_PLANE; // 0
498 		}
499 
500 		if(plane[3]+BOX_PLANE_EPSILON >=_fmin)
501 		{
502 			return BT_CONST_COLLIDE_PLANE; //1
503 		}
504 		return BT_CONST_FRONT_PLANE;//2
505 	}
506 
507 	SIMD_FORCE_INLINE bool overlapping_trans_conservative(const btAABB & box, btTransform & trans1_to_0) const
508 	{
509 		btAABB tbox = box;
510 		tbox.appy_transform(trans1_to_0);
511 		return has_collision(tbox);
512 	}
513 
514 	SIMD_FORCE_INLINE bool overlapping_trans_conservative2(const btAABB & box,
515 		const BT_BOX_BOX_TRANSFORM_CACHE & trans1_to_0) const
516 	{
517 		btAABB tbox = box;
518 		tbox.appy_transform_trans_cache(trans1_to_0);
519 		return has_collision(tbox);
520 	}
521 
522 	//! transcache is the transformation cache from box to this AABB
523 	SIMD_FORCE_INLINE bool overlapping_trans_cache(
524 		const btAABB & box,const BT_BOX_BOX_TRANSFORM_CACHE & transcache, bool fulltest) const
525 	{
526 
527 		//Taken from OPCODE
528 		btVector3 ea,eb;//extends
529 		btVector3 ca,cb;//extends
530 		get_center_extend(ca,ea);
531 		box.get_center_extend(cb,eb);
532 
533 
534 		btVector3 T;
535 		btScalar t,t2;
536 		int i;
537 
538 		// Class I : A's basis vectors
539 		for(i=0;i<3;i++)
540 		{
541 			T[i] =  transcache.m_R1to0[i].dot(cb) + transcache.m_T1to0[i] - ca[i];
542 			t = transcache.m_AR[i].dot(eb) + ea[i];
543 			if(BT_GREATER(T[i], t))	return false;
544 		}
545 		// Class II : B's basis vectors
546 		for(i=0;i<3;i++)
547 		{
548 			t = bt_mat3_dot_col(transcache.m_R1to0,T,i);
549 			t2 = bt_mat3_dot_col(transcache.m_AR,ea,i) + eb[i];
550 			if(BT_GREATER(t,t2))	return false;
551 		}
552 		// Class III : 9 cross products
553 		if(fulltest)
554 		{
555 			int j,m,n,o,p,q,r;
556 			for(i=0;i<3;i++)
557 			{
558 				m = (i+1)%3;
559 				n = (i+2)%3;
560 				o = i==0?1:0;
561 				p = i==2?1:2;
562 				for(j=0;j<3;j++)
563 				{
564 					q = j==2?1:2;
565 					r = j==0?1:0;
566 					t = T[n]*transcache.m_R1to0[m][j] - T[m]*transcache.m_R1to0[n][j];
567 					t2 = ea[o]*transcache.m_AR[p][j] + ea[p]*transcache.m_AR[o][j] +
568 						eb[r]*transcache.m_AR[i][q] + eb[q]*transcache.m_AR[i][r];
569 					if(BT_GREATER(t,t2))	return false;
570 				}
571 			}
572 		}
573 		return true;
574 	}
575 
576 	//! Simple test for planes.
577 	SIMD_FORCE_INLINE bool collide_plane(
578 		const btVector4 & plane) const
579 	{
580 		eBT_PLANE_INTERSECTION_TYPE classify = plane_classify(plane);
581 		return (classify == BT_CONST_COLLIDE_PLANE);
582 	}
583 
584 	//! test for a triangle, with edges
585 	SIMD_FORCE_INLINE bool collide_triangle_exact(
586 		const btVector3 & p1,
587 		const btVector3 & p2,
588 		const btVector3 & p3,
589 		const btVector4 & triangle_plane) const
590 	{
591 		if(!collide_plane(triangle_plane)) return false;
592 
593 		btVector3 center,extends;
594 		this->get_center_extend(center,extends);
595 
596 		const btVector3 v1(p1 - center);
597 		const btVector3 v2(p2 - center);
598 		const btVector3 v3(p3 - center);
599 
600 		//First axis
601 		btVector3 diff(v2 - v1);
602 		btVector3 abs_diff = diff.absolute();
603 		//Test With X axis
604 		TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v1,v3,extends);
605 		//Test With Y axis
606 		TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v1,v3,extends);
607 		//Test With Z axis
608 		TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v1,v3,extends);
609 
610 
611 		diff = v3 - v2;
612 		abs_diff = diff.absolute();
613 		//Test With X axis
614 		TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v2,v1,extends);
615 		//Test With Y axis
616 		TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v2,v1,extends);
617 		//Test With Z axis
618 		TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v2,v1,extends);
619 
620 		diff = v1 - v3;
621 		abs_diff = diff.absolute();
622 		//Test With X axis
623 		TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v3,v2,extends);
624 		//Test With Y axis
625 		TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v3,v2,extends);
626 		//Test With Z axis
627 		TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v3,v2,extends);
628 
629 		return true;
630 	}
631 };
632 
633 
634 //! Compairison of transformation objects
btCompareTransformsEqual(const btTransform & t1,const btTransform & t2)635 SIMD_FORCE_INLINE bool btCompareTransformsEqual(const btTransform & t1,const btTransform & t2)
636 {
637 	if(!(t1.getOrigin() == t2.getOrigin()) ) return false;
638 
639 	if(!(t1.getBasis().getRow(0) == t2.getBasis().getRow(0)) ) return false;
640 	if(!(t1.getBasis().getRow(1) == t2.getBasis().getRow(1)) ) return false;
641 	if(!(t1.getBasis().getRow(2) == t2.getBasis().getRow(2)) ) return false;
642 	return true;
643 }
644 
645 
646 
647 #endif // GIM_BOX_COLLISION_H_INCLUDED
648