Back to index

radiance  4R0+20100331
rhdisp2.c
Go to the documentation of this file.
00001 #ifndef lint
00002 static const char    RCSid[] = "$Id: rhdisp2.c,v 3.37 2004/01/01 11:21:55 schorsch Exp $";
00003 #endif
00004 /*
00005  * Holodeck beam tracking for display process
00006  */
00007 
00008 #include "rholo.h"
00009 #include "rhdisp.h"
00010 #include "rhdriver.h"
00011 
00012 #ifndef MEYERNG
00013 #define MEYERNG             0.2    /* target mean eye range (rel. to grid) */
00014 #endif
00015 
00016 #define CBEAMBLK     1024   /* cbeam allocation block size */
00017 
00018 static PACKHEAD      *cbeam = NULL;       /* current beam list */
00019 static int    ncbeams = 0;  /* number of sorted beams in cbeam */
00020 static int    xcbeams = 0;  /* extra (unregistered) beams past ncbeams */
00021 static int    maxcbeam = 0; /* size of cbeam array */
00022 
00023 VIEWPOINT     cureye;              /* current eye position */
00024 
00025 static int newcbeam(void);
00026 static int cbeamcmp(const void *cb1, const void *cb2);
00027 static int cbeamcmp2(const void *cb1, const void *cb2);
00028 static int findcbeam(int hd, int bi);
00029 static int getcbeam(int hd, int bi);
00030 static void cbeamsort(int adopt);
00031 
00032 
00033 static int
00034 newcbeam(void)              /* allocate new entry at end of cbeam array */
00035 {
00036        int    i;
00037 
00038        if ((i = ncbeams + xcbeams++) >= maxcbeam) {     /* grow array */
00039               maxcbeam += CBEAMBLK;
00040               if (cbeam == NULL)
00041                      cbeam = (PACKHEAD *)malloc(
00042                                    maxcbeam*sizeof(PACKHEAD) );
00043               else
00044                      cbeam = (PACKHEAD *)realloc((void *)cbeam,
00045                                    maxcbeam*sizeof(PACKHEAD) );
00046               if (cbeam == NULL)
00047                      error(SYSTEM, "out of memory in newcbeam");
00048        }
00049        return(i);
00050 }
00051 
00052 
00053 static int
00054 cbeamcmp(     /* compare two cbeam entries for sort: keep orphans */
00055        const void    *cb1,
00056        const void    *cb2
00057 )
00058 {
00059        register int  c;
00060 
00061        if ((c = ((PACKHEAD*)cb1)->bi - ((PACKHEAD*)cb2)->bi))  /* sort on beam index first */
00062               return(c);
00063        return(((PACKHEAD*)cb1)->hd - ((PACKHEAD*)cb2)->hd);    /* use hd to resolve matches */
00064 }
00065 
00066 
00067 static int
00068 cbeamcmp2(    /* compare two cbeam entries for sort: no orphans */
00069        const void    *cb1,
00070        const void    *cb2
00071 )
00072 {
00073        register int  c;
00074 
00075        if (!((PACKHEAD*)cb1)->nr)                /* put orphans at the end, unsorted */
00076               return(((PACKHEAD*)cb2)->nr);
00077        if (!((PACKHEAD*)cb2)->nr)
00078               return(-1);
00079        if ((c = ((PACKHEAD*)cb1)->bi - ((PACKHEAD*)cb2)->bi))  /* sort on beam index first */
00080               return(c);
00081        return(((PACKHEAD*)cb1)->hd - ((PACKHEAD*)cb2)->hd);    /* use hd to resolve matches */
00082 }
00083 
00084 
00085 static int
00086 findcbeam(    /* find the specified beam in our sorted list */
00087        int    hd,
00088        int    bi
00089 )
00090 {
00091        PACKHEAD      cb;
00092        register PACKHEAD    *p;
00093 
00094        if (ncbeams <= 0)
00095               return(-1);
00096        cb.hd = hd; cb.bi = bi; cb.nr = cb.nc = 0;
00097        p = (PACKHEAD *)bsearch((char *)&cb, (char *)cbeam, ncbeams,
00098                      sizeof(PACKHEAD), cbeamcmp);
00099        if (p == NULL)
00100               return(-1);
00101        return(p - cbeam);
00102 }
00103 
00104 
00105 static int
00106 getcbeam(     /* get the specified beam, allocating as necessary */
00107        register int  hd,
00108        int    bi
00109 )
00110 {
00111        register int  n;
00112                             /* first, look in sorted list */
00113        if ((n = findcbeam(hd, bi)) >= 0)
00114               return(n);
00115                             /* linear search through xcbeams to be sure */
00116        for (n = ncbeams+xcbeams; n-- > ncbeams; )
00117               if (cbeam[n].bi == bi && cbeam[n].hd == hd)
00118                      return(n);
00119                             /* check legality */
00120        if ((hd < 0) | (hd >= HDMAX) || hdlist[hd] == NULL)
00121               error(INTERNAL, "illegal holodeck number in getcbeam");
00122        if ((bi < 1) | (bi > nbeams(hdlist[hd])))
00123               error(INTERNAL, "illegal beam index in getcbeam");
00124        n = newcbeam();             /* allocate and assign */
00125        cbeam[n].hd = hd; cbeam[n].bi = bi; cbeam[n].nr = cbeam[n].nc = 0;
00126        return(n);
00127 }
00128 
00129 
00130 static void
00131 cbeamsort(    /* sort our beam list, possibly turning out orphans */
00132        int    adopt
00133 )
00134 {
00135        register int  i;
00136 
00137        if (!(ncbeams += xcbeams))
00138               return;
00139        xcbeams = 0;
00140        qsort((char *)cbeam, ncbeams, sizeof(PACKHEAD),
00141                      adopt ? cbeamcmp : cbeamcmp2);
00142        if (adopt)
00143               return;
00144        for (i = ncbeams; i--; )    /* identify orphans */
00145               if (cbeam[i].nr)
00146                      break;
00147        xcbeams = ncbeams - ++i;    /* put orphans after ncbeams */
00148        ncbeams = i;
00149 }
00150 
00151 
00152 extern void
00153 beam_init(           /* clear beam list for new view(s) */
00154        int    fresh
00155 )
00156 {
00157        register int  i;
00158 
00159        if (fresh)                  /* discard old beams? */
00160               ncbeams = xcbeams = 0;
00161        else                        /* else clear sample requests */
00162               for (i = ncbeams+xcbeams; i--; )
00163                      cbeam[i].nr = 0;
00164        cureye.rng = 0.;
00165 }
00166 
00167 
00168 extern int16 *
00169 beam_view(           /* add beam view (if advisable) */
00170        VIEW   *vn,
00171        int    hr,
00172        int    vr
00173 )
00174 {
00175        int16  *slist;
00176        BEAMLIST      blist;
00177        double eravg, d;
00178        register HOLO *hp;
00179        register int  i, n;
00180                                    /* compute beams for view */
00181        slist = viewbeams(vn, hr, vr, &blist);
00182        if (*slist < 0) {
00183               error(COMMAND, "no sections visible from this view");
00184               return(NULL);
00185        }
00186                                    /* sort current beam list */
00187        cbeamsort(1);
00188                                    /* add new beams to list */
00189        for (i = blist.nb; i--; ) {
00190               n = getcbeam(blist.bl[i].hd, blist.bl[i].bi);
00191               if (blist.bl[i].nr > cbeam[n].nr)
00192                      cbeam[n].nr = blist.bl[i].nr;
00193        }
00194        free((void *)blist.bl);            /* free list */
00195        if (MEYERNG <= FTINY)
00196               return(slist);
00197                                    /* compute average eye range */
00198        eravg = 0.;
00199        for (n = 0; slist[n] >= 0; n++) {
00200               hp = hdlist[slist[n]];
00201               eravg +=      MEYERNG/3. / VLEN(hp->wg[0]) +
00202                             MEYERNG/3. / VLEN(hp->wg[1]) +
00203                             MEYERNG/3. / VLEN(hp->wg[2]) ;
00204        }
00205        eravg /= (double)n;
00206                                    /* add to current eye position */
00207        if (cureye.rng <= FTINY) {
00208               VCOPY(cureye.vpt, vn->vp);
00209               cureye.rng = eravg;
00210        } else if ((d = sqrt(dist2(vn->vp,cureye.vpt))) + eravg > cureye.rng) {
00211               for (i = 3; i--; )
00212                      cureye.vpt[i] = 0.5*(cureye.vpt[i] + vn->vp[i]);
00213               cureye.rng = 0.5*(cureye.rng + eravg + d);
00214        }
00215        return(slist);
00216 }
00217 
00218 
00219 extern int
00220 beam_sync(                  /* update beam list on server */
00221        int    all
00222 )
00223 {
00224                                    /* set new eye position */
00225        serv_request(DR_VIEWPOINT, sizeof(VIEWPOINT), (char *)&cureye);
00226                                    /* sort list (put orphans at end) */
00227        cbeamsort(all < 0);
00228                                    /* send beam request */
00229        if (all) {
00230               if (ncbeams > 0)
00231                      serv_request(DR_NEWSET,
00232                                    ncbeams*sizeof(PACKHEAD), (char *)cbeam);
00233        } else {
00234               if (ncbeams+xcbeams > 0)
00235                      serv_request(DR_ADJSET,
00236                             (ncbeams+xcbeams)*sizeof(PACKHEAD), (char *)cbeam);
00237        }
00238        xcbeams = 0;                /* truncate our list */
00239        return(ncbeams);
00240 }
00241 
00242 
00243 extern void
00244 gridlines(                  /* run through holodeck section grid lines */
00245        void   (*f)(FVECT wp[2])
00246 )
00247 {
00248        register int  hd, w, i;
00249        int    g0, g1;
00250        FVECT  wp[2], mov;
00251        double d;
00252                                    /* do each wall on each section */
00253        for (hd = 0; hdlist[hd] != NULL; hd++)
00254               for (w = 0; w < 6; w++) {
00255                      g0 = hdwg0[w];
00256                      g1 = hdwg1[w];
00257                      d = 1.0/hdlist[hd]->grid[g0];
00258                      mov[0] = d * hdlist[hd]->xv[g0][0];
00259                      mov[1] = d * hdlist[hd]->xv[g0][1];
00260                      mov[2] = d * hdlist[hd]->xv[g0][2];
00261                      if (w & 1) {
00262                             VSUM(wp[0], hdlist[hd]->orig,
00263                                           hdlist[hd]->xv[w>>1], 1.);
00264                             VSUM(wp[0], wp[0], mov, 1.);
00265                      } else
00266                             VCOPY(wp[0], hdlist[hd]->orig);
00267                      VSUM(wp[1], wp[0], hdlist[hd]->xv[g1], 1.);
00268                      for (i = hdlist[hd]->grid[g0]; ; ) {      /* g0 lines */
00269                             (*f)(wp);
00270                             if (!--i) break;
00271                             wp[0][0] += mov[0]; wp[0][1] += mov[1];
00272                             wp[0][2] += mov[2]; wp[1][0] += mov[0];
00273                             wp[1][1] += mov[1]; wp[1][2] += mov[2];
00274                      }
00275                      d = 1.0/hdlist[hd]->grid[g1];
00276                      mov[0] = d * hdlist[hd]->xv[g1][0];
00277                      mov[1] = d * hdlist[hd]->xv[g1][1];
00278                      mov[2] = d * hdlist[hd]->xv[g1][2];
00279                      if (w & 1)
00280                             VSUM(wp[0], hdlist[hd]->orig,
00281                                           hdlist[hd]->xv[w>>1], 1.);
00282                      else
00283                             VSUM(wp[0], hdlist[hd]->orig, mov, 1.);
00284                      VSUM(wp[1], wp[0], hdlist[hd]->xv[g0], 1.);
00285                      for (i = hdlist[hd]->grid[g1]; ; ) {      /* g1 lines */
00286                             (*f)(wp);
00287                             if (!--i) break;
00288                             wp[0][0] += mov[0]; wp[0][1] += mov[1];
00289                             wp[0][2] += mov[2]; wp[1][0] += mov[0];
00290                             wp[1][1] += mov[1]; wp[1][2] += mov[2];
00291                      }
00292               }
00293 }