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