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 
42 #define MAX_TRI_CLIPPING 16
43 
46 {
51 
53  {
57  GUINT i = m_point_count;
58  while(i--)
59  {
60  m_points[i] = other.m_points[i];
61  }
62  }
63 
65  {
66  }
67 
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 
126 {
127 public:
130 
132  {
133  }
134 
136  {
138  }
139 
141  {
143  }
144 
146  {
148  }
149 
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 
197  const GIM_TRIANGLE & other,
198  GIM_TRIANGLE_CONTACT_DATA & contact_data) const;
199 
201 
207  const GIM_TRIANGLE & other,
208  GIM_TRIANGLE_CONTACT_DATA & contact_data) const
209  {
210  //test box collisioin
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 
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 
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 
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
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:640
#define G_EPSILON
Definition: gim_math.h:60
float dist(const Point3 &pnt0, const Point3 &pnt1)
void apply_transform(const btTransform &trans)
bool collide_triangle_hard_test(const GIM_TRIANGLE &other, GIM_TRIANGLE_CONTACT_DATA &contact_data) const
Test triangles by finding separating axis.
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:58
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:377
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:485
#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:266
#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:407