Back to index

radiance  4R0+20100331
rhd_geom.c
Go to the documentation of this file.
00001 #ifndef lint
00002 static const char    RCSid[] = "$Id: rhd_geom.c,v 3.14 2004/01/01 11:21:55 schorsch Exp $";
00003 #endif
00004 /*
00005  * Geometry drawing operations for OpenGL driver.
00006  */
00007 
00008 #include <string.h>
00009 
00010 #include "rtio.h"
00011 #include "radogl.h"
00012 #include "rhdriver.h"
00013 #include "rhd_odraw.h"
00014 
00015 #ifndef MAXGEO
00016 #define       MAXGEO        8             /* maximum geometry list length */
00017 #endif
00018 #ifndef MAXPORT
00019 #define MAXPORT             (MAXGEO*4)    /* maximum number of portal files */
00020 #endif
00021 
00022 int    gmPortals = 0;                     /* current portal GL list id */
00023 static int    Nlists = 0;          /* number of lists allocated */
00024 static char   *curportlist[MAXPORT];      /* current portal list */
00025 static char   *newportlist[MAXPORT];      /* new portal file list */
00026 
00027 static struct gmEntry {
00028        char   *gfile;                     /* geometry file name */
00029        FVECT  cent;                /* centroid */
00030        RREAL  rad;                 /* radius */
00031        int    listid;                     /* display list identifier */
00032        int    nlists;                     /* number of lists allocated */
00033 } gmCurrent[MAXGEO], gmNext[MAXGEO];      /* current and next list */
00034 
00035 #define FORALLGEOM(ot,i)    for (i=0;i<MAXGEO&&ot[i].gfile!=NULL;i++)
00036 
00037 #define FORALLPORT(pl,i)           for (i=0;i<MAXPORT&&pl[i]!=NULL;i++)
00038 
00039 
00040 
00041 
00042 extern void
00043 gmNewGeom(                  /* add new geometry to next list */
00044        char   *file
00045 )
00046 {
00047        register int  i, j;
00048                                    /* check if already in next list */
00049        FORALLGEOM(gmNext, i)
00050               if (!strcmp(file, gmNext[i].gfile))
00051                      return;
00052        if (i >= MAXGEO) {
00053               error(WARNING, "too many section octrees -- ignoring extra");
00054               return;
00055        }
00056                                    /* check if copy in current list */
00057        FORALLGEOM(gmCurrent, j)
00058               if (!strcmp(file, gmCurrent[j].gfile)) {
00059                      gmNext[i] = gmCurrent[j];
00060                      return;
00061               }
00062                                    /* else load new octree */
00063        gmNext[i].gfile = savestr(file);
00064        dolights = 0;
00065        domats = 1;
00066        gmNext[i].listid = rgl_octlist(file, gmNext[i].cent, &gmNext[i].rad,
00067                                    &gmNext[i].nlists);
00068        gmNext[i].rad *= 1.732;            /* go to corners */
00069 #ifdef DEBUG
00070        fprintf(stderr, "Loaded octree \"%s\" into listID %d with radius %f\n",
00071                      file, gmNext[i].listid, gmNext[i].rad);
00072 #endif
00073 }
00074 
00075 
00076 extern void
00077 gmEndGeom(void)                    /* make next list current */
00078 {
00079        register int  i, j;
00080 
00081        FORALLGEOM(gmCurrent, i) {
00082               FORALLGEOM(gmNext, j)
00083                      if (gmNext[j].listid == gmCurrent[i].listid)
00084                             break;
00085               if (j >= MAXGEO || gmNext[j].gfile == NULL) {
00086                      glDeleteLists(gmCurrent[i].listid, /* not found */
00087                                    gmCurrent[i].nlists);
00088                      freestr(gmCurrent[i].gfile);
00089               }
00090        }
00091        memcpy((void *)gmCurrent, (void *)gmNext, sizeof(gmNext));
00092        memset((void *)gmNext, '\0', sizeof(gmNext));
00093 }
00094 
00095 
00096 extern int
00097 gmDrawGeom(void)                   /* draw current list of octrees */
00098 {
00099        register int  n;
00100 
00101        FORALLGEOM(gmCurrent, n)
00102               glCallList(gmCurrent[n].listid);
00103        return(n);
00104 }
00105 
00106 
00107 extern void
00108 gmDrawPortals(       /* draw portals with specific RGBA value */
00109        int    r,
00110        int    g,
00111        int    b,
00112        int    a
00113 )
00114 {
00115        if (!gmPortals || (r<0) & (g<0) & (b<0) & (a<0))
00116               return;
00117        glPushAttrib(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT|
00118                      GL_POLYGON_BIT|GL_LIGHTING_BIT);
00119        glDisable(GL_LIGHTING);
00120        glDisable(GL_DITHER);
00121        glShadeModel(GL_FLAT);
00122        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
00123                                    /* don't actually write depth */
00124        glDepthMask(GL_FALSE);
00125                                    /* draw only selected channels */
00126        glColorMask(r>=0, g>=0, b>=0, a>=0);
00127        glColor4ub(r&0xff, g&0xff, b&0xff, a&0xff);
00128        glCallList(gmPortals);             /* draw them portals */
00129        glPopAttrib();
00130 }
00131 
00132 
00133 extern void
00134 gmDepthLimit( /* compute approximate depth limits for view */
00135        double dl[2],
00136        FVECT  vorg,
00137        FVECT  vdir
00138 )
00139 {
00140        FVECT  v;
00141        double dcent;
00142        register int  i;
00143 
00144        dl[0] = FHUGE; dl[1] = 0.;
00145        FORALLGEOM(gmCurrent, i) {
00146               VSUB(v, gmCurrent[i].cent, vorg);
00147               dcent = DOT(v, vdir);
00148               if (dl[0] > dcent-gmCurrent[i].rad)
00149                      dl[0] = dcent-gmCurrent[i].rad;
00150               if (dl[1] < dcent+gmCurrent[i].rad)
00151                      dl[1] = dcent+gmCurrent[i].rad;
00152        }
00153        if (dl[0] < 0.)
00154               dl[0] = 0.;
00155 }
00156 
00157 
00158 extern void
00159 gmNewPortal(         /* add portal file(s) to our new list */
00160        char   *pflist
00161 )
00162 {
00163        register int  i;
00164        char   newfile[128];
00165 
00166        if (pflist == NULL)
00167               return;
00168        while ((pflist = nextword(newfile, sizeof(newfile), pflist)) != NULL) {
00169               FORALLPORT(newportlist,i)
00170                      if (!strcmp(newportlist[i], newfile))
00171                             goto endloop; /* in list already */
00172               if (i >= MAXPORT) {
00173                      error(WARNING, "too many portals -- ignoring extra");
00174                      return;
00175               }
00176               newportlist[i] = savestr(newfile);
00177        endloop:;
00178        }
00179 }
00180 
00181 
00182 static int
00183 sstrcmp(ss0, ss1)
00184 char   **ss0, **ss1;
00185 {
00186        return(strcmp(*ss0, *ss1));
00187 }
00188 
00189 
00190 extern int
00191 gmEndPortal(void)                  /* close portal list and return GL list */
00192 {
00193        register int  n;
00194 
00195        FORALLPORT(newportlist, n);
00196        if (!n) {                   /* free old GL list */
00197               if (gmPortals)
00198                      glDeleteLists(gmPortals, Nlists);
00199               gmPortals = 0;
00200        } else
00201               qsort(newportlist, n, sizeof(char *), sstrcmp);
00202        FORALLPORT(newportlist, n)         /* compare sorted lists */
00203               if (curportlist[n] == NULL ||
00204                             strcmp(curportlist[n],newportlist[n])) {
00205                                           /* load new list */
00206                      if (gmPortals)
00207                             glDeleteLists(gmPortals, 1);
00208                      FORALLPORT(newportlist, n);
00209                      dolights = 0;
00210                      domats = 0;
00211                      gmPortals = rgl_filelist(n, newportlist, &Nlists);
00212                      break;
00213               }
00214        FORALLPORT(curportlist, n)         /* free old file list */
00215               freestr(curportlist[n]);
00216        memcpy((void *)curportlist, (void *)newportlist, sizeof(newportlist));
00217        memset((void *)newportlist, '\0', sizeof(newportlist));
00218        return(gmPortals);                 /* return GL list id */
00219 }