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

Bullet Collision Detection & Physics Library

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