Back to index

radiance  4R0+20100331
tmesh.c
Go to the documentation of this file.
00001 #ifndef lint
00002 static const char RCSid[] = "$Id: tmesh.c,v 2.5 2006/03/02 17:16:56 greg Exp $";
00003 #endif
00004 /*
00005  * Compute and print barycentric coordinates for triangle meshes
00006  */
00007 
00008 #include <stdio.h>
00009 
00010 #include "fvect.h"
00011 
00012 #include "tmesh.h"
00013 
00014 #define ABS(x)              ((x) >= 0 ? (x) : -(x))
00015 
00016 
00017 int
00018 flat_tri(v1, v2, v3, n1, n2, n3)   /* determine if triangle is flat */
00019 FVECT  v1, v2, v3, n1, n2, n3;
00020 {
00021        double d1, d2, d3;
00022        FVECT  vt1, vt2, vn;
00023                                    /* compute default normal */
00024        VSUB(vt1, v2, v1);
00025        VSUB(vt2, v3, v2);
00026        VCROSS(vn, vt1, vt2);
00027        if (normalize(vn) == 0.0)
00028               return(DEGEN);
00029                                    /* compare to supplied normals */
00030        d1 = DOT(vn, n1); d2 = DOT(vn, n2); d3 = DOT(vn, n3);
00031        if (d1 < 0 && d2 < 0 && d3 < 0) {
00032               if (d1 > -COSTOL || d2 > -COSTOL || d3 > -COSTOL)
00033                      return(RVBENT);
00034               return(RVFLAT);
00035        }
00036        if (d1 < COSTOL || d2 < COSTOL || d3 < COSTOL)
00037               return(ISBENT);
00038        return(ISFLAT);
00039 }
00040 
00041 
00042 int
00043 comp_baryc(bcm, v1, v2, v3)        /* compute barycentric vectors */
00044 register BARYCCM     *bcm;
00045 RREAL                *v1, *v2, *v3;
00046 {
00047        RREAL  *vt;
00048        FVECT  va, vab, vcb;
00049        double d;
00050        int    ax0, ax1;
00051        register int  i;
00052                                    /* compute major axis */
00053        VSUB(vab, v1, v2);
00054        VSUB(vcb, v3, v2);
00055        VCROSS(va, vab, vcb);
00056        bcm->ax = ABS(va[0]) > ABS(va[1]) ? 0 : 1;
00057        bcm->ax = ABS(va[bcm->ax]) > ABS(va[2]) ? bcm->ax : 2;
00058        if ((ax0 = bcm->ax + 1) >= 3) ax0 -= 3;
00059        if ((ax1 = ax0 + 1) >= 3) ax1 -= 3;
00060        for (i = 0; i < 2; i++) {
00061               vab[0] = v1[ax0] - v2[ax0];
00062               vcb[0] = v3[ax0] - v2[ax0];
00063               vab[1] = v1[ax1] - v2[ax1];
00064               vcb[1] = v3[ax1] - v2[ax1];
00065               d = vcb[0]*vcb[0] + vcb[1]*vcb[1];
00066               if (d <= FTINY*FTINY)
00067                      return(-1);
00068               d = (vcb[0]*vab[0]+vcb[1]*vab[1])/d;
00069               va[0] = vab[0] - vcb[0]*d;
00070               va[1] = vab[1] - vcb[1]*d;
00071               d = va[0]*va[0] + va[1]*va[1];
00072               if (d <= FTINY*FTINY)
00073                      return(-1);
00074               d = 1.0/d;
00075               bcm->tm[i][0] = va[0] *= d;
00076               bcm->tm[i][1] = va[1] *= d;
00077               bcm->tm[i][2] = -(v2[ax0]*va[0]+v2[ax1]*va[1]);
00078                                    /* rotate vertices */
00079               vt = v1;
00080               v1 = v2;
00081               v2 = v3;
00082               v3 = vt;
00083        }
00084        return(0);
00085 }
00086 
00087 
00088 void
00089 eval_baryc(wt, p, bcm)             /* evaluate barycentric weights at p */
00090 RREAL  wt[3];
00091 FVECT  p;
00092 register BARYCCM     *bcm;
00093 {
00094        double u, v;
00095        int    i;
00096        
00097        if ((i = bcm->ax + 1) >= 3) i -= 3;
00098        u = p[i];
00099        if (++i >= 3) i -= 3;
00100        v = p[i];
00101        wt[0] = u*bcm->tm[0][0] + v*bcm->tm[0][1] + bcm->tm[0][2];
00102        wt[1] = u*bcm->tm[1][0] + v*bcm->tm[1][1] + bcm->tm[1][2];
00103        wt[2] = 1. - wt[1] - wt[0];
00104 }
00105 
00106 
00107 int
00108 get_baryc(wt, p, v1, v2, v3)       /* compute barycentric weights at p */
00109 RREAL  wt[3];
00110 FVECT  p;
00111 FVECT  v1, v2, v3;
00112 {
00113        BARYCCM       bcm;
00114        
00115        if (comp_baryc(&bcm, v1, v2, v3) < 0)
00116               return(-1);
00117        eval_baryc(wt, p, &bcm);
00118        return(0);
00119 }
00120 
00121 
00122 #if 0
00123 int
00124 get_baryc(wt, p, v1, v2, v3)       /* compute barycentric weights at p */
00125 RREAL  wt[3];
00126 FVECT  p;
00127 FVECT  v1, v2, v3;
00128 {
00129        FVECT  ac, bc, pc, cros;
00130        double normf;
00131                             /* area formula w/o 2-D optimization */
00132        VSUB(ac, v1, v3);
00133        VSUB(bc, v2, v3);
00134        VSUB(pc, p, v3);
00135        VCROSS(cros, ac, bc);
00136        normf = DOT(cros,cros)
00137        if (normf <= 0.0)
00138               return(-1);
00139        normf = 1./sqrt(normf);
00140        VCROSS(cros, bc, pc);
00141        wt[0] = VLEN(cros) * normf;
00142        VCROSS(cros, ac, pc);
00143        wt[1] = VLEN(cros) * normf;
00144        wt[2] = 1. - wt[1] - wt[0];
00145        return(0);
00146 }
00147 #endif
00148 
00149 
00150 void
00151 put_baryc(bcm, com, n)             /* put barycentric coord. vectors */
00152 register BARYCCM     *bcm;
00153 register RREAL              com[][3];
00154 int                  n;
00155 {
00156        double a, b;
00157        register int  i;
00158 
00159        printf("%d\t%d\n", 1+3*n, bcm->ax);
00160        for (i = 0; i < n; i++) {
00161               a = com[i][0] - com[i][2];
00162               b = com[i][1] - com[i][2];
00163               printf("%14.8f %14.8f %14.8f\n",
00164                      bcm->tm[0][0]*a + bcm->tm[1][0]*b,
00165                      bcm->tm[0][1]*a + bcm->tm[1][1]*b,
00166                      bcm->tm[0][2]*a + bcm->tm[1][2]*b + com[i][2]);
00167        }
00168 }