--- ray/src/hd/rhd_geom.c 1998/12/18 11:55:19 3.1 +++ ray/src/hd/rhd_geom.c 2004/01/01 11:21:55 3.14 @@ -1,102 +1,219 @@ -/* Copyright (c) 1998 Silicon Graphics, Inc. */ - #ifndef lint -static char SCCSid[] = "$SunId$ SGI"; +static const char RCSid[] = "$Id: rhd_geom.c,v 3.14 2004/01/01 11:21:55 schorsch Exp $"; #endif - /* - * Octree drawing operations for OpenGL driver. + * Geometry drawing operations for OpenGL driver. */ +#include + +#include "rtio.h" #include "radogl.h" +#include "rhdriver.h" +#include "rhd_odraw.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 int Nlists = 0; /* number of lists allocated */ +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 */ + RREAL rad; /* radius */ int listid; /* display list identifier */ -} otCurrent[MAXOCTREE], otNext[MAXOCTREE]; /* current and next list */ + int nlists; /* number of lists allocated */ +} 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)) { + gmNext[i] = gmCurrent[j]; return; } /* else load new octree */ - otNext[i].otfile = fname; + gmNext[i].gfile = savestr(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, + &gmNext[i].nlists); + gmNext[i].rad *= 1.732; /* go to corners */ #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 */ +extern void +gmEndGeom(void) /* 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, /* not found */ + gmCurrent[i].nlists); + freestr(gmCurrent[i].gfile); + } } - bcopy((char *)otNext, (char *)otCurrent, sizeof(otNext)); - otNext[0].otfile = NULL; + memcpy((void *)gmCurrent, (void *)gmNext, sizeof(gmNext)); + memset((void *)gmNext, '\0', sizeof(gmNext)); } -int -otDrawOctrees() /* draw current list of octrees */ +extern int +gmDrawGeom(void) /* draw current list of octrees */ { - register int i; + register int n; - FORALLOCT(otCurrent, i) - glCallList(otCurrent[i].listid); - return(i); + FORALLGEOM(gmCurrent, n) + glCallList(gmCurrent[n].listid); + return(n); } -otDepthLimit(dl, vorg, vdir) /* compute approximate depth limits for view */ -double dl[2]; -FVECT vorg, vdir; +extern void +gmDrawPortals( /* draw portals with specific RGBA value */ + int r, + int g, + int b, + int a +) { + if (!gmPortals || (r<0) & (g<0) & (b<0) & (a<0)) + return; + glPushAttrib(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT| + GL_POLYGON_BIT|GL_LIGHTING_BIT); + glDisable(GL_LIGHTING); + glDisable(GL_DITHER); + glShadeModel(GL_FLAT); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + /* don't actually write depth */ + glDepthMask(GL_FALSE); + /* draw only selected channels */ + glColorMask(r>=0, g>=0, b>=0, a>=0); + glColor4ub(r&0xff, g&0xff, b&0xff, a&0xff); + glCallList(gmPortals); /* draw them portals */ + glPopAttrib(); +} + + +extern void +gmDepthLimit( /* compute approximate depth limits for view */ + double dl[2], + FVECT vorg, + FVECT vdir +) +{ FVECT v; double dcent; 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.; +} + + +extern void +gmNewPortal( /* add portal file(s) to our new list */ + char *pflist +) +{ + register int i; + char newfile[128]; + + if (pflist == NULL) + return; + while ((pflist = nextword(newfile, sizeof(newfile), pflist)) != NULL) { + 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)); +} + + +extern int +gmEndPortal(void) /* close portal list and return GL list */ +{ + register int n; + + FORALLPORT(newportlist, n); + if (!n) { /* free old GL list */ + if (gmPortals) + glDeleteLists(gmPortals, Nlists); + 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, &Nlists); + break; + } + FORALLPORT(curportlist, n) /* free old file list */ + freestr(curportlist[n]); + memcpy((void *)curportlist, (void *)newportlist, sizeof(newportlist)); + memset((void *)newportlist, '\0', sizeof(newportlist)); + return(gmPortals); /* return GL list id */ }