Blender V2.61 - r43446

gim_basic_geometry_operations.h

Go to the documentation of this file.
00001 #ifndef GIM_BASIC_GEOMETRY_OPERATIONS_H_INCLUDED
00002 #define GIM_BASIC_GEOMETRY_OPERATIONS_H_INCLUDED
00003 
00009 /*
00010 -----------------------------------------------------------------------------
00011 This source file is part of GIMPACT Library.
00012 
00013 For the latest info, see http://gimpact.sourceforge.net/
00014 
00015 Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371.
00016 email: projectileman@yahoo.com
00017 
00018  This library is free software; you can redistribute it and/or
00019  modify it under the terms of EITHER:
00020    (1) The GNU Lesser General Public License as published by the Free
00021        Software Foundation; either version 2.1 of the License, or (at
00022        your option) any later version. The text of the GNU Lesser
00023        General Public License is included with this library in the
00024        file GIMPACT-LICENSE-LGPL.TXT.
00025    (2) The BSD-style license that is included with this library in
00026        the file GIMPACT-LICENSE-BSD.TXT.
00027    (3) The zlib/libpng license that is included with this library in
00028        the file GIMPACT-LICENSE-ZLIB.TXT.
00029 
00030  This library is distributed in the hope that it will be useful,
00031  but WITHOUT ANY WARRANTY; without even the implied warranty of
00032  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
00033  GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
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 //***************** SEGMENT and LINE FUNCTIONS **********************************///
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;//plane
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)//ARE PARALELE
00414     {
00415         //project B over A
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         //mid points
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     /*Closest point on segment*/
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     //get minimum
00521     order_indices[0] = values[0] < values[1] ? (values[0] < values[2] ? 0 : 2) : (values[1] < values[2] ? 1 : 2);
00522 
00523     //get second and third
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