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 
45 {
50 
52  {
56  GUINT i = m_point_count;
57  while (i--)
58  {
59  m_points[i] = other.m_points[i];
60  }
61  }
62 
64  {
65  }
66 
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 
121 {
122 public:
125 
127  {
128  }
129 
131  {
132  return GIM_AABB(m_vertices[0], m_vertices[1], m_vertices[2], m_margin);
133  }
134 
136  {
137  TRIANGLE_NORMAL(m_vertices[0], m_vertices[1], m_vertices[2], normal);
138  }
139 
141  {
142  TRIANGLE_PLANE(m_vertices[0], m_vertices[1], m_vertices[2], plane);
143  ;
144  }
145 
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 
192  const GIM_TRIANGLE &other,
193  GIM_TRIANGLE_CONTACT_DATA &contact_data) const;
194 
196 
202  const GIM_TRIANGLE &other,
203  GIM_TRIANGLE_CONTACT_DATA &contact_data) const
204  {
205  //test box collisioin
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 
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 
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 
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
GREAL
#define GREAL
Definition: gim_math.h:37
GIM_TRIANGLE::get_normal
void get_normal(btVector3 &normal) const
Definition: gim_tri_collision.h:135
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
G_REAL_INFINITY
#define G_REAL_INFINITY
Definition: gim_math.h:54
TRIANGLE_PLANE
#define TRIANGLE_PLANE(v1, v2, v3, plane)
plane is a vec4f
Definition: gim_basic_geometry_operations.h:66
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_CONTACT_DATA::GIM_TRIANGLE_CONTACT_DATA
GIM_TRIANGLE_CONTACT_DATA()
Definition: gim_tri_collision.h:63
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
btVector3::setValue
void setValue(const btScalar &_x, const btScalar &_y, const btScalar &_z)
Definition: btVector3.h:640
btScalar
float btScalar
The btScalar type abstracts floating point numbers, to easily switch between double and single floati...
Definition: btScalar.h:294
MAT_SET_Z
#define MAT_SET_Z(mat, vec3)
Get the triple(3) col of a transform matrix.
Definition: gim_linear_math.h:1436
btVector3::cross
btVector3 cross(const btVector3 &v) const
Return the cross product between this and another vector.
Definition: btVector3.h:380
GIM_TRIANGLE::get_box
GIM_AABB get_box() const
Definition: gim_tri_collision.h:130
btVector3::dot
btScalar dot(const btVector3 &v) const
Return the dot product.
Definition: btVector3.h:229
GIM_TRIANGLE_CONTACT_DATA::copy_from
void copy_from(const GIM_TRIANGLE_CONTACT_DATA &other)
Definition: gim_tri_collision.h:51
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
GUINT
#define GUINT
Definition: gim_math.h:40
VEC_NORMALIZE
#define VEC_NORMALIZE(a)
Vector length.
Definition: gim_linear_math.h:267
btVector4
Definition: btVector3.h:1073
GIM_AABB::has_collision
bool has_collision(const GIM_AABB &other) const
Definition: gim_box_collision.h:381
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_CONTACT_DATA::m_penetration_depth
GREAL m_penetration_depth
Definition: gim_tri_collision.h:46
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
GIM_TRIANGLE_CONTACT_DATA::GIM_TRIANGLE_CONTACT_DATA
GIM_TRIANGLE_CONTACT_DATA(const GIM_TRIANGLE_CONTACT_DATA &other)
Definition: gim_tri_collision.h:67
btFabs
btScalar btFabs(btScalar x)
Definition: btScalar.h:477
GIM_TRIANGLE::m_margin
btScalar m_margin
Definition: gim_tri_collision.h:123
GIM_AABB
Axis aligned box.
Definition: gim_box_collision.h:195
GIM_TRIANGLE::GIM_TRIANGLE
GIM_TRIANGLE()
Definition: gim_tri_collision.h:126
GIM_TRIANGLE
Class for colliding triangles.
Definition: gim_tri_collision.h:120
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::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_EPSILON
#define G_EPSILON
Definition: gim_math.h:56
btTransform::getBasis
btMatrix3x3 & getBasis()
Return the basis matrix for the rotation.
Definition: btTransform.h:108
GIM_TRIANGLE::get_plane
void get_plane(btVector4 &plane) const
Definition: gim_tri_collision.h:140
GIM_TRIANGLE_CONTACT_DATA::m_point_count
GUINT m_point_count
Definition: gim_tri_collision.h:47
MAX_TRI_CLIPPING
#define MAX_TRI_CLIPPING
Definition: gim_tri_collision.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
Structure for collision.
Definition: gim_tri_collision.h:44
DISTANCE_PLANE_3D_FUNC
This function calcs the distance from a 3D plane.
Definition: gim_clip_polygon.h:37
btTransform
The btTransform class supports rigid transforms with only translation and rotation and no scaling/she...
Definition: btTransform.h:28
gim_clip_polygon.h
btVector3
btVector3 can be used to represent 3D points and vectors.
Definition: btVector3.h:80
GIM_TRIANGLE_CONTACT_DATA::m_separating_normal
btVector4 m_separating_normal
Definition: gim_tri_collision.h:48
GIM_TRIANGLE::apply_transform
void apply_transform(const btTransform &trans)
Definition: gim_tri_collision.h:146
gim_box_collision.h
SIMD_FORCE_INLINE
#define SIMD_FORCE_INLINE
Definition: btScalar.h:83
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
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
VEC_CROSS
#define VEC_CROSS(c, a, b)
Vector cross.
Definition: gim_linear_math.h:294
GIM_TRIANGLE_CONTACT_DATA::m_points
btVector3 m_points[MAX_TRI_CLIPPING]
Definition: gim_tri_collision.h:49
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::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
DISTANCE_PLANE_POINT
#define DISTANCE_PLANE_POINT(plane, point)
Definition: gim_basic_geometry_operations.h:89
TRIANGLE_NORMAL
#define TRIANGLE_NORMAL(v1, v2, v3, n)
Definition: gim_basic_geometry_operations.h:48
MAT_SET_X
#define MAT_SET_X(mat, vec3)
Get the triple(3) col of a transform matrix.
Definition: gim_linear_math.h:1420
MAT_SET_Y
#define MAT_SET_Y(mat, vec3)
Get the triple(3) col of a transform matrix.
Definition: gim_linear_math.h:1428
btVector3::closestAxis
int closestAxis() const
Definition: btVector3.h:487
GIM_TRIANGLE::m_vertices
btVector3 m_vertices[3]
Definition: gim_tri_collision.h:124
btTransform::setOrigin
void setOrigin(const btVector3 &origin)
Set the translational element.
Definition: btTransform.h:146