1
#ifndef GIM_BOX_COLLISION_H_INCLUDED
2
#define GIM_BOX_COLLISION_H_INCLUDED
4
/*! \file gim_box_collision.h
5
\author Francisco Len N�jera
8
-----------------------------------------------------------------------------
9
This source file is part of GIMPACT Library.
11
For the latest info, see http://gimpact.sourceforge.net/
13
Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
14
email: projectileman@yahoo.com
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.
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.
33
-----------------------------------------------------------------------------
35
#include "gim_basic_geometry_operations.h"
36
#include "LinearMath/btTransform.h"
38
/*! \defgroup BOUND_AABB_OPERATIONS
43
//SIMD_FORCE_INLINE bool test_cross_edge_box(
44
// const btVector3 & edge,
45
// const btVector3 & absolute_edge,
46
// const btVector3 & pointa,
47
// const btVector3 & pointb, const btVector3 & extend,
50
// int component_index0,
51
// int component_index1)
53
// // dir coords are -z and y
55
// const btScalar dir0 = -edge[dir_index0];
56
// const btScalar dir1 = edge[dir_index1];
57
// btScalar pmin = pointa[component_index0]*dir0 + pointa[component_index1]*dir1;
58
// btScalar pmax = pointb[component_index0]*dir0 + pointb[component_index1]*dir1;
62
// GIM_SWAP_NUMBERS(pmin,pmax);
65
// const btScalar rad = extend[component_index0] * absolute_edge[dir_index0] +
66
// extend[component_index1] * absolute_edge[dir_index1];
68
// if(pmin>rad || -rad>pmax) return false;
72
//SIMD_FORCE_INLINE bool test_cross_edge_box_X_axis(
73
// const btVector3 & edge,
74
// const btVector3 & absolute_edge,
75
// const btVector3 & pointa,
76
// const btVector3 & pointb, btVector3 & extend)
79
// return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,2,1,1,2);
83
//SIMD_FORCE_INLINE bool test_cross_edge_box_Y_axis(
84
// const btVector3 & edge,
85
// const btVector3 & absolute_edge,
86
// const btVector3 & pointa,
87
// const btVector3 & pointb, btVector3 & extend)
90
// return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,0,2,2,0);
93
//SIMD_FORCE_INLINE bool test_cross_edge_box_Z_axis(
94
// const btVector3 & edge,
95
// const btVector3 & absolute_edge,
96
// const btVector3 & pointa,
97
// const btVector3 & pointb, btVector3 & extend)
100
// return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,1,0,0,1);
103
#define TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,i_dir_0,i_dir_1,i_comp_0,i_comp_1)\
105
const btScalar dir0 = -edge[i_dir_0];\
106
const btScalar dir1 = edge[i_dir_1];\
107
btScalar pmin = pointa[i_comp_0]*dir0 + pointa[i_comp_1]*dir1;\
108
btScalar pmax = pointb[i_comp_0]*dir0 + pointb[i_comp_1]*dir1;\
111
GIM_SWAP_NUMBERS(pmin,pmax); \
113
const btScalar abs_dir0 = absolute_edge[i_dir_0];\
114
const btScalar abs_dir1 = absolute_edge[i_dir_1];\
115
const btScalar rad = _extend[i_comp_0] * abs_dir0 + _extend[i_comp_1] * abs_dir1;\
116
if(pmin>rad || -rad>pmax) return false;\
120
#define TEST_CROSS_EDGE_BOX_X_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\
122
TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,2,1,1,2);\
125
#define TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\
127
TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,0,2,2,0);\
130
#define TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\
132
TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,1,0,0,1);\
137
//! Class for transforming a model1 to the space of model0
138
class GIM_BOX_BOX_TRANSFORM_CACHE
141
btVector3 m_T1to0;//!< Transforms translation of model1 to model 0
142
btMatrix3x3 m_R1to0;//!< Transforms Rotation of model1 to model 0, equal to R0' * R1
143
btMatrix3x3 m_AR;//!< Absolute value of m_R1to0
145
SIMD_FORCE_INLINE void calc_absolute_matrix()
147
static const btVector3 vepsi(1e-6f,1e-6f,1e-6f);
148
m_AR[0] = vepsi + m_R1to0[0].absolute();
149
m_AR[1] = vepsi + m_R1to0[1].absolute();
150
m_AR[2] = vepsi + m_R1to0[2].absolute();
153
GIM_BOX_BOX_TRANSFORM_CACHE()
158
GIM_BOX_BOX_TRANSFORM_CACHE(mat4f trans1_to_0)
160
COPY_MATRIX_3X3(m_R1to0,trans1_to_0)
161
MAT_GET_TRANSLATION(trans1_to_0,m_T1to0)
162
calc_absolute_matrix();
165
//! Calc the transformation relative 1 to 0. Inverts matrics by transposing
166
SIMD_FORCE_INLINE void calc_from_homogenic(const btTransform & trans0,const btTransform & trans1)
169
m_R1to0 = trans0.getBasis().transpose();
170
m_T1to0 = m_R1to0 * (-trans0.getOrigin());
172
m_T1to0 += m_R1to0*trans1.getOrigin();
173
m_R1to0 *= trans1.getBasis();
175
calc_absolute_matrix();
178
//! Calcs the full invertion of the matrices. Useful for scaling matrices
179
SIMD_FORCE_INLINE void calc_from_full_invert(const btTransform & trans0,const btTransform & trans1)
181
m_R1to0 = trans0.getBasis().inverse();
182
m_T1to0 = m_R1to0 * (-trans0.getOrigin());
184
m_T1to0 += m_R1to0*trans1.getOrigin();
185
m_R1to0 *= trans1.getBasis();
187
calc_absolute_matrix();
190
SIMD_FORCE_INLINE btVector3 transform(const btVector3 & point)
192
return btVector3(m_R1to0[0].dot(point) + m_T1to0.x(),
193
m_R1to0[1].dot(point) + m_T1to0.y(),
194
m_R1to0[2].dot(point) + m_T1to0.z());
199
#define BOX_PLANE_EPSILON 0.000001f
212
GIM_AABB(const btVector3 & V1,
213
const btVector3 & V2,
214
const btVector3 & V3)
216
m_min[0] = GIM_MIN3(V1[0],V2[0],V3[0]);
217
m_min[1] = GIM_MIN3(V1[1],V2[1],V3[1]);
218
m_min[2] = GIM_MIN3(V1[2],V2[2],V3[2]);
220
m_max[0] = GIM_MAX3(V1[0],V2[0],V3[0]);
221
m_max[1] = GIM_MAX3(V1[1],V2[1],V3[1]);
222
m_max[2] = GIM_MAX3(V1[2],V2[2],V3[2]);
225
GIM_AABB(const btVector3 & V1,
226
const btVector3 & V2,
227
const btVector3 & V3,
230
m_min[0] = GIM_MIN3(V1[0],V2[0],V3[0]);
231
m_min[1] = GIM_MIN3(V1[1],V2[1],V3[1]);
232
m_min[2] = GIM_MIN3(V1[2],V2[2],V3[2]);
234
m_max[0] = GIM_MAX3(V1[0],V2[0],V3[0]);
235
m_max[1] = GIM_MAX3(V1[1],V2[1],V3[1]);
236
m_max[2] = GIM_MAX3(V1[2],V2[2],V3[2]);
246
GIM_AABB(const GIM_AABB &other):
247
m_min(other.m_min),m_max(other.m_max)
251
GIM_AABB(const GIM_AABB &other,btScalar margin ):
252
m_min(other.m_min),m_max(other.m_max)
262
SIMD_FORCE_INLINE void invalidate()
264
m_min[0] = G_REAL_INFINITY;
265
m_min[1] = G_REAL_INFINITY;
266
m_min[2] = G_REAL_INFINITY;
267
m_max[0] = -G_REAL_INFINITY;
268
m_max[1] = -G_REAL_INFINITY;
269
m_max[2] = -G_REAL_INFINITY;
272
SIMD_FORCE_INLINE void increment_margin(btScalar margin)
282
SIMD_FORCE_INLINE void copy_with_margin(const GIM_AABB &other, btScalar margin)
284
m_min[0] = other.m_min[0] - margin;
285
m_min[1] = other.m_min[1] - margin;
286
m_min[2] = other.m_min[2] - margin;
288
m_max[0] = other.m_max[0] + margin;
289
m_max[1] = other.m_max[1] + margin;
290
m_max[2] = other.m_max[2] + margin;
293
template<typename CLASS_POINT>
294
SIMD_FORCE_INLINE void calc_from_triangle(
295
const CLASS_POINT & V1,
296
const CLASS_POINT & V2,
297
const CLASS_POINT & V3)
299
m_min[0] = GIM_MIN3(V1[0],V2[0],V3[0]);
300
m_min[1] = GIM_MIN3(V1[1],V2[1],V3[1]);
301
m_min[2] = GIM_MIN3(V1[2],V2[2],V3[2]);
303
m_max[0] = GIM_MAX3(V1[0],V2[0],V3[0]);
304
m_max[1] = GIM_MAX3(V1[1],V2[1],V3[1]);
305
m_max[2] = GIM_MAX3(V1[2],V2[2],V3[2]);
308
template<typename CLASS_POINT>
309
SIMD_FORCE_INLINE void calc_from_triangle_margin(
310
const CLASS_POINT & V1,
311
const CLASS_POINT & V2,
312
const CLASS_POINT & V3, btScalar margin)
314
m_min[0] = GIM_MIN3(V1[0],V2[0],V3[0]);
315
m_min[1] = GIM_MIN3(V1[1],V2[1],V3[1]);
316
m_min[2] = GIM_MIN3(V1[2],V2[2],V3[2]);
318
m_max[0] = GIM_MAX3(V1[0],V2[0],V3[0]);
319
m_max[1] = GIM_MAX3(V1[1],V2[1],V3[1]);
320
m_max[2] = GIM_MAX3(V1[2],V2[2],V3[2]);
330
//! Apply a transform to an AABB
331
SIMD_FORCE_INLINE void appy_transform(const btTransform & trans)
333
btVector3 center = (m_max+m_min)*0.5f;
334
btVector3 extends = m_max - center;
335
// Compute new center
336
center = trans(center);
338
btVector3 textends(extends.dot(trans.getBasis().getRow(0).absolute()),
339
extends.dot(trans.getBasis().getRow(1).absolute()),
340
extends.dot(trans.getBasis().getRow(2).absolute()));
342
m_min = center - textends;
343
m_max = center + textends;
347
SIMD_FORCE_INLINE void merge(const GIM_AABB & box)
349
m_min[0] = GIM_MIN(m_min[0],box.m_min[0]);
350
m_min[1] = GIM_MIN(m_min[1],box.m_min[1]);
351
m_min[2] = GIM_MIN(m_min[2],box.m_min[2]);
353
m_max[0] = GIM_MAX(m_max[0],box.m_max[0]);
354
m_max[1] = GIM_MAX(m_max[1],box.m_max[1]);
355
m_max[2] = GIM_MAX(m_max[2],box.m_max[2]);
359
template<typename CLASS_POINT>
360
SIMD_FORCE_INLINE void merge_point(const CLASS_POINT & point)
362
m_min[0] = GIM_MIN(m_min[0],point[0]);
363
m_min[1] = GIM_MIN(m_min[1],point[1]);
364
m_min[2] = GIM_MIN(m_min[2],point[2]);
366
m_max[0] = GIM_MAX(m_max[0],point[0]);
367
m_max[1] = GIM_MAX(m_max[1],point[1]);
368
m_max[2] = GIM_MAX(m_max[2],point[2]);
371
//! Gets the extend and center
372
SIMD_FORCE_INLINE void get_center_extend(btVector3 & center,btVector3 & extend) const
374
center = (m_max+m_min)*0.5f;
375
extend = m_max - center;
378
//! Finds the intersecting box between this box and the other.
379
SIMD_FORCE_INLINE void find_intersection(const GIM_AABB & other, GIM_AABB & intersection) const
381
intersection.m_min[0] = GIM_MAX(other.m_min[0],m_min[0]);
382
intersection.m_min[1] = GIM_MAX(other.m_min[1],m_min[1]);
383
intersection.m_min[2] = GIM_MAX(other.m_min[2],m_min[2]);
385
intersection.m_max[0] = GIM_MIN(other.m_max[0],m_max[0]);
386
intersection.m_max[1] = GIM_MIN(other.m_max[1],m_max[1]);
387
intersection.m_max[2] = GIM_MIN(other.m_max[2],m_max[2]);
391
SIMD_FORCE_INLINE bool has_collision(const GIM_AABB & other) const
393
if(m_min[0] > other.m_max[0] ||
394
m_max[0] < other.m_min[0] ||
395
m_min[1] > other.m_max[1] ||
396
m_max[1] < other.m_min[1] ||
397
m_min[2] > other.m_max[2] ||
398
m_max[2] < other.m_min[2])
405
/*! \brief Finds the Ray intersection parameter.
406
\param aabb Aligned box
407
\param vorigin A vec3f with the origin of the ray
408
\param vdir A vec3f with the direction of the ray
410
SIMD_FORCE_INLINE bool collide_ray(const btVector3 & vorigin,const btVector3 & vdir)
412
btVector3 extents,center;
413
this->get_center_extend(center,extents);;
415
btScalar Dx = vorigin[0] - center[0];
416
if(GIM_GREATER(Dx, extents[0]) && Dx*vdir[0]>=0.0f) return false;
417
btScalar Dy = vorigin[1] - center[1];
418
if(GIM_GREATER(Dy, extents[1]) && Dy*vdir[1]>=0.0f) return false;
419
btScalar Dz = vorigin[2] - center[2];
420
if(GIM_GREATER(Dz, extents[2]) && Dz*vdir[2]>=0.0f) return false;
423
btScalar f = vdir[1] * Dz - vdir[2] * Dy;
424
if(btFabs(f) > extents[1]*btFabs(vdir[2]) + extents[2]*btFabs(vdir[1])) return false;
425
f = vdir[2] * Dx - vdir[0] * Dz;
426
if(btFabs(f) > extents[0]*btFabs(vdir[2]) + extents[2]*btFabs(vdir[0]))return false;
427
f = vdir[0] * Dy - vdir[1] * Dx;
428
if(btFabs(f) > extents[0]*btFabs(vdir[1]) + extents[1]*btFabs(vdir[0]))return false;
433
SIMD_FORCE_INLINE void projection_interval(const btVector3 & direction, btScalar &vmin, btScalar &vmax) const
435
btVector3 center = (m_max+m_min)*0.5f;
436
btVector3 extend = m_max-center;
438
btScalar _fOrigin = direction.dot(center);
439
btScalar _fMaximumExtent = extend.dot(direction.absolute());
440
vmin = _fOrigin - _fMaximumExtent;
441
vmax = _fOrigin + _fMaximumExtent;
444
SIMD_FORCE_INLINE ePLANE_INTERSECTION_TYPE plane_classify(const btVector4 &plane) const
446
btScalar _fmin,_fmax;
447
this->projection_interval(plane,_fmin,_fmax);
449
if(plane[3] > _fmax + BOX_PLANE_EPSILON)
451
return G_BACK_PLANE; // 0
454
if(plane[3]+BOX_PLANE_EPSILON >=_fmin)
456
return G_COLLIDE_PLANE; //1
458
return G_FRONT_PLANE;//2
461
SIMD_FORCE_INLINE bool overlapping_trans_conservative(const GIM_AABB & box, btTransform & trans1_to_0)
464
tbox.appy_transform(trans1_to_0);
465
return has_collision(tbox);
468
//! transcache is the transformation cache from box to this AABB
469
SIMD_FORCE_INLINE bool overlapping_trans_cache(
470
const GIM_AABB & box,const GIM_BOX_BOX_TRANSFORM_CACHE & transcache, bool fulltest)
474
btVector3 ea,eb;//extends
475
btVector3 ca,cb;//extends
476
get_center_extend(ca,ea);
477
box.get_center_extend(cb,eb);
484
// Class I : A's basis vectors
487
T[i] = transcache.m_R1to0[i].dot(cb) + transcache.m_T1to0[i] - ca[i];
488
t = transcache.m_AR[i].dot(eb) + ea[i];
489
if(GIM_GREATER(T[i], t)) return false;
491
// Class II : B's basis vectors
494
t = MAT_DOT_COL(transcache.m_R1to0,T,i);
495
t2 = MAT_DOT_COL(transcache.m_AR,ea,i) + eb[i];
496
if(GIM_GREATER(t,t2)) return false;
498
// Class III : 9 cross products
512
t = T[n]*transcache.m_R1to0[m][j] - T[m]*transcache.m_R1to0[n][j];
513
t2 = ea[o]*transcache.m_AR[p][j] + ea[p]*transcache.m_AR[o][j] +
514
eb[r]*transcache.m_AR[i][q] + eb[q]*transcache.m_AR[i][r];
515
if(GIM_GREATER(t,t2)) return false;
522
//! Simple test for planes.
523
SIMD_FORCE_INLINE bool collide_plane(
524
const btVector4 & plane)
526
ePLANE_INTERSECTION_TYPE classify = plane_classify(plane);
527
return (classify == G_COLLIDE_PLANE);
530
//! test for a triangle, with edges
531
SIMD_FORCE_INLINE bool collide_triangle_exact(
532
const btVector3 & p1,
533
const btVector3 & p2,
534
const btVector3 & p3,
535
const btVector4 & triangle_plane)
537
if(!collide_plane(triangle_plane)) return false;
539
btVector3 center,extends;
540
this->get_center_extend(center,extends);
542
const btVector3 v1(p1 - center);
543
const btVector3 v2(p2 - center);
544
const btVector3 v3(p3 - center);
547
btVector3 diff(v2 - v1);
548
btVector3 abs_diff = diff.absolute();
550
TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v1,v3,extends);
552
TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v1,v3,extends);
554
TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v1,v3,extends);
558
abs_diff = diff.absolute();
560
TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v2,v1,extends);
562
TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v2,v1,extends);
564
TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v2,v1,extends);
567
abs_diff = diff.absolute();
569
TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v3,v2,extends);
571
TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v3,v2,extends);
573
TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v3,v2,extends);
580
//! Compairison of transformation objects
581
SIMD_FORCE_INLINE bool btCompareTransformsEqual(const btTransform & t1,const btTransform & t2)
583
if(!(t1.getOrigin() == t2.getOrigin()) ) return false;
585
if(!(t1.getBasis().getRow(0) == t2.getBasis().getRow(0)) ) return false;
586
if(!(t1.getBasis().getRow(1) == t2.getBasis().getRow(1)) ) return false;
587
if(!(t1.getBasis().getRow(2) == t2.getBasis().getRow(2)) ) return false;
594
#endif // GIM_BOX_COLLISION_H_INCLUDED
1
#ifndef GIM_BOX_COLLISION_H_INCLUDED
2
#define GIM_BOX_COLLISION_H_INCLUDED
4
/*! \file gim_box_collision.h
5
\author Francisco Len N�jera
8
-----------------------------------------------------------------------------
9
This source file is part of GIMPACT Library.
11
For the latest info, see http://gimpact.sourceforge.net/
13
Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
14
email: projectileman@yahoo.com
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.
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.
33
-----------------------------------------------------------------------------
35
#include "gim_basic_geometry_operations.h"
36
#include "LinearMath/btTransform.h"
40
//SIMD_FORCE_INLINE bool test_cross_edge_box(
41
// const btVector3 & edge,
42
// const btVector3 & absolute_edge,
43
// const btVector3 & pointa,
44
// const btVector3 & pointb, const btVector3 & extend,
47
// int component_index0,
48
// int component_index1)
50
// // dir coords are -z and y
52
// const btScalar dir0 = -edge[dir_index0];
53
// const btScalar dir1 = edge[dir_index1];
54
// btScalar pmin = pointa[component_index0]*dir0 + pointa[component_index1]*dir1;
55
// btScalar pmax = pointb[component_index0]*dir0 + pointb[component_index1]*dir1;
59
// GIM_SWAP_NUMBERS(pmin,pmax);
62
// const btScalar rad = extend[component_index0] * absolute_edge[dir_index0] +
63
// extend[component_index1] * absolute_edge[dir_index1];
65
// if(pmin>rad || -rad>pmax) return false;
69
//SIMD_FORCE_INLINE bool test_cross_edge_box_X_axis(
70
// const btVector3 & edge,
71
// const btVector3 & absolute_edge,
72
// const btVector3 & pointa,
73
// const btVector3 & pointb, btVector3 & extend)
76
// return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,2,1,1,2);
80
//SIMD_FORCE_INLINE bool test_cross_edge_box_Y_axis(
81
// const btVector3 & edge,
82
// const btVector3 & absolute_edge,
83
// const btVector3 & pointa,
84
// const btVector3 & pointb, btVector3 & extend)
87
// return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,0,2,2,0);
90
//SIMD_FORCE_INLINE bool test_cross_edge_box_Z_axis(
91
// const btVector3 & edge,
92
// const btVector3 & absolute_edge,
93
// const btVector3 & pointa,
94
// const btVector3 & pointb, btVector3 & extend)
97
// return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,1,0,0,1);
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)\
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;\
108
GIM_SWAP_NUMBERS(pmin,pmax); \
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;\
117
#define TEST_CROSS_EDGE_BOX_X_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\
119
TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,2,1,1,2);\
122
#define TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\
124
TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,0,2,2,0);\
127
#define TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\
129
TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,1,0,0,1);\
134
//! Class for transforming a model1 to the space of model0
135
class GIM_BOX_BOX_TRANSFORM_CACHE
138
btVector3 m_T1to0;//!< Transforms translation of model1 to model 0
139
btMatrix3x3 m_R1to0;//!< Transforms Rotation of model1 to model 0, equal to R0' * R1
140
btMatrix3x3 m_AR;//!< Absolute value of m_R1to0
142
SIMD_FORCE_INLINE void calc_absolute_matrix()
144
static const btVector3 vepsi(1e-6f,1e-6f,1e-6f);
145
m_AR[0] = vepsi + m_R1to0[0].absolute();
146
m_AR[1] = vepsi + m_R1to0[1].absolute();
147
m_AR[2] = vepsi + m_R1to0[2].absolute();
150
GIM_BOX_BOX_TRANSFORM_CACHE()
155
GIM_BOX_BOX_TRANSFORM_CACHE(mat4f trans1_to_0)
157
COPY_MATRIX_3X3(m_R1to0,trans1_to_0)
158
MAT_GET_TRANSLATION(trans1_to_0,m_T1to0)
159
calc_absolute_matrix();
162
//! Calc the transformation relative 1 to 0. Inverts matrics by transposing
163
SIMD_FORCE_INLINE void calc_from_homogenic(const btTransform & trans0,const btTransform & trans1)
166
m_R1to0 = trans0.getBasis().transpose();
167
m_T1to0 = m_R1to0 * (-trans0.getOrigin());
169
m_T1to0 += m_R1to0*trans1.getOrigin();
170
m_R1to0 *= trans1.getBasis();
172
calc_absolute_matrix();
175
//! Calcs the full invertion of the matrices. Useful for scaling matrices
176
SIMD_FORCE_INLINE void calc_from_full_invert(const btTransform & trans0,const btTransform & trans1)
178
m_R1to0 = trans0.getBasis().inverse();
179
m_T1to0 = m_R1to0 * (-trans0.getOrigin());
181
m_T1to0 += m_R1to0*trans1.getOrigin();
182
m_R1to0 *= trans1.getBasis();
184
calc_absolute_matrix();
187
SIMD_FORCE_INLINE btVector3 transform(const btVector3 & point)
189
return btVector3(m_R1to0[0].dot(point) + m_T1to0.x(),
190
m_R1to0[1].dot(point) + m_T1to0.y(),
191
m_R1to0[2].dot(point) + m_T1to0.z());
196
#define BOX_PLANE_EPSILON 0.000001f
209
GIM_AABB(const btVector3 & V1,
210
const btVector3 & V2,
211
const btVector3 & V3)
213
m_min[0] = GIM_MIN3(V1[0],V2[0],V3[0]);
214
m_min[1] = GIM_MIN3(V1[1],V2[1],V3[1]);
215
m_min[2] = GIM_MIN3(V1[2],V2[2],V3[2]);
217
m_max[0] = GIM_MAX3(V1[0],V2[0],V3[0]);
218
m_max[1] = GIM_MAX3(V1[1],V2[1],V3[1]);
219
m_max[2] = GIM_MAX3(V1[2],V2[2],V3[2]);
222
GIM_AABB(const btVector3 & V1,
223
const btVector3 & V2,
224
const btVector3 & V3,
227
m_min[0] = GIM_MIN3(V1[0],V2[0],V3[0]);
228
m_min[1] = GIM_MIN3(V1[1],V2[1],V3[1]);
229
m_min[2] = GIM_MIN3(V1[2],V2[2],V3[2]);
231
m_max[0] = GIM_MAX3(V1[0],V2[0],V3[0]);
232
m_max[1] = GIM_MAX3(V1[1],V2[1],V3[1]);
233
m_max[2] = GIM_MAX3(V1[2],V2[2],V3[2]);
243
GIM_AABB(const GIM_AABB &other):
244
m_min(other.m_min),m_max(other.m_max)
248
GIM_AABB(const GIM_AABB &other,btScalar margin ):
249
m_min(other.m_min),m_max(other.m_max)
259
SIMD_FORCE_INLINE void invalidate()
261
m_min[0] = G_REAL_INFINITY;
262
m_min[1] = G_REAL_INFINITY;
263
m_min[2] = G_REAL_INFINITY;
264
m_max[0] = -G_REAL_INFINITY;
265
m_max[1] = -G_REAL_INFINITY;
266
m_max[2] = -G_REAL_INFINITY;
269
SIMD_FORCE_INLINE void increment_margin(btScalar margin)
279
SIMD_FORCE_INLINE void copy_with_margin(const GIM_AABB &other, btScalar margin)
281
m_min[0] = other.m_min[0] - margin;
282
m_min[1] = other.m_min[1] - margin;
283
m_min[2] = other.m_min[2] - margin;
285
m_max[0] = other.m_max[0] + margin;
286
m_max[1] = other.m_max[1] + margin;
287
m_max[2] = other.m_max[2] + margin;
290
template<typename CLASS_POINT>
291
SIMD_FORCE_INLINE void calc_from_triangle(
292
const CLASS_POINT & V1,
293
const CLASS_POINT & V2,
294
const CLASS_POINT & V3)
296
m_min[0] = GIM_MIN3(V1[0],V2[0],V3[0]);
297
m_min[1] = GIM_MIN3(V1[1],V2[1],V3[1]);
298
m_min[2] = GIM_MIN3(V1[2],V2[2],V3[2]);
300
m_max[0] = GIM_MAX3(V1[0],V2[0],V3[0]);
301
m_max[1] = GIM_MAX3(V1[1],V2[1],V3[1]);
302
m_max[2] = GIM_MAX3(V1[2],V2[2],V3[2]);
305
template<typename CLASS_POINT>
306
SIMD_FORCE_INLINE void calc_from_triangle_margin(
307
const CLASS_POINT & V1,
308
const CLASS_POINT & V2,
309
const CLASS_POINT & V3, btScalar margin)
311
m_min[0] = GIM_MIN3(V1[0],V2[0],V3[0]);
312
m_min[1] = GIM_MIN3(V1[1],V2[1],V3[1]);
313
m_min[2] = GIM_MIN3(V1[2],V2[2],V3[2]);
315
m_max[0] = GIM_MAX3(V1[0],V2[0],V3[0]);
316
m_max[1] = GIM_MAX3(V1[1],V2[1],V3[1]);
317
m_max[2] = GIM_MAX3(V1[2],V2[2],V3[2]);
327
//! Apply a transform to an AABB
328
SIMD_FORCE_INLINE void appy_transform(const btTransform & trans)
330
btVector3 center = (m_max+m_min)*0.5f;
331
btVector3 extends = m_max - center;
332
// Compute new center
333
center = trans(center);
335
btVector3 textends(extends.dot(trans.getBasis().getRow(0).absolute()),
336
extends.dot(trans.getBasis().getRow(1).absolute()),
337
extends.dot(trans.getBasis().getRow(2).absolute()));
339
m_min = center - textends;
340
m_max = center + textends;
344
SIMD_FORCE_INLINE void merge(const GIM_AABB & box)
346
m_min[0] = GIM_MIN(m_min[0],box.m_min[0]);
347
m_min[1] = GIM_MIN(m_min[1],box.m_min[1]);
348
m_min[2] = GIM_MIN(m_min[2],box.m_min[2]);
350
m_max[0] = GIM_MAX(m_max[0],box.m_max[0]);
351
m_max[1] = GIM_MAX(m_max[1],box.m_max[1]);
352
m_max[2] = GIM_MAX(m_max[2],box.m_max[2]);
356
template<typename CLASS_POINT>
357
SIMD_FORCE_INLINE void merge_point(const CLASS_POINT & point)
359
m_min[0] = GIM_MIN(m_min[0],point[0]);
360
m_min[1] = GIM_MIN(m_min[1],point[1]);
361
m_min[2] = GIM_MIN(m_min[2],point[2]);
363
m_max[0] = GIM_MAX(m_max[0],point[0]);
364
m_max[1] = GIM_MAX(m_max[1],point[1]);
365
m_max[2] = GIM_MAX(m_max[2],point[2]);
368
//! Gets the extend and center
369
SIMD_FORCE_INLINE void get_center_extend(btVector3 & center,btVector3 & extend) const
371
center = (m_max+m_min)*0.5f;
372
extend = m_max - center;
375
//! Finds the intersecting box between this box and the other.
376
SIMD_FORCE_INLINE void find_intersection(const GIM_AABB & other, GIM_AABB & intersection) const
378
intersection.m_min[0] = GIM_MAX(other.m_min[0],m_min[0]);
379
intersection.m_min[1] = GIM_MAX(other.m_min[1],m_min[1]);
380
intersection.m_min[2] = GIM_MAX(other.m_min[2],m_min[2]);
382
intersection.m_max[0] = GIM_MIN(other.m_max[0],m_max[0]);
383
intersection.m_max[1] = GIM_MIN(other.m_max[1],m_max[1]);
384
intersection.m_max[2] = GIM_MIN(other.m_max[2],m_max[2]);
388
SIMD_FORCE_INLINE bool has_collision(const GIM_AABB & other) const
390
if(m_min[0] > other.m_max[0] ||
391
m_max[0] < other.m_min[0] ||
392
m_min[1] > other.m_max[1] ||
393
m_max[1] < other.m_min[1] ||
394
m_min[2] > other.m_max[2] ||
395
m_max[2] < other.m_min[2])
402
/*! \brief Finds the Ray intersection parameter.
403
\param aabb Aligned box
404
\param vorigin A vec3f with the origin of the ray
405
\param vdir A vec3f with the direction of the ray
407
SIMD_FORCE_INLINE bool collide_ray(const btVector3 & vorigin,const btVector3 & vdir)
409
btVector3 extents,center;
410
this->get_center_extend(center,extents);;
412
btScalar Dx = vorigin[0] - center[0];
413
if(GIM_GREATER(Dx, extents[0]) && Dx*vdir[0]>=0.0f) return false;
414
btScalar Dy = vorigin[1] - center[1];
415
if(GIM_GREATER(Dy, extents[1]) && Dy*vdir[1]>=0.0f) return false;
416
btScalar Dz = vorigin[2] - center[2];
417
if(GIM_GREATER(Dz, extents[2]) && Dz*vdir[2]>=0.0f) return false;
420
btScalar f = vdir[1] * Dz - vdir[2] * Dy;
421
if(btFabs(f) > extents[1]*btFabs(vdir[2]) + extents[2]*btFabs(vdir[1])) return false;
422
f = vdir[2] * Dx - vdir[0] * Dz;
423
if(btFabs(f) > extents[0]*btFabs(vdir[2]) + extents[2]*btFabs(vdir[0]))return false;
424
f = vdir[0] * Dy - vdir[1] * Dx;
425
if(btFabs(f) > extents[0]*btFabs(vdir[1]) + extents[1]*btFabs(vdir[0]))return false;
430
SIMD_FORCE_INLINE void projection_interval(const btVector3 & direction, btScalar &vmin, btScalar &vmax) const
432
btVector3 center = (m_max+m_min)*0.5f;
433
btVector3 extend = m_max-center;
435
btScalar _fOrigin = direction.dot(center);
436
btScalar _fMaximumExtent = extend.dot(direction.absolute());
437
vmin = _fOrigin - _fMaximumExtent;
438
vmax = _fOrigin + _fMaximumExtent;
441
SIMD_FORCE_INLINE ePLANE_INTERSECTION_TYPE plane_classify(const btVector4 &plane) const
443
btScalar _fmin,_fmax;
444
this->projection_interval(plane,_fmin,_fmax);
446
if(plane[3] > _fmax + BOX_PLANE_EPSILON)
448
return G_BACK_PLANE; // 0
451
if(plane[3]+BOX_PLANE_EPSILON >=_fmin)
453
return G_COLLIDE_PLANE; //1
455
return G_FRONT_PLANE;//2
458
SIMD_FORCE_INLINE bool overlapping_trans_conservative(const GIM_AABB & box, btTransform & trans1_to_0)
461
tbox.appy_transform(trans1_to_0);
462
return has_collision(tbox);
465
//! transcache is the transformation cache from box to this AABB
466
SIMD_FORCE_INLINE bool overlapping_trans_cache(
467
const GIM_AABB & box,const GIM_BOX_BOX_TRANSFORM_CACHE & transcache, bool fulltest)
471
btVector3 ea,eb;//extends
472
btVector3 ca,cb;//extends
473
get_center_extend(ca,ea);
474
box.get_center_extend(cb,eb);
481
// Class I : A's basis vectors
484
T[i] = transcache.m_R1to0[i].dot(cb) + transcache.m_T1to0[i] - ca[i];
485
t = transcache.m_AR[i].dot(eb) + ea[i];
486
if(GIM_GREATER(T[i], t)) return false;
488
// Class II : B's basis vectors
491
t = MAT_DOT_COL(transcache.m_R1to0,T,i);
492
t2 = MAT_DOT_COL(transcache.m_AR,ea,i) + eb[i];
493
if(GIM_GREATER(t,t2)) return false;
495
// Class III : 9 cross products
509
t = T[n]*transcache.m_R1to0[m][j] - T[m]*transcache.m_R1to0[n][j];
510
t2 = ea[o]*transcache.m_AR[p][j] + ea[p]*transcache.m_AR[o][j] +
511
eb[r]*transcache.m_AR[i][q] + eb[q]*transcache.m_AR[i][r];
512
if(GIM_GREATER(t,t2)) return false;
519
//! Simple test for planes.
520
SIMD_FORCE_INLINE bool collide_plane(
521
const btVector4 & plane)
523
ePLANE_INTERSECTION_TYPE classify = plane_classify(plane);
524
return (classify == G_COLLIDE_PLANE);
527
//! test for a triangle, with edges
528
SIMD_FORCE_INLINE bool collide_triangle_exact(
529
const btVector3 & p1,
530
const btVector3 & p2,
531
const btVector3 & p3,
532
const btVector4 & triangle_plane)
534
if(!collide_plane(triangle_plane)) return false;
536
btVector3 center,extends;
537
this->get_center_extend(center,extends);
539
const btVector3 v1(p1 - center);
540
const btVector3 v2(p2 - center);
541
const btVector3 v3(p3 - center);
544
btVector3 diff(v2 - v1);
545
btVector3 abs_diff = diff.absolute();
547
TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v1,v3,extends);
549
TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v1,v3,extends);
551
TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v1,v3,extends);
555
abs_diff = diff.absolute();
557
TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v2,v1,extends);
559
TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v2,v1,extends);
561
TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v2,v1,extends);
564
abs_diff = diff.absolute();
566
TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v3,v2,extends);
568
TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v3,v2,extends);
570
TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v3,v2,extends);
577
//! Compairison of transformation objects
578
SIMD_FORCE_INLINE bool btCompareTransformsEqual(const btTransform & t1,const btTransform & t2)
580
if(!(t1.getOrigin() == t2.getOrigin()) ) return false;
582
if(!(t1.getBasis().getRow(0) == t2.getBasis().getRow(0)) ) return false;
583
if(!(t1.getBasis().getRow(1) == t2.getBasis().getRow(1)) ) return false;
584
if(!(t1.getBasis().getRow(2) == t2.getBasis().getRow(2)) ) return false;
590
#endif // GIM_BOX_COLLISION_H_INCLUDED