gim_tri_collision.h
Go to the documentation of this file.
00001 #ifndef GIM_TRI_COLLISION_H_INCLUDED
00002 #define GIM_TRI_COLLISION_H_INCLUDED
00003 
00007 /*
00008 -----------------------------------------------------------------------------
00009 This source file is part of GIMPACT Library.
00010 
00011 For the latest info, see http://gimpact.sourceforge.net/
00012 
00013 Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
00014 email: projectileman@yahoo.com
00015 
00016  This library is free software; you can redistribute it and/or
00017  modify it under the terms of EITHER:
00018    (1) The GNU Lesser General Public License as published by the Free
00019        Software Foundation; either version 2.1 of the License, or (at
00020        your option) any later version. The text of the GNU Lesser
00021        General Public License is included with this library in the
00022        file GIMPACT-LICENSE-LGPL.TXT.
00023    (2) The BSD-style license that is included with this library in
00024        the file GIMPACT-LICENSE-BSD.TXT.
00025    (3) The zlib/libpng license that is included with this library in
00026        the file GIMPACT-LICENSE-ZLIB.TXT.
00027 
00028  This library is distributed in the hope that it will be useful,
00029  but WITHOUT ANY WARRANTY; without even the implied warranty of
00030  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
00031  GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
00032 
00033 -----------------------------------------------------------------------------
00034 */
00035 
00036 #include "gim_box_collision.h"
00037 #include "gim_clip_polygon.h"
00038 
00039 
00040 
00041 
00042 #define MAX_TRI_CLIPPING 16
00043 
00045 struct GIM_TRIANGLE_CONTACT_DATA
00046 {
00047     GREAL m_penetration_depth;
00048     GUINT m_point_count;
00049     btVector4 m_separating_normal;
00050     btVector3 m_points[MAX_TRI_CLIPPING];
00051 
00052         SIMD_FORCE_INLINE void copy_from(const GIM_TRIANGLE_CONTACT_DATA& other)
00053         {
00054                 m_penetration_depth = other.m_penetration_depth;
00055                 m_separating_normal = other.m_separating_normal;
00056                 m_point_count = other.m_point_count;
00057                 GUINT i = m_point_count;
00058                 while(i--)
00059                 {
00060                         m_points[i] = other.m_points[i];
00061                 }
00062         }
00063 
00064         GIM_TRIANGLE_CONTACT_DATA()
00065         {
00066         }
00067 
00068         GIM_TRIANGLE_CONTACT_DATA(const GIM_TRIANGLE_CONTACT_DATA& other)
00069         {
00070                 copy_from(other);
00071         }
00072 
00073         
00074         
00075 
00077     template<typename DISTANCE_FUNC,typename CLASS_PLANE>
00078     SIMD_FORCE_INLINE void mergepoints_generic(const CLASS_PLANE & plane,
00079                                 GREAL margin, const btVector3 * points, GUINT point_count, DISTANCE_FUNC distance_func)
00080     {   
00081         m_point_count = 0;
00082         m_penetration_depth= -1000.0f;
00083 
00084                 GUINT point_indices[MAX_TRI_CLIPPING];
00085 
00086                 GUINT _k;
00087 
00088                 for(_k=0;_k<point_count;_k++)
00089                 {
00090                         GREAL _dist = -distance_func(plane,points[_k]) + margin;
00091 
00092                         if(_dist>=0.0f)
00093                         {
00094                                 if(_dist>m_penetration_depth)
00095                                 {
00096                                         m_penetration_depth = _dist;
00097                                         point_indices[0] = _k;
00098                                         m_point_count=1;
00099                                 }
00100                                 else if((_dist+G_EPSILON)>=m_penetration_depth)
00101                                 {
00102                                         point_indices[m_point_count] = _k;
00103                                         m_point_count++;
00104                                 }
00105                         }
00106                 }
00107 
00108                 for( _k=0;_k<m_point_count;_k++)
00109                 {
00110                         m_points[_k] = points[point_indices[_k]];
00111                 }
00112         }
00113 
00115         SIMD_FORCE_INLINE void merge_points(const btVector4 & plane, GREAL margin,
00116                                                                                  const btVector3 * points, GUINT point_count)
00117         {
00118                 m_separating_normal = plane;
00119                 mergepoints_generic(plane, margin, points, point_count, DISTANCE_PLANE_3D_FUNC());
00120         }
00121 };
00122 
00123 
00125 class GIM_TRIANGLE
00126 {
00127 public:
00128         btScalar m_margin;
00129     btVector3 m_vertices[3];
00130 
00131     GIM_TRIANGLE():m_margin(0.1f)
00132     {
00133     }
00134 
00135     SIMD_FORCE_INLINE GIM_AABB get_box()  const
00136     {
00137         return GIM_AABB(m_vertices[0],m_vertices[1],m_vertices[2],m_margin);
00138     }
00139 
00140     SIMD_FORCE_INLINE void get_normal(btVector3 &normal)  const
00141     {
00142         TRIANGLE_NORMAL(m_vertices[0],m_vertices[1],m_vertices[2],normal);
00143     }
00144 
00145     SIMD_FORCE_INLINE void get_plane(btVector4 &plane)  const
00146     {
00147         TRIANGLE_PLANE(m_vertices[0],m_vertices[1],m_vertices[2],plane);;
00148     }
00149 
00150     SIMD_FORCE_INLINE void apply_transform(const btTransform & trans)
00151     {
00152         m_vertices[0] = trans(m_vertices[0]);
00153         m_vertices[1] = trans(m_vertices[1]);
00154         m_vertices[2] = trans(m_vertices[2]);
00155     }
00156 
00157     SIMD_FORCE_INLINE void get_edge_plane(GUINT edge_index,const btVector3 &triangle_normal,btVector4 &plane)  const
00158     {
00159                 const btVector3 & e0 = m_vertices[edge_index];
00160                 const btVector3 & e1 = m_vertices[(edge_index+1)%3];
00161                 EDGE_PLANE(e0,e1,triangle_normal,plane);
00162     }
00163 
00165 
00171     SIMD_FORCE_INLINE void get_triangle_transform(btTransform & triangle_transform)  const
00172     {
00173         btMatrix3x3 & matrix = triangle_transform.getBasis();
00174 
00175         btVector3 zaxis;
00176         get_normal(zaxis);
00177         MAT_SET_Z(matrix,zaxis);
00178 
00179         btVector3 xaxis = m_vertices[1] - m_vertices[0];
00180         VEC_NORMALIZE(xaxis);
00181         MAT_SET_X(matrix,xaxis);
00182 
00183         //y axis
00184         xaxis = zaxis.cross(xaxis);
00185         MAT_SET_Y(matrix,xaxis);
00186 
00187         triangle_transform.setOrigin(m_vertices[0]);
00188     }
00189 
00190 
00192 
00196         bool collide_triangle_hard_test(
00197                 const GIM_TRIANGLE & other,
00198                 GIM_TRIANGLE_CONTACT_DATA & contact_data) const;
00199 
00201 
00206         SIMD_FORCE_INLINE bool collide_triangle(
00207                 const GIM_TRIANGLE & other,
00208                 GIM_TRIANGLE_CONTACT_DATA & contact_data) const
00209         {
00210                 //test box collisioin
00211                 GIM_AABB boxu(m_vertices[0],m_vertices[1],m_vertices[2],m_margin);
00212                 GIM_AABB boxv(other.m_vertices[0],other.m_vertices[1],other.m_vertices[2],other.m_margin);
00213                 if(!boxu.has_collision(boxv)) return false;
00214 
00215                 //do hard test
00216                 return collide_triangle_hard_test(other,contact_data);
00217         }
00218 
00247         SIMD_FORCE_INLINE bool get_uv_parameters(
00248                         const btVector3 & point,
00249                         const btVector3 & tri_plane,
00250                         GREAL & u, GREAL & v) const
00251         {
00252                 btVector3 _axe1 = m_vertices[1]-m_vertices[0];
00253                 btVector3 _axe2 = m_vertices[2]-m_vertices[0];
00254                 btVector3 _vecproj = point - m_vertices[0];
00255                 GUINT _i1 = (tri_plane.closestAxis()+1)%3;
00256                 GUINT _i2 = (_i1+1)%3;
00257                 if(btFabs(_axe2[_i2])<G_EPSILON)
00258                 {
00259                         u = (_vecproj[_i2]*_axe2[_i1] - _vecproj[_i1]*_axe2[_i2]) /(_axe1[_i2]*_axe2[_i1]  - _axe1[_i1]*_axe2[_i2]);
00260                         v = (_vecproj[_i1] - u*_axe1[_i1])/_axe2[_i1];
00261                 }
00262                 else
00263                 {
00264                         u = (_vecproj[_i1]*_axe2[_i2] - _vecproj[_i2]*_axe2[_i1]) /(_axe1[_i1]*_axe2[_i2]  - _axe1[_i2]*_axe2[_i1]);
00265                         v = (_vecproj[_i2] - u*_axe1[_i2])/_axe2[_i2];
00266                 }
00267 
00268                 if(u<-G_EPSILON)
00269                 {
00270                         return false;
00271                 }
00272                 else if(v<-G_EPSILON)
00273                 {
00274                         return false;
00275                 }
00276                 else
00277                 {
00278                         btScalar sumuv;
00279                         sumuv = u+v;
00280                         if(sumuv<-G_EPSILON)
00281                         {
00282                                 return false;
00283                         }
00284                         else if(sumuv-1.0f>G_EPSILON)
00285                         {
00286                                 return false;
00287                         }
00288                 }
00289                 return true;
00290         }
00291 
00293 
00296         SIMD_FORCE_INLINE bool is_point_inside(const btVector3 & point, const btVector3 & tri_normal) const
00297         {
00298                 //Test with edge 0
00299                 btVector4 edge_plane;
00300                 this->get_edge_plane(0,tri_normal,edge_plane);
00301                 GREAL dist = DISTANCE_PLANE_POINT(edge_plane,point);
00302                 if(dist-m_margin>0.0f) return false; // outside plane
00303 
00304                 this->get_edge_plane(1,tri_normal,edge_plane);
00305                 dist = DISTANCE_PLANE_POINT(edge_plane,point);
00306                 if(dist-m_margin>0.0f) return false; // outside plane
00307 
00308                 this->get_edge_plane(2,tri_normal,edge_plane);
00309                 dist = DISTANCE_PLANE_POINT(edge_plane,point);
00310                 if(dist-m_margin>0.0f) return false; // outside plane
00311                 return true;
00312         }
00313 
00314 
00316         SIMD_FORCE_INLINE bool ray_collision(
00317                 const btVector3 & vPoint,
00318                 const btVector3 & vDir, btVector3 & pout, btVector3 & triangle_normal,
00319                 GREAL & tparam, GREAL tmax = G_REAL_INFINITY)
00320         {
00321                 btVector4 faceplane;
00322                 {
00323                         btVector3 dif1 = m_vertices[1] - m_vertices[0];
00324                         btVector3 dif2 = m_vertices[2] - m_vertices[0];
00325                 VEC_CROSS(faceplane,dif1,dif2);
00326                 faceplane[3] = m_vertices[0].dot(faceplane);
00327                 }
00328 
00329                 GUINT res = LINE_PLANE_COLLISION(faceplane,vDir,vPoint,pout,tparam, btScalar(0), tmax);
00330                 if(res == 0) return false;
00331                 if(! is_point_inside(pout,faceplane)) return false;
00332 
00333                 if(res==2) //invert normal
00334                 {
00335                         triangle_normal.setValue(-faceplane[0],-faceplane[1],-faceplane[2]);
00336                 }
00337                 else
00338                 {
00339                         triangle_normal.setValue(faceplane[0],faceplane[1],faceplane[2]);
00340                 }
00341 
00342                 VEC_NORMALIZE(triangle_normal);
00343 
00344                 return true;
00345         }
00346 
00347 
00349         SIMD_FORCE_INLINE bool ray_collision_front_side(
00350                 const btVector3 & vPoint,
00351                 const btVector3 & vDir, btVector3 & pout, btVector3 & triangle_normal,
00352                 GREAL & tparam, GREAL tmax = G_REAL_INFINITY)
00353         {
00354                 btVector4 faceplane;
00355                 {
00356                         btVector3 dif1 = m_vertices[1] - m_vertices[0];
00357                         btVector3 dif2 = m_vertices[2] - m_vertices[0];
00358                 VEC_CROSS(faceplane,dif1,dif2);
00359                 faceplane[3] = m_vertices[0].dot(faceplane);
00360                 }
00361 
00362                 GUINT res = LINE_PLANE_COLLISION(faceplane,vDir,vPoint,pout,tparam, btScalar(0), tmax);
00363                 if(res != 1) return false;
00364 
00365                 if(!is_point_inside(pout,faceplane)) return false;
00366 
00367                 triangle_normal.setValue(faceplane[0],faceplane[1],faceplane[2]);
00368 
00369                 VEC_NORMALIZE(triangle_normal);
00370 
00371                 return true;
00372         }
00373 
00374 };
00375 
00376 
00377 
00378 
00379 #endif // GIM_TRI_COLLISION_H_INCLUDED
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines


bullet
Author(s): Erwin Coumans, ROS package maintained by Tully Foote
autogenerated on Wed Oct 31 2012 07:54:31