--- ray/src/hd/rhdobj.c 1998/08/21 11:38:22 3.2 +++ ray/src/hd/rhdobj.c 1998/12/31 12:57:06 3.9 @@ -5,7 +5,7 @@ static char SCCSid[] = "$SunId$ SGI"; #endif /* - * Routines for loading and displaying Radiance objects under OpenGL in rholo. + * Routines for loading and displaying Radiance objects in rholo with GLX. */ #include "radogl.h" @@ -22,7 +22,7 @@ int (*dobj_lightsamp)() = NULL; /* pointer to function #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 5.0 /* source threshold w.r.t. mean */ @@ -320,9 +320,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); @@ -414,14 +416,13 @@ memerr: } -static int +static cmderror(cn, err) /* report command error */ int cn; char *err; { sprintf(errmsg, "%s: %s", rhdcmd[cn], err); error(COMMAND, errmsg); - return(cn); } @@ -430,6 +431,7 @@ dobj_command(cmd, args) /* run object display command char *cmd; register char *args; { + int somechange = 0; int cn, na, doxfm; register int nn; char *alist[MAXAC+1], *nm; @@ -457,15 +459,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: @@ -474,15 +478,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++) @@ -490,7 +499,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; @@ -503,21 +513,22 @@ 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")); } @@ -542,6 +553,10 @@ char *oct, *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) { sprintf(errmsg, "cannot find octree \"%s\"", oct); @@ -549,7 +564,6 @@ char *oct, *nam; 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"); @@ -562,6 +576,7 @@ char *oct, *nam; op->xfav[op->xfac=0] = NULL; /* load octree into display list */ dolights = 0; + domats = 1; op->listid = rgl_octlist(fpath, op->center, &op->radius); /* start rtrace */ rtargv[RTARGC-1] = fpath; @@ -605,28 +620,55 @@ dobj_cleanup() /* free all resources */ } -dobj_xform(nam, add, ac, av) /* set/add transform for nam */ +dobj_xform(nam, rel, ac, av) /* set/add transform for nam */ char *nam; -int add, ac; +int rel, 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"); @@ -663,9 +705,9 @@ FILE *fp; return(0); } getdcent(ocent, op); - 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" : + 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], getdrad(op)); if (op->xfac) @@ -724,6 +766,10 @@ char *oldnm, *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) @@ -763,9 +809,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 */ @@ -786,18 +833,18 @@ FVECT rorg, rdir; register DOBJECT *op; FVECT xorg, xdir; double darr[6]; - + /* check each visible object? */ if (nm == NULL || *nm == '*') { double dist, mindist = 1.01*FHUGE; - /* check each visible object */ + + 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) { - dist = mindist; - if (nm != NULL) - strcpy(nm, op->name); + if (nm != NULL) strcpy(nm, op->name); + mindist = dist; } } return(mindist); @@ -807,7 +854,7 @@ FVECT rorg, rdir; error(COMMAND, "unknown object"); return(FHUGE); } - if (op->xfac) { /* transform ray */ + 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); @@ -821,12 +868,14 @@ FVECT rorg, rdir; /* return distance */ if (darr[0] >= .99*FHUGE) return(FHUGE); - return(darr[0] * op->xfb.f.sca); + return(darr[0]*op->xfb.f.sca); } +int dobj_render() /* render our objects in OpenGL */ { + int nrendered = 0; GLboolean normalizing; GLfloat vec[4]; FVECT v1; @@ -837,11 +886,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); @@ -887,7 +936,7 @@ dobj_render() /* render our objects in OpenGL */ glLightfv(glightid[i], GL_AMBIENT, vec); glEnable(glightid[i]); } - } else { /* no sources to draw on */ + } else { /* fake lighting */ vec[0] = vec[1] = vec[2] = 0.; vec[3] = 1.; glLightModelfv(GL_LIGHT_MODEL_AMBIENT, vec); getdcent(v1, op); @@ -923,6 +972,7 @@ dobj_render() /* render our objects in OpenGL */ } /* render the display list */ glCallList(op->listid); + nrendered++; /* restore matrix */ if (op->xfac) { glMatrixMode(GL_MODELVIEW); @@ -937,8 +987,8 @@ dobj_render() /* render our objects in OpenGL */ 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); }