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