Blender V2.61 - r43446

math_geom.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00019  * All rights reserved.
00020  
00021  * The Original Code is: some of this file.
00022  *
00023  * ***** END GPL LICENSE BLOCK *****
00024  * */
00025 
00032 #include "MEM_guardedalloc.h"
00033 
00034 #include "BLI_math.h"
00035 #include "BLI_memarena.h"
00036 #include "BLI_utildefines.h"
00037 
00038 /********************************** Polygons *********************************/
00039 
00040 void cent_tri_v3(float cent[3], const float v1[3], const float v2[3], const float v3[3])
00041 {
00042     cent[0]= 0.33333f*(v1[0]+v2[0]+v3[0]);
00043     cent[1]= 0.33333f*(v1[1]+v2[1]+v3[1]);
00044     cent[2]= 0.33333f*(v1[2]+v2[2]+v3[2]);
00045 }
00046 
00047 void cent_quad_v3(float cent[3], const float v1[3], const float v2[3], const float v3[3], const float v4[3])
00048 {
00049     cent[0]= 0.25f*(v1[0]+v2[0]+v3[0]+v4[0]);
00050     cent[1]= 0.25f*(v1[1]+v2[1]+v3[1]+v4[1]);
00051     cent[2]= 0.25f*(v1[2]+v2[2]+v3[2]+v4[2]);
00052 }
00053 
00054 float normal_tri_v3(float n[3], const float v1[3], const float v2[3], const float v3[3])
00055 {
00056     float n1[3],n2[3];
00057 
00058     n1[0]= v1[0]-v2[0];
00059     n2[0]= v2[0]-v3[0];
00060     n1[1]= v1[1]-v2[1];
00061     n2[1]= v2[1]-v3[1];
00062     n1[2]= v1[2]-v2[2];
00063     n2[2]= v2[2]-v3[2];
00064     n[0]= n1[1]*n2[2]-n1[2]*n2[1];
00065     n[1]= n1[2]*n2[0]-n1[0]*n2[2];
00066     n[2]= n1[0]*n2[1]-n1[1]*n2[0];
00067 
00068     return normalize_v3(n);
00069 }
00070 
00071 float normal_quad_v3(float n[3], const float v1[3], const float v2[3], const float v3[3], const float v4[3])
00072 {
00073     /* real cross! */
00074     float n1[3],n2[3];
00075 
00076     n1[0]= v1[0]-v3[0];
00077     n1[1]= v1[1]-v3[1];
00078     n1[2]= v1[2]-v3[2];
00079 
00080     n2[0]= v2[0]-v4[0];
00081     n2[1]= v2[1]-v4[1];
00082     n2[2]= v2[2]-v4[2];
00083 
00084     n[0]= n1[1]*n2[2]-n1[2]*n2[1];
00085     n[1]= n1[2]*n2[0]-n1[0]*n2[2];
00086     n[2]= n1[0]*n2[1]-n1[1]*n2[0];
00087 
00088     return normalize_v3(n);
00089 }
00090 
00091 float area_tri_v2(const float v1[2], const float v2[2], const float v3[2])
00092 {
00093     return 0.5f * fabsf((v1[0]-v2[0])*(v2[1]-v3[1]) + (v1[1]-v2[1])*(v3[0]-v2[0]));
00094 }
00095 
00096 float area_tri_signed_v2(const float v1[2], const float v2[2], const float v3[2])
00097 {
00098     return 0.5f * ((v1[0]-v2[0])*(v2[1]-v3[1]) + (v1[1]-v2[1])*(v3[0]-v2[0]));
00099 }
00100 
00101 float area_quad_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3])  /* only convex Quadrilaterals */
00102 {
00103     float len, vec1[3], vec2[3], n[3];
00104 
00105     sub_v3_v3v3(vec1, v2, v1);
00106     sub_v3_v3v3(vec2, v4, v1);
00107     cross_v3_v3v3(n, vec1, vec2);
00108     len= normalize_v3(n);
00109 
00110     sub_v3_v3v3(vec1, v4, v3);
00111     sub_v3_v3v3(vec2, v2, v3);
00112     cross_v3_v3v3(n, vec1, vec2);
00113     len+= normalize_v3(n);
00114 
00115     return (len/2.0f);
00116 }
00117 
00118 float area_tri_v3(const float v1[3], const float v2[3], const float v3[3])  /* Triangles */
00119 {
00120     float len, vec1[3], vec2[3], n[3];
00121 
00122     sub_v3_v3v3(vec1, v3, v2);
00123     sub_v3_v3v3(vec2, v1, v2);
00124     cross_v3_v3v3(n, vec1, vec2);
00125     len= normalize_v3(n);
00126 
00127     return (len/2.0f);
00128 }
00129 
00130 float area_poly_v3(int nr, float verts[][3], const float normal[3])
00131 {
00132     float x, y, z, area, max;
00133     float *cur, *prev;
00134     int a, px=0, py=1;
00135 
00136     /* first: find dominant axis: 0==X, 1==Y, 2==Z
00137      * don't use 'axis_dominant_v3()' because we need max axis too */
00138     x= fabsf(normal[0]);
00139     y= fabsf(normal[1]);
00140     z= fabsf(normal[2]);
00141     max = MAX3(x, y, z);
00142     if(max==y) py=2;
00143     else if(max==x) {
00144         px=1; 
00145         py= 2;
00146     }
00147 
00148     /* The Trapezium Area Rule */
00149     prev= verts[nr-1];
00150     cur= verts[0];
00151     area= 0;
00152     for(a=0; a<nr; a++) {
00153         area+= (cur[px]-prev[px])*(cur[py]+prev[py]);
00154         prev= verts[a];
00155         cur= verts[a+1];
00156     }
00157 
00158     return fabsf(0.5f * area / max);
00159 }
00160 
00161 /********************************* Distance **********************************/
00162 
00163 /* distance v1 to line v2-v3 */
00164 /* using Hesse formula, NO LINE PIECE! */
00165 float dist_to_line_v2(const float v1[2], const float v2[2], const float v3[2])
00166 {
00167     float a[2],deler;
00168 
00169     a[0]= v2[1]-v3[1];
00170     a[1]= v3[0]-v2[0];
00171     deler= (float)sqrt(a[0]*a[0]+a[1]*a[1]);
00172     if(deler== 0.0f) return 0;
00173 
00174     return fabsf((v1[0]-v2[0])*a[0]+(v1[1]-v2[1])*a[1])/deler;
00175 
00176 }
00177 
00178 /* distance v1 to line-piece v2-v3 */
00179 float dist_to_line_segment_v2(const float v1[2], const float v2[2], const float v3[2])
00180 {
00181     float labda, rc[2], pt[2], len;
00182     
00183     rc[0]= v3[0]-v2[0];
00184     rc[1]= v3[1]-v2[1];
00185     len= rc[0]*rc[0]+ rc[1]*rc[1];
00186     if(len==0.0f) {
00187         rc[0]= v1[0]-v2[0];
00188         rc[1]= v1[1]-v2[1];
00189         return (float)(sqrt(rc[0]*rc[0]+ rc[1]*rc[1]));
00190     }
00191     
00192     labda= (rc[0]*(v1[0]-v2[0]) + rc[1]*(v1[1]-v2[1]))/len;
00193     if(labda <= 0.0f) {
00194         pt[0]= v2[0];
00195         pt[1]= v2[1];
00196     }
00197     else if(labda >= 1.0f) {
00198         pt[0]= v3[0];
00199         pt[1]= v3[1];
00200     }
00201     else {
00202         pt[0]= labda*rc[0]+v2[0];
00203         pt[1]= labda*rc[1]+v2[1];
00204     }
00205 
00206     rc[0]= pt[0]-v1[0];
00207     rc[1]= pt[1]-v1[1];
00208     return sqrtf(rc[0]*rc[0]+ rc[1]*rc[1]);
00209 }
00210 
00211 /* point closest to v1 on line v2-v3 in 2D */
00212 void closest_to_line_segment_v2(float close_r[2], const float p[2], const float l1[2], const float l2[2])
00213 {
00214     float lambda, cp[2];
00215 
00216     lambda= closest_to_line_v2(cp,p, l1, l2);
00217 
00218     if(lambda <= 0.0f)
00219         copy_v2_v2(close_r, l1);
00220     else if(lambda >= 1.0f)
00221         copy_v2_v2(close_r, l2);
00222     else
00223         copy_v2_v2(close_r, cp);
00224 }
00225 
00226 /* point closest to v1 on line v2-v3 in 3D */
00227 void closest_to_line_segment_v3(float close_r[3], const float v1[3], const float v2[3], const float v3[3])
00228 {
00229     float lambda, cp[3];
00230 
00231     lambda= closest_to_line_v3(cp,v1, v2, v3);
00232 
00233     if(lambda <= 0.0f)
00234         copy_v3_v3(close_r, v2);
00235     else if(lambda >= 1.0f)
00236         copy_v3_v3(close_r, v3);
00237     else
00238         copy_v3_v3(close_r, cp);
00239 }
00240 
00241 /* find the closest point on a plane to another point and store it in close_r
00242  * close_r:       return coordinate
00243  * plane_co:      a point on the plane
00244  * plane_no_unit: the plane's normal, and d is the last number in the plane equation 0 = ax + by + cz + d
00245  * pt:            the point that you want the nearest of
00246  */
00247 
00248 // const float norm[3], const float coord[3], const float point[3], float dst_r[3]
00249 void closest_to_plane_v3(float close_r[3], const float plane_co[3], const float plane_no_unit[3], const float pt[3])
00250 {
00251     float temp[3];
00252     float dotprod;
00253 
00254     sub_v3_v3v3(temp, pt, plane_co);
00255     dotprod= dot_v3v3(temp, plane_no_unit);
00256 
00257     close_r[0] = pt[0] - (plane_no_unit[0] * dotprod);
00258     close_r[1] = pt[1] - (plane_no_unit[1] * dotprod);
00259     close_r[2] = pt[2] - (plane_no_unit[2] * dotprod);
00260 }
00261 
00262 /* signed distance from the point to the plane in 3D */
00263 float dist_to_plane_normalized_v3(const float p[3], const float plane_co[3], const float plane_no_unit[3])
00264 {
00265     float plane_co_other[3];
00266 
00267     add_v3_v3v3(plane_co_other, plane_co, plane_no_unit);
00268 
00269     return line_point_factor_v3(p, plane_co, plane_co_other);
00270 }
00271 
00272 float dist_to_plane_v3(const float p[3], const float plane_co[3], const float plane_no[3])
00273 {
00274     float plane_no_unit[3];
00275     float plane_co_other[3];
00276 
00277     normalize_v3_v3(plane_no_unit, plane_no);
00278     add_v3_v3v3(plane_co_other, plane_co, plane_no_unit);
00279 
00280     return line_point_factor_v3(p, plane_co, plane_co_other);
00281 }
00282 
00283 /* distance v1 to line-piece v2-v3 in 3D */
00284 float dist_to_line_segment_v3(const float v1[3], const float v2[3], const float v3[3])
00285 {
00286     float closest[3];
00287 
00288     closest_to_line_segment_v3(closest, v1, v2, v3);
00289 
00290     return len_v3v3(closest, v1);
00291 }
00292 
00293 /******************************* Intersection ********************************/
00294 
00295 /* intersect Line-Line, shorts */
00296 int isect_line_line_v2_int(const int v1[2], const int v2[2], const int v3[2], const int v4[2])
00297 {
00298     float div, labda, mu;
00299     
00300     div= (float)((v2[0]-v1[0])*(v4[1]-v3[1])-(v2[1]-v1[1])*(v4[0]-v3[0]));
00301     if(div==0.0f) return ISECT_LINE_LINE_COLINEAR;
00302     
00303     labda= ((float)(v1[1]-v3[1])*(v4[0]-v3[0])-(v1[0]-v3[0])*(v4[1]-v3[1]))/div;
00304     
00305     mu= ((float)(v1[1]-v3[1])*(v2[0]-v1[0])-(v1[0]-v3[0])*(v2[1]-v1[1]))/div;
00306     
00307     if(labda>=0.0f && labda<=1.0f && mu>=0.0f && mu<=1.0f) {
00308         if(labda==0.0f || labda==1.0f || mu==0.0f || mu==1.0f) return ISECT_LINE_LINE_EXACT;
00309         return ISECT_LINE_LINE_CROSS;
00310     }
00311     return ISECT_LINE_LINE_NONE;
00312 }
00313 
00314 /* intersect Line-Line, floats */
00315 int isect_line_line_v2(const float v1[2], const float v2[2], const float v3[2], const float v4[2])
00316 {
00317     float div, labda, mu;
00318     
00319     div= (v2[0]-v1[0])*(v4[1]-v3[1])-(v2[1]-v1[1])*(v4[0]-v3[0]);
00320     if(div==0.0f) return ISECT_LINE_LINE_COLINEAR;
00321     
00322     labda= ((float)(v1[1]-v3[1])*(v4[0]-v3[0])-(v1[0]-v3[0])*(v4[1]-v3[1]))/div;
00323     
00324     mu= ((float)(v1[1]-v3[1])*(v2[0]-v1[0])-(v1[0]-v3[0])*(v2[1]-v1[1]))/div;
00325     
00326     if(labda>=0.0f && labda<=1.0f && mu>=0.0f && mu<=1.0f) {
00327         if(labda==0.0f || labda==1.0f || mu==0.0f || mu==1.0f) return ISECT_LINE_LINE_EXACT;
00328         return ISECT_LINE_LINE_CROSS;
00329     }
00330     return ISECT_LINE_LINE_NONE;
00331 }
00332 
00333 /* get intersection point of two 2D segments and return intersection type:
00334     -1: colliniar
00335      1: intersection */
00336 int isect_seg_seg_v2_point(const float v1[2], const float v2[2], const float v3[2], const float v4[2], float vi[2])
00337 {
00338     float a1, a2, b1, b2, c1, c2, d;
00339     float u, v;
00340     const float eps= 0.000001f;
00341 
00342     a1= v2[0]-v1[0];
00343     b1= v4[0]-v3[0];
00344     c1= v1[0]-v4[0];
00345 
00346     a2= v2[1]-v1[1];
00347     b2= v4[1]-v3[1];
00348     c2= v1[1]-v4[1];
00349 
00350     d= a1*b2-a2*b1;
00351 
00352     if(d==0) {
00353         if(a1*c2-a2*c1==0.0f && b1*c2-b2*c1==0.0f) { /* equal lines */
00354             float a[2], b[2], c[2];
00355             float u2;
00356 
00357             if(len_v2v2(v1, v2)==0.0f) {
00358                 if(len_v2v2(v3, v4)>eps) {
00359                     /* use non-point segment as basis */
00360                     SWAP(const float *, v1, v3);
00361                     SWAP(const float *, v2, v4);
00362                 } else { /* both of segments are points */
00363                     if(equals_v2v2(v1, v3)) { /* points are equal */
00364                         copy_v2_v2(vi, v1);
00365                         return 1;
00366                     }
00367 
00368                     /* two different points */
00369                     return -1;
00370                 }
00371             }
00372 
00373             sub_v2_v2v2(a, v3, v1);
00374             sub_v2_v2v2(b, v2, v1);
00375             sub_v2_v2v2(c, v2, v1);
00376             u= dot_v2v2(a, b) / dot_v2v2(c, c);
00377 
00378             sub_v2_v2v2(a, v4, v1);
00379             u2= dot_v2v2(a, b) / dot_v2v2(c, c);
00380 
00381             if(u>u2) SWAP(float, u, u2);
00382 
00383             if(u>1.0f+eps || u2<-eps) return -1; /* non-ovlerlapping segments */
00384             else if(maxf(0.0f, u) == minf(1.0f, u2)){ /* one common point: can return result */
00385                 interp_v2_v2v2(vi, v1, v2, maxf(0, u));
00386                 return 1;
00387             }
00388         }
00389 
00390         /* lines are colliniar */
00391         return -1;
00392     }
00393 
00394     u= (c2*b1-b2*c1)/d;
00395     v= (c1*a2-a1*c2)/d;
00396 
00397     if(u>=-eps && u<=1.0f+eps && v>=-eps && v<=1.0f+eps) { /* intersection */
00398         interp_v2_v2v2(vi, v1, v2, u);
00399         return 1;
00400     }
00401 
00402     /* out of segment intersection */
00403     return -1;
00404 }
00405 
00406 int isect_line_sphere_v3(const float l1[3], const float l2[3],
00407                          const float sp[3], const float r,
00408                          float r_p1[3], float r_p2[3])
00409 {
00410     /* l1:         coordinates (point of line)
00411      * l2:         coordinates (point of line)
00412      * sp, r:      coordinates and radius (sphere)
00413      * r_p1, r_p2: return intersection coordinates
00414      */
00415 
00416 
00417     /* adapted for use in blender by Campbell Barton - 2011
00418      *
00419      * atelier iebele abel - 2001
00420      * atelier@iebele.nl
00421      * http://www.iebele.nl
00422      *
00423      * sphere_line_intersection function adapted from:
00424      * http://astronomy.swin.edu.au/pbourke/geometry/sphereline
00425      * Paul Bourke pbourke@swin.edu.au
00426      */
00427 
00428     const float ldir[3]= {
00429         l2[0] - l1[0],
00430         l2[1] - l1[1],
00431         l2[2] - l1[2]
00432     };
00433 
00434     const float a= dot_v3v3(ldir, ldir);
00435 
00436     const float b= 2.0f *
00437             (ldir[0] * (l1[0] - sp[0]) +
00438              ldir[1] * (l1[1] - sp[1]) +
00439              ldir[2] * (l1[2] - sp[2]));
00440 
00441     const float c=
00442             dot_v3v3(sp, sp) +
00443             dot_v3v3(l1, l1) -
00444             (2.0f * dot_v3v3(sp, l1)) -
00445             (r * r);
00446 
00447     const float i = b * b - 4.0f * a * c;
00448 
00449     float mu;
00450 
00451     if (i < 0.0f) {
00452         /* no intersections */
00453         return 0;
00454     }
00455     else if (i == 0.0f) {
00456         /* one intersection */
00457         mu = -b / (2.0f * a);
00458         madd_v3_v3v3fl(r_p1, l1, ldir, mu);
00459         return 1;
00460     }
00461     else if (i > 0.0f) {
00462         const float i_sqrt= sqrt(i); /* avoid calc twice */
00463 
00464         /* first intersection */
00465         mu = (-b + i_sqrt) / (2.0f * a);
00466         madd_v3_v3v3fl(r_p1, l1, ldir, mu);
00467 
00468         /* second intersection */
00469         mu = (-b - i_sqrt) / (2.0f * a);
00470         madd_v3_v3v3fl(r_p2, l1, ldir, mu);
00471         return 2;
00472     }
00473     else {
00474         /* math domain error - nan */
00475         return -1;
00476     }
00477 }
00478 
00479 /* keep in sync with isect_line_sphere_v3 */
00480 int isect_line_sphere_v2(const float l1[2], const float l2[2],
00481                          const float sp[2], const float r,
00482                          float r_p1[2], float r_p2[2])
00483 {
00484     const float ldir[2]= {
00485         l2[0] - l1[0],
00486         l2[1] - l1[1]
00487     };
00488 
00489     const float a= dot_v2v2(ldir, ldir);
00490 
00491     const float b= 2.0f *
00492             (ldir[0] * (l1[0] - sp[0]) +
00493              ldir[1] * (l1[1] - sp[1]));
00494 
00495     const float c=
00496             dot_v2v2(sp, sp) +
00497             dot_v2v2(l1, l1) -
00498             (2.0f * dot_v2v2(sp, l1)) -
00499             (r * r);
00500 
00501     const float i = b * b - 4.0f * a * c;
00502 
00503     float mu;
00504 
00505     if (i < 0.0f) {
00506         /* no intersections */
00507         return 0;
00508     }
00509     else if (i == 0.0f) {
00510         /* one intersection */
00511         mu = -b / (2.0f * a);
00512         madd_v2_v2v2fl(r_p1, l1, ldir, mu);
00513         return 1;
00514     }
00515     else if (i > 0.0f) {
00516         const float i_sqrt= sqrt(i); /* avoid calc twice */
00517 
00518         /* first intersection */
00519         mu = (-b + i_sqrt) / (2.0f * a);
00520         madd_v2_v2v2fl(r_p1, l1, ldir, mu);
00521 
00522         /* second intersection */
00523         mu = (-b - i_sqrt) / (2.0f * a);
00524         madd_v2_v2v2fl(r_p2, l1, ldir, mu);
00525         return 2;
00526     }
00527     else {
00528         /* math domain error - nan */
00529         return -1;
00530     }
00531 }
00532 
00533 /*
00534 -1: colliniar
00535  1: intersection
00536 
00537 */
00538 static short IsectLLPt2Df(const float x0, const float y0, const float x1, const float y1,
00539                      const float x2, const float y2, const float x3, const float y3, float *xi,float *yi)
00540 
00541 {
00542     /*
00543     this function computes the intersection of the sent lines
00544     and returns the intersection point, note that the function assumes
00545     the lines intersect. the function can handle vertical as well
00546     as horizontal lines. note the function isn't very clever, it simply
00547     applies the math, but we don't need speed since this is a
00548     pre-processing step
00549     */
00550     float c1,c2, // constants of linear equations
00551     det_inv,  // the inverse of the determinant of the coefficient
00552     m1,m2;    // the slopes of each line
00553     /*
00554     compute slopes, note the cludge for infinity, however, this will
00555     be close enough
00556     */
00557     if (fabs(x1-x0) > 0.000001)
00558         m1 = (y1-y0) / (x1-x0);
00559     else
00560         return -1; /*m1 = (float) 1e+10;*/   // close enough to infinity
00561 
00562     if (fabs(x3-x2) > 0.000001)
00563         m2 = (y3-y2) / (x3-x2);
00564     else
00565         return -1; /*m2 = (float) 1e+10;*/   // close enough to infinity
00566 
00567     if (fabs(m1-m2) < 0.000001)
00568         return -1; /* parallel lines */
00569     
00570 // compute constants
00571 
00572     c1 = (y0-m1*x0);
00573     c2 = (y2-m2*x2);
00574 
00575 // compute the inverse of the determinate
00576 
00577     det_inv = 1.0f / (-m1 + m2);
00578 
00579 // use Kramers rule to compute xi and yi
00580 
00581     *xi= ((-c2 + c1) *det_inv);
00582     *yi= ((m2*c1 - m1*c2) *det_inv);
00583     
00584     return 1; 
00585 } // end Intersect_Lines
00586 
00587 /* point in tri */
00588 
00589 int isect_point_tri_v2(const float pt[2], const float v1[2], const float v2[2], const float v3[2])
00590 {
00591     if (line_point_side_v2(v1,v2,pt)>=0.0f) {
00592         if (line_point_side_v2(v2,v3,pt)>=0.0f) {
00593             if (line_point_side_v2(v3,v1,pt)>=0.0f) {
00594                 return 1;
00595             }
00596         }
00597     } else {
00598         if (! (line_point_side_v2(v2,v3,pt)>=0.0f)) {
00599             if (! (line_point_side_v2(v3,v1,pt)>=0.0f)) {
00600                 return -1;
00601             }
00602         }
00603     }
00604     
00605     return 0;
00606 }
00607 /* point in quad - only convex quads */
00608 int isect_point_quad_v2(const float pt[2], const float v1[2], const float v2[2], const float v3[2], const float v4[2])
00609 {
00610     if (line_point_side_v2(v1,v2,pt)>=0.0f) {
00611         if (line_point_side_v2(v2,v3,pt)>=0.0f) {
00612             if (line_point_side_v2(v3,v4,pt)>=0.0f) {
00613                 if (line_point_side_v2(v4,v1,pt)>=0.0f) {
00614                     return 1;
00615                 }
00616             }
00617         }
00618     } else {
00619         if (! (line_point_side_v2(v2,v3,pt)>=0.0f)) {
00620             if (! (line_point_side_v2(v3,v4,pt)>=0.0f)) {
00621                 if (! (line_point_side_v2(v4,v1,pt)>=0.0f)) {
00622                     return -1;
00623                 }
00624             }
00625         }
00626     }
00627     
00628     return 0;
00629 }
00630 
00631 /* moved from effect.c
00632    test if the line starting at p1 ending at p2 intersects the triangle v0..v2
00633    return non zero if it does 
00634 */
00635 int isect_line_tri_v3(const float p1[3], const float p2[3],
00636                       const float v0[3], const float v1[3], const float v2[3],
00637                       float *r_lambda, float r_uv[2])
00638 {
00639 
00640     float p[3], s[3], d[3], e1[3], e2[3], q[3];
00641     float a, f, u, v;
00642     
00643     sub_v3_v3v3(e1, v1, v0);
00644     sub_v3_v3v3(e2, v2, v0);
00645     sub_v3_v3v3(d, p2, p1);
00646     
00647     cross_v3_v3v3(p, d, e2);
00648     a = dot_v3v3(e1, p);
00649     if ((a > -0.000001f) && (a < 0.000001f)) return 0;
00650     f = 1.0f/a;
00651     
00652     sub_v3_v3v3(s, p1, v0);
00653     
00654     u = f * dot_v3v3(s, p);
00655     if ((u < 0.0f)||(u > 1.0f)) return 0;
00656     
00657     cross_v3_v3v3(q, s, e1);
00658     
00659     v = f * dot_v3v3(d, q);
00660     if ((v < 0.0f)||((u + v) > 1.0f)) return 0;
00661 
00662     *r_lambda = f * dot_v3v3(e2, q);
00663     if ((*r_lambda < 0.0f)||(*r_lambda > 1.0f)) return 0;
00664 
00665     if(r_uv) {
00666         r_uv[0]= u;
00667         r_uv[1]= v;
00668     }
00669     
00670     return 1;
00671 }
00672 /* moved from effect.c
00673    test if the ray starting at p1 going in d direction intersects the triangle v0..v2
00674    return non zero if it does 
00675 */
00676 int isect_ray_tri_v3(const float p1[3], const float d[3],
00677                      const float v0[3], const float v1[3], const float v2[3],
00678                      float *r_lambda, float r_uv[2])
00679 {
00680     float p[3], s[3], e1[3], e2[3], q[3];
00681     float a, f, u, v;
00682     
00683     sub_v3_v3v3(e1, v1, v0);
00684     sub_v3_v3v3(e2, v2, v0);
00685     
00686     cross_v3_v3v3(p, d, e2);
00687     a = dot_v3v3(e1, p);
00688     /* note: these values were 0.000001 in 2.4x but for projection snapping on
00689      * a human head (1BU==1m), subsurf level 2, this gave many errors - campbell */
00690     if ((a > -0.00000001f) && (a < 0.00000001f)) return 0;
00691     f = 1.0f/a;
00692     
00693     sub_v3_v3v3(s, p1, v0);
00694     
00695     u = f * dot_v3v3(s, p);
00696     if ((u < 0.0f)||(u > 1.0f)) return 0;
00697 
00698     cross_v3_v3v3(q, s, e1);
00699     
00700     v = f * dot_v3v3(d, q);
00701     if ((v < 0.0f)||((u + v) > 1.0f)) return 0;
00702 
00703     *r_lambda = f * dot_v3v3(e2, q);
00704     if ((*r_lambda < 0.0f)) return 0;
00705 
00706     if(r_uv) {
00707         r_uv[0]= u;
00708         r_uv[1]= v;
00709     }
00710     
00711     return 1;
00712 }
00713 
00714 int isect_ray_plane_v3(const float p1[3], const float d[3],
00715                        const float v0[3], const float v1[3], const float v2[3],
00716                        float *r_lambda, const int clip)
00717 {
00718     float p[3], s[3], e1[3], e2[3], q[3];
00719     float a, f;
00720     /* float  u, v; */ /*UNUSED*/
00721 
00722     sub_v3_v3v3(e1, v1, v0);
00723     sub_v3_v3v3(e2, v2, v0);
00724     
00725     cross_v3_v3v3(p, d, e2);
00726     a = dot_v3v3(e1, p);
00727     /* note: these values were 0.000001 in 2.4x but for projection snapping on
00728      * a human head (1BU==1m), subsurf level 2, this gave many errors - campbell */
00729     if ((a > -0.00000001f) && (a < 0.00000001f)) return 0;
00730     f = 1.0f/a;
00731     
00732     sub_v3_v3v3(s, p1, v0);
00733     
00734     /* u = f * dot_v3v3(s, p); */ /*UNUSED*/
00735 
00736     cross_v3_v3v3(q, s, e1);
00737     
00738     /* v = f * dot_v3v3(d, q); */ /*UNUSED*/
00739 
00740     *r_lambda = f * dot_v3v3(e2, q);
00741     if (clip && (*r_lambda < 0.0f)) return 0;
00742 
00743     return 1;
00744 }
00745 
00746 int isect_ray_tri_epsilon_v3(const float p1[3], const float d[3],
00747                              const float v0[3], const float v1[3], const float v2[3],
00748                              float *r_lambda, float uv[2], const float epsilon)
00749 {
00750     float p[3], s[3], e1[3], e2[3], q[3];
00751     float a, f, u, v;
00752 
00753     sub_v3_v3v3(e1, v1, v0);
00754     sub_v3_v3v3(e2, v2, v0);
00755 
00756     cross_v3_v3v3(p, d, e2);
00757     a = dot_v3v3(e1, p);
00758     if (a == 0.0f) return 0;
00759     f = 1.0f/a;
00760 
00761     sub_v3_v3v3(s, p1, v0);
00762 
00763     u = f * dot_v3v3(s, p);
00764     if ((u < -epsilon)||(u > 1.0f+epsilon)) return 0;
00765 
00766     cross_v3_v3v3(q, s, e1);
00767 
00768     v = f * dot_v3v3(d, q);
00769     if ((v < -epsilon)||((u + v) > 1.0f+epsilon)) return 0;
00770 
00771     *r_lambda = f * dot_v3v3(e2, q);
00772     if ((*r_lambda < 0.0f)) return 0;
00773 
00774     if(uv) {
00775         uv[0]= u;
00776         uv[1]= v;
00777     }
00778 
00779     return 1;
00780 }
00781 
00782 int isect_ray_tri_threshold_v3(const float p1[3], const float d[3],
00783                                const float v0[3], const float v1[3], const float v2[3],
00784                                float *r_lambda, float r_uv[2], const float threshold)
00785 {
00786     float p[3], s[3], e1[3], e2[3], q[3];
00787     float a, f, u, v;
00788     float du = 0, dv = 0;
00789     
00790     sub_v3_v3v3(e1, v1, v0);
00791     sub_v3_v3v3(e2, v2, v0);
00792     
00793     cross_v3_v3v3(p, d, e2);
00794     a = dot_v3v3(e1, p);
00795     if ((a > -0.000001f) && (a < 0.000001f)) return 0;
00796     f = 1.0f/a;
00797     
00798     sub_v3_v3v3(s, p1, v0);
00799     
00800     cross_v3_v3v3(q, s, e1);
00801     *r_lambda = f * dot_v3v3(e2, q);
00802     if ((*r_lambda < 0.0f)) return 0;
00803     
00804     u = f * dot_v3v3(s, p);
00805     v = f * dot_v3v3(d, q);
00806     
00807     if (u < 0) du = u;
00808     if (u > 1) du = u - 1;
00809     if (v < 0) dv = v;
00810     if (v > 1) dv = v - 1;
00811     if (u > 0 && v > 0 && u + v > 1)
00812     {
00813         float t = u + v - 1;
00814         du = u - t/2;
00815         dv = v - t/2;
00816     }
00817 
00818     mul_v3_fl(e1, du);
00819     mul_v3_fl(e2, dv);
00820     
00821     if (dot_v3v3(e1, e1) + dot_v3v3(e2, e2) > threshold * threshold)
00822     {
00823         return 0;
00824     }
00825 
00826     if(r_uv) {
00827         r_uv[0]= u;
00828         r_uv[1]= v;
00829     }
00830     
00831     return 1;
00832 }
00833 
00834 int isect_line_plane_v3(float out[3], const float l1[3], const float l2[3], const float plane_co[3], const float plane_no[3], const short no_flip)
00835 {
00836     float l_vec[3]; /* l1 -> l2 normalized vector */
00837     float p_no[3]; /* 'plane_no' normalized */
00838     float dot;
00839 
00840     sub_v3_v3v3(l_vec, l2, l1);
00841 
00842     normalize_v3(l_vec);
00843     normalize_v3_v3(p_no, plane_no);
00844 
00845     dot= dot_v3v3(l_vec, p_no);
00846     if(dot == 0.0f) {
00847         return 0;
00848     }
00849     else {
00850         float l1_plane[3]; /* line point aligned with the plane */
00851         float dist; /* 'plane_no' aligned distance to the 'plane_co' */
00852 
00853         /* for pradictable flipping since the plane is only used to
00854          * define a direction, ignore its flipping and aligned with 'l_vec' */
00855         if(dot < 0.0f) {
00856             dot= -dot;
00857             negate_v3(p_no);
00858         }
00859 
00860         add_v3_v3v3(l1_plane, l1, p_no);
00861 
00862         dist = line_point_factor_v3(plane_co, l1, l1_plane);
00863 
00864         /* treat line like a ray, when 'no_flip' is set */
00865         if(no_flip && dist < 0.0f) {
00866             dist= -dist;
00867         }
00868 
00869         mul_v3_fl(l_vec, dist / dot);
00870 
00871         add_v3_v3v3(out, l1, l_vec);
00872 
00873         return 1;
00874     }
00875 }
00876 
00877 /* note: return normal isnt unit length */
00878 void isect_plane_plane_v3(float r_isect_co[3], float r_isect_no[3],
00879                           const float plane_a_co[3], const float plane_a_no[3],
00880                           const float plane_b_co[3], const float plane_b_no[3])
00881 {
00882     float plane_a_co_other[3];
00883     cross_v3_v3v3(r_isect_no, plane_a_no, plane_b_no); /* direction is simply the cross product */
00884     cross_v3_v3v3(plane_a_co_other, plane_a_no, r_isect_no);
00885     add_v3_v3(plane_a_co_other, plane_a_co);
00886     isect_line_plane_v3(r_isect_co, plane_a_co, plane_a_co_other, plane_b_co, plane_b_no, FALSE);
00887 }
00888 
00889 
00890 /* Adapted from the paper by Kasper Fauerby */
00891 /* "Improved Collision detection and Response" */
00892 static int getLowestRoot(const float a, const float b, const float c, const float maxR, float *root)
00893 {
00894     // Check if a solution exists
00895     float determinant = b*b - 4.0f*a*c;
00896 
00897     // If determinant is negative it means no solutions.
00898     if (determinant >= 0.0f)
00899     {
00900         // calculate the two roots: (if determinant == 0 then
00901         // x1==x2 but lets disregard that slight optimization)
00902         float sqrtD = (float)sqrt(determinant);
00903         float r1 = (-b - sqrtD) / (2.0f*a);
00904         float r2 = (-b + sqrtD) / (2.0f*a);
00905         
00906         // Sort so x1 <= x2
00907         if (r1 > r2)
00908             SWAP(float, r1, r2);
00909 
00910         // Get lowest root:
00911         if (r1 > 0.0f && r1 < maxR)
00912         {
00913             *root = r1;
00914             return 1;
00915         }
00916 
00917         // It is possible that we want x2 - this can happen
00918         // if x1 < 0
00919         if (r2 > 0.0f && r2 < maxR)
00920         {
00921             *root = r2;
00922             return 1;
00923         }
00924     }
00925     // No (valid) solutions
00926     return 0;
00927 }
00928 
00929 int isect_sweeping_sphere_tri_v3(
00930         const float p1[3], const float p2[3], const float radius,
00931         const float v0[3], const float v1[3], const float v2[3],
00932         float *r_lambda, float ipoint[3])
00933 {
00934     float e1[3], e2[3], e3[3], point[3], vel[3], /*dist[3],*/ nor[3], temp[3], bv[3];
00935     float a, b, c, d, e, x, y, z, radius2=radius*radius;
00936     float elen2,edotv,edotbv,nordotv;
00937     float newLambda;
00938     int found_by_sweep=0;
00939 
00940     sub_v3_v3v3(e1,v1,v0);
00941     sub_v3_v3v3(e2,v2,v0);
00942     sub_v3_v3v3(vel,p2,p1);
00943 
00944 /*---test plane of tri---*/
00945     cross_v3_v3v3(nor,e1,e2);
00946     normalize_v3(nor);
00947 
00948     /* flip normal */
00949     if(dot_v3v3(nor,vel)>0.0f) negate_v3(nor);
00950     
00951     a=dot_v3v3(p1,nor)-dot_v3v3(v0,nor);
00952     nordotv=dot_v3v3(nor,vel);
00953 
00954     if (fabsf(nordotv) < 0.000001f)
00955     {
00956         if(fabsf(a) >= radius) {
00957             return 0;
00958         }
00959     }
00960     else
00961     {
00962         float t0=(-a+radius)/nordotv;
00963         float t1=(-a-radius)/nordotv;
00964 
00965         if(t0>t1)
00966             SWAP(float, t0, t1);
00967 
00968         if(t0>1.0f || t1<0.0f) return 0;
00969 
00970         /* clamp to [0,1] */
00971         CLAMP(t0, 0.0f, 1.0f);
00972         CLAMP(t1, 0.0f, 1.0f);
00973 
00974         /*---test inside of tri---*/
00975         /* plane intersection point */
00976 
00977         point[0] = p1[0] + vel[0]*t0 - nor[0]*radius;
00978         point[1] = p1[1] + vel[1]*t0 - nor[1]*radius;
00979         point[2] = p1[2] + vel[2]*t0 - nor[2]*radius;
00980 
00981 
00982         /* is the point in the tri? */
00983         a=dot_v3v3(e1,e1);
00984         b=dot_v3v3(e1,e2);
00985         c=dot_v3v3(e2,e2);
00986 
00987         sub_v3_v3v3(temp,point,v0);
00988         d=dot_v3v3(temp,e1);
00989         e=dot_v3v3(temp,e2);
00990         
00991         x=d*c-e*b;
00992         y=e*a-d*b;
00993         z=x+y-(a*c-b*b);
00994 
00995 
00996         if(z <= 0.0f && (x >= 0.0f && y >= 0.0f))
00997         {
00998         //(((unsigned int)z)& ~(((unsigned int)x)|((unsigned int)y))) & 0x80000000){
00999             *r_lambda=t0;
01000             copy_v3_v3(ipoint,point);
01001             return 1;
01002         }
01003     }
01004 
01005 
01006     *r_lambda=1.0f;
01007 
01008 /*---test points---*/
01009     a=dot_v3v3(vel,vel);
01010 
01011     /*v0*/
01012     sub_v3_v3v3(temp,p1,v0);
01013     b=2.0f*dot_v3v3(vel,temp);
01014     c=dot_v3v3(temp,temp)-radius2;
01015 
01016     if(getLowestRoot(a, b, c, *r_lambda, r_lambda))
01017     {
01018         copy_v3_v3(ipoint,v0);
01019         found_by_sweep=1;
01020     }
01021 
01022     /*v1*/
01023     sub_v3_v3v3(temp,p1,v1);
01024     b=2.0f*dot_v3v3(vel,temp);
01025     c=dot_v3v3(temp,temp)-radius2;
01026 
01027     if(getLowestRoot(a, b, c, *r_lambda, r_lambda))
01028     {
01029         copy_v3_v3(ipoint,v1);
01030         found_by_sweep=1;
01031     }
01032     
01033     /*v2*/
01034     sub_v3_v3v3(temp,p1,v2);
01035     b=2.0f*dot_v3v3(vel,temp);
01036     c=dot_v3v3(temp,temp)-radius2;
01037 
01038     if(getLowestRoot(a, b, c, *r_lambda, r_lambda))
01039     {
01040         copy_v3_v3(ipoint,v2);
01041         found_by_sweep=1;
01042     }
01043 
01044 /*---test edges---*/
01045     sub_v3_v3v3(e3,v2,v1); //wasnt yet calculated
01046 
01047 
01048     /*e1*/
01049     sub_v3_v3v3(bv,v0,p1);
01050 
01051     elen2 = dot_v3v3(e1,e1);
01052     edotv = dot_v3v3(e1,vel);
01053     edotbv = dot_v3v3(e1,bv);
01054 
01055     a=elen2*(-dot_v3v3(vel,vel))+edotv*edotv;
01056     b=2.0f*(elen2*dot_v3v3(vel,bv)-edotv*edotbv);
01057     c=elen2*(radius2-dot_v3v3(bv,bv))+edotbv*edotbv;
01058 
01059     if(getLowestRoot(a, b, c, *r_lambda, &newLambda))
01060     {
01061         e=(edotv*newLambda-edotbv)/elen2;
01062 
01063         if(e >= 0.0f && e <= 1.0f)
01064         {
01065             *r_lambda = newLambda;
01066             copy_v3_v3(ipoint,e1);
01067             mul_v3_fl(ipoint,e);
01068             add_v3_v3(ipoint, v0);
01069             found_by_sweep=1;
01070         }
01071     }
01072 
01073     /*e2*/
01074     /*bv is same*/
01075     elen2 = dot_v3v3(e2,e2);
01076     edotv = dot_v3v3(e2,vel);
01077     edotbv = dot_v3v3(e2,bv);
01078 
01079     a=elen2*(-dot_v3v3(vel,vel))+edotv*edotv;
01080     b=2.0f*(elen2*dot_v3v3(vel,bv)-edotv*edotbv);
01081     c=elen2*(radius2-dot_v3v3(bv,bv))+edotbv*edotbv;
01082 
01083     if(getLowestRoot(a, b, c, *r_lambda, &newLambda))
01084     {
01085         e=(edotv*newLambda-edotbv)/elen2;
01086 
01087         if(e >= 0.0f && e <= 1.0f)
01088         {
01089             *r_lambda = newLambda;
01090             copy_v3_v3(ipoint,e2);
01091             mul_v3_fl(ipoint,e);
01092             add_v3_v3(ipoint, v0);
01093             found_by_sweep=1;
01094         }
01095     }
01096 
01097     /*e3*/
01098     /* sub_v3_v3v3(bv,v0,p1); */ /* UNUSED */
01099     /* elen2 = dot_v3v3(e1,e1); */ /* UNUSED */
01100     /* edotv = dot_v3v3(e1,vel); */ /* UNUSED */
01101     /* edotbv = dot_v3v3(e1,bv); */ /* UNUSED */
01102 
01103     sub_v3_v3v3(bv,v1,p1);
01104     elen2 = dot_v3v3(e3,e3);
01105     edotv = dot_v3v3(e3,vel);
01106     edotbv = dot_v3v3(e3,bv);
01107 
01108     a=elen2*(-dot_v3v3(vel,vel))+edotv*edotv;
01109     b=2.0f*(elen2*dot_v3v3(vel,bv)-edotv*edotbv);
01110     c=elen2*(radius2-dot_v3v3(bv,bv))+edotbv*edotbv;
01111 
01112     if(getLowestRoot(a, b, c, *r_lambda, &newLambda))
01113     {
01114         e=(edotv*newLambda-edotbv)/elen2;
01115 
01116         if(e >= 0.0f && e <= 1.0f)
01117         {
01118             *r_lambda = newLambda;
01119             copy_v3_v3(ipoint,e3);
01120             mul_v3_fl(ipoint,e);
01121             add_v3_v3(ipoint, v1);
01122             found_by_sweep=1;
01123         }
01124     }
01125 
01126 
01127     return found_by_sweep;
01128 }
01129 int isect_axial_line_tri_v3(const int axis, const float p1[3], const float p2[3],
01130                             const float v0[3], const float v1[3], const float v2[3], float *r_lambda)
01131 {
01132     float p[3], e1[3], e2[3];
01133     float u, v, f;
01134     int a0=axis, a1=(axis+1)%3, a2=(axis+2)%3;
01135 
01136     //return isect_line_tri_v3(p1,p2,v0,v1,v2,lambda);
01137 
01139     //if(MIN3(v0[a1],v1[a1],v2[a1]) > p1[a1]) return 0;
01140     //if(MIN3(v0[a2],v1[a2],v2[a2]) > p1[a2]) return 0;
01141     //if(MAX3(v0[a1],v1[a1],v2[a1]) < p1[a1]) return 0;
01142     //if(MAX3(v0[a2],v1[a2],v2[a2]) < p1[a2]) return 0;
01143 
01145     
01146     sub_v3_v3v3(e1,v1,v0);
01147     sub_v3_v3v3(e2,v2,v0);
01148     sub_v3_v3v3(p,v0,p1);
01149 
01150     f= (e2[a1]*e1[a2]-e2[a2]*e1[a1]);
01151     if ((f > -0.000001f) && (f < 0.000001f)) return 0;
01152 
01153     v= (p[a2]*e1[a1]-p[a1]*e1[a2])/f;
01154     if ((v < 0.0f)||(v > 1.0f)) return 0;
01155     
01156     f= e1[a1];
01157     if((f > -0.000001f) && (f < 0.000001f)){
01158         f= e1[a2];
01159         if((f > -0.000001f) && (f < 0.000001f)) return 0;
01160         u= (-p[a2]-v*e2[a2])/f;
01161     }
01162     else
01163         u= (-p[a1]-v*e2[a1])/f;
01164 
01165     if ((u < 0.0f) || ((u + v) > 1.0f)) return 0;
01166 
01167     *r_lambda = (p[a0]+u*e1[a0]+v*e2[a0])/(p2[a0]-p1[a0]);
01168 
01169     if ((*r_lambda < 0.0f) || (*r_lambda > 1.0f)) return 0;
01170 
01171     return 1;
01172 }
01173 
01174 /* Returns the number of point of interests
01175  * 0 - lines are colinear
01176  * 1 - lines are coplanar, i1 is set to intersection
01177  * 2 - i1 and i2 are the nearest points on line 1 (v1, v2) and line 2 (v3, v4) respectively 
01178  * */
01179 int isect_line_line_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3], float i1[3], float i2[3])
01180 {
01181     float a[3], b[3], c[3], ab[3], cb[3], dir1[3], dir2[3];
01182     float d;
01183     
01184     sub_v3_v3v3(c, v3, v1);
01185     sub_v3_v3v3(a, v2, v1);
01186     sub_v3_v3v3(b, v4, v3);
01187 
01188     normalize_v3_v3(dir1, a);
01189     normalize_v3_v3(dir2, b);
01190     d = dot_v3v3(dir1, dir2);
01191     if (d == 1.0f || d == -1.0f) {
01192         /* colinear */
01193         return 0;
01194     }
01195 
01196     cross_v3_v3v3(ab, a, b);
01197     d = dot_v3v3(c, ab);
01198 
01199     /* test if the two lines are coplanar */
01200     if (d > -0.000001f && d < 0.000001f) {
01201         cross_v3_v3v3(cb, c, b);
01202 
01203         mul_v3_fl(a, dot_v3v3(cb, ab) / dot_v3v3(ab, ab));
01204         add_v3_v3v3(i1, v1, a);
01205         copy_v3_v3(i2, i1);
01206         
01207         return 1; /* one intersection only */
01208     }
01209     /* if not */
01210     else {
01211         float n[3], t[3];
01212         float v3t[3], v4t[3];
01213         sub_v3_v3v3(t, v1, v3);
01214 
01215         /* offset between both plane where the lines lies */
01216         cross_v3_v3v3(n, a, b);
01217         project_v3_v3v3(t, t, n);
01218 
01219         /* for the first line, offset the second line until it is coplanar */
01220         add_v3_v3v3(v3t, v3, t);
01221         add_v3_v3v3(v4t, v4, t);
01222         
01223         sub_v3_v3v3(c, v3t, v1);
01224         sub_v3_v3v3(a, v2, v1);
01225         sub_v3_v3v3(b, v4t, v3t);
01226 
01227         cross_v3_v3v3(ab, a, b);
01228         cross_v3_v3v3(cb, c, b);
01229 
01230         mul_v3_fl(a, dot_v3v3(cb, ab) / dot_v3v3(ab, ab));
01231         add_v3_v3v3(i1, v1, a);
01232 
01233         /* for the second line, just substract the offset from the first intersection point */
01234         sub_v3_v3v3(i2, i1, t);
01235         
01236         return 2; /* two nearest points */
01237     }
01238 } 
01239 
01240 /* Intersection point strictly between the two lines
01241  * 0 when no intersection is found 
01242  * */
01243 int isect_line_line_strict_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3], float vi[3], float *r_lambda)
01244 {
01245     float a[3], b[3], c[3], ab[3], cb[3], ca[3], dir1[3], dir2[3];
01246     float d;
01247     
01248     sub_v3_v3v3(c, v3, v1);
01249     sub_v3_v3v3(a, v2, v1);
01250     sub_v3_v3v3(b, v4, v3);
01251 
01252     normalize_v3_v3(dir1, a);
01253     normalize_v3_v3(dir2, b);
01254     d = dot_v3v3(dir1, dir2);
01255     if (d == 1.0f || d == -1.0f || d == 0) {
01256         /* colinear or one vector is zero-length*/
01257         return 0;
01258     }
01259 
01260     cross_v3_v3v3(ab, a, b);
01261     d = dot_v3v3(c, ab);
01262 
01263     /* test if the two lines are coplanar */
01264     if (d > -0.000001f && d < 0.000001f) {
01265         float f1, f2;
01266         cross_v3_v3v3(cb, c, b);
01267         cross_v3_v3v3(ca, c, a);
01268 
01269         f1 = dot_v3v3(cb, ab) / dot_v3v3(ab, ab);
01270         f2 = dot_v3v3(ca, ab) / dot_v3v3(ab, ab);
01271         
01272         if (f1 >= 0 && f1 <= 1 &&
01273             f2 >= 0 && f2 <= 1)
01274         {
01275             mul_v3_fl(a, f1);
01276             add_v3_v3v3(vi, v1, a);
01277 
01278             if (r_lambda) *r_lambda = f1;
01279 
01280             return 1; /* intersection found */
01281         }
01282         else
01283         {
01284             return 0;
01285         }
01286     }
01287     else
01288     {
01289         return 0;
01290     }
01291 } 
01292 
01293 int isect_aabb_aabb_v3(const float min1[3], const float max1[3], const float min2[3], const float max2[3])
01294 {
01295     return (min1[0]<max2[0] && min1[1]<max2[1] && min1[2]<max2[2] &&
01296             min2[0]<max1[0] && min2[1]<max1[1] && min2[2]<max1[2]);
01297 }
01298 
01299 /* find closest point to p on line through l1,l2 and return lambda,
01300  * where (0 <= lambda <= 1) when cp is in the line segement l1,l2
01301  */
01302 float closest_to_line_v3(float cp[3], const float p[3], const float l1[3], const float l2[3])
01303 {
01304     float h[3],u[3],lambda;
01305     sub_v3_v3v3(u, l2, l1);
01306     sub_v3_v3v3(h, p, l1);
01307     lambda =dot_v3v3(u,h)/dot_v3v3(u,u);
01308     cp[0] = l1[0] + u[0] * lambda;
01309     cp[1] = l1[1] + u[1] * lambda;
01310     cp[2] = l1[2] + u[2] * lambda;
01311     return lambda;
01312 }
01313 
01314 float closest_to_line_v2(float cp[2],const float p[2], const float l1[2], const float l2[2])
01315 {
01316     float h[2],u[2],lambda;
01317     sub_v2_v2v2(u, l2, l1);
01318     sub_v2_v2v2(h, p, l1);
01319     lambda =dot_v2v2(u,h)/dot_v2v2(u,u);
01320     cp[0] = l1[0] + u[0] * lambda;
01321     cp[1] = l1[1] + u[1] * lambda;
01322     return lambda;
01323 }
01324 
01325 /* little sister we only need to know lambda */
01326 float line_point_factor_v3(const float p[3], const float l1[3], const float l2[3])
01327 {
01328     float h[3],u[3];
01329     sub_v3_v3v3(u, l2, l1);
01330     sub_v3_v3v3(h, p, l1);
01331     return(dot_v3v3(u,h)/dot_v3v3(u,u));
01332 }
01333 
01334 float line_point_factor_v2(const float p[2], const float l1[2], const float l2[2])
01335 {
01336     float h[2], u[2];
01337     sub_v2_v2v2(u, l2, l1);
01338     sub_v2_v2v2(h, p, l1);
01339     return(dot_v2v2(u, h)/dot_v2v2(u, u));
01340 }
01341 
01342 /* Similar to LineIntersectsTriangleUV, except it operates on a quad and in 2d, assumes point is in quad */
01343 void isect_point_quad_uv_v2(const float v0[2], const float v1[2], const float v2[2], const float v3[2], const float pt[2], float r_uv[2])
01344 {
01345     float x0,y0, x1,y1, wtot, v2d[2], w1, w2;
01346     
01347     /* used for parallel lines */
01348     float pt3d[3], l1[3], l2[3], pt_on_line[3];
01349     
01350     /* compute 2 edges  of the quad  intersection point */
01351     if (IsectLLPt2Df(v0[0],v0[1],v1[0],v1[1],  v2[0],v2[1],v3[0],v3[1], &x0,&y0) == 1) {
01352         /* the intersection point between the quad-edge intersection and the point in the quad we want the uv's for */
01353         /* should never be paralle !! */
01354         /*printf("\tnot parallel 1\n");*/
01355         IsectLLPt2Df(pt[0],pt[1],x0,y0,  v0[0],v0[1],v3[0],v3[1], &x1,&y1);
01356         
01357         /* Get the weights from the new intersection point, to each edge */
01358         v2d[0] = x1-v0[0];
01359         v2d[1] = y1-v0[1];
01360         w1 = len_v2(v2d);
01361         
01362         v2d[0] = x1-v3[0]; /* some but for the other vert */
01363         v2d[1] = y1-v3[1];
01364         w2 = len_v2(v2d);
01365         wtot = w1+w2;
01366         /*w1 = w1/wtot;*/
01367         /*w2 = w2/wtot;*/
01368         r_uv[0] = w1/wtot;
01369     } else {
01370         /* lines are parallel, lambda_cp_line_ex is 3d grrr */
01371         /*printf("\tparallel1\n");*/
01372         pt3d[0] = pt[0];
01373         pt3d[1] = pt[1];
01374         pt3d[2] = l1[2] = l2[2] = 0.0f;
01375         
01376         l1[0] = v0[0]; l1[1] = v0[1];
01377         l2[0] = v1[0]; l2[1] = v1[1];
01378         closest_to_line_v3(pt_on_line,pt3d, l1, l2);
01379         v2d[0] = pt[0]-pt_on_line[0]; /* same, for the other vert */
01380         v2d[1] = pt[1]-pt_on_line[1];
01381         w1 = len_v2(v2d);
01382         
01383         l1[0] = v2[0]; l1[1] = v2[1];
01384         l2[0] = v3[0]; l2[1] = v3[1];
01385         closest_to_line_v3(pt_on_line,pt3d, l1, l2);
01386         v2d[0] = pt[0]-pt_on_line[0]; /* same, for the other vert */
01387         v2d[1] = pt[1]-pt_on_line[1];
01388         w2 = len_v2(v2d);
01389         wtot = w1+w2;
01390         r_uv[0] = w1/wtot;
01391     }
01392     
01393     /* Same as above to calc the uv[1] value, alternate calculation */
01394     
01395     if (IsectLLPt2Df(v0[0],v0[1],v3[0],v3[1],  v1[0],v1[1],v2[0],v2[1], &x0,&y0) == 1) { /* was v0,v1  v2,v3  now v0,v3  v1,v2*/
01396         /* never paralle if above was not */
01397         /*printf("\tnot parallel2\n");*/
01398         IsectLLPt2Df(pt[0],pt[1],x0,y0,  v0[0],v0[1],v1[0],v1[1], &x1,&y1);/* was v0,v3  now v0,v1*/
01399         
01400         v2d[0] = x1-v0[0];
01401         v2d[1] = y1-v0[1];
01402         w1 = len_v2(v2d);
01403         
01404         v2d[0] = x1-v1[0];
01405         v2d[1] = y1-v1[1];
01406         w2 = len_v2(v2d);
01407         wtot = w1+w2;
01408         r_uv[1] = w1/wtot;
01409     } else {
01410         /* lines are parallel, lambda_cp_line_ex is 3d grrr */
01411         /*printf("\tparallel2\n");*/
01412         pt3d[0] = pt[0];
01413         pt3d[1] = pt[1];
01414         pt3d[2] = l1[2] = l2[2] = 0.0f;
01415         
01416         
01417         l1[0] = v0[0]; l1[1] = v0[1];
01418         l2[0] = v3[0]; l2[1] = v3[1];
01419         closest_to_line_v3(pt_on_line,pt3d, l1, l2);
01420         v2d[0] = pt[0]-pt_on_line[0]; /* some but for the other vert */
01421         v2d[1] = pt[1]-pt_on_line[1];
01422         w1 = len_v2(v2d);
01423         
01424         l1[0] = v1[0]; l1[1] = v1[1];
01425         l2[0] = v2[0]; l2[1] = v2[1];
01426         closest_to_line_v3(pt_on_line,pt3d, l1, l2);
01427         v2d[0] = pt[0]-pt_on_line[0]; /* some but for the other vert */
01428         v2d[1] = pt[1]-pt_on_line[1];
01429         w2 = len_v2(v2d);
01430         wtot = w1+w2;
01431         r_uv[1] = w1/wtot;
01432     }
01433     /* may need to flip UV's here */
01434 }
01435 
01436 /* same as above but does tri's and quads, tri's are a bit of a hack */
01437 void isect_point_face_uv_v2(const int isquad, const float v0[2], const float v1[2], const float v2[2], const float v3[2], const float pt[2], float r_uv[2])
01438 {
01439     if (isquad) {
01440         isect_point_quad_uv_v2(v0, v1, v2, v3, pt, r_uv);
01441     }
01442     else {
01443         /* not for quads, use for our abuse of LineIntersectsTriangleUV */
01444         float p1_3d[3], p2_3d[3], v0_3d[3], v1_3d[3], v2_3d[3], lambda;
01445             
01446         p1_3d[0] = p2_3d[0] = r_uv[0];
01447         p1_3d[1] = p2_3d[1] = r_uv[1];
01448         p1_3d[2] = 1.0f;
01449         p2_3d[2] = -1.0f;
01450         v0_3d[2] = v1_3d[2] = v2_3d[2] = 0.0;
01451         
01452         /* generate a new fuv, (this is possibly a non optimal solution,
01453          * since we only need 2d calculation but use 3d func's)
01454          * 
01455          * this method makes an imaginary triangle in 2d space using the UV's from the derived mesh face
01456          * Then find new uv coords using the fuv and this face with LineIntersectsTriangleUV.
01457          * This means the new values will be correct in relation to the derived meshes face. 
01458          */
01459         copy_v2_v2(v0_3d, v0);
01460         copy_v2_v2(v1_3d, v1);
01461         copy_v2_v2(v2_3d, v2);
01462         
01463         /* Doing this in 3D is not nice */
01464         isect_line_tri_v3(p1_3d, p2_3d, v0_3d, v1_3d, v2_3d, &lambda, r_uv);
01465     }
01466 }
01467 
01468 #if 0 // XXX this version used to be used in isect_point_tri_v2_int() and was called IsPointInTri2D
01469 int isect_point_tri_v2(float pt[2], float v1[2], float v2[2], float v3[2])
01470 {
01471     float inp1, inp2, inp3;
01472     
01473     inp1= (v2[0]-v1[0])*(v1[1]-pt[1]) + (v1[1]-v2[1])*(v1[0]-pt[0]);
01474     inp2= (v3[0]-v2[0])*(v2[1]-pt[1]) + (v2[1]-v3[1])*(v2[0]-pt[0]);
01475     inp3= (v1[0]-v3[0])*(v3[1]-pt[1]) + (v3[1]-v1[1])*(v3[0]-pt[0]);
01476     
01477     if(inp1<=0.0f && inp2<=0.0f && inp3<=0.0f) return 1;
01478     if(inp1>=0.0f && inp2>=0.0f && inp3>=0.0f) return 1;
01479     
01480     return 0;
01481 }
01482 #endif
01483 
01484 #if 0
01485 int isect_point_tri_v2(float v0[2], float v1[2], float v2[2], float pt[2])
01486 {
01487         /* not for quads, use for our abuse of LineIntersectsTriangleUV */
01488         float p1_3d[3], p2_3d[3], v0_3d[3], v1_3d[3], v2_3d[3];
01489         /* not used */
01490         float lambda, uv[3];
01491             
01492         p1_3d[0] = p2_3d[0] = uv[0]= pt[0];
01493         p1_3d[1] = p2_3d[1] = uv[1]= uv[2]= pt[1];
01494         p1_3d[2] = 1.0f;
01495         p2_3d[2] = -1.0f;
01496         v0_3d[2] = v1_3d[2] = v2_3d[2] = 0.0;
01497         
01498         /* generate a new fuv, (this is possibly a non optimal solution,
01499          * since we only need 2d calculation but use 3d func's)
01500          * 
01501          * this method makes an imaginary triangle in 2d space using the UV's from the derived mesh face
01502          * Then find new uv coords using the fuv and this face with LineIntersectsTriangleUV.
01503          * This means the new values will be correct in relation to the derived meshes face. 
01504          */
01505         copy_v2_v2(v0_3d, v0);
01506         copy_v2_v2(v1_3d, v1);
01507         copy_v2_v2(v2_3d, v2);
01508         
01509         /* Doing this in 3D is not nice */
01510         return isect_line_tri_v3(p1_3d, p2_3d, v0_3d, v1_3d, v2_3d, &lambda, uv);
01511 }
01512 #endif
01513 
01514 /*
01515 
01516     x1,y2
01517     |  \
01518     |   \     .(a,b)
01519     |    \
01520     x1,y1-- x2,y1
01521 
01522 */
01523 int isect_point_tri_v2_int(const int x1, const int y1, const int x2, const int y2, const int a, const int b)
01524 {
01525     float v1[2], v2[2], v3[2], p[2];
01526     
01527     v1[0]= (float)x1;
01528     v1[1]= (float)y1;
01529     
01530     v2[0]= (float)x1;
01531     v2[1]= (float)y2;
01532     
01533     v3[0]= (float)x2;
01534     v3[1]= (float)y1;
01535     
01536     p[0]= (float)a;
01537     p[1]= (float)b;
01538     
01539     return isect_point_tri_v2(p, v1, v2, v3);
01540 }
01541 
01542 static int point_in_slice(const float p[3], const float v1[3], const float l1[3], const float l2[3])
01543 {
01544 /* 
01545 what is a slice ?
01546 some maths:
01547 a line including l1,l2 and a point not on the line 
01548 define a subset of R3 delimeted by planes parallel to the line and orthogonal 
01549 to the (point --> line) distance vector,one plane on the line one on the point, 
01550 the room inside usually is rather small compared to R3 though still infinte
01551 useful for restricting (speeding up) searches 
01552 e.g. all points of triangular prism are within the intersection of 3 'slices'
01553 onother trivial case : cube 
01554 but see a 'spat' which is a deformed cube with paired parallel planes needs only 3 slices too
01555 */
01556     float h,rp[3],cp[3],q[3];
01557 
01558     closest_to_line_v3(cp,v1,l1,l2);
01559     sub_v3_v3v3(q,cp,v1);
01560 
01561     sub_v3_v3v3(rp,p,v1);
01562     h=dot_v3v3(q,rp)/dot_v3v3(q,q);
01563     if (h < 0.0f || h > 1.0f) return 0;
01564     return 1;
01565 }
01566 
01567 #if 0
01568 /*adult sister defining the slice planes by the origin and the normal  
01569 NOTE |normal| may not be 1 but defining the thickness of the slice*/
01570 static int point_in_slice_as(float p[3],float origin[3],float normal[3])
01571 {
01572     float h,rp[3];
01573     sub_v3_v3v3(rp,p,origin);
01574     h=dot_v3v3(normal,rp)/dot_v3v3(normal,normal);
01575     if (h < 0.0f || h > 1.0f) return 0;
01576     return 1;
01577 }
01578 
01579 /*mama (knowing the squared length of the normal)*/
01580 static int point_in_slice_m(float p[3],float origin[3],float normal[3],float lns)
01581 {
01582     float h,rp[3];
01583     sub_v3_v3v3(rp,p,origin);
01584     h=dot_v3v3(normal,rp)/lns;
01585     if (h < 0.0f || h > 1.0f) return 0;
01586     return 1;
01587 }
01588 #endif
01589 
01590 int isect_point_tri_prism_v3(const float p[3], const float v1[3], const float v2[3], const float v3[3])
01591 {
01592     if(!point_in_slice(p,v1,v2,v3)) return 0;
01593     if(!point_in_slice(p,v2,v3,v1)) return 0;
01594     if(!point_in_slice(p,v3,v1,v2)) return 0;
01595     return 1;
01596 }
01597 
01598 int clip_line_plane(float p1[3], float p2[3], const float plane[4])
01599 {
01600     float dp[3], n[3], div, t, pc[3];
01601 
01602     copy_v3_v3(n, plane);
01603     sub_v3_v3v3(dp, p2, p1);
01604     div= dot_v3v3(dp, n);
01605 
01606     if(div == 0.0f) /* parallel */
01607         return 1;
01608 
01609     t= -(dot_v3v3(p1, n) + plane[3])/div;
01610 
01611     if(div > 0.0f) {
01612         /* behind plane, completely clipped */
01613         if(t >= 1.0f) {
01614             zero_v3(p1);
01615             zero_v3(p2);
01616             return 0;
01617         }
01618 
01619         /* intersect plane */
01620         if(t > 0.0f) {
01621             madd_v3_v3v3fl(pc, p1, dp, t);
01622             copy_v3_v3(p1, pc);
01623             return 1;
01624         }
01625 
01626         return 1;
01627     }
01628     else {
01629         /* behind plane, completely clipped */
01630         if(t <= 0.0f) {
01631             zero_v3(p1);
01632             zero_v3(p2);
01633             return 0;
01634         }
01635 
01636         /* intersect plane */
01637         if(t < 1.0f) {
01638             madd_v3_v3v3fl(pc, p1, dp, t);
01639             copy_v3_v3(p2, pc);
01640             return 1;
01641         }
01642 
01643         return 1;
01644     }
01645 }
01646 
01647 
01648 void plot_line_v2v2i(const int p1[2], const int p2[2], int (*callback)(int, int, void *), void *userData)
01649 {
01650     int x1= p1[0];
01651     int y1= p1[1];
01652     int x2= p2[0];
01653     int y2= p2[1];
01654 
01655     signed char ix;
01656     signed char iy;
01657 
01658     // if x1 == x2 or y1 == y2, then it does not matter what we set here
01659     int delta_x = (x2 > x1?(ix = 1, x2 - x1):(ix = -1, x1 - x2)) << 1;
01660     int delta_y = (y2 > y1?(iy = 1, y2 - y1):(iy = -1, y1 - y2)) << 1;
01661 
01662     if(callback(x1, y1, userData) == 0) {
01663         return;
01664     }
01665 
01666     if (delta_x >= delta_y) {
01667         // error may go below zero
01668         int error = delta_y - (delta_x >> 1);
01669 
01670         while (x1 != x2) {
01671             if (error >= 0) {
01672                 if (error || (ix > 0)) {
01673                     y1 += iy;
01674                     error -= delta_x;
01675                 }
01676                 // else do nothing
01677             }
01678             // else do nothing
01679 
01680             x1 += ix;
01681             error += delta_y;
01682 
01683             if(callback(x1, y1, userData) == 0) {
01684                 return ;
01685             }
01686         }
01687     }
01688     else {
01689         // error may go below zero
01690         int error = delta_x - (delta_y >> 1);
01691 
01692         while (y1 != y2) {
01693             if (error >= 0) {
01694                 if (error || (iy > 0)) {
01695                     x1 += ix;
01696                     error -= delta_y;
01697                 }
01698                 // else do nothing
01699             }
01700             // else do nothing
01701 
01702             y1 += iy;
01703             error += delta_x;
01704 
01705             if(callback(x1, y1, userData) == 0) {
01706                 return;
01707             }
01708         }
01709     }
01710 }
01711 
01712 /****************************** Interpolation ********************************/
01713 
01714 /* get the 2 dominant axis values, 0==X, 1==Y, 2==Z */
01715 void axis_dominant_v3(int *axis_a, int *axis_b, const float axis[3])
01716 {
01717     const float xn= fabsf(axis[0]);
01718     const float yn= fabsf(axis[1]);
01719     const float zn= fabsf(axis[2]);
01720 
01721     if      (zn >= xn && zn >= yn) { *axis_a= 0; *axis_b= 1; }
01722     else if (yn >= xn && yn >= zn) { *axis_a= 0; *axis_b= 2; }
01723     else                           { *axis_a= 1; *axis_b= 2; }
01724 }
01725 
01726 static float tri_signed_area(const float v1[3], const float v2[3], const float v3[3], const int i, const int j)
01727 {
01728     return 0.5f*((v1[i]-v2[i])*(v2[j]-v3[j]) + (v1[j]-v2[j])*(v3[i]-v2[i]));
01729 }
01730 
01731 static int barycentric_weights(const float v1[3], const float v2[3], const float v3[3], const float co[3], const float n[3], float w[3])
01732 {
01733     float a1, a2, a3, asum;
01734     int i, j;
01735 
01736     axis_dominant_v3(&i, &j, n);
01737 
01738     a1= tri_signed_area(v2, v3, co, i, j);
01739     a2= tri_signed_area(v3, v1, co, i, j);
01740     a3= tri_signed_area(v1, v2, co, i, j);
01741 
01742     asum= a1 + a2 + a3;
01743 
01744     if (fabsf(asum) < FLT_EPSILON) {
01745         /* zero area triangle */
01746         w[0]= w[1]= w[2]= 1.0f/3.0f;
01747         return 1;
01748     }
01749 
01750     asum= 1.0f/asum;
01751     w[0]= a1*asum;
01752     w[1]= a2*asum;
01753     w[2]= a3*asum;
01754 
01755     return 0;
01756 }
01757 
01758 void interp_weights_face_v3(float w[4], const float v1[3], const float v2[3], const float v3[3], const float v4[3], const float co[3])
01759 {
01760     float w2[3];
01761 
01762     w[0]= w[1]= w[2]= w[3]= 0.0f;
01763 
01764     /* first check for exact match */
01765     if(equals_v3v3(co, v1))
01766         w[0]= 1.0f;
01767     else if(equals_v3v3(co, v2))
01768         w[1]= 1.0f;
01769     else if(equals_v3v3(co, v3))
01770         w[2]= 1.0f;
01771     else if(v4 && equals_v3v3(co, v4))
01772         w[3]= 1.0f;
01773     else {
01774         /* otherwise compute barycentric interpolation weights */
01775         float n1[3], n2[3], n[3];
01776         int degenerate;
01777 
01778         sub_v3_v3v3(n1, v1, v3);
01779         if (v4) {
01780             sub_v3_v3v3(n2, v2, v4);
01781         }
01782         else {
01783             sub_v3_v3v3(n2, v2, v3);
01784         }
01785         cross_v3_v3v3(n, n1, n2);
01786 
01787         /* OpenGL seems to split this way, so we do too */
01788         if (v4) {
01789             degenerate= barycentric_weights(v1, v2, v4, co, n, w);
01790             SWAP(float, w[2], w[3]);
01791 
01792             if(degenerate || (w[0] < 0.0f)) {
01793                 /* if w[1] is negative, co is on the other side of the v1-v3 edge,
01794                    so we interpolate using the other triangle */
01795                 degenerate= barycentric_weights(v2, v3, v4, co, n, w2);
01796 
01797                 if(!degenerate) {
01798                     w[0]= 0.0f;
01799                     w[1]= w2[0];
01800                     w[2]= w2[1];
01801                     w[3]= w2[2];
01802                 }
01803             }
01804         }
01805         else
01806             barycentric_weights(v1, v2, v3, co, n, w);
01807     }
01808 }
01809 
01810 /* used by projection painting
01811  * note: using area_tri_signed_v2 means locations outside the triangle are correctly weighted */
01812 void barycentric_weights_v2(const float v1[2], const float v2[2], const float v3[2], const float co[2], float w[3])
01813 {
01814     float wtot_inv, wtot;
01815 
01816     w[0] = area_tri_signed_v2(v2, v3, co);
01817     w[1] = area_tri_signed_v2(v3, v1, co);
01818     w[2] = area_tri_signed_v2(v1, v2, co);
01819     wtot = w[0]+w[1]+w[2];
01820 
01821     if (wtot != 0.0f) {
01822         wtot_inv = 1.0f/wtot;
01823 
01824         w[0] = w[0]*wtot_inv;
01825         w[1] = w[1]*wtot_inv;
01826         w[2] = w[2]*wtot_inv;
01827     }
01828     else /* dummy values for zero area face */
01829         w[0] = w[1] = w[2] = 1.0f/3.0f;
01830 }
01831 
01832 /* given 2 triangles in 3D space, and a point in relation to the first triangle.
01833  * calculate the location of a point in relation to the second triangle.
01834  * Useful for finding relative positions with geometry */
01835 void barycentric_transform(float pt_tar[3], float const pt_src[3],
01836         const float tri_tar_p1[3], const float tri_tar_p2[3], const float tri_tar_p3[3],
01837         const float tri_src_p1[3], const float tri_src_p2[3], const float tri_src_p3[3])
01838 {
01839     /* this works by moving the source triangle so its normal is pointing on the Z
01840      * axis where its barycentric wights can be calculated in 2D and its Z offset can
01841      *  be re-applied. The weights are applied directly to the targets 3D points and the
01842      *  z-depth is used to scale the targets normal as an offset.
01843      * This saves transforming the target into its Z-Up orientation and back (which could also work) */
01844     const float z_up[3] = {0, 0, 1};
01845     float no_tar[3], no_src[3];
01846     float quat_src[4];
01847     float pt_src_xy[3];
01848     float  tri_xy_src[3][3];
01849     float w_src[3];
01850     float area_tar, area_src;
01851     float z_ofs_src;
01852 
01853     normal_tri_v3(no_tar, tri_tar_p1, tri_tar_p2, tri_tar_p3);
01854     normal_tri_v3(no_src, tri_src_p1, tri_src_p2, tri_src_p3);
01855 
01856     rotation_between_vecs_to_quat(quat_src, no_src, z_up);
01857     normalize_qt(quat_src);
01858 
01859     copy_v3_v3(pt_src_xy, pt_src);
01860     copy_v3_v3(tri_xy_src[0], tri_src_p1);
01861     copy_v3_v3(tri_xy_src[1], tri_src_p2);
01862     copy_v3_v3(tri_xy_src[2], tri_src_p3);
01863 
01864     /* make the source tri xy space */
01865     mul_qt_v3(quat_src, pt_src_xy);
01866     mul_qt_v3(quat_src, tri_xy_src[0]);
01867     mul_qt_v3(quat_src, tri_xy_src[1]);
01868     mul_qt_v3(quat_src, tri_xy_src[2]);
01869 
01870     barycentric_weights_v2(tri_xy_src[0], tri_xy_src[1], tri_xy_src[2], pt_src_xy, w_src);
01871     interp_v3_v3v3v3(pt_tar, tri_tar_p1, tri_tar_p2, tri_tar_p3, w_src);
01872 
01873     area_tar= sqrtf(area_tri_v3(tri_tar_p1, tri_tar_p2, tri_tar_p3));
01874     area_src= sqrtf(area_tri_v2(tri_xy_src[0], tri_xy_src[1], tri_xy_src[2]));
01875 
01876     z_ofs_src= pt_src_xy[2] - tri_xy_src[0][2];
01877     madd_v3_v3v3fl(pt_tar, pt_tar, no_tar, (z_ofs_src / area_src) * area_tar);
01878 }
01879 
01880 /* given an array with some invalid values this function interpolates valid values
01881  * replacing the invalid ones */
01882 int interp_sparse_array(float *array, int const list_size, const float skipval)
01883 {
01884     int found_invalid = 0;
01885     int found_valid = 0;
01886     int i;
01887 
01888     for (i=0; i < list_size; i++) {
01889         if(array[i] == skipval)
01890             found_invalid= 1;
01891         else
01892             found_valid= 1;
01893     }
01894 
01895     if(found_valid==0) {
01896         return -1;
01897     }
01898     else if (found_invalid==0) {
01899         return 0;
01900     }
01901     else {
01902         /* found invalid depths, interpolate */
01903         float valid_last= skipval;
01904         int valid_ofs= 0;
01905 
01906         float *array_up= MEM_callocN(sizeof(float) * list_size, "interp_sparse_array up");
01907         float *array_down= MEM_callocN(sizeof(float) * list_size, "interp_sparse_array up");
01908 
01909         int *ofs_tot_up= MEM_callocN(sizeof(int) * list_size, "interp_sparse_array tup");
01910         int *ofs_tot_down= MEM_callocN(sizeof(int) * list_size, "interp_sparse_array tdown");
01911 
01912         for (i=0; i < list_size; i++) {
01913             if(array[i] == skipval) {
01914                 array_up[i]= valid_last;
01915                 ofs_tot_up[i]= ++valid_ofs;
01916             }
01917             else {
01918                 valid_last= array[i];
01919                 valid_ofs= 0;
01920             }
01921         }
01922 
01923         valid_last= skipval;
01924         valid_ofs= 0;
01925 
01926         for (i=list_size-1; i >= 0; i--) {
01927             if(array[i] == skipval) {
01928                 array_down[i]= valid_last;
01929                 ofs_tot_down[i]= ++valid_ofs;
01930             }
01931             else {
01932                 valid_last= array[i];
01933                 valid_ofs= 0;
01934             }
01935         }
01936 
01937         /* now blend */
01938         for (i=0; i < list_size; i++) {
01939             if(array[i] == skipval) {
01940                 if(array_up[i] != skipval && array_down[i] != skipval) {
01941                     array[i]= ((array_up[i] * ofs_tot_down[i]) +  (array_down[i] * ofs_tot_up[i])) / (float)(ofs_tot_down[i] + ofs_tot_up[i]);
01942                 } else if (array_up[i] != skipval) {
01943                     array[i]= array_up[i];
01944                 } else if (array_down[i] != skipval) {
01945                     array[i]= array_down[i];
01946                 }
01947             }
01948         }
01949 
01950         MEM_freeN(array_up);
01951         MEM_freeN(array_down);
01952 
01953         MEM_freeN(ofs_tot_up);
01954         MEM_freeN(ofs_tot_down);
01955     }
01956 
01957     return 1;
01958 }
01959 
01960 /* Mean value weights - smooth interpolation weights for polygons with
01961  * more than 3 vertices */
01962 static float mean_value_half_tan(const float v1[3], const float v2[3], const float v3[3])
01963 {
01964     float d2[3], d3[3], cross[3], area, dot, len;
01965 
01966     sub_v3_v3v3(d2, v2, v1);
01967     sub_v3_v3v3(d3, v3, v1);
01968     cross_v3_v3v3(cross, d2, d3);
01969 
01970     area= len_v3(cross);
01971     dot= dot_v3v3(d2, d3);
01972     len= len_v3(d2)*len_v3(d3);
01973 
01974     if(area == 0.0f)
01975         return 0.0f;
01976     else
01977         return (len - dot)/area;
01978 }
01979 
01980 void interp_weights_poly_v3(float *w, float v[][3], const int n, const float co[3])
01981 {
01982     float totweight, t1, t2, len, *vmid, *vprev, *vnext;
01983     int i;
01984 
01985     totweight= 0.0f;
01986 
01987     for(i=0; i<n; i++) {
01988         vmid= v[i];
01989         vprev= (i == 0)? v[n-1]: v[i-1];
01990         vnext= (i == n-1)? v[0]: v[i+1];
01991 
01992         t1= mean_value_half_tan(co, vprev, vmid);
01993         t2= mean_value_half_tan(co, vmid, vnext);
01994 
01995         len= len_v3v3(co, vmid);
01996         w[i]= (t1+t2)/len;
01997         totweight += w[i];
01998     }
01999 
02000     if(totweight != 0.0f)
02001         for(i=0; i<n; i++)
02002             w[i] /= totweight;
02003 }
02004 
02005 /* (x1,v1)(t1=0)------(x2,v2)(t2=1), 0<t<1 --> (x,v)(t) */
02006 void interp_cubic_v3(float x[3], float v[3], const float x1[3], const float v1[3], const float x2[3], const float v2[3], const float t)
02007 {
02008     float a[3],b[3];
02009     float t2= t*t;
02010     float t3= t2*t;
02011 
02012     /* cubic interpolation */
02013     a[0]= v1[0] + v2[0] + 2*(x1[0] - x2[0]);
02014     a[1]= v1[1] + v2[1] + 2*(x1[1] - x2[1]);
02015     a[2]= v1[2] + v2[2] + 2*(x1[2] - x2[2]);
02016 
02017     b[0]= -2*v1[0] - v2[0] - 3*(x1[0] - x2[0]);
02018     b[1]= -2*v1[1] - v2[1] - 3*(x1[1] - x2[1]);
02019     b[2]= -2*v1[2] - v2[2] - 3*(x1[2] - x2[2]);
02020 
02021     x[0]= a[0]*t3 + b[0]*t2 + v1[0]*t + x1[0];
02022     x[1]= a[1]*t3 + b[1]*t2 + v1[1]*t + x1[1];
02023     x[2]= a[2]*t3 + b[2]*t2 + v1[2]*t + x1[2];
02024 
02025     v[0]= 3*a[0]*t2 + 2*b[0]*t + v1[0];
02026     v[1]= 3*a[1]*t2 + 2*b[1]*t + v1[1];
02027     v[2]= 3*a[2]*t2 + 2*b[2]*t + v1[2];
02028 }
02029 
02030 /* unfortunately internal calculations have to be done at double precision to achieve correct/stable results. */
02031 
02032 #define IS_ZERO(x) ((x>(-DBL_EPSILON) && x<DBL_EPSILON) ? 1 : 0)
02033 
02034 /* Barycentric reverse  */
02035 void resolve_tri_uv(float r_uv[2], const float st[2], const float st0[2], const float st1[2], const float st2[2])
02036 {
02037     /* find UV such that
02038        t= u*t0 + v*t1 + (1-u-v)*t2
02039        u*(t0-t2) + v*(t1-t2)= t-t2 */
02040     const double a= st0[0]-st2[0], b= st1[0]-st2[0];
02041     const double c= st0[1]-st2[1], d= st1[1]-st2[1];
02042     const double det= a*d - c*b;
02043 
02044     if(IS_ZERO(det)==0) {  /* det should never be zero since the determinant is the signed ST area of the triangle. */
02045         const double x[]= {st[0]-st2[0], st[1]-st2[1]};
02046 
02047         r_uv[0]= (float)((d*x[0] - b*x[1])/det);
02048         r_uv[1]= (float)(((-c)*x[0] + a*x[1])/det);
02049     } else zero_v2(r_uv);
02050 }
02051 
02052 /* bilinear reverse */
02053 void resolve_quad_uv(float r_uv[2], const float st[2], const float st0[2], const float st1[2], const float st2[2], const float st3[2])
02054 {
02055     const double signed_area= (st0[0]*st1[1] - st0[1]*st1[0]) + (st1[0]*st2[1] - st1[1]*st2[0]) +
02056                               (st2[0]*st3[1] - st2[1]*st3[0]) + (st3[0]*st0[1] - st3[1]*st0[0]);
02057 
02058     /* X is 2D cross product (determinant)
02059        A= (p0-p) X (p0-p3)*/
02060     const double a= (st0[0]-st[0])*(st0[1]-st3[1]) - (st0[1]-st[1])*(st0[0]-st3[0]);
02061 
02062     /* B= ( (p0-p) X (p1-p2) + (p1-p) X (p0-p3) ) / 2 */
02063     const double b= 0.5 * ( ((st0[0]-st[0])*(st1[1]-st2[1]) - (st0[1]-st[1])*(st1[0]-st2[0])) +
02064                              ((st1[0]-st[0])*(st0[1]-st3[1]) - (st1[1]-st[1])*(st0[0]-st3[0])) );
02065 
02066     /* C = (p1-p) X (p1-p2) */
02067     const double fC= (st1[0]-st[0])*(st1[1]-st2[1]) - (st1[1]-st[1])*(st1[0]-st2[0]);
02068     const double denom= a - 2*b + fC;
02069 
02070     // clear outputs
02071     zero_v2(r_uv);
02072 
02073     if(IS_ZERO(denom)!=0) {
02074         const double fDen= a-fC;
02075         if(IS_ZERO(fDen)==0)
02076             r_uv[0]= (float)(a / fDen);
02077     } else {
02078         const double desc_sq= b*b - a*fC;
02079         const double desc= sqrt(desc_sq<0.0?0.0:desc_sq);
02080         const double s= signed_area>0 ? (-1.0) : 1.0;
02081 
02082         r_uv[0]= (float)(( (a-b) + s * desc ) / denom);
02083     }
02084 
02085     /* find UV such that
02086       fST = (1-u)(1-v)*ST0 + u*(1-v)*ST1 + u*v*ST2 + (1-u)*v*ST3 */
02087     {
02088         const double denom_s= (1-r_uv[0])*(st0[0]-st3[0]) + r_uv[0]*(st1[0]-st2[0]);
02089         const double denom_t= (1-r_uv[0])*(st0[1]-st3[1]) + r_uv[0]*(st1[1]-st2[1]);
02090         int i= 0; double denom= denom_s;
02091 
02092         if(fabs(denom_s)<fabs(denom_t)) {
02093             i= 1;
02094             denom=denom_t;
02095         }
02096 
02097         if(IS_ZERO(denom)==0)
02098             r_uv[1]= (float) (( (1.0f-r_uv[0])*(st0[i]-st[i]) + r_uv[0]*(st1[i]-st[i]) ) / denom);
02099     }
02100 }
02101 
02102 #undef IS_ZERO
02103 
02104 /***************************** View & Projection *****************************/
02105 
02106 void orthographic_m4(float matrix[][4], const float left, const float right, const float bottom, const float top, const float nearClip, const float farClip)
02107 {
02108     float Xdelta, Ydelta, Zdelta;
02109  
02110     Xdelta = right - left;
02111     Ydelta = top - bottom;
02112     Zdelta = farClip - nearClip;
02113     if (Xdelta == 0.0f || Ydelta == 0.0f || Zdelta == 0.0f) {
02114         return;
02115     }
02116     unit_m4(matrix);
02117     matrix[0][0] = 2.0f/Xdelta;
02118     matrix[3][0] = -(right + left)/Xdelta;
02119     matrix[1][1] = 2.0f/Ydelta;
02120     matrix[3][1] = -(top + bottom)/Ydelta;
02121     matrix[2][2] = -2.0f/Zdelta;        /* note: negate Z   */
02122     matrix[3][2] = -(farClip + nearClip)/Zdelta;
02123 }
02124 
02125 void perspective_m4(float mat[4][4], const float left, const float right, const float bottom, const float top, const float nearClip, const float farClip)
02126 {
02127     float Xdelta, Ydelta, Zdelta;
02128 
02129     Xdelta = right - left;
02130     Ydelta = top - bottom;
02131     Zdelta = farClip - nearClip;
02132 
02133     if (Xdelta == 0.0f || Ydelta == 0.0f || Zdelta == 0.0f) {
02134         return;
02135     }
02136     mat[0][0] = nearClip * 2.0f/Xdelta;
02137     mat[1][1] = nearClip * 2.0f/Ydelta;
02138     mat[2][0] = (right + left)/Xdelta;      /* note: negate Z   */
02139     mat[2][1] = (top + bottom)/Ydelta;
02140     mat[2][2] = -(farClip + nearClip)/Zdelta;
02141     mat[2][3] = -1.0f;
02142     mat[3][2] = (-2.0f * nearClip * farClip)/Zdelta;
02143     mat[0][1] = mat[0][2] = mat[0][3] =
02144         mat[1][0] = mat[1][2] = mat[1][3] =
02145         mat[3][0] = mat[3][1] = mat[3][3] = 0.0;
02146 
02147 }
02148 
02149 /* translate a matrix created by orthographic_m4 or perspective_m4 in XY coords (used to jitter the view) */
02150 void window_translate_m4(float winmat[][4], float perspmat[][4], const float x, const float y)
02151 {
02152     if(winmat[2][3] == -1.0f) {
02153         /* in the case of a win-matrix, this means perspective always */
02154         float v1[3];
02155         float v2[3];
02156         float len1, len2;
02157 
02158         v1[0]= perspmat[0][0];
02159         v1[1]= perspmat[1][0];
02160         v1[2]= perspmat[2][0];
02161 
02162         v2[0]= perspmat[0][1];
02163         v2[1]= perspmat[1][1];
02164         v2[2]= perspmat[2][1];
02165 
02166         len1= (1.0f / len_v3(v1));
02167         len2= (1.0f / len_v3(v2));
02168 
02169         winmat[2][0] += len1 * winmat[0][0] * x;
02170         winmat[2][1] += len2 * winmat[1][1] * y;
02171     }
02172     else {
02173         winmat[3][0] += x;
02174         winmat[3][1] += y;
02175     }
02176 }
02177 
02178 static void i_multmatrix(float icand[][4], float Vm[][4])
02179 {
02180     int row, col;
02181     float temp[4][4];
02182 
02183     for(row=0 ; row<4 ; row++) 
02184         for(col=0 ; col<4 ; col++)
02185             temp[row][col] = icand[row][0] * Vm[0][col]
02186                            + icand[row][1] * Vm[1][col]
02187                            + icand[row][2] * Vm[2][col]
02188                            + icand[row][3] * Vm[3][col];
02189     copy_m4_m4(Vm, temp);
02190 }
02191 
02192 
02193 void polarview_m4(float Vm[][4],float dist, float azimuth, float incidence, float twist)
02194 {
02195 
02196     unit_m4(Vm);
02197 
02198     translate_m4(Vm,0.0, 0.0, -dist);
02199     rotate_m4(Vm,'Z',-twist);
02200     rotate_m4(Vm,'X',-incidence);
02201     rotate_m4(Vm,'Z',-azimuth);
02202 }
02203 
02204 void lookat_m4(float mat[][4],float vx, float vy, float vz, float px, float py, float pz, float twist)
02205 {
02206     float sine, cosine, hyp, hyp1, dx, dy, dz;
02207     float mat1[4][4]= MAT4_UNITY;
02208     
02209     unit_m4(mat);
02210 
02211     rotate_m4(mat, 'Z', -twist);
02212 
02213     dx = px - vx;
02214     dy = py - vy;
02215     dz = pz - vz;
02216     hyp = dx * dx + dz * dz;    /* hyp squared  */
02217     hyp1 = (float)sqrt(dy*dy + hyp);
02218     hyp = (float)sqrt(hyp);     /* the real hyp */
02219     
02220     if (hyp1 != 0.0f) {     /* rotate X */
02221         sine = -dy / hyp1;
02222         cosine = hyp /hyp1;
02223     } else {
02224         sine = 0;
02225         cosine = 1.0f;
02226     }
02227     mat1[1][1] = cosine;
02228     mat1[1][2] = sine;
02229     mat1[2][1] = -sine;
02230     mat1[2][2] = cosine;
02231     
02232     i_multmatrix(mat1, mat);
02233 
02234     mat1[1][1] = mat1[2][2] = 1.0f; /* be careful here to reinit    */
02235     mat1[1][2] = mat1[2][1] = 0.0;  /* those modified by the last   */
02236     
02237     /* paragraph    */
02238     if (hyp != 0.0f) {          /* rotate Y */
02239         sine = dx / hyp;
02240         cosine = -dz / hyp;
02241     } else {
02242         sine = 0;
02243         cosine = 1.0f;
02244     }
02245     mat1[0][0] = cosine;
02246     mat1[0][2] = -sine;
02247     mat1[2][0] = sine;
02248     mat1[2][2] = cosine;
02249     
02250     i_multmatrix(mat1, mat);
02251     translate_m4(mat,-vx,-vy,-vz);  /* translate viewpoint to origin */
02252 }
02253 
02254 int box_clip_bounds_m4(float boundbox[2][3], const float bounds[4], float winmat[4][4])
02255 {
02256     float mat[4][4], vec[4];
02257     int a, fl, flag= -1;
02258 
02259     copy_m4_m4(mat, winmat);
02260 
02261     for(a=0; a<8; a++) {
02262         vec[0]= (a & 1)? boundbox[0][0]: boundbox[1][0];
02263         vec[1]= (a & 2)? boundbox[0][1]: boundbox[1][1];
02264         vec[2]= (a & 4)? boundbox[0][2]: boundbox[1][2];
02265         vec[3]= 1.0;
02266         mul_m4_v4(mat, vec);
02267 
02268         fl= 0;
02269         if(bounds) {
02270             if(vec[0] > bounds[1]*vec[3]) fl |= 1;
02271             if(vec[0]< bounds[0]*vec[3]) fl |= 2;
02272             if(vec[1] > bounds[3]*vec[3]) fl |= 4;
02273             if(vec[1]< bounds[2]*vec[3]) fl |= 8;
02274         }
02275         else {
02276             if(vec[0] < -vec[3]) fl |= 1;
02277             if(vec[0] > vec[3]) fl |= 2;
02278             if(vec[1] < -vec[3]) fl |= 4;
02279             if(vec[1] > vec[3]) fl |= 8;
02280         }
02281         if(vec[2] < -vec[3]) fl |= 16;
02282         if(vec[2] > vec[3]) fl |= 32;
02283 
02284         flag &= fl;
02285         if(flag==0) return 0;
02286     }
02287 
02288     return flag;
02289 }
02290 
02291 void box_minmax_bounds_m4(float min[3], float max[3], float boundbox[2][3], float mat[4][4])
02292 {
02293     float mn[3], mx[3], vec[3];
02294     int a;
02295 
02296     copy_v3_v3(mn, min);
02297     copy_v3_v3(mx, max);
02298 
02299     for(a=0; a<8; a++) {
02300         vec[0]= (a & 1)? boundbox[0][0]: boundbox[1][0];
02301         vec[1]= (a & 2)? boundbox[0][1]: boundbox[1][1];
02302         vec[2]= (a & 4)? boundbox[0][2]: boundbox[1][2];
02303 
02304         mul_m4_v3(mat, vec);
02305         DO_MINMAX(vec, mn, mx);
02306     }
02307 
02308     copy_v3_v3(min, mn);
02309     copy_v3_v3(max, mx);
02310 }
02311 
02312 /********************************** Mapping **********************************/
02313 
02314 void map_to_tube(float *u, float *v, const float x, const float y, const float z)
02315 {
02316     float len;
02317     
02318     *v = (z + 1.0f) / 2.0f;
02319     
02320     len= (float)sqrt(x*x+y*y);
02321     if(len > 0.0f)
02322         *u = (float)((1.0 - (atan2(x/len,y/len) / M_PI)) / 2.0);
02323     else
02324         *v = *u = 0.0f; /* to avoid un-initialized variables */
02325 }
02326 
02327 void map_to_sphere(float *u, float *v, const float x, const float y, const float z)
02328 {
02329     float len;
02330     
02331     len= (float)sqrt(x*x+y*y+z*z);
02332     if(len > 0.0f) {
02333         if(x==0.0f && y==0.0f) *u= 0.0f;    /* othwise domain error */
02334         else *u = (1.0f - atan2f(x,y) / (float)M_PI) / 2.0f;
02335 
02336         *v = 1.0f - (float)saacos(z/len)/(float)M_PI;
02337     } else {
02338         *v = *u = 0.0f; /* to avoid un-initialized variables */
02339     }
02340 }
02341 
02342 /********************************* Normals **********************************/
02343 
02344 void accumulate_vertex_normals(float n1[3], float n2[3], float n3[3],
02345     float n4[3], const float f_no[3], const float co1[3], const float co2[3],
02346     const float co3[3], const float co4[3])
02347 {
02348     float vdiffs[4][3];
02349     const int nverts= (n4!=NULL && co4!=NULL)? 4: 3;
02350 
02351     /* compute normalized edge vectors */
02352     sub_v3_v3v3(vdiffs[0], co2, co1);
02353     sub_v3_v3v3(vdiffs[1], co3, co2);
02354 
02355     if(nverts==3) {
02356         sub_v3_v3v3(vdiffs[2], co1, co3);
02357     }
02358     else {
02359         sub_v3_v3v3(vdiffs[2], co4, co3);
02360         sub_v3_v3v3(vdiffs[3], co1, co4);
02361         normalize_v3(vdiffs[3]);
02362     }
02363 
02364     normalize_v3(vdiffs[0]);
02365     normalize_v3(vdiffs[1]);
02366     normalize_v3(vdiffs[2]);
02367 
02368     /* accumulate angle weighted face normal */
02369     {
02370         float *vn[]= {n1, n2, n3, n4};
02371         const float *prev_edge = vdiffs[nverts-1];
02372         int i;
02373 
02374         for(i=0; i<nverts; i++) {
02375             const float *cur_edge= vdiffs[i];
02376             const float fac= saacos(-dot_v3v3(cur_edge, prev_edge));
02377 
02378             // accumulate
02379             madd_v3_v3fl(vn[i], f_no, fac);
02380             prev_edge = cur_edge;
02381         }
02382     }
02383 }
02384 
02385 /********************************* Tangents **********************************/
02386 
02387 /* For normal map tangents we need to detect uv boundaries, and only average
02388  * tangents in case the uvs are connected. Alternative would be to store 1 
02389  * tangent per face rather than 4 per face vertex, but that's not compatible
02390  * with games */
02391 
02392 
02393 /* from BKE_mesh.h */
02394 #define STD_UV_CONNECT_LIMIT    0.0001f
02395 
02396 void sum_or_add_vertex_tangent(void *arena, VertexTangent **vtang, const float tang[3], const float uv[2])
02397 {
02398     VertexTangent *vt;
02399 
02400     /* find a tangent with connected uvs */
02401     for(vt= *vtang; vt; vt=vt->next) {
02402         if(fabsf(uv[0]-vt->uv[0]) < STD_UV_CONNECT_LIMIT && fabsf(uv[1]-vt->uv[1]) < STD_UV_CONNECT_LIMIT) {
02403             add_v3_v3(vt->tang, tang);
02404             return;
02405         }
02406     }
02407 
02408     /* if not found, append a new one */
02409     vt= BLI_memarena_alloc((MemArena *)arena, sizeof(VertexTangent));
02410     copy_v3_v3(vt->tang, tang);
02411     vt->uv[0]= uv[0];
02412     vt->uv[1]= uv[1];
02413 
02414     if(*vtang)
02415         vt->next= *vtang;
02416     *vtang= vt;
02417 }
02418 
02419 float *find_vertex_tangent(VertexTangent *vtang, const float uv[2])
02420 {
02421     VertexTangent *vt;
02422     static float nulltang[3] = {0.0f, 0.0f, 0.0f};
02423 
02424     for(vt= vtang; vt; vt=vt->next)
02425         if(fabsf(uv[0]-vt->uv[0]) < STD_UV_CONNECT_LIMIT && fabsf(uv[1]-vt->uv[1]) < STD_UV_CONNECT_LIMIT)
02426             return vt->tang;
02427 
02428     return nulltang;    /* shouldn't happen, except for nan or so */
02429 }
02430 
02431 void tangent_from_uv(float uv1[2], float uv2[2], float uv3[3], float co1[3], float co2[3], float co3[3], float n[3], float tang[3])
02432 {
02433     float s1= uv2[0] - uv1[0];
02434     float s2= uv3[0] - uv1[0];
02435     float t1= uv2[1] - uv1[1];
02436     float t2= uv3[1] - uv1[1];
02437     float det= (s1 * t2 - s2 * t1);
02438 
02439     if(det != 0.0f) { /* otherwise 'tang' becomes nan */
02440         float tangv[3], ct[3], e1[3], e2[3];
02441 
02442         det= 1.0f/det;
02443 
02444         /* normals in render are inversed... */
02445         sub_v3_v3v3(e1, co1, co2);
02446         sub_v3_v3v3(e2, co1, co3);
02447         tang[0] = (t2*e1[0] - t1*e2[0])*det;
02448         tang[1] = (t2*e1[1] - t1*e2[1])*det;
02449         tang[2] = (t2*e1[2] - t1*e2[2])*det;
02450         tangv[0] = (s1*e2[0] - s2*e1[0])*det;
02451         tangv[1] = (s1*e2[1] - s2*e1[1])*det;
02452         tangv[2] = (s1*e2[2] - s2*e1[2])*det;
02453         cross_v3_v3v3(ct, tang, tangv);
02454     
02455         /* check flip */
02456         if ((ct[0]*n[0] + ct[1]*n[1] + ct[2]*n[2]) < 0.0f)
02457             negate_v3(tang);
02458     }
02459     else {
02460         tang[0]= tang[1]= tang[2]=  0.0;
02461     }
02462 }
02463 
02464 /****************************** Vector Clouds ********************************/
02465 
02466 /* vector clouds */
02467 /* void vcloud_estimate_transform(int list_size, float (*pos)[3], float *weight,float (*rpos)[3], float *rweight,
02468                                  float lloc[3],float rloc[3],float lrot[3][3],float lscale[3][3])
02469 
02470 input
02471 (
02472 int list_size
02473 4 lists as pointer to array[list_size]
02474 1. current pos array of 'new' positions 
02475 2. current weight array of 'new'weights (may be NULL pointer if you have no weights )
02476 3. reference rpos array of 'old' positions
02477 4. reference rweight array of 'old'weights (may be NULL pointer if you have no weights )
02478 )
02479 output  
02480 (
02481 float lloc[3] center of mass pos
02482 float rloc[3] center of mass rpos
02483 float lrot[3][3] rotation matrix
02484 float lscale[3][3] scale matrix
02485 pointers may be NULL if not needed
02486 )
02487 
02488 */
02489 /* can't believe there is none in math utils */
02490 static float _det_m3(float m2[3][3])
02491 {
02492     float det = 0.f;
02493     if (m2){
02494     det= m2[0][0]* (m2[1][1]*m2[2][2] - m2[1][2]*m2[2][1])
02495         -m2[1][0]* (m2[0][1]*m2[2][2] - m2[0][2]*m2[2][1])
02496         +m2[2][0]* (m2[0][1]*m2[1][2] - m2[0][2]*m2[1][1]);
02497     }
02498     return det;
02499 }
02500 
02501 
02502 void vcloud_estimate_transform(int list_size, float (*pos)[3], float *weight,float (*rpos)[3], float *rweight,
02503                             float lloc[3],float rloc[3],float lrot[3][3],float lscale[3][3])
02504 {
02505     float accu_com[3]= {0.0f,0.0f,0.0f}, accu_rcom[3]= {0.0f,0.0f,0.0f};
02506     float accu_weight = 0.0f,accu_rweight = 0.0f,eps = 0.000001f;
02507 
02508     int a;
02509     /* first set up a nice default response */
02510     if (lloc) zero_v3(lloc);
02511     if (rloc) zero_v3(rloc);
02512     if (lrot) unit_m3(lrot);
02513     if (lscale) unit_m3(lscale);
02514     /* do com for both clouds */
02515     if (pos && rpos && (list_size > 0)) /* paranoya check */
02516     {
02517         /* do com for both clouds */
02518         for(a=0; a<list_size; a++){
02519             if (weight){
02520                 float v[3];
02521                 copy_v3_v3(v,pos[a]);
02522                 mul_v3_fl(v,weight[a]);
02523                 add_v3_v3(accu_com, v);
02524                 accu_weight +=weight[a]; 
02525             }
02526             else add_v3_v3(accu_com, pos[a]);
02527 
02528             if (rweight){
02529                 float v[3];
02530                 copy_v3_v3(v,rpos[a]);
02531                 mul_v3_fl(v,rweight[a]);
02532                 add_v3_v3(accu_rcom, v);
02533                 accu_rweight +=rweight[a]; 
02534             }
02535             else add_v3_v3(accu_rcom, rpos[a]);
02536 
02537         }
02538         if (!weight || !rweight){
02539             accu_weight = accu_rweight = list_size;
02540         }
02541 
02542         mul_v3_fl(accu_com,1.0f/accu_weight);
02543         mul_v3_fl(accu_rcom,1.0f/accu_rweight);
02544         if (lloc) copy_v3_v3(lloc,accu_com);
02545         if (rloc) copy_v3_v3(rloc,accu_rcom);
02546         if (lrot || lscale){ /* caller does not want rot nor scale, strange but legal */
02547             /*so now do some reverse engeneering and see if we can split rotation from scale ->Polardecompose*/
02548             /* build 'projection' matrix */
02549             float m[3][3],mr[3][3],q[3][3],qi[3][3];
02550             float va[3],vb[3],stunt[3];
02551             float odet,ndet;
02552             int i=0,imax=15;
02553             zero_m3(m);
02554             zero_m3(mr);
02555 
02556             /* build 'projection' matrix */
02557             for(a=0; a<list_size; a++){
02558                 sub_v3_v3v3(va,rpos[a],accu_rcom);
02559                 /* mul_v3_fl(va,bp->mass);  mass needs renormalzation here ?? */
02560                 sub_v3_v3v3(vb,pos[a],accu_com);
02561                 /* mul_v3_fl(va,rp->mass); */
02562                 m[0][0] += va[0] * vb[0];
02563                 m[0][1] += va[0] * vb[1];
02564                 m[0][2] += va[0] * vb[2];
02565 
02566                 m[1][0] += va[1] * vb[0];
02567                 m[1][1] += va[1] * vb[1];
02568                 m[1][2] += va[1] * vb[2];
02569 
02570                 m[2][0] += va[2] * vb[0];
02571                 m[2][1] += va[2] * vb[1];
02572                 m[2][2] += va[2] * vb[2];
02573 
02574                 /* building the referenc matrix on the fly
02575                 needed to scale properly later*/
02576 
02577                 mr[0][0] += va[0] * va[0];
02578                 mr[0][1] += va[0] * va[1];
02579                 mr[0][2] += va[0] * va[2];
02580 
02581                 mr[1][0] += va[1] * va[0];
02582                 mr[1][1] += va[1] * va[1];
02583                 mr[1][2] += va[1] * va[2];
02584 
02585                 mr[2][0] += va[2] * va[0];
02586                 mr[2][1] += va[2] * va[1];
02587                 mr[2][2] += va[2] * va[2];
02588             }
02589             copy_m3_m3(q,m);
02590             stunt[0] = q[0][0]; stunt[1] = q[1][1]; stunt[2] = q[2][2];
02591             /* renormalizing for numeric stability */
02592             mul_m3_fl(q,1.f/len_v3(stunt)); 
02593 
02594             /* this is pretty much Polardecompose 'inline' the algo based on Higham's thesis */
02595             /* without the far case ... but seems to work here pretty neat                   */
02596             odet = 0.f;
02597             ndet = _det_m3(q);
02598             while((odet-ndet)*(odet-ndet) > eps && i<imax){
02599                 invert_m3_m3(qi,q);
02600                 transpose_m3(qi);
02601                 add_m3_m3m3(q,q,qi);
02602                 mul_m3_fl(q,0.5f);
02603                 odet =ndet;
02604                 ndet =_det_m3(q);
02605                 i++;
02606             }
02607 
02608             if (i){
02609                 float scale[3][3];
02610                 float irot[3][3];
02611                 if(lrot) copy_m3_m3(lrot,q);
02612                 invert_m3_m3(irot,q);
02613                 invert_m3_m3(qi,mr);
02614                 mul_m3_m3m3(q,m,qi); 
02615                 mul_m3_m3m3(scale,irot,q); 
02616                 if(lscale) copy_m3_m3(lscale,scale);
02617 
02618             }
02619         }
02620     }
02621 }
02622 
02623 /******************************* Form Factor *********************************/
02624 
02625 static void vec_add_dir(float r[3], const float v1[3], const float v2[3], const float fac)
02626 {
02627     r[0]= v1[0] + fac*(v2[0] - v1[0]);
02628     r[1]= v1[1] + fac*(v2[1] - v1[1]);
02629     r[2]= v1[2] + fac*(v2[2] - v1[2]);
02630 }
02631 
02632 static int ff_visible_quad(const float p[3], const float n[3], const float v0[3], const float v1[3], const float v2[3], float q0[3], float q1[3], float q2[3], float q3[3])
02633 {
02634     static const float epsilon = 1e-6f;
02635     float c, sd[3];
02636     
02637     c= dot_v3v3(n, p);
02638 
02639     /* signed distances from the vertices to the plane. */
02640     sd[0]= dot_v3v3(n, v0) - c;
02641     sd[1]= dot_v3v3(n, v1) - c;
02642     sd[2]= dot_v3v3(n, v2) - c;
02643 
02644     if(fabsf(sd[0]) < epsilon) sd[0] = 0.0f;
02645     if(fabsf(sd[1]) < epsilon) sd[1] = 0.0f;
02646     if(fabsf(sd[2]) < epsilon) sd[2] = 0.0f;
02647 
02648     if(sd[0] > 0) {
02649         if(sd[1] > 0) {
02650             if(sd[2] > 0) {
02651                 // +++
02652                 copy_v3_v3(q0, v0);
02653                 copy_v3_v3(q1, v1);
02654                 copy_v3_v3(q2, v2);
02655                 copy_v3_v3(q3, q2);
02656             }
02657             else if(sd[2] < 0) {
02658                 // ++-
02659                 copy_v3_v3(q0, v0);
02660                 copy_v3_v3(q1, v1);
02661                 vec_add_dir(q2, v1, v2, (sd[1]/(sd[1]-sd[2])));
02662                 vec_add_dir(q3, v0, v2, (sd[0]/(sd[0]-sd[2])));
02663             }
02664             else {
02665                 // ++0
02666                 copy_v3_v3(q0, v0);
02667                 copy_v3_v3(q1, v1);
02668                 copy_v3_v3(q2, v2);
02669                 copy_v3_v3(q3, q2);
02670             }
02671         }
02672         else if(sd[1] < 0) {
02673             if(sd[2] > 0) {
02674                 // +-+
02675                 copy_v3_v3(q0, v0);
02676                 vec_add_dir(q1, v0, v1, (sd[0]/(sd[0]-sd[1])));
02677                 vec_add_dir(q2, v1, v2, (sd[1]/(sd[1]-sd[2])));
02678                 copy_v3_v3(q3, v2);
02679             }
02680             else if(sd[2] < 0) {
02681                 // +--
02682                 copy_v3_v3(q0, v0);
02683                 vec_add_dir(q1, v0, v1, (sd[0]/(sd[0]-sd[1])));
02684                 vec_add_dir(q2, v0, v2, (sd[0]/(sd[0]-sd[2])));
02685                 copy_v3_v3(q3, q2);
02686             }
02687             else {
02688                 // +-0
02689                 copy_v3_v3(q0, v0);
02690                 vec_add_dir(q1, v0, v1, (sd[0]/(sd[0]-sd[1])));
02691                 copy_v3_v3(q2, v2);
02692                 copy_v3_v3(q3, q2);
02693             }
02694         }
02695         else {
02696             if(sd[2] > 0) {
02697                 // +0+
02698                 copy_v3_v3(q0, v0);
02699                 copy_v3_v3(q1, v1);
02700                 copy_v3_v3(q2, v2);
02701                 copy_v3_v3(q3, q2);
02702             }
02703             else if(sd[2] < 0) {
02704                 // +0-
02705                 copy_v3_v3(q0, v0);
02706                 copy_v3_v3(q1, v1);
02707                 vec_add_dir(q2, v0, v2, (sd[0]/(sd[0]-sd[2])));
02708                 copy_v3_v3(q3, q2);
02709             }
02710             else {
02711                 // +00
02712                 copy_v3_v3(q0, v0);
02713                 copy_v3_v3(q1, v1);
02714                 copy_v3_v3(q2, v2);
02715                 copy_v3_v3(q3, q2);
02716             }
02717         }
02718     }
02719     else if(sd[0] < 0) {
02720         if(sd[1] > 0) {
02721             if(sd[2] > 0) {
02722                 // -++
02723                 vec_add_dir(q0, v0, v1, (sd[0]/(sd[0]-sd[1])));
02724                 copy_v3_v3(q1, v1);
02725                 copy_v3_v3(q2, v2);
02726                 vec_add_dir(q3, v0, v2, (sd[0]/(sd[0]-sd[2])));
02727             }
02728             else if(sd[2] < 0) {
02729                 // -+-
02730                 vec_add_dir(q0, v0, v1, (sd[0]/(sd[0]-sd[1])));
02731                 copy_v3_v3(q1, v1);
02732                 vec_add_dir(q2, v1, v2, (sd[1]/(sd[1]-sd[2])));
02733                 copy_v3_v3(q3, q2);
02734             }
02735             else {
02736                 // -+0
02737                 vec_add_dir(q0, v0, v1, (sd[0]/(sd[0]-sd[1])));
02738                 copy_v3_v3(q1, v1);
02739                 copy_v3_v3(q2, v2);
02740                 copy_v3_v3(q3, q2);
02741             }
02742         }
02743         else if(sd[1] < 0) {
02744             if(sd[2] > 0) {
02745                 // --+
02746                 vec_add_dir(q0, v0, v2, (sd[0]/(sd[0]-sd[2])));
02747                 vec_add_dir(q1, v1, v2, (sd[1]/(sd[1]-sd[2])));
02748                 copy_v3_v3(q2, v2);
02749                 copy_v3_v3(q3, q2);
02750             }
02751             else if(sd[2] < 0) {
02752                 // ---
02753                 return 0;
02754             }
02755             else {
02756                 // --0
02757                 return 0;
02758             }
02759         }
02760         else {
02761             if(sd[2] > 0) {
02762                 // -0+
02763                 vec_add_dir(q0, v0, v2, (sd[0]/(sd[0]-sd[2])));
02764                 copy_v3_v3(q1, v1);
02765                 copy_v3_v3(q2, v2);
02766                 copy_v3_v3(q3, q2);
02767             }
02768             else if(sd[2] < 0) {
02769                 // -0-
02770                 return 0;
02771             }
02772             else {
02773                 // -00
02774                 return 0;
02775             }
02776         }
02777     }
02778     else {
02779         if(sd[1] > 0) {
02780             if(sd[2] > 0) {
02781                 // 0++
02782                 copy_v3_v3(q0, v0);
02783                 copy_v3_v3(q1, v1);
02784                 copy_v3_v3(q2, v2);
02785                 copy_v3_v3(q3, q2);
02786             }
02787             else if(sd[2] < 0) {
02788                 // 0+-
02789                 copy_v3_v3(q0, v0);
02790                 copy_v3_v3(q1, v1);
02791                 vec_add_dir(q2, v1, v2, (sd[1]/(sd[1]-sd[2])));
02792                 copy_v3_v3(q3, q2);
02793             }
02794             else {
02795                 // 0+0
02796                 copy_v3_v3(q0, v0);
02797                 copy_v3_v3(q1, v1);
02798                 copy_v3_v3(q2, v2);
02799                 copy_v3_v3(q3, q2);
02800             }
02801         }
02802         else if(sd[1] < 0) {
02803             if(sd[2] > 0) {
02804                 // 0-+
02805                 copy_v3_v3(q0, v0);
02806                 vec_add_dir(q1, v1, v2, (sd[1]/(sd[1]-sd[2])));
02807                 copy_v3_v3(q2, v2);
02808                 copy_v3_v3(q3, q2);
02809             }
02810             else if(sd[2] < 0) {
02811                 // 0--
02812                 return 0;
02813             }
02814             else {
02815                 // 0-0
02816                 return 0;
02817             }
02818         }
02819         else {
02820             if(sd[2] > 0) {
02821                 // 00+
02822                 copy_v3_v3(q0, v0);
02823                 copy_v3_v3(q1, v1);
02824                 copy_v3_v3(q2, v2);
02825                 copy_v3_v3(q3, q2);
02826             }
02827             else if(sd[2] < 0) {
02828                 // 00-
02829                 return 0;
02830             }
02831             else {
02832                 // 000
02833                 return 0;
02834             }
02835         }
02836     }
02837 
02838     return 1;
02839 }
02840 
02841 /* altivec optimization, this works, but is unused */
02842 
02843 #if 0
02844 #include <Accelerate/Accelerate.h>
02845 
02846 typedef union {
02847     vFloat v;
02848     float f[4];
02849 } vFloatResult;
02850 
02851 static vFloat vec_splat_float(float val)
02852 {
02853     return (vFloat){val, val, val, val};
02854 }
02855 
02856 static float ff_quad_form_factor(float *p, float *n, float *q0, float *q1, float *q2, float *q3)
02857 {
02858     vFloat vcos, rlen, vrx, vry, vrz, vsrx, vsry, vsrz, gx, gy, gz, vangle;
02859     vUInt8 rotate = (vUInt8){4,5,6,7,8,9,10,11,12,13,14,15,0,1,2,3};
02860     vFloatResult vresult;
02861     float result;
02862 
02863     /* compute r* */
02864     vrx = (vFloat){q0[0], q1[0], q2[0], q3[0]} - vec_splat_float(p[0]);
02865     vry = (vFloat){q0[1], q1[1], q2[1], q3[1]} - vec_splat_float(p[1]);
02866     vrz = (vFloat){q0[2], q1[2], q2[2], q3[2]} - vec_splat_float(p[2]);
02867 
02868     /* normalize r* */
02869     rlen = vec_rsqrte(vrx*vrx + vry*vry + vrz*vrz + vec_splat_float(1e-16f));
02870     vrx = vrx*rlen;
02871     vry = vry*rlen;
02872     vrz = vrz*rlen;
02873 
02874     /* rotate r* for cross and dot */
02875     vsrx= vec_perm(vrx, vrx, rotate);
02876     vsry= vec_perm(vry, vry, rotate);
02877     vsrz= vec_perm(vrz, vrz, rotate);
02878 
02879     /* cross product */
02880     gx = vsry*vrz - vsrz*vry;
02881     gy = vsrz*vrx - vsrx*vrz;
02882     gz = vsrx*vry - vsry*vrx;
02883 
02884     /* normalize */
02885     rlen = vec_rsqrte(gx*gx + gy*gy + gz*gz + vec_splat_float(1e-16f));
02886     gx = gx*rlen;
02887     gy = gy*rlen;
02888     gz = gz*rlen;
02889 
02890     /* angle */
02891     vcos = vrx*vsrx + vry*vsry + vrz*vsrz;
02892     vcos= vec_max(vec_min(vcos, vec_splat_float(1.0f)), vec_splat_float(-1.0f));
02893     vangle= vacosf(vcos);
02894 
02895     /* dot */
02896     vresult.v = (vec_splat_float(n[0])*gx +
02897                  vec_splat_float(n[1])*gy +
02898                  vec_splat_float(n[2])*gz)*vangle;
02899 
02900     result= (vresult.f[0] + vresult.f[1] + vresult.f[2] + vresult.f[3])*(0.5f/(float)M_PI);
02901     result= MAX2(result, 0.0f);
02902 
02903     return result;
02904 }
02905 
02906 #endif
02907 
02908 /* SSE optimization, acos code doesn't work */
02909 
02910 #if 0
02911 
02912 #include <xmmintrin.h>
02913 
02914 static __m128 sse_approx_acos(__m128 x)
02915 {
02916     /* needs a better approximation than taylor expansion of acos, since that
02917      * gives big erros for near 1.0 values, sqrt(2*x)*acos(1-x) should work
02918      * better, see http://www.tom.womack.net/projects/sse-fast-arctrig.html */
02919 
02920     return _mm_set_ps1(1.0f);
02921 }
02922 
02923 static float ff_quad_form_factor(float *p, float *n, float *q0, float *q1, float *q2, float *q3)
02924 {
02925     float r0[3], r1[3], r2[3], r3[3], g0[3], g1[3], g2[3], g3[3];
02926     float a1, a2, a3, a4, dot1, dot2, dot3, dot4, result;
02927     float fresult[4] __attribute__((aligned(16)));
02928     __m128 qx, qy, qz, rx, ry, rz, rlen, srx, sry, srz, gx, gy, gz, glen, rcos, angle, aresult;
02929 
02930     /* compute r */
02931     qx = _mm_set_ps(q3[0], q2[0], q1[0], q0[0]);
02932     qy = _mm_set_ps(q3[1], q2[1], q1[1], q0[1]);
02933     qz = _mm_set_ps(q3[2], q2[2], q1[2], q0[2]);
02934 
02935     rx = qx - _mm_set_ps1(p[0]);
02936     ry = qy - _mm_set_ps1(p[1]);
02937     rz = qz - _mm_set_ps1(p[2]);
02938 
02939     /* normalize r */
02940     rlen = _mm_rsqrt_ps(rx*rx + ry*ry + rz*rz + _mm_set_ps1(1e-16f));
02941     rx = rx*rlen;
02942     ry = ry*rlen;
02943     rz = rz*rlen;
02944 
02945     /* cross product */
02946     srx = _mm_shuffle_ps(rx, rx, _MM_SHUFFLE(0,3,2,1));
02947     sry = _mm_shuffle_ps(ry, ry, _MM_SHUFFLE(0,3,2,1));
02948     srz = _mm_shuffle_ps(rz, rz, _MM_SHUFFLE(0,3,2,1));
02949 
02950     gx = sry*rz - srz*ry;
02951     gy = srz*rx - srx*rz;
02952     gz = srx*ry - sry*rx;
02953 
02954     /* normalize g */
02955     glen = _mm_rsqrt_ps(gx*gx + gy*gy + gz*gz + _mm_set_ps1(1e-16f));
02956     gx = gx*glen;
02957     gy = gy*glen;
02958     gz = gz*glen;
02959 
02960     /* compute angle */
02961     rcos = rx*srx + ry*sry + rz*srz;
02962     rcos= _mm_max_ps(_mm_min_ps(rcos, _mm_set_ps1(1.0f)), _mm_set_ps1(-1.0f));
02963 
02964     angle = sse_approx_cos(rcos);
02965     aresult = (_mm_set_ps1(n[0])*gx + _mm_set_ps1(n[1])*gy + _mm_set_ps1(n[2])*gz)*angle;
02966 
02967     /* sum together */
02968     result= (fresult[0] + fresult[1] + fresult[2] + fresult[3])*(0.5f/(float)M_PI);
02969     result= MAX2(result, 0.0f);
02970 
02971     return result;
02972 }
02973 
02974 #endif
02975 
02976 static void ff_normalize(float n[3])
02977 {
02978     float d;
02979     
02980     d= dot_v3v3(n, n);
02981 
02982     if(d > 1.0e-35F) {
02983         d= 1.0f/sqrtf(d);
02984 
02985         n[0] *= d; 
02986         n[1] *= d; 
02987         n[2] *= d;
02988     } 
02989 }
02990 
02991 static float ff_quad_form_factor(const float p[3], const float n[3], const float q0[3], const float q1[3], const float q2[3], const float q3[3])
02992 {
02993     float r0[3], r1[3], r2[3], r3[3], g0[3], g1[3], g2[3], g3[3];
02994     float a1, a2, a3, a4, dot1, dot2, dot3, dot4, result;
02995 
02996     sub_v3_v3v3(r0, q0, p);
02997     sub_v3_v3v3(r1, q1, p);
02998     sub_v3_v3v3(r2, q2, p);
02999     sub_v3_v3v3(r3, q3, p);
03000 
03001     ff_normalize(r0);
03002     ff_normalize(r1);
03003     ff_normalize(r2);
03004     ff_normalize(r3);
03005 
03006     cross_v3_v3v3(g0, r1, r0); ff_normalize(g0);
03007     cross_v3_v3v3(g1, r2, r1); ff_normalize(g1);
03008     cross_v3_v3v3(g2, r3, r2); ff_normalize(g2);
03009     cross_v3_v3v3(g3, r0, r3); ff_normalize(g3);
03010 
03011     a1= saacosf(dot_v3v3(r0, r1));
03012     a2= saacosf(dot_v3v3(r1, r2));
03013     a3= saacosf(dot_v3v3(r2, r3));
03014     a4= saacosf(dot_v3v3(r3, r0));
03015 
03016     dot1= dot_v3v3(n, g0);
03017     dot2= dot_v3v3(n, g1);
03018     dot3= dot_v3v3(n, g2);
03019     dot4= dot_v3v3(n, g3);
03020 
03021     result= (a1*dot1 + a2*dot2 + a3*dot3 + a4*dot4)*0.5f/(float)M_PI;
03022     result= MAX2(result, 0.0f);
03023 
03024     return result;
03025 }
03026 
03027 float form_factor_hemi_poly(float p[3], float n[3], float v1[3], float v2[3], float v3[3], float v4[3])
03028 {
03029     /* computes how much hemisphere defined by point and normal is
03030        covered by a quad or triangle, cosine weighted */
03031     float q0[3], q1[3], q2[3], q3[3], contrib= 0.0f;
03032 
03033     if(ff_visible_quad(p, n, v1, v2, v3, q0, q1, q2, q3))
03034         contrib += ff_quad_form_factor(p, n, q0, q1, q2, q3);
03035     
03036     if(v4 && ff_visible_quad(p, n, v1, v3, v4, q0, q1, q2, q3))
03037         contrib += ff_quad_form_factor(p, n, q0, q1, q2, q3);
03038 
03039     return contrib;
03040 }