Bullet Collision Detection & Physics Library: gim_tri_collision.h Source File

Bullet Collision Detection & Physics Library

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

gim_tri_collision.h
Go to the documentation of this file.
1 #ifndef GIM_TRI_COLLISION_H_INCLUDED
2 #define GIM_TRI_COLLISION_H_INCLUDED
3
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
36 #include "gim_box_collision.h"
37 #include "gim_clip_polygon.h"
38
39
40
41
42 #define MAX_TRI_CLIPPING 16
43
45 struct GIM_TRIANGLE_CONTACT_DATA
46 {
47 GREAL m_penetration_depth;
48 GUINT m_point_count;
49 btVector4 m_separating_normal;
50 btVector3 m_points[MAX_TRI_CLIPPING];
51
52 SIMD_FORCE_INLINE void copy_from(const GIM_TRIANGLE_CONTACT_DATA& other)
53 {
54 m_penetration_depth = other.m_penetration_depth;
55 m_separating_normal = other.m_separating_normal;
56 m_point_count = other.m_point_count;
57 GUINT i = m_point_count;
58 while(i--)
59 {
60 m_points[i] = other.m_points[i];
61 }
62 }
63
64 GIM_TRIANGLE_CONTACT_DATA()
65 {
66 }
67
68 GIM_TRIANGLE_CONTACT_DATA(const GIM_TRIANGLE_CONTACT_DATA& other)
69 {
70 copy_from(other);
71 }
72
73
74
75
77 template<typename DISTANCE_FUNC,typename CLASS_PLANE>
78 SIMD_FORCE_INLINE void mergepoints_generic(const CLASS_PLANE & plane,
79 GREAL margin, const btVector3 * points, GUINT point_count, DISTANCE_FUNC distance_func)
80 {
81 m_point_count = 0;
82 m_penetration_depth= -1000.0f;
83
84 GUINT point_indices[MAX_TRI_CLIPPING];
85
86 GUINT _k;
87
88 for(_k=0;_k<point_count;_k++)
89 {
90 GREAL _dist = -distance_func(plane,points[_k]) + margin;
91
92 if(_dist>=0.0f)
93 {
94 if(_dist>m_penetration_depth)
95 {
96 m_penetration_depth = _dist;
97 point_indices[0] = _k;
98 m_point_count=1;
99 }
100 else if((_dist+G_EPSILON)>=m_penetration_depth)
101 {
102 point_indices[m_point_count] = _k;
103 m_point_count++;
104 }
105 }
106 }
107
108 for( _k=0;_k<m_point_count;_k++)
109 {
110 m_points[_k] = points[point_indices[_k]];
111 }
112 }
113
115 SIMD_FORCE_INLINE void merge_points(const btVector4 & plane, GREAL margin,
116 const btVector3 * points, GUINT point_count)
117 {
118 m_separating_normal = plane;
119 mergepoints_generic(plane, margin, points, point_count, DISTANCE_PLANE_3D_FUNC());
120 }
121 };
122
123
125 class GIM_TRIANGLE
126 {
127 public:
128 btScalar m_margin;
129 btVector3 m_vertices[3];
130
131 GIM_TRIANGLE():m_margin(0.1f)
132 {
133 }
134
135 SIMD_FORCE_INLINE GIM_AABB get_box() const
136 {
137 return GIM_AABB(m_vertices[0],m_vertices[1],m_vertices[2],m_margin);
138 }
139
140 SIMD_FORCE_INLINE void get_normal(btVector3 &normal) const
141 {
142 TRIANGLE_NORMAL(m_vertices[0],m_vertices[1],m_vertices[2],normal);
143 }
144
145 SIMD_FORCE_INLINE void get_plane(btVector4 &plane) const
146 {
147 TRIANGLE_PLANE(m_vertices[0],m_vertices[1],m_vertices[2],plane);;
148 }
149
150 SIMD_FORCE_INLINE void apply_transform(const btTransform & trans)
151 {
152 m_vertices[0] = trans(m_vertices[0]);
153 m_vertices[1] = trans(m_vertices[1]);
154 m_vertices[2] = trans(m_vertices[2]);
155 }
156
157 SIMD_FORCE_INLINE void get_edge_plane(GUINT edge_index,const btVector3 &triangle_normal,btVector4 &plane) const
158 {
159 const btVector3 & e0 = m_vertices[edge_index];
160 const btVector3 & e1 = m_vertices[(edge_index+1)%3];
161 EDGE_PLANE(e0,e1,triangle_normal,plane);
162 }
163
165
171 SIMD_FORCE_INLINE void get_triangle_transform(btTransform & triangle_transform) const
172 {
173 btMatrix3x3 & matrix = triangle_transform.getBasis();
174
175 btVector3 zaxis;
176 get_normal(zaxis);
177 MAT_SET_Z(matrix,zaxis);
178
179 btVector3 xaxis = m_vertices[1] - m_vertices[0];
180 VEC_NORMALIZE(xaxis);
181 MAT_SET_X(matrix,xaxis);
182
183 //y axis
184 xaxis = zaxis.cross(xaxis);
185 MAT_SET_Y(matrix,xaxis);
186
187 triangle_transform.setOrigin(m_vertices[0]);
188 }
189
190
192
196 bool collide_triangle_hard_test(
197 const GIM_TRIANGLE & other,
198 GIM_TRIANGLE_CONTACT_DATA & contact_data) const;
199
201
206 SIMD_FORCE_INLINE bool collide_triangle(
207 const GIM_TRIANGLE & other,
208 GIM_TRIANGLE_CONTACT_DATA & contact_data) const
209 {
210 //test box collisioin
211 GIM_AABB boxu(m_vertices[0],m_vertices[1],m_vertices[2],m_margin);
212 GIM_AABB boxv(other.m_vertices[0],other.m_vertices[1],other.m_vertices[2],other.m_margin);
213 if(!boxu.has_collision(boxv)) return false;
214
215 //do hard test
216 return collide_triangle_hard_test(other,contact_data);
217 }
218
247 SIMD_FORCE_INLINE bool get_uv_parameters(
248 const btVector3 & point,
249 const btVector3 & tri_plane,
250 GREAL & u, GREAL & v) const
251 {
252 btVector3 _axe1 = m_vertices[1]-m_vertices[0];
253 btVector3 _axe2 = m_vertices[2]-m_vertices[0];
254 btVector3 _vecproj = point - m_vertices[0];
255 GUINT _i1 = (tri_plane.closestAxis()+1)%3;
256 GUINT _i2 = (_i1+1)%3;
257 if(btFabs(_axe2[_i2])<G_EPSILON)
258 {
259 u = (_vecproj[_i2]*_axe2[_i1] - _vecproj[_i1]*_axe2[_i2]) /(_axe1[_i2]*_axe2[_i1] - _axe1[_i1]*_axe2[_i2]);
260 v = (_vecproj[_i1] - u*_axe1[_i1])/_axe2[_i1];
261 }
262 else
263 {
264 u = (_vecproj[_i1]*_axe2[_i2] - _vecproj[_i2]*_axe2[_i1]) /(_axe1[_i1]*_axe2[_i2] - _axe1[_i2]*_axe2[_i1]);
265 v = (_vecproj[_i2] - u*_axe1[_i2])/_axe2[_i2];
266 }
267
268 if(u<-G_EPSILON)
269 {
270 return false;
271 }
272 else if(v<-G_EPSILON)
273 {
274 return false;
275 }
276 else
277 {
278 btScalar sumuv;
279 sumuv = u+v;
280 if(sumuv<-G_EPSILON)
281 {
282 return false;
283 }
284 else if(sumuv-1.0f>G_EPSILON)
285 {
286 return false;
287 }
288 }
289 return true;
290 }
291
293
296 SIMD_FORCE_INLINE bool is_point_inside(const btVector3 & point, const btVector3 & tri_normal) const
297 {
298 //Test with edge 0
299 btVector4 edge_plane;
300 this->get_edge_plane(0,tri_normal,edge_plane);
301 GREAL dist = DISTANCE_PLANE_POINT(edge_plane,point);
302 if(dist-m_margin>0.0f) return false; // outside plane
303
304 this->get_edge_plane(1,tri_normal,edge_plane);
305 dist = DISTANCE_PLANE_POINT(edge_plane,point);
306 if(dist-m_margin>0.0f) return false; // outside plane
307
308 this->get_edge_plane(2,tri_normal,edge_plane);
309 dist = DISTANCE_PLANE_POINT(edge_plane,point);
310 if(dist-m_margin>0.0f) return false; // outside plane
311 return true;
312 }
313
314
316 SIMD_FORCE_INLINE bool ray_collision(
317 const btVector3 & vPoint,
318 const btVector3 & vDir, btVector3 & pout, btVector3 & triangle_normal,
319 GREAL & tparam, GREAL tmax = G_REAL_INFINITY)
320 {
321 btVector4 faceplane;
322 {
323 btVector3 dif1 = m_vertices[1] - m_vertices[0];
324 btVector3 dif2 = m_vertices[2] - m_vertices[0];
325 VEC_CROSS(faceplane,dif1,dif2);
326 faceplane[3] = m_vertices[0].dot(faceplane);
327 }
328
329 GUINT res = LINE_PLANE_COLLISION(faceplane,vDir,vPoint,pout,tparam, btScalar(0), tmax);
330 if(res == 0) return false;
331 if(! is_point_inside(pout,faceplane)) return false;
332
333 if(res==2) //invert normal
334 {
335 triangle_normal.setValue(-faceplane[0],-faceplane[1],-faceplane[2]);
336 }
337 else
338 {
339 triangle_normal.setValue(faceplane[0],faceplane[1],faceplane[2]);
340 }
341
342 VEC_NORMALIZE(triangle_normal);
343
344 return true;
345 }
346
347
349 SIMD_FORCE_INLINE bool ray_collision_front_side(
350 const btVector3 & vPoint,
351 const btVector3 & vDir, btVector3 & pout, btVector3 & triangle_normal,
352 GREAL & tparam, GREAL tmax = G_REAL_INFINITY)
353 {
354 btVector4 faceplane;
355 {
356 btVector3 dif1 = m_vertices[1] - m_vertices[0];
357 btVector3 dif2 = m_vertices[2] - m_vertices[0];
358 VEC_CROSS(faceplane,dif1,dif2);
359 faceplane[3] = m_vertices[0].dot(faceplane);
360 }
361
362 GUINT res = LINE_PLANE_COLLISION(faceplane,vDir,vPoint,pout,tparam, btScalar(0), tmax);
363 if(res != 1) return false;
364
365 if(!is_point_inside(pout,faceplane)) return false;
366
367 triangle_normal.setValue(faceplane[0],faceplane[1],faceplane[2]);
368
369 VEC_NORMALIZE(triangle_normal);
370
371 return true;
372 }
373
374 };
375
376
377
378
379 #endif // GIM_TRI_COLLISION_H_INCLUDED
btTransform::setOrigin
void setOrigin(const btVector3 &origin)
Set the translational element.
Definition: btTransform.h:150
LINE_PLANE_COLLISION
GUINT LINE_PLANE_COLLISION(const CLASS_PLANE &plane, const CLASS_POINT &vDir, const CLASS_POINT &vPoint, CLASS_POINT &pout, T &tparam, T tmin, T tmax)
line collision
Definition: gim_basic_geometry_operations.h:267
TRIANGLE_PLANE
#define TRIANGLE_PLANE(v1, v2, v3, plane)
plane is a vec4f
Definition: gim_basic_geometry_operations.h:66
GIM_TRIANGLE_CONTACT_DATA::m_points
btVector3 m_points[MAX_TRI_CLIPPING]
Definition: gim_tri_collision.h:50
EDGE_PLANE
#define EDGE_PLANE(e1, e2, n, plane)
Calc a plane from an edge an a normal. plane is a vec4f.
Definition: gim_basic_geometry_operations.h:78
btVector3::setValue
void setValue(const btScalar &_x, const btScalar &_y, const btScalar &_z)
Definition: btVector3.h:640
G_EPSILON
#define G_EPSILON
Definition: gim_math.h:60
GIM_TRIANGLE::apply_transform
void apply_transform(const btTransform &trans)
Definition: gim_tri_collision.h:150
GIM_TRIANGLE::collide_triangle_hard_test
bool collide_triangle_hard_test(const GIM_TRIANGLE &other, GIM_TRIANGLE_CONTACT_DATA &contact_data) const
Test triangles by finding separating axis.
Definition: gim_tri_collision.cpp:626
GIM_TRIANGLE_CONTACT_DATA::copy_from
void copy_from(const GIM_TRIANGLE_CONTACT_DATA &other)
Definition: gim_tri_collision.h:52
GIM_TRIANGLE::ray_collision_front_side
bool ray_collision_front_side(const btVector3 &vPoint, const btVector3 &vDir, btVector3 &pout, btVector3 &triangle_normal, GREAL &tparam, GREAL tmax=G_REAL_INFINITY)
one direccion ray collision
Definition: gim_tri_collision.h:349
GIM_TRIANGLE::m_vertices
btVector3 m_vertices[3]
Definition: gim_tri_collision.h:129
GIM_AABB::has_collision
bool has_collision(const GIM_AABB &other) const
Definition: gim_box_collision.h:386
SIMD_FORCE_INLINE
#define SIMD_FORCE_INLINE
Definition: btScalar.h:63
GIM_AABB
Axis aligned box.
Definition: gim_box_collision.h:197
MAT_SET_X
#define MAT_SET_X(mat, vec3)
Get the triple(3) col of a transform matrix.
Definition: gim_linear_math.h:1499
GIM_TRIANGLE::get_edge_plane
void get_edge_plane(GUINT edge_index, const btVector3 &triangle_normal, btVector4 &plane) const
Definition: gim_tri_collision.h:157
btVector3::dot
btScalar dot(const btVector3 &v) const
Return the dot product.
Definition: btVector3.h:235
GREAL
#define GREAL
Definition: gim_math.h:39
GIM_TRIANGLE_CONTACT_DATA::mergepoints_generic
void mergepoints_generic(const CLASS_PLANE &plane, GREAL margin, const btVector3 *points, GUINT point_count, DISTANCE_FUNC distance_func)
classify points that are closer
Definition: gim_tri_collision.h:78
GIM_TRIANGLE::GIM_TRIANGLE
GIM_TRIANGLE()
Definition: gim_tri_collision.h:131
GIM_TRIANGLE::get_plane
void get_plane(btVector4 &plane) const
Definition: gim_tri_collision.h:145
btVector4
Definition: btVector3.h:1077
GIM_TRIANGLE_CONTACT_DATA::m_point_count
GUINT m_point_count
Definition: gim_tri_collision.h:48
DISTANCE_PLANE_3D_FUNC
This function calcs the distance from a 3D plane.
Definition: gim_clip_polygon.h:38
GIM_TRIANGLE_CONTACT_DATA::GIM_TRIANGLE_CONTACT_DATA
GIM_TRIANGLE_CONTACT_DATA(const GIM_TRIANGLE_CONTACT_DATA &other)
Definition: gim_tri_collision.h:68
GIM_TRIANGLE::get_normal
void get_normal(btVector3 &normal) const
Definition: gim_tri_collision.h:140
GIM_TRIANGLE::is_point_inside
bool is_point_inside(const btVector3 &point, const btVector3 &tri_normal) const
is point in triangle beam?
Definition: gim_tri_collision.h:296
GIM_TRIANGLE::collide_triangle
bool collide_triangle(const GIM_TRIANGLE &other, GIM_TRIANGLE_CONTACT_DATA &contact_data) const
Test boxes before doing hard test.
Definition: gim_tri_collision.h:206
GIM_TRIANGLE
Class for colliding triangles.
Definition: gim_tri_collision.h:125
MAT_SET_Y
#define MAT_SET_Y(mat, vec3)
Get the triple(3) col of a transform matrix.
Definition: gim_linear_math.h:1507
btVector3::cross
btVector3 cross(const btVector3 &v) const
Return the cross product between this and another vector.
Definition: btVector3.h:377
GIM_TRIANGLE_CONTACT_DATA::m_penetration_depth
GREAL m_penetration_depth
Definition: gim_tri_collision.h:47
btTransform::getBasis
btMatrix3x3 & getBasis()
Return the basis matrix for the rotation.
Definition: btTransform.h:112
btVector3
btVector3 can be used to represent 3D points and vectors.
Definition: btVector3.h:83
gim_box_collision.h
btVector3::closestAxis
int closestAxis() const
Definition: btVector3.h:485
MAX_TRI_CLIPPING
#define MAX_TRI_CLIPPING
Definition: gim_tri_collision.h:42
btTransform
The btTransform class supports rigid transforms with only translation and rotation and no scaling/she...
Definition: btTransform.h:34
GIM_TRIANGLE_CONTACT_DATA
Structure for collision.
Definition: gim_tri_collision.h:45
DISTANCE_PLANE_POINT
#define DISTANCE_PLANE_POINT(plane, point)
Definition: gim_basic_geometry_operations.h:86
GIM_TRIANGLE::get_triangle_transform
void get_triangle_transform(btTransform &triangle_transform) const
Gets the relative transformation of this triangle.
Definition: gim_tri_collision.h:171
GIM_TRIANGLE_CONTACT_DATA::GIM_TRIANGLE_CONTACT_DATA
GIM_TRIANGLE_CONTACT_DATA()
Definition: gim_tri_collision.h:64
VEC_CROSS
#define VEC_CROSS(c, a, b)
Vector cross.
Definition: gim_linear_math.h:320
G_REAL_INFINITY
#define G_REAL_INFINITY
Definition: gim_math.h:58
GUINT
#define GUINT
Definition: gim_math.h:42
btMatrix3x3
The btMatrix3x3 class implements a 3x3 rotation matrix, to perform linear algebra in combination with...
Definition: btMatrix3x3.h:48
GIM_TRIANGLE_CONTACT_DATA::m_separating_normal
btVector4 m_separating_normal
Definition: gim_tri_collision.h:49
GIM_TRIANGLE::ray_collision
bool ray_collision(const btVector3 &vPoint, const btVector3 &vDir, btVector3 &pout, btVector3 &triangle_normal, GREAL &tparam, GREAL tmax=G_REAL_INFINITY)
Bidireccional ray collision.
Definition: gim_tri_collision.h:316
GIM_TRIANGLE::get_box
GIM_AABB get_box() const
Definition: gim_tri_collision.h:135
GIM_TRIANGLE::m_margin
btScalar m_margin
Definition: gim_tri_collision.h:128
gim_clip_polygon.h
GIM_TRIANGLE::get_uv_parameters
bool get_uv_parameters(const btVector3 &point, const btVector3 &tri_plane, GREAL &u, GREAL &v) const
Definition: gim_tri_collision.h:247
MAT_SET_Z
#define MAT_SET_Z(mat, vec3)
Get the triple(3) col of a transform matrix.
Definition: gim_linear_math.h:1515
TRIANGLE_NORMAL
#define TRIANGLE_NORMAL(v1, v2, v3, n)
Definition: gim_basic_geometry_operations.h:49
btScalar
float btScalar
The btScalar type abstracts floating point numbers, to easily switch between double and single floati...
Definition: btScalar.h:278
VEC_NORMALIZE
#define VEC_NORMALIZE(a)
Vector length.
Definition: gim_linear_math.h:295
GIM_TRIANGLE_CONTACT_DATA::merge_points
void merge_points(const btVector4 &plane, GREAL margin, const btVector3 *points, GUINT point_count)
classify points that are closer
Definition: gim_tri_collision.h:115
btFabs
btScalar btFabs(btScalar x)
Definition: btScalar.h:449