Back to index

radiance  4R0+20100331
rhd_qtree2c.c
Go to the documentation of this file.
00001 #ifndef lint
00002 static const char    RCSid[] = "$Id: rhd_qtree2c.c,v 3.3 2004/01/01 11:21:55 schorsch Exp $";
00003 #endif
00004 /*
00005  * Quadtree display support routines for cone output.
00006  */
00007 
00008 #include "standard.h"
00009 #include "rhd_qtree.h"
00010 
00011 static void redraw(RTREE *tp, int x0, int y0, int x1, int y1, int l[2][2]);
00012 static void cpaint(BYTE rgb[3], float *p, int x0, int y0, int x1, int y1);
00013 static void update(BYTE ca[3], RTREE *tp, int x0, int y0, int x1, int y1);
00014 
00015 
00016 
00017 static void
00018 redraw(       /* mark portion of a tree for redraw */
00019        register RTREE       *tp,
00020        int    x0,
00021        int    y0,
00022        int    x1,
00023        int    y1,
00024        int    l[2][2]
00025 )
00026 {
00027        int    quads = CH_ANY;
00028        int    mx, my;
00029        register int  i;
00030                                    /* compute midpoint */
00031        mx = (x0 + x1) >> 1;
00032        my = (y0 + y1) >> 1;
00033                                    /* see what to do */
00034        if (l[0][0] > mx)
00035               quads &= ~(CHF(UL)|CHF(DL));
00036        else if (l[0][1] < mx)
00037               quads &= ~(CHF(UR)|CHF(DR));
00038        if (l[1][0] > my)
00039               quads &= ~(CHF(DR)|CHF(DL));
00040        else if (l[1][1] < my)
00041               quads &= ~(CHF(UR)|CHF(UL));
00042        tp->flgs |= quads;          /* mark quadrants for update */
00043                                    /* climb the branches */
00044        for (i = 0; i < 4; i++)
00045               if (tp->flgs & BRF(i) && quads & CHF(i))
00046                      redraw(tp->k[i].b, i&01 ? mx : x0, i&02 ? my : y0,
00047                                    i&01 ? x1 : mx, i&02 ? y1 : my, l);
00048 }
00049 
00050 
00051 static void
00052 cpaint(       /* paint a cone within a rectangle */
00053        BYTE   rgb[3],
00054        register float       *p,
00055        int    x0,
00056        int    y0,
00057        int    x1,
00058        int    y1
00059 )
00060 {
00061        static FVECT  ip, wp;
00062        double rad;
00063                                           /* compute base radius */
00064        rad = (double)(y1 - y0 + x1 - x0)/(odev.hres + odev.vres);
00065                                           /* approximate apex pos? */
00066        if (p == NULL || y1-y0 <= qtMinNodesiz || x1-x0 <= qtMinNodesiz) {
00067               ip[0] = (double)(x0 + x1)/(odev.hres<<1);
00068               ip[1] = (double)(y0 + y1)/(odev.vres<<1);
00069               if (p != NULL) {
00070                      wp[0] = p[0] - odev.v.vp[0];
00071                      wp[1] = p[1] - odev.v.vp[1];
00072                      wp[2] = p[2] - odev.v.vp[2];
00073                      if (odev.v.type == VT_PER)
00074                             ip[2] = DOT(wp,odev.v.vdir);
00075                      else
00076                             ip[2] = VLEN(wp);
00077               } else
00078                      ip[2] = FHUGE;
00079        } else if (odev.v.type == VT_PER) {       /* special case (faster) */
00080               wp[0] = p[0] - odev.v.vp[0];
00081               wp[1] = p[1] - odev.v.vp[1];
00082               wp[2] = p[2] - odev.v.vp[2];
00083               ip[2] = DOT(wp,odev.v.vdir);
00084               ip[0] = DOT(wp,odev.v.hvec)/(ip[2]*odev.v.hn2) +
00085                             0.5 - odev.v.hoff;
00086               ip[1] = DOT(wp,odev.v.vvec)/(ip[2]*odev.v.vn2) +
00087                             0.5 - odev.v.voff;
00088        } else {                           /* general case */
00089               VCOPY(wp, p);
00090               viewloc(ip, &odev.v, wp);
00091        }
00092        dev_cone(rgb, ip, rad);
00093 }
00094 
00095 
00096 static void
00097 update(       /* update tree display as needed */
00098        BYTE   ca[3],        /* returned average color */
00099        register RTREE       *tp,
00100        int    x0,
00101        int    y0,
00102        int    x1,
00103        int    y1
00104 )
00105 {
00106        int    csm[3], nc;
00107        register BYTE *cp;
00108        BYTE   rgb[3];
00109        int    gaps = 0;
00110        int    mx, my;
00111        register int  i;
00112                                    /* compute midpoint */
00113        mx = (x0 + x1) >> 1;
00114        my = (y0 + y1) >> 1;
00115                                    /* draw leaves */
00116        csm[0] = csm[1] = csm[2] = nc = 0;
00117        for (i = 0; i < 4; i++) {
00118               if (tp->flgs & LFF(i)) {
00119                      cp = qtL.rgb[tp->k[i].li];
00120                      csm[0] += cp[0]; csm[1] += cp[1]; csm[2] += cp[2];
00121                      nc++;
00122                      if (tp->flgs & CHF(i))
00123                             cpaint(cp, qtL.wp[tp->k[i].li],
00124                                    i&01 ? mx : x0, i&02 ? my : y0,
00125                                    i&01 ? x1 : mx, i&02 ? y1 : my);
00126               } else if ((tp->flgs & CHBRF(i)) == CHF(i))
00127                      gaps |= 1<<i; /* empty stem */
00128        }
00129                                    /* do branches */
00130        for (i = 0; i < 4; i++)
00131               if ((tp->flgs & CHBRF(i)) == CHBRF(i)) {
00132                      update(rgb, tp->k[i].b, i&01 ? mx : x0, i&02 ? my : y0,
00133                                    i&01 ? x1 : mx, i&02 ? y1 : my);
00134                      csm[0] += rgb[0]; csm[1] += rgb[1]; csm[2] += rgb[2];
00135                      nc++;
00136               }
00137        if (nc > 1) {
00138               ca[0] = csm[0]/nc; ca[1] = csm[1]/nc; ca[2] = csm[2]/nc;
00139        } else {
00140               ca[0] = csm[0]; ca[1] = csm[1]; ca[2] = csm[2];
00141        }
00142                                    /* fill in gaps with average */
00143        for (i = 0; gaps && i < 4; gaps >>= 1, i++)
00144               if (gaps & 01)
00145                      cpaint(ca, (float *)NULL,
00146                                    i&01 ? mx : x0, i&02 ? my : y0,
00147                                    i&01 ? x1 : mx, i&02 ? y1 : my);
00148        tp->flgs &= ~CH_ANY;        /* all done */
00149 }
00150 
00151 
00152 extern void
00153 qtRedraw(     /* redraw part or all of our screen */
00154        int    x0,
00155        int    y0,
00156        int    x1,
00157        int    y1
00158 )
00159 {
00160        int    lim[2][2];
00161 
00162        if (is_stump(&qtrunk))
00163               return;
00164        if (!(qtMapLeaves((lim[0][0]=x0) <= 0) & ((lim[1][0]=y0) <= 0) &
00165               ((lim[0][1]=x1) >= odev.hres-1) & ((lim[1][1]=y1) >= odev.vres-1)))
00166               return;
00167        redraw(&qtrunk, 0, 0, odev.hres, odev.vres, lim);
00168 }
00169 
00170 
00171 extern void
00172 qtUpdate(void)                     /* update our tree display */
00173 {
00174        BYTE   ca[3];
00175 
00176        if (is_stump(&qtrunk))
00177               return;
00178        if (!qtMapLeaves(0))
00179               return;
00180        update(ca, &qtrunk, 0, 0, odev.hres, odev.vres);
00181 }