--- ray/src/hd/rhdobj.c 1998/08/19 17:45:24 3.1 +++ ray/src/hd/rhdobj.c 2004/03/30 20:40:04 3.17 @@ -1,31 +1,33 @@ -/* Copyright (c) 1998 Silicon Graphics, Inc. */ - #ifndef lint -static char SCCSid[] = "$SunId$ SGI"; +static const char RCSid[] = "$Id: rhdobj.c,v 3.17 2004/03/30 20:40:04 greg Exp $"; #endif - /* - * Routines for loading and displaying Radiance objects under OpenGL in rholo. + * Routines for loading and displaying Radiance objects in rholo with GLX. */ +#include +#include + #include "radogl.h" #include "tonemap.h" #include "rhdisp.h" #include "rhdriver.h" #include "rhdobj.h" +#include "rtprocess.h" extern FILE *sstdout; /* user standard output */ char rhdcmd[DO_NCMDS][8] = DO_INIT; /* user command list */ -int (*dobj_lightsamp)() = NULL; /* pointer to function to get lights */ +/* pointer to function to get lights */ +void (*dobj_lightsamp)(COLR clr, FVECT direc, FVECT pos) = NULL; #define AVGREFL 0.5 /* assumed average reflectance */ -#define MAXAC 64 /* maximum number of args */ +#define MAXAC 512 /* maximum number of args */ #ifndef MINTHRESH -#define MINTHRESH 7.0 /* source threshold w.r.t. mean */ +#define MINTHRESH 5.0 /* source threshold w.r.t. mean */ #endif #ifndef NALT @@ -53,9 +55,10 @@ typedef struct dobject { struct dobject *next; /* next object in list */ char name[64]; /* object name */ FVECT center; /* orig. object center */ - FLOAT radius; /* orig. object radius */ + RREAL radius; /* orig. object radius */ int listid; /* GL display list identifier */ - int rtp[3]; /* associated rtrace process */ + int nlists; /* number of lists allocated */ + SUBPROC rtp; /* associated rtrace process */ DLIGHTS *ol; /* object lights */ FULLXF xfb; /* coordinate transform */ short drawcode; /* drawing code */ @@ -69,6 +72,9 @@ static DOBJECT *curobj; /* current (last referred) ob static int lastxfac; /* last number of transform args */ static char *lastxfav[MAXAC+1]; /* saved transform arguments */ +#define getdcent(c,op) multp3(c,(op)->center,(op)->xfb.f.xfm) +#define getdrad(op) ((op)->radius*(op)->xfb.f.sca) + #define RTARGC 8 static char *rtargv[RTARGC+1] = {"rtrace", "-h-", "-w-", "-fdd", "-x", "1", "-oL"}; @@ -80,10 +86,21 @@ static struct { #define curname (curobj==NULL ? (char *)NULL : curobj->name) +static DOBJECT *getdobj(char *nm); +static int freedobj(DOBJECT *op); +static int savedxf(DOBJECT *op); +static void ssph_sample(COLR clr, FVECT direc, FVECT pos); +static void ssph_direc(FVECT direc, int alt, int azi); +static int ssph_neigh(int sp[2], int next); +static int ssph_compute(void); +static int getdlights(DOBJECT *op, int force); +static void cmderror(int cn, char *err); + static DOBJECT * -getdobj(nm) /* get object from list by name */ -char *nm; +getdobj( /* get object from list by name */ + char *nm +) { register DOBJECT *op; @@ -98,9 +115,10 @@ char *nm; } -static -freedobj(op) /* free resources and memory assoc. with op */ -register DOBJECT *op; +static int +freedobj( /* free resources and memory assoc. with op */ + register DOBJECT *op +) { int foundlink = 0; DOBJECT ohead; @@ -116,19 +134,20 @@ register DOBJECT *op; } dobjects = ohead.next; if (!foundlink) { - glDeleteLists(op->listid, 1); - close_process(op->rtp); + glDeleteLists(op->listid, op->nlists); + close_process(&(op->rtp)); } while (op->xfac) freestr(op->xfav[--op->xfac]); - free((char *)op); + free((void *)op); return(1); } -static -savedxf(op) /* save transform for display object */ -register DOBJECT *op; +static int +savedxf( /* save transform for display object */ + register DOBJECT *op +) { /* free old */ while (lastxfac) @@ -146,10 +165,12 @@ register DOBJECT *op; } -static -ssph_sample(clr, direc, pos) /* add sample to current source sphere */ -COLR clr; -FVECT direc, pos; +static void +ssph_sample( /* add sample to current source sphere */ + COLR clr, + FVECT direc, + FVECT pos +) { COLOR col; double d; @@ -173,10 +194,12 @@ FVECT direc, pos; } -static -ssph_direc(direc, alt, azi) /* compute sphere sampling direction */ -FVECT direc; -int alt, azi; +static void +ssph_direc( /* compute sphere sampling direction */ + FVECT direc, + int alt, + int azi +) { double phi, d; @@ -189,9 +212,10 @@ int alt, azi; static int -ssph_neigh(sp, next) /* neighbor counter on sphere */ -register int sp[2]; -int next; +ssph_neigh( /* neighbor counter on sphere */ + register int sp[2], + int next +) { static short nneigh = 0; /* neighbor count */ static short neighlist[NAZI+6][2]; /* neighbor list (0 is home) */ @@ -204,7 +228,7 @@ int next; sp[1] = neighlist[nneigh][1]; return(1); } - if (sp[0] < 0 | sp[0] >= NALT | sp[1] < 0 | sp[1] >= NAZI) + if ((sp[0] < 0) | (sp[0] >= NALT) | (sp[1] < 0) | (sp[1] >= NAZI)) return(nneigh=0); neighlist[0][0] = sp[0]; neighlist[0][1] = sp[1]; nneigh = 1; @@ -254,8 +278,8 @@ int next; } -static -ssph_compute() /* compute source set from sphere samples */ +static int +ssph_compute(void) /* compute source set from sphere samples */ { int ncells, nsamps; COLOR csum; @@ -278,9 +302,9 @@ ssph_compute() /* compute source set from sphere sam nsamps += ssamp[alt][azi].nsamp; ncells++; } - if (dlightsets == NULL | ncells < NALT*NAZI/4) { - bzero((char *)ssamp, sizeof(ssamp)); - return(0); + if ((dlightsets == NULL) | (ncells < NALT*NAZI/4)) { + ncells = 0; + goto done; } /* harmonic mean distance */ if (dlightsets->ravg > FTINY) @@ -289,11 +313,15 @@ ssph_compute() /* compute source set from sphere sam dlightsets->ravg = FHUGE; /* light source threshold */ thresh = MINTHRESH*bright(csum)/ncells; + if (thresh <= FTINY) { + ncells = 0; + goto done; + } /* avg. reflected brightness */ d = AVGREFL / (double)ncells; scalecolor(csum, d); - if (tmCvColors(&dlightsets->larb, TM_NOCHROM, csum, 1) != TM_E_OK) - error(CONSISTENCY, "bad tone mapping in ssph_compute"); + if (tmCvColors(&dlightsets->larb, TM_NOCHROM, &csum, 1) != TM_E_OK) + error(CONSISTENCY, "tone mapping problem in ssph_compute"); /* greedy light source clustering */ while (dlightsets->nl < MAXLIGHTS) { maxbr = 0.; /* find brightest cell */ @@ -313,9 +341,11 @@ ssph_compute() /* compute source set from sphere sam continue; /* too dim */ ssph_direc(v, alt, azi); /* else add it in */ VSUM(ls->direc, ls->direc, v, d); - ls->omega++; + ls->omega += 1.; addcolor(ls->val, ssamp[alt][azi].val); + /* remove from list */ setcolor(ssamp[alt][azi].val, 0., 0., 0.); + ssamp[alt][azi].nsamp = 0; } d = 1./ls->omega; /* avg. brightness */ scalecolor(ls->val, d); @@ -329,16 +359,17 @@ ssph_compute() /* compute source set from sphere sam addcolor(dlightsets->lamb, ssamp[alt][azi].val); d = 1.0/ncells; scalecolor(dlightsets->lamb, d); - /* clear sphere sample array */ - bzero((char *)ssamp, sizeof(ssamp)); +done: /* clear sphere sample array */ + memset((void *)ssamp, '\0', sizeof(ssamp)); return(ncells); } -static -getdlights(op, force) /* get lights for display object */ -register DOBJECT *op; -int force; +static int +getdlights( /* get lights for display object */ + register DOBJECT *op, + int force +) { double d2, mind2 = FHUGE*FHUGE; FVECT ocent; @@ -349,21 +380,21 @@ int force; if (op->drawcode != DO_LIGHT) return(0); /* check for usable light set */ - multp3(ocent, op->center, op->xfb.f.xfm); + getdcent(ocent, op); for (dl = dlightsets; dl != NULL; dl = dl->next) if ((d2 = dist2(dl->lcent, ocent)) < mind2) { op->ol = dl; mind2 = d2; } /* the following is heuristic */ - d2 = 2.*op->radius*op->xfb.f.sca; d2 *= d2; + d2 = 2.*getdrad(op); d2 *= d2; if ((dl = op->ol) != NULL && (mind2 < 0.0625*dl->ravg*dl->ravg || - mind2 < 4.*op->radius*op->xfb.f.sca*op->radius*op->xfb.f.sca)) + mind2 < 4.*getdrad(op)*getdrad(op))) return(1); if (!force) return(0); /* need to compute new light set */ - copystruct(&cvw, &stdview); + cvw = stdview; cvw.type = VT_PER; VCOPY(cvw.vp, ocent); cvw.vup[0] = 1.; cvw.vup[1] = cvw.vup[2] = 0.; @@ -397,33 +428,36 @@ int force; quit(0); if (!ssph_compute()) { /* compute light sources from sphere */ dlightsets = dl->next; - free((char *)dl); + free((void *)dl); return(0); } op->ol = dl; return(1); memerr: error(SYSTEM, "out of memory in getdlights"); + return 0; /* pro forma return */ } -static int -cmderror(cn, err) /* report command error */ -int cn; -char *err; +static void +cmderror( /* report command error */ + int cn, + char *err +) { sprintf(errmsg, "%s: %s", rhdcmd[cn], err); error(COMMAND, errmsg); - return(cn); } -int -dobj_command(cmd, args) /* run object display command */ -char *cmd; -register char *args; +extern int +dobj_command( /* run object display command */ + char *cmd, + register char *args +) { - int cn, na, doxfm; + int somechange = 0; + int cn, na; register int nn; char *alist[MAXAC+1], *nm; /* find command */ @@ -450,15 +484,17 @@ register char *args; dobj_load(alist[0], alist[0]); else if (na == 2) dobj_load(alist[0], alist[1]); - else - return(cmderror(cn, "need octree [name]")); + else { + cmderror(cn, "need octree [name]"); + return(0); + } break; - case DO_UNLOAD: /* unload an object */ + case DO_UNLOAD: /* clear an object */ if (na > 1) goto toomany; if (na && alist[0][0] == '*') - dobj_cleanup(); + somechange += dobj_cleanup(); else - dobj_unload(na ? alist[0] : curname); + somechange += dobj_unload(na ? alist[0] : curname); break; case DO_XFORM: /* transform object */ case DO_MOVE: @@ -467,15 +503,20 @@ register char *args; } else { nm = curname; nn = 0; } - if (cn == DO_MOVE && nn >= na) - return(cmderror(cn, "missing transform")); - dobj_xform(nm, cn==DO_MOVE, na-nn, alist+nn); + if (cn == DO_MOVE && nn >= na) { + cmderror(cn, "missing transform"); + return(0); + } + somechange += dobj_xform(nm, cn==DO_MOVE, na-nn, alist+nn); break; case DO_UNMOVE: /* undo last transform */ - dobj_unmove(); + somechange += dobj_unmove(); break; case DO_OBJECT: /* print object statistics */ - dobj_putstats(na ? alist[0] : curname, sstdout); + if (dobj_putstats(na ? alist[0] : curname, sstdout)) + if (na && alist[0][0] != '*' && (curobj == NULL || + strcmp(alist[0], curobj->name))) + savedxf(curobj = getdobj(alist[0])); break; case DO_DUP: /* duplicate object */ for (nn = 0; nn < na; nn++) @@ -483,7 +524,8 @@ register char *args; break; switch (nn) { case 0: - return(cmderror(cn, "need new object name")); + cmderror(cn, "need new object name"); + return(0); case 1: nm = curname; break; @@ -496,30 +538,34 @@ register char *args; if (!dobj_dup(nm, alist[nn-1])) break; if (na > nn) - dobj_xform(curname, 1, na-nn, alist+nn); + somechange += dobj_xform(curname, 1, na-nn, alist+nn); else curobj->drawcode = DO_HIDE; + savedxf(curobj); break; case DO_SHOW: /* change rendering option */ case DO_LIGHT: case DO_HIDE: if (na > 1) goto toomany; dobj_lighting(na ? alist[0] : curname, cn); + somechange++; break; default: error(CONSISTENCY, "bad command id in dobj_command"); } - dev_view(&odev.v); /* redraw */ - return(cn); + return(somechange); toomany: - return(cmderror(cn, "too many arguments")); + cmderror(cn, "too many arguments"); + return(-1); } -dobj_load(oct, nam) /* create/load an octree object */ -char *oct, *nam; +extern int +dobj_load( /* create/load an octree object */ + char *oct, + char *nam +) { - extern char *getlibpath(), *getpath(); char *fpp, fpath[128]; register DOBJECT *op; /* check arguments */ @@ -531,18 +577,21 @@ char *oct, *nam; error(COMMAND, "missing name"); return(0); } - if (*nam == '*' | *nam == '-') { + if ((*nam == '*') | (*nam == '-')) { error(COMMAND, "illegal name"); return(0); } + if (getdobj(nam) != NULL) { + error(COMMAND, "name already taken (clear first)"); + return(0); + } /* get octree path */ - if ((fpp = getpath(oct, getlibpath(), R_OK)) == NULL) { + if ((fpp = getpath(oct, getrlibpath(), R_OK)) == NULL) { sprintf(errmsg, "cannot find octree \"%s\"", oct); error(COMMAND, errmsg); return(0); } strcpy(fpath, fpp); - freedobj(getdobj(nam)); /* free previous use of nam */ op = (DOBJECT *)malloc(sizeof(DOBJECT)); if (op == NULL) error(SYSTEM, "out of memory in dobj_load"); @@ -555,11 +604,12 @@ char *oct, *nam; op->xfav[op->xfac=0] = NULL; /* load octree into display list */ dolights = 0; - op->listid = rgl_octlist(fpath, op->center, &op->radius); + domats = 1; + op->listid = rgl_octlist(fpath, op->center, &op->radius, &op->nlists); /* start rtrace */ rtargv[RTARGC-1] = fpath; rtargv[RTARGC] = NULL; - open_process(op->rtp, rtargv); + open_process(&(op->rtp), rtargv); /* insert into main list */ op->next = dobjects; curobj = dobjects = op; @@ -568,8 +618,10 @@ char *oct, *nam; } -dobj_unload(nam) /* free the named object */ -char *nam; +extern int +dobj_unload( /* free the named object */ + char *nam +) { register DOBJECT *op; @@ -583,7 +635,8 @@ char *nam; } -dobj_cleanup() /* free all resources */ +extern int +dobj_cleanup(void) /* free all resources */ { register DLIGHTS *lp; @@ -592,34 +645,64 @@ dobj_cleanup() /* free all resources */ savedxf(curobj = NULL); while ((lp = dlightsets) != NULL) { dlightsets = lp->next; - free((char *)lp); + free((void *)lp); } return(1); } -dobj_xform(nam, add, ac, av) /* set/add transform for nam */ -char *nam; -int add, ac; -char **av; +extern int +dobj_xform( /* set/add transform for nam */ + char *nam, + int rel, + int ac, + char **av +) { register DOBJECT *op; + FVECT cent; + double rad; + char scoord[16]; + int i; if ((op = getdobj(nam)) == NULL) { error(COMMAND, "no object"); return(0); } - if (add) add = op->xfac; - if (ac + add > MAXAC) { + if (rel) + rel = op->xfac + 8; + if (ac + rel > MAXAC) { error(COMMAND, "too many transform arguments"); return(0); } - savedxf(curobj = op); - if (!add) + savedxf(curobj = op); /* remember current transform */ + if (rel && ac == 4 && !strcmp(av[0], "-t")) + rel = -1; /* don't move for translate */ + else { + getdcent(cent, op); /* don't move if near orig. */ + rad = getdrad(op); + if (DOT(cent,cent) < rad*rad) + rel = -1; + } + if (!rel) { /* remove old transform */ while (op->xfac) freestr(op->xfav[--op->xfac]); + } else if (rel > 0) { /* relative move */ + op->xfav[op->xfac++] = savestr("-t"); + for (i = 0; i < 3; i++) { + sprintf(scoord, "%.4e", -cent[i]); + op->xfav[op->xfac++] = savestr(scoord); + } + } while (ac--) op->xfav[op->xfac++] = savestr(*av++); + if (rel > 0) { /* move back */ + op->xfav[op->xfac++] = savestr("-t"); + for (i = 0; i < 3; i++) { + sprintf(scoord, "%.4e", cent[i]); + op->xfav[op->xfac++] = savestr(scoord); + } + } op->xfav[op->xfac] = NULL; if (fullxf(&op->xfb, op->xfac, op->xfav) != op->xfac) { error(COMMAND, "bad transform arguments"); @@ -633,9 +716,11 @@ char **av; } -dobj_putstats(nam, fp) /* put out statistics for nam */ -char *nam; -FILE *fp; +extern int +dobj_putstats( /* put out statistics for nam */ + char *nam, + FILE *fp +) { FVECT ocent; register DOBJECT *op; @@ -655,12 +740,12 @@ FILE *fp; error(COMMAND, "unknown object"); return(0); } - multp3(ocent, op->center, op->xfb.f.xfm); - fprintf(fp, "%s: %s, center [%f %f %f], radius %f", op->name, - op->drawcode==DO_HIDE ? "hid" : - op->drawcode==DO_LIGHT && op->ol!=NULL ? "lit" : + getdcent(ocent, op); + fprintf(fp, "%s: %s, center [%g %g %g], radius %g", op->name, + op->drawcode==DO_HIDE ? "hidden" : + op->drawcode==DO_LIGHT && op->ol!=NULL ? "lighted" : "shown", - ocent[0],ocent[1],ocent[2], op->radius*op->xfb.f.sca); + ocent[0],ocent[1],ocent[2], getdrad(op)); if (op->xfac) fputs(", (xform", fp); for (i = 0; i < op->xfac; i++) { @@ -674,7 +759,8 @@ FILE *fp; } -dobj_unmove() /* undo last transform change */ +extern int +dobj_unmove(void) /* undo last transform change */ { int txfac; char *txfav[MAXAC+1]; @@ -684,13 +770,13 @@ dobj_unmove() /* undo last transform change */ return(0); } /* hold last transform */ - bcopy((char *)lastxfav, (char *)txfav, + memcpy((void *)txfav, (void *)lastxfav, (txfac=lastxfac)*sizeof(char *)); /* save this transform */ - bcopy((char *)curobj->xfav, (char *)lastxfav, + memcpy((void *)lastxfav, (void *)curobj->xfav, (lastxfac=curobj->xfac)*sizeof(char *)); /* copy back last transform */ - bcopy((char *)txfav, (char *)curobj->xfav, + memcpy((void *)curobj->xfav, (void *)txfav, (curobj->xfac=txfac)*sizeof(char *)); /* set matrices */ fullxf(&curobj->xfb, curobj->xfac, curobj->xfav); @@ -700,8 +786,11 @@ dobj_unmove() /* undo last transform change */ } -dobj_dup(oldnm, nam) /* duplicate object oldnm as nam */ -char *oldnm, *nam; +extern int +dobj_dup( /* duplicate object oldnm as nam */ + char *oldnm, + char *nam +) { register DOBJECT *op, *opdup; /* check arguments */ @@ -713,15 +802,19 @@ char *oldnm, *nam; error(COMMAND, "missing name"); return(0); } - if (*nam == '*' | *nam == '-') { + if ((*nam == '*') | (*nam == '-')) { error(COMMAND, "illegal name"); return(0); } + if (getdobj(nam) != NULL) { + error(COMMAND, "name already taken (clear first)"); + return(0); + } /* allocate and copy struct */ opdup = (DOBJECT *)malloc(sizeof(DOBJECT)); if (opdup == NULL) error(SYSTEM, "out of memory in dobj_dup"); - copystruct(opdup, op); + *opdup = *op; /* rename */ strcpy(opdup->name, nam); /* get our own copy of transform */ @@ -735,9 +828,11 @@ char *oldnm, *nam; } -dobj_lighting(nam, cn) /* set up lighting for display object */ -char *nam; -int cn; +extern int +dobj_lighting( /* set up lighting for display object */ + char *nam, + int cn +) { int i, res[2]; VIEW *dv; @@ -756,9 +851,10 @@ int cn; } else if ((op = getdobj(nam)) == NULL) { error(COMMAND, "unknown object"); return(0); - } else if ((op->drawcode = cn) == DO_LIGHT) - getdlights(op, 1); - else + } else if ((op->drawcode = cn) == DO_LIGHT) { + if (!getdlights(op, 1)) + error(COMMAND, "insufficient samples to light object"); + } else op->ol = NULL; if (dobj_lightsamp != NULL) { /* restore beam set */ @@ -768,43 +864,66 @@ int cn; beam_view(dv, res[0], res[1]); beam_sync(1); /* update server */ } + return 0; /* XXX not sure if this is the right value */ } -double -dobj_trace(rorg, rdir) /* check for ray intersection with objects */ -FVECT rorg, rdir; +extern double +dobj_trace( /* check for ray intersection with object(s) */ + char nm[], + FVECT rorg, + FVECT rdir +) { register DOBJECT *op; FVECT xorg, xdir; - double darr[6], mindist = FHUGE; - /* check each visible object */ - for (op = dobjects; op != NULL; op = op->next) { - if (op->drawcode == DO_HIDE) - continue; - if (op->xfac) { /* transform ray */ - multp3(xorg, rorg, op->xfb.b.xfm); - multv3(xdir, rdir, op->xfb.b.xfm); - VCOPY(darr, xorg); VCOPY(darr+3, xdir); - } else { - VCOPY(darr, rorg); VCOPY(darr+3, rdir); + double darr[6]; + /* check each visible object? */ + if (nm == NULL || *nm == '*') { + double dist, mindist = 1.01*FHUGE; + + if (nm != NULL) nm[0] = '\0'; + for (op = dobjects; op != NULL; op = op->next) { + if (op->drawcode == DO_HIDE) + continue; + dist = dobj_trace(op->name, rorg, rdir); + if (dist < mindist) { + if (nm != NULL) strcpy(nm, op->name); + mindist = dist; + } } - /* trace it */ - if (process(op->rtp, darr, darr, sizeof(double), - 6*sizeof(double)) != sizeof(double)) - error(SYSTEM, "rtrace communication error"); - /* get closest */ - if ((darr[0] *= op->xfb.f.sca) < mindist) - mindist = darr[0]; + return(mindist); } - return(mindist); + /* else check particular object */ + if ((op = getdobj(nm)) == NULL) { + error(COMMAND, "unknown object"); + return(FHUGE); + } + if (op->xfac) { /* put ray in local coordinates */ + multp3(xorg, rorg, op->xfb.b.xfm); + multv3(xdir, rdir, op->xfb.b.xfm); + VCOPY(darr, xorg); VCOPY(darr+3, xdir); + } else { + VCOPY(darr, rorg); VCOPY(darr+3, rdir); + } + /* trace it */ + if (process(&(op->rtp), (char *)darr, (char *)darr, sizeof(double), + 6*sizeof(double)) != sizeof(double)) + error(SYSTEM, "rtrace communication error"); + /* return distance */ + if (darr[0] >= .99*FHUGE) + return(FHUGE); + return(darr[0]*op->xfb.f.sca); } -dobj_render() /* render our objects in OpenGL */ +extern int +dobj_render(void) /* render our objects in OpenGL */ { + int nrendered = 0; GLboolean normalizing; GLfloat vec[4]; + FVECT v1; register DOBJECT *op; register int i; /* anything to render? */ @@ -812,11 +931,11 @@ dobj_render() /* render our objects in OpenGL */ if (op->drawcode != DO_HIDE) break; if (op == NULL) - return(1); + return(0); /* set up general rendering params */ glGetBooleanv(GL_NORMALIZE, &normalizing); - glPushAttrib(GL_LIGHTING_BIT|GL_TRANSFORM_BIT| - GL_DEPTH_BUFFER_BIT|GL_POLYGON_BIT); + glPushAttrib(GL_LIGHTING_BIT|GL_TRANSFORM_BIT|GL_ENABLE_BIT| + GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_POLYGON_BIT); glDepthFunc(GL_LESS); glEnable(GL_DEPTH_TEST); glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); @@ -836,7 +955,7 @@ dobj_render() /* render our objects in OpenGL */ if (op->drawcode == DO_LIGHT && op->ol != NULL) { BYTE pval; double expval, d; - + /* use computed sources */ if (tmMapPixels(&pval, &op->ol->larb, TM_NOCHROM, 1) != TM_E_OK) error(CONSISTENCY, "dobj_render w/o tone map"); @@ -862,14 +981,30 @@ dobj_render() /* render our objects in OpenGL */ glLightfv(glightid[i], GL_AMBIENT, vec); glEnable(glightid[i]); } - } else { - vec[0] = vec[1] = vec[2] = 1.; vec[3] = 1.; + } else { /* fake lighting */ + vec[0] = vec[1] = vec[2] = 0.; vec[3] = 1.; glLightModelfv(GL_LIGHT_MODEL_AMBIENT, vec); + getdcent(v1, op); + VSUB(v1, odev.v.vp, v1); + if (normalize(v1) <= getdrad(op)) { + vec[0] = -odev.v.vdir[0]; + vec[1] = -odev.v.vdir[1]; + vec[2] = -odev.v.vdir[2]; + } else + VCOPY(vec, v1); + vec[3] = 0.; + glLightfv(GL_LIGHT0, GL_POSITION, vec); + vec[0] = vec[1] = vec[2] = .7; vec[3] = 1.; + glLightfv(GL_LIGHT0, GL_SPECULAR, vec); + glLightfv(GL_LIGHT0, GL_DIFFUSE, vec); + vec[0] = vec[1] = vec[2] = .3; vec[3] = 1.; + glLightfv(GL_LIGHT0, GL_AMBIENT, vec); + glEnable(GL_LIGHT0); } /* set up object transform */ if (op->xfac) { - if (!normalizing && op->xfb.f.sca < 1.-FTINY | - op->xfb.f.sca > 1.+FTINY) + if (!normalizing && (op->xfb.f.sca < 1.-FTINY) | + (op->xfb.f.sca > 1.+FTINY)) glEnable(GL_NORMALIZE); glMatrixMode(GL_MODELVIEW); glPushMatrix(); @@ -882,6 +1017,7 @@ dobj_render() /* render our objects in OpenGL */ } /* render the display list */ glCallList(op->listid); + nrendered++; /* restore matrix */ if (op->xfac) { glMatrixMode(GL_MODELVIEW); @@ -893,9 +1029,11 @@ dobj_render() /* render our objects in OpenGL */ if (op->drawcode == DO_LIGHT && op->ol != NULL) for (i = op->ol->nl; i--; ) glDisable(glightid[i]); + else + glDisable(GL_LIGHT0); /* check errors */ - rgl_checkerr("rendering object in dobj_render"); } glPopAttrib(); /* restore rendering params */ - return(1); + rgl_checkerr("rendering objects in dobj_render"); + return(nrendered); }