--- ray/src/hd/rhd_geom.c 1998/12/18 11:55:19 3.1 +++ ray/src/hd/rhd_geom.c 1998/12/20 20:35:43 3.2 @@ -5,82 +5,106 @@ static char SCCSid[] = "$SunId$ SGI"; #endif /* - * Octree drawing operations for OpenGL driver. + * Geometry drawing operations for OpenGL driver. */ #include "radogl.h" +#include "rhdriver.h" -#ifndef MAXOCTREE -#define MAXOCTREE 8 /* maximum octrees to load at once */ +#ifndef MAXGEO +#define MAXGEO 8 /* maximum geometry list length */ #endif +#ifndef MAXPORT +#define MAXPORT (MAXGEO*4) /* maximum number of portal files */ +#endif -static struct otEntry { - char *otfile; /* octree file name */ +int gmPortals = 0; /* current portal GL list id */ +static char *curportlist[MAXPORT]; /* current portal list */ +static char *newportlist[MAXPORT]; /* new portal file list */ + +static struct gmEntry { + char *gfile; /* geometry file name */ FVECT cent; /* centroid */ FLOAT rad; /* radius */ int listid; /* display list identifier */ -} otCurrent[MAXOCTREE], otNext[MAXOCTREE]; /* current and next list */ +} gmCurrent[MAXGEO], gmNext[MAXGEO]; /* current and next list */ -#define FORALLOCT(ot,i) for (i=0;i= MAXOCTREE) { + if (i >= MAXGEO) { error(WARNING, "too many section octrees -- ignoring extra"); return; } /* check if copy in current list */ - FORALLOCT(otCurrent, j) - if (!strcmp(fname, otCurrent[j].otfile)) { - copystruct(&otNext[i], &otCurrent[i]); + FORALLGEOM(gmCurrent, j) + if (!strcmp(file, gmCurrent[j].gfile)) { + copystruct(&gmNext[i], &gmCurrent[j]); return; } /* else load new octree */ - otNext[i].otfile = fname; + gmNext[i].gfile = file; dolights = 0; - otNext[i].listid = rgl_octlist(fname, otNext[i].cent, &otNext[i].rad); + domats = 1; + gmNext[i].listid = rgl_octlist(file, gmNext[i].cent, &gmNext[i].rad); #ifdef DEBUG fprintf(stderr, "Loaded octree \"%s\" into listID %d with radius %f\n", - fname, otNext[i].listid, otNext[i].rad); + file, gmNext[i].listid, gmNext[i].rad); #endif } -otEndOctree() /* make next list current */ +gmEndGeom() /* make next list current */ { register int i, j; - FORALLOCT(otCurrent, i) { - FORALLOCT(otNext, j) - if (otNext[j].listid == otCurrent[i].listid) + FORALLGEOM(gmCurrent, i) { + FORALLGEOM(gmNext, j) + if (gmNext[j].listid == gmCurrent[i].listid) break; - if (j >= MAXOCTREE || otNext[j].otfile == NULL) - glDeleteLists(otCurrent[i].listid, 1); /* not found */ + if (j >= MAXGEO || gmNext[j].gfile == NULL) + glDeleteLists(gmCurrent[i].listid, 1); /* not found */ } - bcopy((char *)otNext, (char *)otCurrent, sizeof(otNext)); - otNext[0].otfile = NULL; + bcopy((char *)gmNext, (char *)gmCurrent, sizeof(gmNext)); + bzero((char *)gmNext, sizeof(gmNext)); } int -otDrawOctrees() /* draw current list of octrees */ +gmDrawGeom(clearports) /* draw current list of octrees (and ports) */ +int clearports; { - register int i; + register int n; - FORALLOCT(otCurrent, i) - glCallList(otCurrent[i].listid); - return(i); + FORALLGEOM(gmCurrent, n) + glCallList(gmCurrent[n].listid); + if (!n | !clearports | !gmPortals) + return(n); + /* mark alpha channel over the portals */ + glPushAttrib(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT); + glDepthMask(GL_FALSE); + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); + glClear(GL_COLOR_BUFFER_BIT); + glColor4ub(0, 0, 0, 0xff); /* write alpha buffer as mask */ + glCallList(gmPortals); /* draw them portals */ + glPopAttrib(); + return(n); } -otDepthLimit(dl, vorg, vdir) /* compute approximate depth limits for view */ +gmDepthLimit(dl, vorg, vdir) /* compute approximate depth limits for view */ double dl[2]; FVECT vorg, vdir; { @@ -89,14 +113,80 @@ FVECT vorg, vdir; register int i; dl[0] = FHUGE; dl[1] = 0.; - FORALLOCT(otCurrent, i) { - VSUB(v, otCurrent[i].cent, vorg); + FORALLGEOM(gmCurrent, i) { + VSUB(v, gmCurrent[i].cent, vorg); dcent = DOT(v, vdir); - if (dl[0] > dcent-otCurrent[i].rad) - dl[0] = dcent-otCurrent[i].rad; - if (dl[1] < dcent+otCurrent[i].rad) - dl[1] = dcent+otCurrent[i].rad; + if (dl[0] > dcent-gmCurrent[i].rad) + dl[0] = dcent-gmCurrent[i].rad; + if (dl[1] < dcent+gmCurrent[i].rad) + dl[1] = dcent+gmCurrent[i].rad; } if (dl[0] < 0.) dl[0] = 0.; +} + + +gmNewPortal(pflist) /* add portal file(s) to our new list */ +char *pflist; +{ + register int i, j; + char newfile[128]; + + if (pflist == NULL) + return; + while (*pflist) { + atos(newfile, sizeof(newfile), pflist); + if (!*newfile) + break; + pflist = sskip(pflist); + FORALLPORT(newportlist,i) + if (!strcmp(newportlist[i], newfile)) + goto endloop; /* in list already */ + if (i >= MAXPORT) { + error(WARNING, "too many portals -- ignoring extra"); + return; + } + newportlist[i] = savestr(newfile); + endloop:; + } +} + + +static int +sstrcmp(ss0, ss1) +char **ss0, **ss1; +{ + return(strcmp(*ss0, *ss1)); +} + + +int +gmEndPortal() /* close portal list and return GL list */ +{ + register int n; + + FORALLPORT(newportlist, n); + if (!n) { /* free old GL list */ + if (gmPortals) + glDeleteLists(gmPortals, 1); + gmPortals = 0; + } else + qsort(newportlist, n, sizeof(char *), sstrcmp); + FORALLPORT(newportlist, n) /* compare sorted lists */ + if (curportlist[n] == NULL || + strcmp(curportlist[n],newportlist[n])) { + /* load new list */ + if (gmPortals) + glDeleteLists(gmPortals, 1); + FORALLPORT(newportlist, n); + dolights = 0; + domats = 0; + gmPortals = rgl_filelist(n, newportlist); + break; + } + FORALLPORT(curportlist, n) /* free old file list */ + freestr(curportlist[n]); + bcopy((char *)newportlist, (char *)curportlist, sizeof(newportlist)); + bzero((char *)newportlist, sizeof(newportlist)); + return(gmPortals); /* return GL list id */ }