| 1 |  | 
|---|
| 2 | /*! \file gim_tri_collision.h | 
|---|
| 3 | \author Francisco Len Nßjera | 
|---|
| 4 | */ | 
|---|
| 5 | /* | 
|---|
| 6 | ----------------------------------------------------------------------------- | 
|---|
| 7 | This source file is part of GIMPACT Library. | 
|---|
| 8 |  | 
|---|
| 9 | For the latest info, see http://gimpact.sourceforge.net/ | 
|---|
| 10 |  | 
|---|
| 11 | Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371. | 
|---|
| 12 | email: projectileman@yahoo.com | 
|---|
| 13 |  | 
|---|
| 14 |  This library is free software; you can redistribute it and/or | 
|---|
| 15 |  modify it under the terms of EITHER: | 
|---|
| 16 |    (1) The GNU Lesser General Public License as published by the Free | 
|---|
| 17 |        Software Foundation; either version 2.1 of the License, or (at | 
|---|
| 18 |        your option) any later version. The text of the GNU Lesser | 
|---|
| 19 |        General Public License is included with this library in the | 
|---|
| 20 |        file GIMPACT-LICENSE-LGPL.TXT. | 
|---|
| 21 |    (2) The BSD-style license that is included with this library in | 
|---|
| 22 |        the file GIMPACT-LICENSE-BSD.TXT. | 
|---|
| 23 |    (3) The zlib/libpng license that is included with this library in | 
|---|
| 24 |        the file GIMPACT-LICENSE-ZLIB.TXT. | 
|---|
| 25 |  | 
|---|
| 26 |  This library is distributed in the hope that it will be useful, | 
|---|
| 27 |  but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|---|
| 28 |  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files | 
|---|
| 29 |  GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details. | 
|---|
| 30 |  | 
|---|
| 31 | ----------------------------------------------------------------------------- | 
|---|
| 32 | */ | 
|---|
| 33 |  | 
|---|
| 34 | #include "gim_tri_collision.h" | 
|---|
| 35 |  | 
|---|
| 36 |  | 
|---|
| 37 | #define TRI_LOCAL_EPSILON 0.000001f | 
|---|
| 38 | #define MIN_EDGE_EDGE_DIS 0.00001f | 
|---|
| 39 |  | 
|---|
| 40 |  | 
|---|
| 41 | class GIM_TRIANGLE_CALCULATION_CACHE | 
|---|
| 42 | { | 
|---|
| 43 | public: | 
|---|
| 44 |         GREAL margin;    | 
|---|
| 45 |         btVector3 tu_vertices[3]; | 
|---|
| 46 |         btVector3 tv_vertices[3]; | 
|---|
| 47 |         btVector4 tu_plane; | 
|---|
| 48 |         btVector4 tv_plane; | 
|---|
| 49 |         btVector3 closest_point_u; | 
|---|
| 50 |         btVector3 closest_point_v; | 
|---|
| 51 |         btVector3 edge_edge_dir; | 
|---|
| 52 |         btVector3 distances; | 
|---|
| 53 |         GREAL du[4]; | 
|---|
| 54 |         GREAL du0du1; | 
|---|
| 55 |         GREAL du0du2; | 
|---|
| 56 |         GREAL dv[4]; | 
|---|
| 57 |         GREAL dv0dv1; | 
|---|
| 58 |         GREAL dv0dv2;    | 
|---|
| 59 |         btVector3 temp_points[MAX_TRI_CLIPPING]; | 
|---|
| 60 |         btVector3 temp_points1[MAX_TRI_CLIPPING]; | 
|---|
| 61 |         btVector3 contact_points[MAX_TRI_CLIPPING]; | 
|---|
| 62 |          | 
|---|
| 63 |  | 
|---|
| 64 |  | 
|---|
| 65 |         //! if returns false, the faces are paralele | 
|---|
| 66 |         SIMD_FORCE_INLINE bool compute_intervals( | 
|---|
| 67 |                                         const GREAL &D0, | 
|---|
| 68 |                                         const GREAL &D1, | 
|---|
| 69 |                                         const GREAL &D2, | 
|---|
| 70 |                                         const GREAL &D0D1, | 
|---|
| 71 |                                         const GREAL &D0D2, | 
|---|
| 72 |                                         GREAL & scale_edge0, | 
|---|
| 73 |                                         GREAL & scale_edge1, | 
|---|
| 74 |                                         GUINT &edge_index0, | 
|---|
| 75 |                                         GUINT &edge_index1) | 
|---|
| 76 |         { | 
|---|
| 77 |                 if(D0D1>0.0f) | 
|---|
| 78 |                 { | 
|---|
| 79 |                         /* here we know that D0D2<=0.0 */ | 
|---|
| 80 |                         /* that is D0, D1 are on the same side, D2 on the other or on the plane */ | 
|---|
| 81 |                         scale_edge0 = -D2/(D0-D2); | 
|---|
| 82 |                         scale_edge1 = -D1/(D2-D1); | 
|---|
| 83 |                         edge_index0 = 2;edge_index1 = 1; | 
|---|
| 84 |                 } | 
|---|
| 85 |                 else if(D0D2>0.0f) | 
|---|
| 86 |                 { | 
|---|
| 87 |                         /* here we know that d0d1<=0.0 */ | 
|---|
| 88 |                         scale_edge0 = -D0/(D1-D0); | 
|---|
| 89 |                         scale_edge1 = -D1/(D2-D1); | 
|---|
| 90 |                         edge_index0 = 0;edge_index1 = 1; | 
|---|
| 91 |                 } | 
|---|
| 92 |                 else if(D1*D2>0.0f || D0!=0.0f) | 
|---|
| 93 |                 { | 
|---|
| 94 |                         /* here we know that d0d1<=0.0 or that D0!=0.0 */ | 
|---|
| 95 |                         scale_edge0 = -D0/(D1-D0); | 
|---|
| 96 |                         scale_edge1 = -D2/(D0-D2); | 
|---|
| 97 |                         edge_index0 = 0 ;edge_index1 = 2; | 
|---|
| 98 |                 } | 
|---|
| 99 |                 else | 
|---|
| 100 |                 { | 
|---|
| 101 |                         return false; | 
|---|
| 102 |                 } | 
|---|
| 103 |                 return true; | 
|---|
| 104 |         } | 
|---|
| 105 |  | 
|---|
| 106 |  | 
|---|
| 107 |         //! clip triangle | 
|---|
| 108 |         /*! | 
|---|
| 109 |         */ | 
|---|
| 110 |         SIMD_FORCE_INLINE GUINT clip_triangle( | 
|---|
| 111 |                 const btVector4 & tri_plane, | 
|---|
| 112 |                 const btVector3 * tripoints, | 
|---|
| 113 |                 const btVector3 * srcpoints, | 
|---|
| 114 |                 btVector3 * clip_points) | 
|---|
| 115 |         { | 
|---|
| 116 |                 // edge 0 | 
|---|
| 117 |  | 
|---|
| 118 |                 btVector4 edgeplane; | 
|---|
| 119 |  | 
|---|
| 120 |                 EDGE_PLANE(tripoints[0],tripoints[1],tri_plane,edgeplane); | 
|---|
| 121 |  | 
|---|
| 122 |                 GUINT clipped_count = PLANE_CLIP_TRIANGLE3D( | 
|---|
| 123 |                         edgeplane,srcpoints[0],srcpoints[1],srcpoints[2],temp_points); | 
|---|
| 124 |  | 
|---|
| 125 |                 if(clipped_count == 0) return 0; | 
|---|
| 126 |  | 
|---|
| 127 |                 // edge 1 | 
|---|
| 128 |  | 
|---|
| 129 |                 EDGE_PLANE(tripoints[1],tripoints[2],tri_plane,edgeplane); | 
|---|
| 130 |  | 
|---|
| 131 |                 clipped_count = PLANE_CLIP_POLYGON3D( | 
|---|
| 132 |                         edgeplane,temp_points,clipped_count,temp_points1); | 
|---|
| 133 |  | 
|---|
| 134 |                 if(clipped_count == 0) return 0; | 
|---|
| 135 |  | 
|---|
| 136 |                 // edge 2 | 
|---|
| 137 |  | 
|---|
| 138 |                 EDGE_PLANE(tripoints[2],tripoints[0],tri_plane,edgeplane); | 
|---|
| 139 |  | 
|---|
| 140 |                 clipped_count = PLANE_CLIP_POLYGON3D( | 
|---|
| 141 |                         edgeplane,temp_points1,clipped_count,clip_points); | 
|---|
| 142 |  | 
|---|
| 143 |                 return clipped_count; | 
|---|
| 144 |  | 
|---|
| 145 |  | 
|---|
| 146 |                 /*GUINT i0 = (tri_plane.closestAxis()+1)%3; | 
|---|
| 147 |                 GUINT i1 = (i0+1)%3; | 
|---|
| 148 |                 // edge 0 | 
|---|
| 149 |                 btVector3 temp_points[MAX_TRI_CLIPPING]; | 
|---|
| 150 |                 btVector3 temp_points1[MAX_TRI_CLIPPING]; | 
|---|
| 151 |  | 
|---|
| 152 |                 GUINT clipped_count= PLANE_CLIP_TRIANGLE_GENERIC( | 
|---|
| 153 |                         0,srcpoints[0],srcpoints[1],srcpoints[2],temp_points, | 
|---|
| 154 |                         DISTANCE_EDGE(tripoints[0],tripoints[1],i0,i1)); | 
|---|
| 155 |                  | 
|---|
| 156 |                  | 
|---|
| 157 |                 if(clipped_count == 0) return 0; | 
|---|
| 158 |  | 
|---|
| 159 |                 // edge 1 | 
|---|
| 160 |                 clipped_count = PLANE_CLIP_POLYGON_GENERIC( | 
|---|
| 161 |                         0,temp_points,clipped_count,temp_points1, | 
|---|
| 162 |                         DISTANCE_EDGE(tripoints[1],tripoints[2],i0,i1)); | 
|---|
| 163 |  | 
|---|
| 164 |                 if(clipped_count == 0) return 0; | 
|---|
| 165 |  | 
|---|
| 166 |                 // edge 2 | 
|---|
| 167 |                 clipped_count = PLANE_CLIP_POLYGON_GENERIC( | 
|---|
| 168 |                         0,temp_points1,clipped_count,clipped_points, | 
|---|
| 169 |                         DISTANCE_EDGE(tripoints[2],tripoints[0],i0,i1)); | 
|---|
| 170 |  | 
|---|
| 171 |                 return clipped_count;*/ | 
|---|
| 172 |         } | 
|---|
| 173 |  | 
|---|
| 174 |         SIMD_FORCE_INLINE void sort_isect( | 
|---|
| 175 |                 GREAL & isect0,GREAL & isect1,GUINT &e0,GUINT &e1,btVector3 & vec0,btVector3 & vec1) | 
|---|
| 176 |         { | 
|---|
| 177 |                 if(isect1<isect0) | 
|---|
| 178 |                 { | 
|---|
| 179 |                         //swap | 
|---|
| 180 |                         GIM_SWAP_NUMBERS(isect0,isect1); | 
|---|
| 181 |                         GIM_SWAP_NUMBERS(e0,e1); | 
|---|
| 182 |                         btVector3 tmp = vec0; | 
|---|
| 183 |                         vec0 = vec1; | 
|---|
| 184 |                         vec1 = tmp; | 
|---|
| 185 |                 } | 
|---|
| 186 |         } | 
|---|
| 187 |  | 
|---|
| 188 |         //! Test verifying interval intersection with the direction between planes | 
|---|
| 189 |         /*! | 
|---|
| 190 |         \pre tv_plane and tu_plane must be set | 
|---|
| 191 |         \post | 
|---|
| 192 |         distances[2] is set with the distance | 
|---|
| 193 |         closest_point_u, closest_point_v, edge_edge_dir are set too | 
|---|
| 194 |         \return | 
|---|
| 195 |         - 0: faces are paralele | 
|---|
| 196 |         - 1: face U casts face V | 
|---|
| 197 |         - 2: face V casts face U | 
|---|
| 198 |         - 3: nearest edges | 
|---|
| 199 |         */ | 
|---|
| 200 |         SIMD_FORCE_INLINE GUINT cross_line_intersection_test() | 
|---|
| 201 |         { | 
|---|
| 202 |                 // Compute direction of intersection line | 
|---|
| 203 |                 edge_edge_dir = tu_plane.cross(tv_plane); | 
|---|
| 204 |                 GREAL Dlen; | 
|---|
| 205 |                 VEC_LENGTH(edge_edge_dir,Dlen); | 
|---|
| 206 |  | 
|---|
| 207 |                 if(Dlen<0.0001) | 
|---|
| 208 |                 { | 
|---|
| 209 |                         return 0; //faces near paralele | 
|---|
| 210 |                 } | 
|---|
| 211 |  | 
|---|
| 212 |                 edge_edge_dir*= 1/Dlen;//normalize | 
|---|
| 213 |  | 
|---|
| 214 |  | 
|---|
| 215 |                 // Compute interval for triangle 1 | 
|---|
| 216 |                 GUINT tu_e0,tu_e1;//edge indices | 
|---|
| 217 |                 GREAL tu_scale_e0,tu_scale_e1;//edge scale | 
|---|
| 218 |                 if(!compute_intervals(du[0],du[1],du[2], | 
|---|
| 219 |                         du0du1,du0du2,tu_scale_e0,tu_scale_e1,tu_e0,tu_e1)) return 0; | 
|---|
| 220 |  | 
|---|
| 221 |                 // Compute interval for triangle 2 | 
|---|
| 222 |                 GUINT tv_e0,tv_e1;//edge indices | 
|---|
| 223 |                 GREAL tv_scale_e0,tv_scale_e1;//edge scale | 
|---|
| 224 |  | 
|---|
| 225 |                 if(!compute_intervals(dv[0],dv[1],dv[2], | 
|---|
| 226 |                         dv0dv1,dv0dv2,tv_scale_e0,tv_scale_e1,tv_e0,tv_e1)) return 0; | 
|---|
| 227 |  | 
|---|
| 228 |                 //proyected vertices | 
|---|
| 229 |                 btVector3 up_e0 = tu_vertices[tu_e0].lerp(tu_vertices[(tu_e0+1)%3],tu_scale_e0); | 
|---|
| 230 |                 btVector3 up_e1 = tu_vertices[tu_e1].lerp(tu_vertices[(tu_e1+1)%3],tu_scale_e1); | 
|---|
| 231 |  | 
|---|
| 232 |                 btVector3 vp_e0 = tv_vertices[tv_e0].lerp(tv_vertices[(tv_e0+1)%3],tv_scale_e0); | 
|---|
| 233 |                 btVector3 vp_e1 = tv_vertices[tv_e1].lerp(tv_vertices[(tv_e1+1)%3],tv_scale_e1); | 
|---|
| 234 |  | 
|---|
| 235 |                 //proyected intervals | 
|---|
| 236 |                 GREAL isect_u[] = {up_e0.dot(edge_edge_dir),up_e1.dot(edge_edge_dir)}; | 
|---|
| 237 |                 GREAL isect_v[] = {vp_e0.dot(edge_edge_dir),vp_e1.dot(edge_edge_dir)}; | 
|---|
| 238 |  | 
|---|
| 239 |                 sort_isect(isect_u[0],isect_u[1],tu_e0,tu_e1,up_e0,up_e1); | 
|---|
| 240 |                 sort_isect(isect_v[0],isect_v[1],tv_e0,tv_e1,vp_e0,vp_e1); | 
|---|
| 241 |  | 
|---|
| 242 |                 const GREAL midpoint_u = 0.5f*(isect_u[0]+isect_u[1]); // midpoint | 
|---|
| 243 |                 const GREAL midpoint_v = 0.5f*(isect_v[0]+isect_v[1]); // midpoint | 
|---|
| 244 |  | 
|---|
| 245 |                 if(midpoint_u<midpoint_v) | 
|---|
| 246 |                 { | 
|---|
| 247 |                         if(isect_u[1]>=isect_v[1]) // face U casts face V | 
|---|
| 248 |                         { | 
|---|
| 249 |                                 return 1; | 
|---|
| 250 |                         } | 
|---|
| 251 |                         else if(isect_v[0]<=isect_u[0]) // face V casts face U | 
|---|
| 252 |                         { | 
|---|
| 253 |                                 return 2; | 
|---|
| 254 |                         } | 
|---|
| 255 |                         // closest points | 
|---|
| 256 |                         closest_point_u = up_e1; | 
|---|
| 257 |                         closest_point_v = vp_e0; | 
|---|
| 258 |                         // calc edges and separation | 
|---|
| 259 |  | 
|---|
| 260 |                         if(isect_u[1]+ MIN_EDGE_EDGE_DIS<isect_v[0]) //calc distance between two lines instead | 
|---|
| 261 |                         { | 
|---|
| 262 |                                 SEGMENT_COLLISION( | 
|---|
| 263 |                                         tu_vertices[tu_e1],tu_vertices[(tu_e1+1)%3], | 
|---|
| 264 |                                         tv_vertices[tv_e0],tv_vertices[(tv_e0+1)%3], | 
|---|
| 265 |                                         closest_point_u, | 
|---|
| 266 |                                         closest_point_v); | 
|---|
| 267 |  | 
|---|
| 268 |                                 edge_edge_dir = closest_point_u-closest_point_v; | 
|---|
| 269 |                                 VEC_LENGTH(edge_edge_dir,distances[2]); | 
|---|
| 270 |                                 edge_edge_dir *= 1.0f/distances[2];// normalize | 
|---|
| 271 |                         } | 
|---|
| 272 |                         else | 
|---|
| 273 |                         { | 
|---|
| 274 |                                 distances[2] = isect_v[0]-isect_u[1];//distance negative | 
|---|
| 275 |                                 //edge_edge_dir *= -1.0f; //normal pointing from V to U | 
|---|
| 276 |                         } | 
|---|
| 277 |  | 
|---|
| 278 |                 } | 
|---|
| 279 |                 else | 
|---|
| 280 |                 { | 
|---|
| 281 |                         if(isect_v[1]>=isect_u[1]) // face V casts face U | 
|---|
| 282 |                         { | 
|---|
| 283 |                                 return 2; | 
|---|
| 284 |                         } | 
|---|
| 285 |                         else if(isect_u[0]<=isect_v[0]) // face U casts face V | 
|---|
| 286 |                         { | 
|---|
| 287 |                                 return 1; | 
|---|
| 288 |                         } | 
|---|
| 289 |                         // closest points | 
|---|
| 290 |                         closest_point_u = up_e0; | 
|---|
| 291 |                         closest_point_v = vp_e1; | 
|---|
| 292 |                         // calc edges and separation | 
|---|
| 293 |  | 
|---|
| 294 |                         if(isect_v[1]+MIN_EDGE_EDGE_DIS<isect_u[0]) //calc distance between two lines instead | 
|---|
| 295 |                         { | 
|---|
| 296 |                                 SEGMENT_COLLISION( | 
|---|
| 297 |                                         tu_vertices[tu_e0],tu_vertices[(tu_e0+1)%3], | 
|---|
| 298 |                                         tv_vertices[tv_e1],tv_vertices[(tv_e1+1)%3], | 
|---|
| 299 |                                         closest_point_u, | 
|---|
| 300 |                                         closest_point_v); | 
|---|
| 301 |  | 
|---|
| 302 |                                 edge_edge_dir = closest_point_u-closest_point_v; | 
|---|
| 303 |                                 VEC_LENGTH(edge_edge_dir,distances[2]); | 
|---|
| 304 |                                 edge_edge_dir *= 1.0f/distances[2];// normalize | 
|---|
| 305 |                         } | 
|---|
| 306 |                         else | 
|---|
| 307 |                         { | 
|---|
| 308 |                                 distances[2] = isect_u[0]-isect_v[1];//distance negative | 
|---|
| 309 |                                 //edge_edge_dir *= -1.0f; //normal pointing from V to U | 
|---|
| 310 |                         } | 
|---|
| 311 |                 } | 
|---|
| 312 |                 return 3; | 
|---|
| 313 |         } | 
|---|
| 314 |  | 
|---|
| 315 |  | 
|---|
| 316 |         //! collides by two sides | 
|---|
| 317 |         SIMD_FORCE_INLINE bool triangle_collision( | 
|---|
| 318 |                                         const btVector3 & u0, | 
|---|
| 319 |                                         const btVector3 & u1, | 
|---|
| 320 |                                         const btVector3 & u2, | 
|---|
| 321 |                                         GREAL margin_u, | 
|---|
| 322 |                                         const btVector3 & v0, | 
|---|
| 323 |                                         const btVector3 & v1, | 
|---|
| 324 |                                         const btVector3 & v2, | 
|---|
| 325 |                                         GREAL margin_v, | 
|---|
| 326 |                                         GIM_TRIANGLE_CONTACT_DATA & contacts) | 
|---|
| 327 |         { | 
|---|
| 328 |  | 
|---|
| 329 |                 margin = margin_u + margin_v; | 
|---|
| 330 |  | 
|---|
| 331 |                 tu_vertices[0] = u0; | 
|---|
| 332 |                 tu_vertices[1] = u1; | 
|---|
| 333 |                 tu_vertices[2] = u2; | 
|---|
| 334 |  | 
|---|
| 335 |                 tv_vertices[0] = v0; | 
|---|
| 336 |                 tv_vertices[1] = v1; | 
|---|
| 337 |                 tv_vertices[2] = v2; | 
|---|
| 338 |  | 
|---|
| 339 |                 //create planes | 
|---|
| 340 |                 // plane v vs U points | 
|---|
| 341 |  | 
|---|
| 342 |                 TRIANGLE_PLANE(tv_vertices[0],tv_vertices[1],tv_vertices[2],tv_plane); | 
|---|
| 343 |  | 
|---|
| 344 |                 du[0] = DISTANCE_PLANE_POINT(tv_plane,tu_vertices[0]); | 
|---|
| 345 |                 du[1] = DISTANCE_PLANE_POINT(tv_plane,tu_vertices[1]); | 
|---|
| 346 |                 du[2] = DISTANCE_PLANE_POINT(tv_plane,tu_vertices[2]); | 
|---|
| 347 |  | 
|---|
| 348 |  | 
|---|
| 349 |                 du0du1 = du[0] * du[1]; | 
|---|
| 350 |                 du0du2 = du[0] * du[2]; | 
|---|
| 351 |  | 
|---|
| 352 |  | 
|---|
| 353 |                 if(du0du1>0.0f && du0du2>0.0f)  // same sign on all of them + not equal 0 ? | 
|---|
| 354 |                 { | 
|---|
| 355 |                         if(du[0]<0) //we need test behind the triangle plane | 
|---|
| 356 |                         { | 
|---|
| 357 |                                 distances[0] = GIM_MAX3(du[0],du[1],du[2]); | 
|---|
| 358 |                                 distances[0] = -distances[0]; | 
|---|
| 359 |                                 if(distances[0]>margin) return false; //never intersect | 
|---|
| 360 |  | 
|---|
| 361 |                                 //reorder triangle v | 
|---|
| 362 |                                 VEC_SWAP(tv_vertices[0],tv_vertices[1]); | 
|---|
| 363 |                                 VEC_SCALE_4(tv_plane,-1.0f,tv_plane); | 
|---|
| 364 |                         } | 
|---|
| 365 |                         else | 
|---|
| 366 |                         { | 
|---|
| 367 |                                 distances[0] = GIM_MIN3(du[0],du[1],du[2]); | 
|---|
| 368 |                                 if(distances[0]>margin) return false; //never intersect | 
|---|
| 369 |                         } | 
|---|
| 370 |                 } | 
|---|
| 371 |                 else | 
|---|
| 372 |                 { | 
|---|
| 373 |                         //Look if we need to invert the triangle | 
|---|
| 374 |                         distances[0] = (du[0]+du[1]+du[2])/3.0f; //centroid | 
|---|
| 375 |  | 
|---|
| 376 |                         if(distances[0]<0.0f) | 
|---|
| 377 |                         { | 
|---|
| 378 |                                 //reorder triangle v | 
|---|
| 379 |                                 VEC_SWAP(tv_vertices[0],tv_vertices[1]); | 
|---|
| 380 |                                 VEC_SCALE_4(tv_plane,-1.0f,tv_plane); | 
|---|
| 381 |  | 
|---|
| 382 |                                 distances[0] = GIM_MAX3(du[0],du[1],du[2]); | 
|---|
| 383 |                                 distances[0] = -distances[0]; | 
|---|
| 384 |                         } | 
|---|
| 385 |                         else | 
|---|
| 386 |                         { | 
|---|
| 387 |                                 distances[0] = GIM_MIN3(du[0],du[1],du[2]); | 
|---|
| 388 |                         } | 
|---|
| 389 |                 } | 
|---|
| 390 |  | 
|---|
| 391 |  | 
|---|
| 392 |                 // plane U vs V points | 
|---|
| 393 |  | 
|---|
| 394 |                 TRIANGLE_PLANE(tu_vertices[0],tu_vertices[1],tu_vertices[2],tu_plane); | 
|---|
| 395 |  | 
|---|
| 396 |                 dv[0] = DISTANCE_PLANE_POINT(tu_plane,tv_vertices[0]); | 
|---|
| 397 |                 dv[1] = DISTANCE_PLANE_POINT(tu_plane,tv_vertices[1]); | 
|---|
| 398 |                 dv[2] = DISTANCE_PLANE_POINT(tu_plane,tv_vertices[2]); | 
|---|
| 399 |  | 
|---|
| 400 |                 dv0dv1 = dv[0] * dv[1]; | 
|---|
| 401 |                 dv0dv2 = dv[0] * dv[2]; | 
|---|
| 402 |  | 
|---|
| 403 |  | 
|---|
| 404 |                 if(dv0dv1>0.0f && dv0dv2>0.0f)  // same sign on all of them + not equal 0 ? | 
|---|
| 405 |                 { | 
|---|
| 406 |                         if(dv[0]<0) //we need test behind the triangle plane | 
|---|
| 407 |                         { | 
|---|
| 408 |                                 distances[1] = GIM_MAX3(dv[0],dv[1],dv[2]); | 
|---|
| 409 |                                 distances[1] = -distances[1]; | 
|---|
| 410 |                                 if(distances[1]>margin) return false; //never intersect | 
|---|
| 411 |  | 
|---|
| 412 |                                 //reorder triangle u | 
|---|
| 413 |                                 VEC_SWAP(tu_vertices[0],tu_vertices[1]); | 
|---|
| 414 |                                 VEC_SCALE_4(tu_plane,-1.0f,tu_plane); | 
|---|
| 415 |                         } | 
|---|
| 416 |                         else | 
|---|
| 417 |                         { | 
|---|
| 418 |                                 distances[1] = GIM_MIN3(dv[0],dv[1],dv[2]); | 
|---|
| 419 |                                 if(distances[1]>margin) return false; //never intersect | 
|---|
| 420 |                         } | 
|---|
| 421 |                 } | 
|---|
| 422 |                 else | 
|---|
| 423 |                 { | 
|---|
| 424 |                         //Look if we need to invert the triangle | 
|---|
| 425 |                         distances[1] = (dv[0]+dv[1]+dv[2])/3.0f; //centroid | 
|---|
| 426 |  | 
|---|
| 427 |                         if(distances[1]<0.0f) | 
|---|
| 428 |                         { | 
|---|
| 429 |                                 //reorder triangle v | 
|---|
| 430 |                                 VEC_SWAP(tu_vertices[0],tu_vertices[1]); | 
|---|
| 431 |                                 VEC_SCALE_4(tu_plane,-1.0f,tu_plane); | 
|---|
| 432 |  | 
|---|
| 433 |                                 distances[1] = GIM_MAX3(dv[0],dv[1],dv[2]); | 
|---|
| 434 |                                 distances[1] = -distances[1]; | 
|---|
| 435 |                         } | 
|---|
| 436 |                         else | 
|---|
| 437 |                         { | 
|---|
| 438 |                                 distances[1] = GIM_MIN3(dv[0],dv[1],dv[2]); | 
|---|
| 439 |                         } | 
|---|
| 440 |                 } | 
|---|
| 441 |  | 
|---|
| 442 |                 GUINT bl; | 
|---|
| 443 |                 /* bl = cross_line_intersection_test(); | 
|---|
| 444 |                 if(bl==3) | 
|---|
| 445 |                 { | 
|---|
| 446 |                         //take edge direction too | 
|---|
| 447 |                         bl = distances.maxAxis(); | 
|---|
| 448 |                 } | 
|---|
| 449 |                 else | 
|---|
| 450 |                 {*/ | 
|---|
| 451 |                         bl = 0; | 
|---|
| 452 |                         if(distances[0]<distances[1]) bl = 1; | 
|---|
| 453 |                 //} | 
|---|
| 454 |  | 
|---|
| 455 |                 if(bl==2) //edge edge separation | 
|---|
| 456 |                 { | 
|---|
| 457 |                         if(distances[2]>margin) return false; | 
|---|
| 458 |  | 
|---|
| 459 |                         contacts.m_penetration_depth = -distances[2] + margin; | 
|---|
| 460 |                         contacts.m_points[0] = closest_point_v; | 
|---|
| 461 |                         contacts.m_point_count = 1; | 
|---|
| 462 |                         VEC_COPY(contacts.m_separating_normal,edge_edge_dir); | 
|---|
| 463 |  | 
|---|
| 464 |                         return true; | 
|---|
| 465 |                 } | 
|---|
| 466 |  | 
|---|
| 467 |                 //clip face against other | 
|---|
| 468 |  | 
|---|
| 469 |                  | 
|---|
| 470 |                 GUINT point_count; | 
|---|
| 471 |                 //TODO | 
|---|
| 472 |                 if(bl == 0) //clip U points against V | 
|---|
| 473 |                 { | 
|---|
| 474 |                         point_count = clip_triangle(tv_plane,tv_vertices,tu_vertices,contact_points); | 
|---|
| 475 |                         if(point_count == 0) return false;                                               | 
|---|
| 476 |                         contacts.merge_points(tv_plane,margin,contact_points,point_count);                       | 
|---|
| 477 |                 } | 
|---|
| 478 |                 else //clip V points against U | 
|---|
| 479 |                 { | 
|---|
| 480 |                         point_count = clip_triangle(tu_plane,tu_vertices,tv_vertices,contact_points); | 
|---|
| 481 |                         if(point_count == 0) return false;                       | 
|---|
| 482 |                         contacts.merge_points(tu_plane,margin,contact_points,point_count); | 
|---|
| 483 |                         contacts.m_separating_normal *= -1.f; | 
|---|
| 484 |                 } | 
|---|
| 485 |                 if(contacts.m_point_count == 0) return false; | 
|---|
| 486 |                 return true; | 
|---|
| 487 |         } | 
|---|
| 488 |  | 
|---|
| 489 | }; | 
|---|
| 490 |  | 
|---|
| 491 |  | 
|---|
| 492 | /*class GIM_TRIANGLE_CALCULATION_CACHE | 
|---|
| 493 | { | 
|---|
| 494 | public: | 
|---|
| 495 |         GREAL margin; | 
|---|
| 496 |         GUINT clipped_count; | 
|---|
| 497 |         btVector3 tu_vertices[3]; | 
|---|
| 498 |         btVector3 tv_vertices[3]; | 
|---|
| 499 |         btVector3 temp_points[MAX_TRI_CLIPPING]; | 
|---|
| 500 |         btVector3 temp_points1[MAX_TRI_CLIPPING]; | 
|---|
| 501 |         btVector3 clipped_points[MAX_TRI_CLIPPING]; | 
|---|
| 502 |         GIM_TRIANGLE_CONTACT_DATA contacts1; | 
|---|
| 503 |         GIM_TRIANGLE_CONTACT_DATA contacts2; | 
|---|
| 504 |  | 
|---|
| 505 |  | 
|---|
| 506 |         //! clip triangle | 
|---|
| 507 |         GUINT clip_triangle( | 
|---|
| 508 |                 const btVector4 & tri_plane, | 
|---|
| 509 |                 const btVector3 * tripoints, | 
|---|
| 510 |                 const btVector3 * srcpoints, | 
|---|
| 511 |                 btVector3 * clipped_points) | 
|---|
| 512 |         { | 
|---|
| 513 |                 // edge 0 | 
|---|
| 514 |  | 
|---|
| 515 |                 btVector4 edgeplane; | 
|---|
| 516 |  | 
|---|
| 517 |                 EDGE_PLANE(tripoints[0],tripoints[1],tri_plane,edgeplane); | 
|---|
| 518 |  | 
|---|
| 519 |                 GUINT clipped_count = PLANE_CLIP_TRIANGLE3D( | 
|---|
| 520 |                         edgeplane,srcpoints[0],srcpoints[1],srcpoints[2],temp_points); | 
|---|
| 521 |  | 
|---|
| 522 |                 if(clipped_count == 0) return 0; | 
|---|
| 523 |  | 
|---|
| 524 |                 // edge 1 | 
|---|
| 525 |  | 
|---|
| 526 |                 EDGE_PLANE(tripoints[1],tripoints[2],tri_plane,edgeplane); | 
|---|
| 527 |  | 
|---|
| 528 |                 clipped_count = PLANE_CLIP_POLYGON3D( | 
|---|
| 529 |                         edgeplane,temp_points,clipped_count,temp_points1); | 
|---|
| 530 |  | 
|---|
| 531 |                 if(clipped_count == 0) return 0; | 
|---|
| 532 |  | 
|---|
| 533 |                 // edge 2 | 
|---|
| 534 |  | 
|---|
| 535 |                 EDGE_PLANE(tripoints[2],tripoints[0],tri_plane,edgeplane); | 
|---|
| 536 |  | 
|---|
| 537 |                 clipped_count = PLANE_CLIP_POLYGON3D( | 
|---|
| 538 |                         edgeplane,temp_points1,clipped_count,clipped_points); | 
|---|
| 539 |  | 
|---|
| 540 |                 return clipped_count; | 
|---|
| 541 |         } | 
|---|
| 542 |  | 
|---|
| 543 |  | 
|---|
| 544 |  | 
|---|
| 545 |  | 
|---|
| 546 |         //! collides only on one side | 
|---|
| 547 |         bool triangle_collision( | 
|---|
| 548 |                                         const btVector3 & u0, | 
|---|
| 549 |                                         const btVector3 & u1, | 
|---|
| 550 |                                         const btVector3 & u2, | 
|---|
| 551 |                                         GREAL margin_u, | 
|---|
| 552 |                                         const btVector3 & v0, | 
|---|
| 553 |                                         const btVector3 & v1, | 
|---|
| 554 |                                         const btVector3 & v2, | 
|---|
| 555 |                                         GREAL margin_v, | 
|---|
| 556 |                                         GIM_TRIANGLE_CONTACT_DATA & contacts) | 
|---|
| 557 |         { | 
|---|
| 558 |  | 
|---|
| 559 |                 margin = margin_u + margin_v; | 
|---|
| 560 |  | 
|---|
| 561 |                  | 
|---|
| 562 |                 tu_vertices[0] = u0; | 
|---|
| 563 |                 tu_vertices[1] = u1; | 
|---|
| 564 |                 tu_vertices[2] = u2; | 
|---|
| 565 |  | 
|---|
| 566 |                 tv_vertices[0] = v0; | 
|---|
| 567 |                 tv_vertices[1] = v1; | 
|---|
| 568 |                 tv_vertices[2] = v2; | 
|---|
| 569 |  | 
|---|
| 570 |                 //create planes | 
|---|
| 571 |                 // plane v vs U points | 
|---|
| 572 |  | 
|---|
| 573 |  | 
|---|
| 574 |                 TRIANGLE_PLANE(tv_vertices[0],tv_vertices[1],tv_vertices[2],contacts1.m_separating_normal); | 
|---|
| 575 |  | 
|---|
| 576 |                 clipped_count = clip_triangle( | 
|---|
| 577 |                         contacts1.m_separating_normal,tv_vertices,tu_vertices,clipped_points); | 
|---|
| 578 |  | 
|---|
| 579 |                 if(clipped_count == 0 ) | 
|---|
| 580 |                 { | 
|---|
| 581 |                          return false;//Reject | 
|---|
| 582 |                 } | 
|---|
| 583 |  | 
|---|
| 584 |                 //find most deep interval face1 | 
|---|
| 585 |                 contacts1.merge_points(contacts1.m_separating_normal,margin,clipped_points,clipped_count); | 
|---|
| 586 |                 if(contacts1.m_point_count == 0) return false; // too far | 
|---|
| 587 |  | 
|---|
| 588 |                 //Normal pointing to triangle1 | 
|---|
| 589 |                 //contacts1.m_separating_normal *= -1.f; | 
|---|
| 590 |  | 
|---|
| 591 |                 //Clip tri1 by tri2 edges | 
|---|
| 592 |  | 
|---|
| 593 |                 TRIANGLE_PLANE(tu_vertices[0],tu_vertices[1],tu_vertices[2],contacts2.m_separating_normal); | 
|---|
| 594 |  | 
|---|
| 595 |                 clipped_count = clip_triangle( | 
|---|
| 596 |                         contacts2.m_separating_normal,tu_vertices,tv_vertices,clipped_points); | 
|---|
| 597 |  | 
|---|
| 598 |                 if(clipped_count == 0 ) | 
|---|
| 599 |                 { | 
|---|
| 600 |                          return false;//Reject | 
|---|
| 601 |                 } | 
|---|
| 602 |  | 
|---|
| 603 |                 //find most deep interval face1 | 
|---|
| 604 |                 contacts2.merge_points(contacts2.m_separating_normal,margin,clipped_points,clipped_count); | 
|---|
| 605 |                 if(contacts2.m_point_count == 0) return false; // too far | 
|---|
| 606 |  | 
|---|
| 607 |                 contacts2.m_separating_normal *= -1.f; | 
|---|
| 608 |  | 
|---|
| 609 |                 ////check most dir for contacts | 
|---|
| 610 |                 if(contacts2.m_penetration_depth<contacts1.m_penetration_depth) | 
|---|
| 611 |                 { | 
|---|
| 612 |                         contacts.copy_from(contacts2); | 
|---|
| 613 |                 } | 
|---|
| 614 |                 else | 
|---|
| 615 |                 { | 
|---|
| 616 |                         contacts.copy_from(contacts1); | 
|---|
| 617 |                 } | 
|---|
| 618 |                 return true; | 
|---|
| 619 |         } | 
|---|
| 620 |  | 
|---|
| 621 |  | 
|---|
| 622 | };*/ | 
|---|
| 623 |  | 
|---|
| 624 |  | 
|---|
| 625 |  | 
|---|
| 626 | bool GIM_TRIANGLE::collide_triangle_hard_test( | 
|---|
| 627 |                 const GIM_TRIANGLE & other, | 
|---|
| 628 |                 GIM_TRIANGLE_CONTACT_DATA & contact_data) const | 
|---|
| 629 | { | 
|---|
| 630 |         GIM_TRIANGLE_CALCULATION_CACHE calc_cache;       | 
|---|
| 631 |         return calc_cache.triangle_collision( | 
|---|
| 632 |                                         m_vertices[0],m_vertices[1],m_vertices[2],m_margin, | 
|---|
| 633 |                                         other.m_vertices[0],other.m_vertices[1],other.m_vertices[2],other.m_margin, | 
|---|
| 634 |                                         contact_data); | 
|---|
| 635 |  | 
|---|
| 636 | } | 
|---|
| 637 |  | 
|---|
| 638 |  | 
|---|
| 639 |  | 
|---|
| 640 |  | 
|---|