00001 #ifndef GIM_BASIC_GEOMETRY_OPERATIONS_H_INCLUDED
00002 #define GIM_BASIC_GEOMETRY_OPERATIONS_H_INCLUDED
00003
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include "gim_linear_math.h"
00040
00041
00042
00043
00044
00045 #define PLANEDIREPSILON 0.0000001f
00046 #define PARALELENORMALS 0.000001f
00047
00048
00049 #define TRIANGLE_NORMAL(v1,v2,v3,n)\
00050 {\
00051 vec3f _dif1,_dif2;\
00052 VEC_DIFF(_dif1,v2,v1);\
00053 VEC_DIFF(_dif2,v3,v1);\
00054 VEC_CROSS(n,_dif1,_dif2);\
00055 VEC_NORMALIZE(n);\
00056 }\
00057
00058 #define TRIANGLE_NORMAL_FAST(v1,v2,v3,n){\
00059 vec3f _dif1,_dif2; \
00060 VEC_DIFF(_dif1,v2,v1); \
00061 VEC_DIFF(_dif2,v3,v1); \
00062 VEC_CROSS(n,_dif1,_dif2); \
00063 }\
00064
00065
00066 #define TRIANGLE_PLANE(v1,v2,v3,plane) {\
00067 TRIANGLE_NORMAL(v1,v2,v3,plane);\
00068 plane[3] = VEC_DOT(v1,plane);\
00069 }\
00070
00071
00072 #define TRIANGLE_PLANE_FAST(v1,v2,v3,plane) {\
00073 TRIANGLE_NORMAL_FAST(v1,v2,v3,plane);\
00074 plane[3] = VEC_DOT(v1,plane);\
00075 }\
00076
00077
00078 #define EDGE_PLANE(e1,e2,n,plane) {\
00079 vec3f _dif; \
00080 VEC_DIFF(_dif,e2,e1); \
00081 VEC_CROSS(plane,_dif,n); \
00082 VEC_NORMALIZE(plane); \
00083 plane[3] = VEC_DOT(e1,plane);\
00084 }\
00085
00086 #define DISTANCE_PLANE_POINT(plane,point) (VEC_DOT(plane,point) - plane[3])
00087
00088 #define PROJECT_POINT_PLANE(point,plane,projected) {\
00089 GREAL _dis;\
00090 _dis = DISTANCE_PLANE_POINT(plane,point);\
00091 VEC_SCALE(projected,-_dis,plane);\
00092 VEC_SUM(projected,projected,point); \
00093 }\
00094
00095
00096 template<typename CLASS_POINT,typename CLASS_PLANE>
00097 SIMD_FORCE_INLINE bool POINT_IN_HULL(
00098 const CLASS_POINT& point,const CLASS_PLANE * planes,GUINT plane_count)
00099 {
00100 GREAL _dis;
00101 for (GUINT _i = 0;_i< plane_count;++_i)
00102 {
00103 _dis = DISTANCE_PLANE_POINT(planes[_i],point);
00104 if(_dis>0.0f) return false;
00105 }
00106 return true;
00107 }
00108
00109 template<typename CLASS_POINT,typename CLASS_PLANE>
00110 SIMD_FORCE_INLINE void PLANE_CLIP_SEGMENT(
00111 const CLASS_POINT& s1,
00112 const CLASS_POINT &s2,const CLASS_PLANE &plane,CLASS_POINT &clipped)
00113 {
00114 GREAL _dis1,_dis2;
00115 _dis1 = DISTANCE_PLANE_POINT(plane,s1);
00116 VEC_DIFF(clipped,s2,s1);
00117 _dis2 = VEC_DOT(clipped,plane);
00118 VEC_SCALE(clipped,-_dis1/_dis2,clipped);
00119 VEC_SUM(clipped,clipped,s1);
00120 }
00121
00122 enum ePLANE_INTERSECTION_TYPE
00123 {
00124 G_BACK_PLANE = 0,
00125 G_COLLIDE_PLANE,
00126 G_FRONT_PLANE
00127 };
00128
00129 enum eLINE_PLANE_INTERSECTION_TYPE
00130 {
00131 G_FRONT_PLANE_S1 = 0,
00132 G_FRONT_PLANE_S2,
00133 G_BACK_PLANE_S1,
00134 G_BACK_PLANE_S2,
00135 G_COLLIDE_PLANE_S1,
00136 G_COLLIDE_PLANE_S2
00137 };
00138
00140
00152 template<typename CLASS_POINT,typename CLASS_PLANE>
00153 SIMD_FORCE_INLINE eLINE_PLANE_INTERSECTION_TYPE PLANE_CLIP_SEGMENT2(
00154 const CLASS_POINT& s1,
00155 const CLASS_POINT &s2,
00156 const CLASS_PLANE &plane,CLASS_POINT &clipped)
00157 {
00158 GREAL _dis1 = DISTANCE_PLANE_POINT(plane,s1);
00159 GREAL _dis2 = DISTANCE_PLANE_POINT(plane,s2);
00160 if(_dis1 >-G_EPSILON && _dis2 >-G_EPSILON)
00161 {
00162 if(_dis1<_dis2) return G_FRONT_PLANE_S1;
00163 return G_FRONT_PLANE_S2;
00164 }
00165 else if(_dis1 <G_EPSILON && _dis2 <G_EPSILON)
00166 {
00167 if(_dis1>_dis2) return G_BACK_PLANE_S1;
00168 return G_BACK_PLANE_S2;
00169 }
00170
00171 VEC_DIFF(clipped,s2,s1);
00172 _dis2 = VEC_DOT(clipped,plane);
00173 VEC_SCALE(clipped,-_dis1/_dis2,clipped);
00174 VEC_SUM(clipped,clipped,s1);
00175 if(_dis1<_dis2) return G_COLLIDE_PLANE_S1;
00176 return G_COLLIDE_PLANE_S2;
00177 }
00178
00180
00194 template<typename CLASS_POINT,typename CLASS_PLANE>
00195 SIMD_FORCE_INLINE eLINE_PLANE_INTERSECTION_TYPE PLANE_CLIP_SEGMENT_CLOSEST(
00196 const CLASS_POINT& s1,
00197 const CLASS_POINT &s2,
00198 const CLASS_PLANE &plane,
00199 CLASS_POINT &clipped1,CLASS_POINT &clipped2)
00200 {
00201 eLINE_PLANE_INTERSECTION_TYPE intersection_type = PLANE_CLIP_SEGMENT2(s1,s2,plane,clipped1);
00202 switch(intersection_type)
00203 {
00204 case G_FRONT_PLANE_S1:
00205 VEC_COPY(clipped1,s1);
00206 VEC_COPY(clipped2,s2);
00207 break;
00208 case G_FRONT_PLANE_S2:
00209 VEC_COPY(clipped1,s2);
00210 VEC_COPY(clipped2,s1);
00211 break;
00212 case G_BACK_PLANE_S1:
00213 VEC_COPY(clipped1,s1);
00214 VEC_COPY(clipped2,s2);
00215 break;
00216 case G_BACK_PLANE_S2:
00217 VEC_COPY(clipped1,s2);
00218 VEC_COPY(clipped2,s1);
00219 break;
00220 case G_COLLIDE_PLANE_S1:
00221 VEC_COPY(clipped2,s1);
00222 break;
00223 case G_COLLIDE_PLANE_S2:
00224 VEC_COPY(clipped2,s2);
00225 break;
00226 }
00227 return intersection_type;
00228 }
00229
00230
00232 #define PLANE_MINOR_AXES(plane, i0, i1) VEC_MINOR_AXES(plane, i0, i1)
00233
00235
00239 template<typename T,typename CLASS_POINT,typename CLASS_PLANE>
00240 SIMD_FORCE_INLINE bool RAY_PLANE_COLLISION(
00241 const CLASS_PLANE & plane,
00242 const CLASS_POINT & vDir,
00243 const CLASS_POINT & vPoint,
00244 CLASS_POINT & pout,T &tparam)
00245 {
00246 GREAL _dis,_dotdir;
00247 _dotdir = VEC_DOT(plane,vDir);
00248 if(_dotdir<PLANEDIREPSILON)
00249 {
00250 return false;
00251 }
00252 _dis = DISTANCE_PLANE_POINT(plane,vPoint);
00253 tparam = -_dis/_dotdir;
00254 VEC_SCALE(pout,tparam,vDir);
00255 VEC_SUM(pout,vPoint,pout);
00256 return true;
00257 }
00258
00260
00266 template<typename T,typename CLASS_POINT,typename CLASS_PLANE>
00267 SIMD_FORCE_INLINE GUINT LINE_PLANE_COLLISION(
00268 const CLASS_PLANE & plane,
00269 const CLASS_POINT & vDir,
00270 const CLASS_POINT & vPoint,
00271 CLASS_POINT & pout,
00272 T &tparam,
00273 T tmin, T tmax)
00274 {
00275 GREAL _dis,_dotdir;
00276 _dotdir = VEC_DOT(plane,vDir);
00277 if(btFabs(_dotdir)<PLANEDIREPSILON)
00278 {
00279 tparam = tmax;
00280 return 0;
00281 }
00282 _dis = DISTANCE_PLANE_POINT(plane,vPoint);
00283 char returnvalue = _dis<0.0f?2:1;
00284 tparam = -_dis/_dotdir;
00285
00286 if(tparam<tmin)
00287 {
00288 returnvalue = 0;
00289 tparam = tmin;
00290 }
00291 else if(tparam>tmax)
00292 {
00293 returnvalue = 0;
00294 tparam = tmax;
00295 }
00296
00297 VEC_SCALE(pout,tparam,vDir);
00298 VEC_SUM(pout,vPoint,pout);
00299 return returnvalue;
00300 }
00301
00312 template<typename CLASS_POINT,typename CLASS_PLANE>
00313 SIMD_FORCE_INLINE bool INTERSECT_PLANES(
00314 const CLASS_PLANE &p1,
00315 const CLASS_PLANE &p2,
00316 CLASS_POINT &p,
00317 CLASS_POINT &d)
00318 {
00319 VEC_CROSS(d,p1,p2);
00320 GREAL denom = VEC_DOT(d, d);
00321 if(GIM_IS_ZERO(denom)) return false;
00322 vec3f _n;
00323 _n[0]=p1[3]*p2[0] - p2[3]*p1[0];
00324 _n[1]=p1[3]*p2[1] - p2[3]*p1[1];
00325 _n[2]=p1[3]*p2[2] - p2[3]*p1[2];
00326 VEC_CROSS(p,_n,d);
00327 p[0]/=denom;
00328 p[1]/=denom;
00329 p[2]/=denom;
00330 return true;
00331 }
00332
00333
00334
00337 template<typename CLASS_POINT>
00338 SIMD_FORCE_INLINE void CLOSEST_POINT_ON_SEGMENT(
00339 CLASS_POINT & cp, const CLASS_POINT & v,
00340 const CLASS_POINT &e1,const CLASS_POINT &e2)
00341 {
00342 vec3f _n;
00343 VEC_DIFF(_n,e2,e1);
00344 VEC_DIFF(cp,v,e1);
00345 GREAL _scalar = VEC_DOT(cp, _n);
00346 _scalar/= VEC_DOT(_n, _n);
00347 if(_scalar <0.0f)
00348 {
00349 VEC_COPY(cp,e1);
00350 }
00351 else if(_scalar >1.0f)
00352 {
00353 VEC_COPY(cp,e2);
00354 }
00355 else
00356 {
00357 VEC_SCALE(cp,_scalar,_n);
00358 VEC_SUM(cp,cp,e1);
00359 }
00360 }
00361
00362
00374 template<typename T,typename CLASS_POINT>
00375 SIMD_FORCE_INLINE bool LINE_INTERSECTION_PARAMS(
00376 const CLASS_POINT & dir1,
00377 CLASS_POINT & point1,
00378 const CLASS_POINT & dir2,
00379 CLASS_POINT & point2,
00380 T& t1,T& t2)
00381 {
00382 GREAL det;
00383 GREAL e1e1 = VEC_DOT(dir1,dir1);
00384 GREAL e1e2 = VEC_DOT(dir1,dir2);
00385 GREAL e2e2 = VEC_DOT(dir2,dir2);
00386 vec3f p1p2;
00387 VEC_DIFF(p1p2,point1,point2);
00388 GREAL p1p2e1 = VEC_DOT(p1p2,dir1);
00389 GREAL p1p2e2 = VEC_DOT(p1p2,dir2);
00390 det = e1e2*e1e2 - e1e1*e2e2;
00391 if(GIM_IS_ZERO(det)) return false;
00392 t1 = (e1e2*p1p2e2 - e2e2*p1p2e1)/det;
00393 t2 = (e1e1*p1p2e2 - e1e2*p1p2e1)/det;
00394 return true;
00395 }
00396
00398 template<typename CLASS_POINT>
00399 SIMD_FORCE_INLINE void SEGMENT_COLLISION(
00400 const CLASS_POINT & vA1,
00401 const CLASS_POINT & vA2,
00402 const CLASS_POINT & vB1,
00403 const CLASS_POINT & vB2,
00404 CLASS_POINT & vPointA,
00405 CLASS_POINT & vPointB)
00406 {
00407 CLASS_POINT _AD,_BD,_N;
00408 vec4f _M;
00409 VEC_DIFF(_AD,vA2,vA1);
00410 VEC_DIFF(_BD,vB2,vB1);
00411 VEC_CROSS(_N,_AD,_BD);
00412 GREAL _tp = VEC_DOT(_N,_N);
00413 if(_tp<G_EPSILON)
00414 {
00415
00416 bool invert_b_order = false;
00417 _M[0] = VEC_DOT(vB1,_AD);
00418 _M[1] = VEC_DOT(vB2,_AD);
00419 if(_M[0]>_M[1])
00420 {
00421 invert_b_order = true;
00422 GIM_SWAP_NUMBERS(_M[0],_M[1]);
00423 }
00424 _M[2] = VEC_DOT(vA1,_AD);
00425 _M[3] = VEC_DOT(vA2,_AD);
00426
00427 _N[0] = (_M[0]+_M[1])*0.5f;
00428 _N[1] = (_M[2]+_M[3])*0.5f;
00429
00430 if(_N[0]<_N[1])
00431 {
00432 if(_M[1]<_M[2])
00433 {
00434 vPointB = invert_b_order?vB1:vB2;
00435 vPointA = vA1;
00436 }
00437 else if(_M[1]<_M[3])
00438 {
00439 vPointB = invert_b_order?vB1:vB2;
00440 CLOSEST_POINT_ON_SEGMENT(vPointA,vPointB,vA1,vA2);
00441 }
00442 else
00443 {
00444 vPointA = vA2;
00445 CLOSEST_POINT_ON_SEGMENT(vPointB,vPointA,vB1,vB2);
00446 }
00447 }
00448 else
00449 {
00450 if(_M[3]<_M[0])
00451 {
00452 vPointB = invert_b_order?vB2:vB1;
00453 vPointA = vA2;
00454 }
00455 else if(_M[3]<_M[1])
00456 {
00457 vPointA = vA2;
00458 CLOSEST_POINT_ON_SEGMENT(vPointB,vPointA,vB1,vB2);
00459 }
00460 else
00461 {
00462 vPointB = invert_b_order?vB1:vB2;
00463 CLOSEST_POINT_ON_SEGMENT(vPointA,vPointB,vA1,vA2);
00464 }
00465 }
00466 return;
00467 }
00468
00469
00470 VEC_CROSS(_M,_N,_BD);
00471 _M[3] = VEC_DOT(_M,vB1);
00472
00473 LINE_PLANE_COLLISION(_M,_AD,vA1,vPointA,_tp,btScalar(0), btScalar(1));
00474
00475 VEC_DIFF(vPointB,vPointA,vB1);
00476 _tp = VEC_DOT(vPointB, _BD);
00477 _tp/= VEC_DOT(_BD, _BD);
00478 _tp = GIM_CLAMP(_tp,0.0f,1.0f);
00479 VEC_SCALE(vPointB,_tp,_BD);
00480 VEC_SUM(vPointB,vPointB,vB1);
00481 }
00482
00483
00484
00485
00487
00497 template<typename T>
00498 SIMD_FORCE_INLINE bool BOX_AXIS_INTERSECT(T pos, T dir,T bmin, T bmax, T & tfirst, T & tlast)
00499 {
00500 if(GIM_IS_ZERO(dir))
00501 {
00502 return !(pos < bmin || pos > bmax);
00503 }
00504 GREAL a0 = (bmin - pos) / dir;
00505 GREAL a1 = (bmax - pos) / dir;
00506 if(a0 > a1) GIM_SWAP_NUMBERS(a0, a1);
00507 tfirst = GIM_MAX(a0, tfirst);
00508 tlast = GIM_MIN(a1, tlast);
00509 if (tlast < tfirst) return false;
00510 return true;
00511 }
00512
00513
00515 template<typename T>
00516 SIMD_FORCE_INLINE void SORT_3_INDICES(
00517 const T * values,
00518 GUINT * order_indices)
00519 {
00520
00521 order_indices[0] = values[0] < values[1] ? (values[0] < values[2] ? 0 : 2) : (values[1] < values[2] ? 1 : 2);
00522
00523
00524 GUINT i0 = (order_indices[0] + 1)%3;
00525 GUINT i1 = (i0 + 1)%3;
00526
00527 if(values[i0] < values[i1])
00528 {
00529 order_indices[1] = i0;
00530 order_indices[2] = i1;
00531 }
00532 else
00533 {
00534 order_indices[1] = i1;
00535 order_indices[2] = i0;
00536 }
00537 }
00538
00539
00540
00541
00542
00543 #endif // GIM_VECTOR_H_INCLUDED