ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/rhdobj.c
(Generate patch)

Comparing ray/src/hd/rhdobj.c (file contents):
Revision 3.1 by gwlarson, Wed Aug 19 17:45:24 1998 UTC vs.
Revision 3.10 by gwlarson, Fri Jan 29 15:33:36 1999 UTC

# Line 5 | Line 5 | static char SCCSid[] = "$SunId$ SGI";
5   #endif
6  
7   /*
8 < * Routines for loading and displaying Radiance objects under OpenGL in rholo.
8 > * Routines for loading and displaying Radiance objects in rholo with GLX.
9   */
10  
11   #include "radogl.h"
# Line 22 | Line 22 | int    (*dobj_lightsamp)() = NULL;     /* pointer to function
22  
23   #define AVGREFL         0.5             /* assumed average reflectance */
24  
25 < #define MAXAC           64              /* maximum number of args */
25 > #define MAXAC           512             /* maximum number of args */
26  
27   #ifndef MINTHRESH
28 < #define MINTHRESH       7.0             /* source threshold w.r.t. mean */
28 > #define MINTHRESH       5.0             /* source threshold w.r.t. mean */
29   #endif
30  
31   #ifndef NALT
# Line 55 | Line 55 | typedef struct dobject {
55          FVECT   center;                 /* orig. object center */
56          FLOAT   radius;                 /* orig. object radius */
57          int     listid;                 /* GL display list identifier */
58 +        int     nlists;                 /* number of lists allocated */
59          int     rtp[3];                 /* associated rtrace process */
60          DLIGHTS *ol;                    /* object lights */
61          FULLXF  xfb;                    /* coordinate transform */
# Line 69 | Line 70 | static DOBJECT *curobj;                /* current (last referred) ob
70   static int      lastxfac;               /* last number of transform args */
71   static char     *lastxfav[MAXAC+1];     /* saved transform arguments */
72  
73 + #define getdcent(c,op)  multp3(c,(op)->center,(op)->xfb.f.xfm)
74 + #define getdrad(op)     ((op)->radius*(op)->xfb.f.sca)
75 +
76   #define RTARGC  8
77   static char     *rtargv[RTARGC+1] = {"rtrace", "-h-", "-w-", "-fdd",
78                                          "-x", "1", "-oL"};
# Line 116 | Line 120 | register DOBJECT       *op;
120          }
121          dobjects = ohead.next;
122          if (!foundlink) {
123 <                glDeleteLists(op->listid, 1);
123 >                glDeleteLists(op->listid, op->nlists);
124                  close_process(op->rtp);
125          }
126          while (op->xfac)
# Line 279 | Line 283 | ssph_compute()                 /* compute source set from sphere sam
283                                  ncells++;
284                          }
285          if (dlightsets == NULL | ncells < NALT*NAZI/4) {
286 <                bzero((char *)ssamp, sizeof(ssamp));
287 <                return(0);
286 >                ncells = 0;
287 >                goto done;
288          }
289                                                  /* harmonic mean distance */
290          if (dlightsets->ravg > FTINY)
# Line 289 | Line 293 | ssph_compute()                 /* compute source set from sphere sam
293                  dlightsets->ravg = FHUGE;
294                                                  /* light source threshold */
295          thresh = MINTHRESH*bright(csum)/ncells;
296 +        if (thresh <= FTINY) {
297 +                ncells = 0;
298 +                goto done;
299 +        }
300                                                  /* avg. reflected brightness */
301          d = AVGREFL / (double)ncells;  
302          scalecolor(csum, d);
303          if (tmCvColors(&dlightsets->larb, TM_NOCHROM, csum, 1) != TM_E_OK)
304 <                error(CONSISTENCY, "bad tone mapping in ssph_compute");
304 >                error(CONSISTENCY, "tone mapping problem in ssph_compute");
305                                          /* greedy light source clustering */
306          while (dlightsets->nl < MAXLIGHTS) {
307                  maxbr = 0.;                     /* find brightest cell */
# Line 313 | Line 321 | ssph_compute()                 /* compute source set from sphere sam
321                                  continue;               /* too dim */
322                          ssph_direc(v, alt, azi);        /* else add it in */
323                          VSUM(ls->direc, ls->direc, v, d);
324 <                        ls->omega++;
324 >                        ls->omega += 1.;
325                          addcolor(ls->val, ssamp[alt][azi].val);
326 +                                                        /* remove from list */
327                          setcolor(ssamp[alt][azi].val, 0., 0., 0.);
328 +                        ssamp[alt][azi].nsamp = 0;
329                  }
330                  d = 1./ls->omega;                       /* avg. brightness */
331                  scalecolor(ls->val, d);
# Line 329 | Line 339 | ssph_compute()                 /* compute source set from sphere sam
339                                  addcolor(dlightsets->lamb, ssamp[alt][azi].val);
340          d = 1.0/ncells;
341          scalecolor(dlightsets->lamb, d);
342 <                                        /* clear sphere sample array */
342 > done:                                   /* clear sphere sample array */
343          bzero((char *)ssamp, sizeof(ssamp));
344          return(ncells);
345   }
# Line 349 | Line 359 | int    force;
359          if (op->drawcode != DO_LIGHT)
360                  return(0);
361                                          /* check for usable light set */
362 <        multp3(ocent, op->center, op->xfb.f.xfm);
362 >        getdcent(ocent, op);
363          for (dl = dlightsets; dl != NULL; dl = dl->next)
364                  if ((d2 = dist2(dl->lcent, ocent)) < mind2) {
365                          op->ol = dl;
366                          mind2 = d2;
367                  }
368                                          /* the following is heuristic */
369 <        d2 = 2.*op->radius*op->xfb.f.sca; d2 *= d2;
369 >        d2 = 2.*getdrad(op); d2 *= d2;
370          if ((dl = op->ol) != NULL && (mind2 < 0.0625*dl->ravg*dl->ravg ||
371 <                mind2 < 4.*op->radius*op->xfb.f.sca*op->radius*op->xfb.f.sca))
371 >                        mind2 < 4.*getdrad(op)*getdrad(op)))
372                  return(1);
373          if (!force)
374                  return(0);
# Line 407 | Line 417 | memerr:
417   }
418  
419  
420 < static int
420 > static
421   cmderror(cn, err)               /* report command error */
422   int     cn;
423   char    *err;
424   {
425          sprintf(errmsg, "%s: %s", rhdcmd[cn], err);
426          error(COMMAND, errmsg);
417        return(cn);
427   }
428  
429  
# Line 423 | Line 432 | dobj_command(cmd, args)                /* run object display command
432   char    *cmd;
433   register char   *args;
434   {
435 +        int     somechange = 0;
436          int     cn, na, doxfm;
437          register int    nn;
438          char    *alist[MAXAC+1], *nm;
# Line 450 | Line 460 | register char  *args;
460                          dobj_load(alist[0], alist[0]);
461                  else if (na == 2)
462                          dobj_load(alist[0], alist[1]);
463 <                else
464 <                        return(cmderror(cn, "need octree [name]"));
463 >                else {
464 >                        cmderror(cn, "need octree [name]");
465 >                        return(0);
466 >                }
467                  break;
468 <        case DO_UNLOAD:                         /* unload an object */
468 >        case DO_UNLOAD:                         /* clear an object */
469                  if (na > 1) goto toomany;
470                  if (na && alist[0][0] == '*')
471 <                        dobj_cleanup();
471 >                        somechange += dobj_cleanup();
472                  else
473 <                        dobj_unload(na ? alist[0] : curname);
473 >                        somechange += dobj_unload(na ? alist[0] : curname);
474                  break;
475          case DO_XFORM:                          /* transform object */
476          case DO_MOVE:
# Line 467 | Line 479 | register char  *args;
479                  } else {
480                          nm = curname; nn = 0;
481                  }
482 <                if (cn == DO_MOVE && nn >= na)
483 <                        return(cmderror(cn, "missing transform"));
484 <                dobj_xform(nm, cn==DO_MOVE, na-nn, alist+nn);
482 >                if (cn == DO_MOVE && nn >= na) {
483 >                        cmderror(cn, "missing transform");
484 >                        return(0);
485 >                }
486 >                somechange += dobj_xform(nm, cn==DO_MOVE, na-nn, alist+nn);
487                  break;
488          case DO_UNMOVE:                         /* undo last transform */
489 <                dobj_unmove();
489 >                somechange += dobj_unmove();
490                  break;
491          case DO_OBJECT:                         /* print object statistics */
492 <                dobj_putstats(na ? alist[0] : curname, sstdout);
492 >                if (dobj_putstats(na ? alist[0] : curname, sstdout))
493 >                        if (na && alist[0][0] != '*' && (curobj == NULL ||
494 >                                        strcmp(alist[0], curobj->name)))
495 >                                savedxf(curobj = getdobj(alist[0]));
496                  break;
497          case DO_DUP:                            /* duplicate object */
498                  for (nn = 0; nn < na; nn++)
# Line 483 | Line 500 | register char  *args;
500                                  break;
501                  switch (nn) {
502                  case 0:
503 <                        return(cmderror(cn, "need new object name"));
503 >                        cmderror(cn, "need new object name");
504 >                        return(0);
505                  case 1:
506                          nm = curname;
507                          break;
# Line 496 | Line 514 | register char  *args;
514                  if (!dobj_dup(nm, alist[nn-1]))
515                          break;
516                  if (na > nn)
517 <                        dobj_xform(curname, 1, na-nn, alist+nn);
517 >                        somechange += dobj_xform(curname, 1, na-nn, alist+nn);
518                  else
519                          curobj->drawcode = DO_HIDE;
520 +                savedxf(curobj);
521                  break;
522          case DO_SHOW:                           /* change rendering option */
523          case DO_LIGHT:
524          case DO_HIDE:
525                  if (na > 1) goto toomany;
526                  dobj_lighting(na ? alist[0] : curname, cn);
527 +                somechange++;
528                  break;
529          default:
530                  error(CONSISTENCY, "bad command id in dobj_command");
531          }
532 <        dev_view(&odev.v);                      /* redraw */
513 <        return(cn);
532 >        return(somechange);
533   toomany:
534          return(cmderror(cn, "too many arguments"));
535   }
# Line 535 | Line 554 | char   *oct, *nam;
554                  error(COMMAND, "illegal name");
555                  return(0);
556          }
557 +        if (getdobj(nam) != NULL) {
558 +                error(COMMAND, "name already taken (clear first)");
559 +                return(0);
560 +        }
561                                          /* get octree path */
562          if ((fpp = getpath(oct, getlibpath(), R_OK)) == NULL) {
563                  sprintf(errmsg, "cannot find octree \"%s\"", oct);
# Line 542 | Line 565 | char   *oct, *nam;
565                  return(0);
566          }
567          strcpy(fpath, fpp);
545        freedobj(getdobj(nam));         /* free previous use of nam */
568          op = (DOBJECT *)malloc(sizeof(DOBJECT));
569          if (op == NULL)
570                  error(SYSTEM, "out of memory in dobj_load");
# Line 555 | Line 577 | char   *oct, *nam;
577          op->xfav[op->xfac=0] = NULL;
578                                          /* load octree into display list */
579          dolights = 0;
580 <        op->listid = rgl_octlist(fpath, op->center, &op->radius);
580 >        domats = 1;
581 >        op->listid = rgl_octlist(fpath, op->center, &op->radius, &op->nlists);
582                                          /* start rtrace */
583          rtargv[RTARGC-1] = fpath;
584          rtargv[RTARGC] = NULL;
# Line 598 | Line 621 | dobj_cleanup()                         /* free all resources */
621   }
622  
623  
624 < dobj_xform(nam, add, ac, av)            /* set/add transform for nam */
624 > dobj_xform(nam, rel, ac, av)            /* set/add transform for nam */
625   char    *nam;
626 < int     add, ac;
626 > int     rel, ac;
627   char    **av;
628   {
629          register DOBJECT        *op;
630 +        FVECT   cent;
631 +        double  rad;
632 +        char    scoord[16];
633 +        int     i;
634  
635          if ((op = getdobj(nam)) == NULL) {
636                  error(COMMAND, "no object");
637                  return(0);
638          }
639 <        if (add) add = op->xfac;
640 <        if (ac + add > MAXAC) {
639 >        if (rel)
640 >                rel = op->xfac + 8;
641 >        if (ac + rel > MAXAC) {
642                  error(COMMAND, "too many transform arguments");
643                  return(0);
644          }
645 <        savedxf(curobj = op);
646 <        if (!add)
645 >        savedxf(curobj = op);           /* remember current transform */
646 >        if (rel && ac == 4 && !strcmp(av[0], "-t"))
647 >                rel = -1;                       /* don't move for translate */
648 >        else {
649 >                getdcent(cent, op);             /* don't move if near orig. */
650 >                rad = getdrad(op);
651 >                if (DOT(cent,cent) < rad*rad)
652 >                        rel = -1;
653 >        }
654 >        if (!rel) {                             /* remove old transform */
655                  while (op->xfac)
656                          freestr(op->xfav[--op->xfac]);
657 +        } else if (rel > 0) {                   /* relative move */
658 +                op->xfav[op->xfac++] = savestr("-t");
659 +                for (i = 0; i < 3; i++) {
660 +                        sprintf(scoord, "%.4e", -cent[i]);
661 +                        op->xfav[op->xfac++] = savestr(scoord);
662 +                }
663 +        }
664          while (ac--)
665                  op->xfav[op->xfac++] = savestr(*av++);
666 +        if (rel > 0) {                          /* move back */
667 +                op->xfav[op->xfac++] = savestr("-t");
668 +                for (i = 0; i < 3; i++) {
669 +                        sprintf(scoord, "%.4e", cent[i]);
670 +                        op->xfav[op->xfac++] = savestr(scoord);
671 +                }
672 +        }
673          op->xfav[op->xfac] = NULL;
674          if (fullxf(&op->xfb, op->xfac, op->xfav) != op->xfac) {
675                  error(COMMAND, "bad transform arguments");
# Line 655 | Line 705 | FILE   *fp;
705                  error(COMMAND, "unknown object");
706                  return(0);
707          }
708 <        multp3(ocent, op->center, op->xfb.f.xfm);
709 <        fprintf(fp, "%s: %s, center [%f %f %f], radius %f", op->name,
710 <                        op->drawcode==DO_HIDE ? "hid" :
711 <                        op->drawcode==DO_LIGHT && op->ol!=NULL ? "lit" :
708 >        getdcent(ocent, op);
709 >        fprintf(fp, "%s: %s, center [%g %g %g], radius %g", op->name,
710 >                        op->drawcode==DO_HIDE ? "hidden" :
711 >                        op->drawcode==DO_LIGHT && op->ol!=NULL ? "lighted" :
712                          "shown",
713 <                        ocent[0],ocent[1],ocent[2], op->radius*op->xfb.f.sca);
713 >                        ocent[0],ocent[1],ocent[2], getdrad(op));
714          if (op->xfac)
715                  fputs(", (xform", fp);
716          for (i = 0; i < op->xfac; i++) {
# Line 717 | Line 767 | char   *oldnm, *nam;
767                  error(COMMAND, "illegal name");
768                  return(0);
769          }
770 +        if (getdobj(nam) != NULL) {
771 +                error(COMMAND, "name already taken (clear first)");
772 +                return(0);
773 +        }
774                                          /* allocate and copy struct */
775          opdup = (DOBJECT *)malloc(sizeof(DOBJECT));
776          if (opdup == NULL)
# Line 756 | Line 810 | int    cn;
810          } else if ((op = getdobj(nam)) == NULL) {
811                  error(COMMAND, "unknown object");
812                  return(0);
813 <        } else if ((op->drawcode = cn) == DO_LIGHT)
814 <                getdlights(op, 1);
815 <        else
813 >        } else if ((op->drawcode = cn) == DO_LIGHT) {
814 >                if (!getdlights(op, 1))
815 >                        error(COMMAND, "insufficient samples to light object");
816 >        } else
817                  op->ol = NULL;
818  
819          if (dobj_lightsamp != NULL) {           /* restore beam set */
# Line 772 | Line 827 | int    cn;
827  
828  
829   double
830 < dobj_trace(rorg, rdir)          /* check for ray intersection with objects */
830 > dobj_trace(nm, rorg, rdir)      /* check for ray intersection with object(s) */
831 > char    nm[];
832   FVECT   rorg, rdir;
833   {
834          register DOBJECT        *op;
835          FVECT   xorg, xdir;
836 <        double  darr[6], mindist = FHUGE;
837 <                                        /* check each visible object */
838 <        for (op = dobjects; op != NULL; op = op->next) {
839 <                if (op->drawcode == DO_HIDE)
840 <                        continue;
841 <                if (op->xfac) {         /* transform ray */
842 <                        multp3(xorg, rorg, op->xfb.b.xfm);
843 <                        multv3(xdir, rdir, op->xfb.b.xfm);
844 <                        VCOPY(darr, xorg); VCOPY(darr+3, xdir);
845 <                } else {
846 <                        VCOPY(darr, rorg); VCOPY(darr+3, rdir);
836 >        double  darr[6];
837 >                                        /* check each visible object? */
838 >        if (nm == NULL || *nm == '*') {
839 >                double  dist, mindist = 1.01*FHUGE;
840 >
841 >                if (nm != NULL) nm[0] = '\0';
842 >                for (op = dobjects; op != NULL; op = op->next) {
843 >                        if (op->drawcode == DO_HIDE)
844 >                                continue;
845 >                        dist = dobj_trace(op->name, rorg, rdir);
846 >                        if (dist < mindist) {
847 >                                if (nm != NULL) strcpy(nm, op->name);
848 >                                mindist = dist;
849 >                        }
850                  }
851 <                                        /* trace it */
793 <                if (process(op->rtp, darr, darr, sizeof(double),
794 <                                6*sizeof(double)) != sizeof(double))
795 <                        error(SYSTEM, "rtrace communication error");
796 <                                        /* get closest */
797 <                if ((darr[0] *= op->xfb.f.sca) < mindist)
798 <                        mindist = darr[0];
851 >                return(mindist);
852          }
853 <        return(mindist);
853 >                                        /* else check particular object */
854 >        if ((op = getdobj(nm)) == NULL) {
855 >                error(COMMAND, "unknown object");
856 >                return(FHUGE);
857 >        }
858 >        if (op->xfac) {         /* put ray in local coordinates */
859 >                multp3(xorg, rorg, op->xfb.b.xfm);
860 >                multv3(xdir, rdir, op->xfb.b.xfm);
861 >                VCOPY(darr, xorg); VCOPY(darr+3, xdir);
862 >        } else {
863 >                VCOPY(darr, rorg); VCOPY(darr+3, rdir);
864 >        }
865 >                                /* trace it */
866 >        if (process(op->rtp, darr, darr, sizeof(double),
867 >                        6*sizeof(double)) != sizeof(double))
868 >                error(SYSTEM, "rtrace communication error");
869 >                                /* return distance */
870 >        if (darr[0] >= .99*FHUGE)
871 >                return(FHUGE);
872 >        return(darr[0]*op->xfb.f.sca);
873   }
874  
875  
876 + int
877   dobj_render()                   /* render our objects in OpenGL */
878   {
879 +        int     nrendered = 0;
880          GLboolean       normalizing;
881          GLfloat vec[4];
882 +        FVECT   v1;
883          register DOBJECT        *op;
884          register int    i;
885                                          /* anything to render? */
# Line 812 | Line 887 | dobj_render()                  /* render our objects in OpenGL */
887                  if (op->drawcode != DO_HIDE)
888                          break;
889          if (op == NULL)
890 <                return(1);
890 >                return(0);
891                                          /* set up general rendering params */
892          glGetBooleanv(GL_NORMALIZE, &normalizing);
893 <        glPushAttrib(GL_LIGHTING_BIT|GL_TRANSFORM_BIT|
894 <                        GL_DEPTH_BUFFER_BIT|GL_POLYGON_BIT);
893 >        glPushAttrib(GL_LIGHTING_BIT|GL_TRANSFORM_BIT|GL_ENABLE_BIT|
894 >                GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_POLYGON_BIT);
895          glDepthFunc(GL_LESS);
896          glEnable(GL_DEPTH_TEST);
897          glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
# Line 836 | Line 911 | dobj_render()                  /* render our objects in OpenGL */
911                  if (op->drawcode == DO_LIGHT && op->ol != NULL) {
912                          BYTE    pval;
913                          double  expval, d;
914 <
914 >                                                /* use computed sources */
915                          if (tmMapPixels(&pval, &op->ol->larb, TM_NOCHROM, 1)
916                                          != TM_E_OK)
917                                  error(CONSISTENCY, "dobj_render w/o tone map");
# Line 862 | Line 937 | dobj_render()                  /* render our objects in OpenGL */
937                                  glLightfv(glightid[i], GL_AMBIENT, vec);
938                                  glEnable(glightid[i]);
939                          }
940 <                } else {
941 <                        vec[0] = vec[1] = vec[2] = 1.; vec[3] = 1.;
940 >                } else {                        /* fake lighting */
941 >                        vec[0] = vec[1] = vec[2] = 0.; vec[3] = 1.;
942                          glLightModelfv(GL_LIGHT_MODEL_AMBIENT, vec);
943 +                        getdcent(v1, op);
944 +                        VSUB(v1, odev.v.vp, v1);
945 +                        if (normalize(v1) <= getdrad(op)) {
946 +                                vec[0] = -odev.v.vdir[0];
947 +                                vec[1] = -odev.v.vdir[1];
948 +                                vec[2] = -odev.v.vdir[2];
949 +                        } else
950 +                                VCOPY(vec, v1);
951 +                        vec[3] = 0.;
952 +                        glLightfv(GL_LIGHT0, GL_POSITION, vec);
953 +                        vec[0] = vec[1] = vec[2] = .7; vec[3] = 1.;
954 +                        glLightfv(GL_LIGHT0, GL_SPECULAR, vec);
955 +                        glLightfv(GL_LIGHT0, GL_DIFFUSE, vec);
956 +                        vec[0] = vec[1] = vec[2] = .3; vec[3] = 1.;
957 +                        glLightfv(GL_LIGHT0, GL_AMBIENT, vec);
958 +                        glEnable(GL_LIGHT0);
959                  }
960                                          /* set up object transform */
961                  if (op->xfac) {
# Line 882 | Line 973 | dobj_render()                  /* render our objects in OpenGL */
973                  }
974                                          /* render the display list */
975                  glCallList(op->listid);
976 +                nrendered++;
977                                          /* restore matrix */
978                  if (op->xfac) {
979                          glMatrixMode(GL_MODELVIEW);
# Line 893 | Line 985 | dobj_render()                  /* render our objects in OpenGL */
985                  if (op->drawcode == DO_LIGHT && op->ol != NULL)
986                          for (i = op->ol->nl; i--; )
987                                  glDisable(glightid[i]);
988 +                else
989 +                        glDisable(GL_LIGHT0);
990                                          /* check errors */
897                rgl_checkerr("rendering object in dobj_render");
991          }
992          glPopAttrib();                  /* restore rendering params */
993 <        return(1);
993 >        rgl_checkerr("rendering objects in dobj_render");
994 >        return(nrendered);
995   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines