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