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 
47 {
52 
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 
66  {
67  }
68 
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 
127 {
128 public:
130  btVector3 m_vertices[3];
131 
132  GIM_TRIANGLE():m_margin(0.1f)
133  {
134  }
135 
137  {
138  return GIM_AABB(m_vertices[0],m_vertices[1],m_vertices[2],m_margin);
139  }
140 
142  {
143  TRIANGLE_NORMAL(m_vertices[0],m_vertices[1],m_vertices[2],normal);
144  }
145 
147  {
148  TRIANGLE_PLANE(m_vertices[0],m_vertices[1],m_vertices[2],plane);;
149  }
150 
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 
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 
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 
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 
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
void setOrigin(const btVector3 &origin)
Set the translational element.
Definition: btTransform.h:150
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
#define TRIANGLE_PLANE(v1, v2, v3, plane)
plane is a vec4f
btVector3 m_points[MAX_TRI_CLIPPING]
#define EDGE_PLANE(e1, e2, n, plane)
Calc a plane from an edge an a normal. plane is a vec4f.
void setValue(const btScalar &_x, const btScalar &_y, const btScalar &_z)
Definition: btVector3.h:652
#define G_EPSILON
Definition: gim_math.h:60
void apply_transform(const btTransform &trans)
void copy_from(const GIM_TRIANGLE_CONTACT_DATA &other)
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
btVector3 m_vertices[3]
bool has_collision(const GIM_AABB &other) const
#define SIMD_FORCE_INLINE
Definition: btScalar.h:81
Axis aligned box.
#define MAT_SET_X(mat, vec3)
Get the triple(3) col of a transform matrix.
void get_edge_plane(GUINT edge_index, const btVector3 &triangle_normal, btVector4 &plane) const
btScalar dot(const btVector3 &v) const
Return the dot product.
Definition: btVector3.h:235
#define GREAL
Definition: gim_math.h:39
void mergepoints_generic(const CLASS_PLANE &plane, GREAL margin, const btVector3 *points, GUINT point_count, DISTANCE_FUNC distance_func)
classify points that are closer
void get_plane(btVector4 &plane) const
This function calcs the distance from a 3D plane.
GIM_TRIANGLE_CONTACT_DATA(const GIM_TRIANGLE_CONTACT_DATA &other)
void get_normal(btVector3 &normal) const
bool is_point_inside(const btVector3 &point, const btVector3 &tri_normal) const
is point in triangle beam?
bool collide_triangle(const GIM_TRIANGLE &other, GIM_TRIANGLE_CONTACT_DATA &contact_data) const
Test boxes before doing hard test.
Class for colliding triangles.
#define MAT_SET_Y(mat, vec3)
Get the triple(3) col of a transform matrix.
btVector3 cross(const btVector3 &v) const
Return the cross product between this and another vector.
Definition: btVector3.h:389
btMatrix3x3 & getBasis()
Return the basis matrix for the rotation.
Definition: btTransform.h:112
btVector3 can be used to represent 3D points and vectors.
Definition: btVector3.h:83
int closestAxis() const
Definition: btVector3.h:497
#define MAX_TRI_CLIPPING
The btTransform class supports rigid transforms with only translation and rotation and no scaling/she...
Definition: btTransform.h:34
Structure for collision.
#define DISTANCE_PLANE_POINT(plane, point)
void get_triangle_transform(btTransform &triangle_transform) const
Gets the relative transformation of this triangle.
#define VEC_CROSS(c, a, b)
Vector cross.
#define G_REAL_INFINITY
Definition: gim_math.h:58
#define GUINT
Definition: gim_math.h:42
The btMatrix3x3 class implements a 3x3 rotation matrix, to perform linear algebra in combination with...
Definition: btMatrix3x3.h:48
bool ray_collision(const btVector3 &vPoint, const btVector3 &vDir, btVector3 &pout, btVector3 &triangle_normal, GREAL &tparam, GREAL tmax=G_REAL_INFINITY)
Bidireccional ray collision.
GIM_AABB get_box() const
bool get_uv_parameters(const btVector3 &point, const btVector3 &tri_plane, GREAL &u, GREAL &v) const
#define MAT_SET_Z(mat, vec3)
Get the triple(3) col of a transform matrix.
#define TRIANGLE_NORMAL(v1, v2, v3, n)
float btScalar
The btScalar type abstracts floating point numbers, to easily switch between double and single floati...
Definition: btScalar.h:292
#define VEC_NORMALIZE(a)
Vector length.
void merge_points(const btVector4 &plane, GREAL margin, const btVector3 *points, GUINT point_count)
classify points that are closer
btScalar btFabs(btScalar x)
Definition: btScalar.h:475