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.16 by schorsch, Thu Jan 1 11:21:55 2004 UTC

# Line 1 | Line 1
1 /* Copyright (c) 1998 Silicon Graphics, Inc. */
2
1   #ifndef lint
2 < static char SCCSid[] = "$SunId$ SGI";
2 > static const char       RCSid[] = "$Id$";
3   #endif
6
4   /*
5 < * Routines for loading and displaying Radiance objects under OpenGL in rholo.
5 > * Routines for loading and displaying Radiance objects in rholo with GLX.
6   */
7  
8 + #include <string.h>
9 + #include <ctype.h>
10 +
11   #include "radogl.h"
12   #include "tonemap.h"
13   #include "rhdisp.h"
14   #include "rhdriver.h"
15   #include "rhdobj.h"
16 + #include "rtprocess.h"
17  
18   extern FILE     *sstdout;               /* user standard output */
19  
20   char    rhdcmd[DO_NCMDS][8] = DO_INIT;  /* user command list */
21  
22 < int     (*dobj_lightsamp)() = NULL;     /* pointer to function to get lights */
22 > /* pointer to function to get lights */
23 > void    (*dobj_lightsamp)(COLR clr, FVECT direc, FVECT pos) = NULL;
24  
25   #define AVGREFL         0.5             /* assumed average reflectance */
26  
27 < #define MAXAC           64              /* maximum number of args */
27 > #define MAXAC           512             /* maximum number of args */
28  
29   #ifndef MINTHRESH
30 < #define MINTHRESH       7.0             /* source threshold w.r.t. mean */
30 > #define MINTHRESH       5.0             /* source threshold w.r.t. mean */
31   #endif
32  
33   #ifndef NALT
# Line 53 | Line 55 | typedef struct dobject {
55          struct dobject  *next;          /* next object in list */
56          char    name[64];               /* object name */
57          FVECT   center;                 /* orig. object center */
58 <        FLOAT   radius;                 /* orig. object radius */
58 >        RREAL   radius;                 /* orig. object radius */
59          int     listid;                 /* GL display list identifier */
60 <        int     rtp[3];                 /* associated rtrace process */
60 >        int     nlists;                 /* number of lists allocated */
61 >        SUBPROC rtp;                    /* associated rtrace process */
62          DLIGHTS *ol;                    /* object lights */
63          FULLXF  xfb;                    /* coordinate transform */
64          short   drawcode;               /* drawing code */
# Line 69 | Line 72 | static DOBJECT *curobj;                /* current (last referred) ob
72   static int      lastxfac;               /* last number of transform args */
73   static char     *lastxfav[MAXAC+1];     /* saved transform arguments */
74  
75 + #define getdcent(c,op)  multp3(c,(op)->center,(op)->xfb.f.xfm)
76 + #define getdrad(op)     ((op)->radius*(op)->xfb.f.sca)
77 +
78   #define RTARGC  8
79   static char     *rtargv[RTARGC+1] = {"rtrace", "-h-", "-w-", "-fdd",
80                                          "-x", "1", "-oL"};
# Line 80 | Line 86 | static struct {
86  
87   #define curname         (curobj==NULL ? (char *)NULL : curobj->name)
88  
89 + static DOBJECT *getdobj(char *nm);
90 + static int freedobj(DOBJECT *op);
91 + static int savedxf(DOBJECT *op);
92 + static void ssph_sample(COLR clr, FVECT direc, FVECT pos);
93 + static void ssph_direc(FVECT direc, int alt, int azi);
94 + static int ssph_neigh(int sp[2], int next);
95 + static int ssph_compute(void);
96 + static int getdlights(DOBJECT *op, int force);
97 + static void cmderror(int cn, char *err);
98  
99 +
100   static DOBJECT *
101 < getdobj(nm)                     /* get object from list by name */
102 < char    *nm;
101 > getdobj(                        /* get object from list by name */
102 >        char    *nm
103 > )
104   {
105          register DOBJECT        *op;
106  
# Line 98 | Line 115 | char   *nm;
115   }
116  
117  
118 < static
119 < freedobj(op)                    /* free resources and memory assoc. with op */
120 < register DOBJECT        *op;
118 > static int
119 > freedobj(                       /* free resources and memory assoc. with op */
120 >        register DOBJECT        *op
121 > )
122   {
123          int     foundlink = 0;
124          DOBJECT ohead;
# Line 116 | Line 134 | register DOBJECT       *op;
134          }
135          dobjects = ohead.next;
136          if (!foundlink) {
137 <                glDeleteLists(op->listid, 1);
138 <                close_process(op->rtp);
137 >                glDeleteLists(op->listid, op->nlists);
138 >                close_process(&(op->rtp));
139          }
140          while (op->xfac)
141                  freestr(op->xfav[--op->xfac]);
142 <        free((char *)op);
142 >        free((void *)op);
143          return(1);
144   }
145  
146  
147 < static
148 < savedxf(op)                     /* save transform for display object */
149 < register DOBJECT        *op;
147 > static int
148 > savedxf(                        /* save transform for display object */
149 >        register DOBJECT        *op
150 > )
151   {
152                                          /* free old */
153          while (lastxfac)
# Line 146 | Line 165 | register DOBJECT       *op;
165   }
166  
167  
168 < static
169 < ssph_sample(clr, direc, pos)    /* add sample to current source sphere */
170 < COLR    clr;
171 < FVECT   direc, pos;
168 > static void
169 > ssph_sample(    /* add sample to current source sphere */
170 >        COLR    clr,
171 >        FVECT   direc,
172 >        FVECT   pos
173 > )
174   {
175          COLOR   col;
176          double  d;
# Line 173 | Line 194 | FVECT  direc, pos;
194   }
195  
196  
197 < static
198 < ssph_direc(direc, alt, azi)     /* compute sphere sampling direction */
199 < FVECT   direc;
200 < int     alt, azi;
197 > static void
198 > ssph_direc(     /* compute sphere sampling direction */
199 >        FVECT   direc,
200 >        int     alt,
201 >        int     azi
202 > )
203   {
204          double  phi, d;
205  
# Line 189 | Line 212 | int    alt, azi;
212  
213  
214   static int
215 < ssph_neigh(sp, next)            /* neighbor counter on sphere */
216 < register int    sp[2];
217 < int     next;
215 > ssph_neigh(             /* neighbor counter on sphere */
216 >        register int    sp[2],
217 >        int     next
218 > )
219   {
220          static short    nneigh = 0;             /* neighbor count */
221          static short    neighlist[NAZI+6][2];   /* neighbor list (0 is home) */
# Line 204 | Line 228 | int    next;
228                  sp[1] = neighlist[nneigh][1];
229                  return(1);
230          }
231 <        if (sp[0] < 0 | sp[0] >= NALT | sp[1] < 0 | sp[1] >= NAZI)
231 >        if ((sp[0] < 0) | (sp[0] >= NALT) | (sp[1] < 0) | (sp[1] >= NAZI))
232                  return(nneigh=0);
233          neighlist[0][0] = sp[0]; neighlist[0][1] = sp[1];
234          nneigh = 1;
# Line 254 | Line 278 | int    next;
278   }
279  
280  
281 < static
282 < ssph_compute()                  /* compute source set from sphere samples */
281 > static int
282 > ssph_compute(void)                      /* compute source set from sphere samples */
283   {
284          int     ncells, nsamps;
285          COLOR   csum;
# Line 278 | Line 302 | ssph_compute()                 /* compute source set from sphere sam
302                                  nsamps += ssamp[alt][azi].nsamp;
303                                  ncells++;
304                          }
305 <        if (dlightsets == NULL | ncells < NALT*NAZI/4) {
306 <                bzero((char *)ssamp, sizeof(ssamp));
307 <                return(0);
305 >        if ((dlightsets == NULL) | (ncells < NALT*NAZI/4)) {
306 >                ncells = 0;
307 >                goto done;
308          }
309                                                  /* harmonic mean distance */
310          if (dlightsets->ravg > FTINY)
# Line 289 | Line 313 | ssph_compute()                 /* compute source set from sphere sam
313                  dlightsets->ravg = FHUGE;
314                                                  /* light source threshold */
315          thresh = MINTHRESH*bright(csum)/ncells;
316 +        if (thresh <= FTINY) {
317 +                ncells = 0;
318 +                goto done;
319 +        }
320                                                  /* avg. reflected brightness */
321          d = AVGREFL / (double)ncells;  
322          scalecolor(csum, d);
323 <        if (tmCvColors(&dlightsets->larb, TM_NOCHROM, csum, 1) != TM_E_OK)
324 <                error(CONSISTENCY, "bad tone mapping in ssph_compute");
323 >        if (tmCvColors(&dlightsets->larb, TM_NOCHROM, &csum, 1) != TM_E_OK)
324 >                error(CONSISTENCY, "tone mapping problem in ssph_compute");
325                                          /* greedy light source clustering */
326          while (dlightsets->nl < MAXLIGHTS) {
327                  maxbr = 0.;                     /* find brightest cell */
# Line 313 | Line 341 | ssph_compute()                 /* compute source set from sphere sam
341                                  continue;               /* too dim */
342                          ssph_direc(v, alt, azi);        /* else add it in */
343                          VSUM(ls->direc, ls->direc, v, d);
344 <                        ls->omega++;
344 >                        ls->omega += 1.;
345                          addcolor(ls->val, ssamp[alt][azi].val);
346 +                                                        /* remove from list */
347                          setcolor(ssamp[alt][azi].val, 0., 0., 0.);
348 +                        ssamp[alt][azi].nsamp = 0;
349                  }
350                  d = 1./ls->omega;                       /* avg. brightness */
351                  scalecolor(ls->val, d);
# Line 329 | Line 359 | ssph_compute()                 /* compute source set from sphere sam
359                                  addcolor(dlightsets->lamb, ssamp[alt][azi].val);
360          d = 1.0/ncells;
361          scalecolor(dlightsets->lamb, d);
362 <                                        /* clear sphere sample array */
363 <        bzero((char *)ssamp, sizeof(ssamp));
362 > done:                                   /* clear sphere sample array */
363 >        memset((void *)ssamp, '\0', sizeof(ssamp));
364          return(ncells);
365   }
366  
367  
368 < static
369 < getdlights(op, force)           /* get lights for display object */
370 < register DOBJECT        *op;
371 < int     force;
368 > static int
369 > getdlights(             /* get lights for display object */
370 >        register DOBJECT        *op,
371 >        int     force
372 > )
373   {
374          double  d2, mind2 = FHUGE*FHUGE;
375          FVECT   ocent;
# Line 349 | Line 380 | int    force;
380          if (op->drawcode != DO_LIGHT)
381                  return(0);
382                                          /* check for usable light set */
383 <        multp3(ocent, op->center, op->xfb.f.xfm);
383 >        getdcent(ocent, op);
384          for (dl = dlightsets; dl != NULL; dl = dl->next)
385                  if ((d2 = dist2(dl->lcent, ocent)) < mind2) {
386                          op->ol = dl;
387                          mind2 = d2;
388                  }
389                                          /* the following is heuristic */
390 <        d2 = 2.*op->radius*op->xfb.f.sca; d2 *= d2;
390 >        d2 = 2.*getdrad(op); d2 *= d2;
391          if ((dl = op->ol) != NULL && (mind2 < 0.0625*dl->ravg*dl->ravg ||
392 <                mind2 < 4.*op->radius*op->xfb.f.sca*op->radius*op->xfb.f.sca))
392 >                        mind2 < 4.*getdrad(op)*getdrad(op)))
393                  return(1);
394          if (!force)
395                  return(0);
396                                          /* need to compute new light set */
397 <        copystruct(&cvw, &stdview);
397 >        cvw = stdview;
398          cvw.type = VT_PER;
399          VCOPY(cvw.vp, ocent);
400          cvw.vup[0] = 1.; cvw.vup[1] = cvw.vup[2] = 0.;
# Line 397 | Line 428 | int    force;
428                          quit(0);
429          if (!ssph_compute()) {          /* compute light sources from sphere */
430                  dlightsets = dl->next;
431 <                free((char *)dl);
431 >                free((void *)dl);
432                  return(0);
433          }
434          op->ol = dl;
435          return(1);
436   memerr:
437          error(SYSTEM, "out of memory in getdlights");
438 +        return 0; /* pro forma return */
439   }
440  
441  
442 < static int
443 < cmderror(cn, err)               /* report command error */
444 < int     cn;
445 < char    *err;
442 > static void
443 > cmderror(               /* report command error */
444 >        int     cn,
445 >        char    *err
446 > )
447   {
448          sprintf(errmsg, "%s: %s", rhdcmd[cn], err);
449          error(COMMAND, errmsg);
417        return(cn);
450   }
451  
452  
453 < int
454 < dobj_command(cmd, args)         /* run object display command */
455 < char    *cmd;
456 < register char   *args;
453 > extern int
454 > dobj_command(           /* run object display command */
455 >        char    *cmd,
456 >        register char   *args
457 > )
458   {
459 <        int     cn, na, doxfm;
459 >        int     somechange = 0;
460 >        int     cn, na;
461          register int    nn;
462          char    *alist[MAXAC+1], *nm;
463                                          /* find command */
# Line 450 | Line 484 | register char  *args;
484                          dobj_load(alist[0], alist[0]);
485                  else if (na == 2)
486                          dobj_load(alist[0], alist[1]);
487 <                else
488 <                        return(cmderror(cn, "need octree [name]"));
487 >                else {
488 >                        cmderror(cn, "need octree [name]");
489 >                        return(0);
490 >                }
491                  break;
492 <        case DO_UNLOAD:                         /* unload an object */
492 >        case DO_UNLOAD:                         /* clear an object */
493                  if (na > 1) goto toomany;
494                  if (na && alist[0][0] == '*')
495 <                        dobj_cleanup();
495 >                        somechange += dobj_cleanup();
496                  else
497 <                        dobj_unload(na ? alist[0] : curname);
497 >                        somechange += dobj_unload(na ? alist[0] : curname);
498                  break;
499          case DO_XFORM:                          /* transform object */
500          case DO_MOVE:
# Line 467 | Line 503 | register char  *args;
503                  } else {
504                          nm = curname; nn = 0;
505                  }
506 <                if (cn == DO_MOVE && nn >= na)
507 <                        return(cmderror(cn, "missing transform"));
508 <                dobj_xform(nm, cn==DO_MOVE, na-nn, alist+nn);
506 >                if (cn == DO_MOVE && nn >= na) {
507 >                        cmderror(cn, "missing transform");
508 >                        return(0);
509 >                }
510 >                somechange += dobj_xform(nm, cn==DO_MOVE, na-nn, alist+nn);
511                  break;
512          case DO_UNMOVE:                         /* undo last transform */
513 <                dobj_unmove();
513 >                somechange += dobj_unmove();
514                  break;
515          case DO_OBJECT:                         /* print object statistics */
516 <                dobj_putstats(na ? alist[0] : curname, sstdout);
516 >                if (dobj_putstats(na ? alist[0] : curname, sstdout))
517 >                        if (na && alist[0][0] != '*' && (curobj == NULL ||
518 >                                        strcmp(alist[0], curobj->name)))
519 >                                savedxf(curobj = getdobj(alist[0]));
520                  break;
521          case DO_DUP:                            /* duplicate object */
522                  for (nn = 0; nn < na; nn++)
# Line 483 | Line 524 | register char  *args;
524                                  break;
525                  switch (nn) {
526                  case 0:
527 <                        return(cmderror(cn, "need new object name"));
527 >                        cmderror(cn, "need new object name");
528 >                        return(0);
529                  case 1:
530                          nm = curname;
531                          break;
# Line 496 | Line 538 | register char  *args;
538                  if (!dobj_dup(nm, alist[nn-1]))
539                          break;
540                  if (na > nn)
541 <                        dobj_xform(curname, 1, na-nn, alist+nn);
541 >                        somechange += dobj_xform(curname, 1, na-nn, alist+nn);
542                  else
543                          curobj->drawcode = DO_HIDE;
544 +                savedxf(curobj);
545                  break;
546          case DO_SHOW:                           /* change rendering option */
547          case DO_LIGHT:
548          case DO_HIDE:
549                  if (na > 1) goto toomany;
550                  dobj_lighting(na ? alist[0] : curname, cn);
551 +                somechange++;
552                  break;
553          default:
554                  error(CONSISTENCY, "bad command id in dobj_command");
555          }
556 <        dev_view(&odev.v);                      /* redraw */
513 <        return(cn);
556 >        return(somechange);
557   toomany:
558 <        return(cmderror(cn, "too many arguments"));
558 >        /* return(cmderror(cn, "too many arguments")); *//* XXX cmderror is void */
559 >        cmderror(cn, "too many arguments");
560 >        return 0; /* XXX not sure if this is the right return value */
561   }
562  
563  
564 < dobj_load(oct, nam)             /* create/load an octree object */
565 < char    *oct, *nam;
564 > extern int
565 > dobj_load(              /* create/load an octree object */
566 >        char    *oct,
567 >        char    *nam
568 > )
569   {
522        extern char     *getlibpath(), *getpath();
570          char    *fpp, fpath[128];
571          register DOBJECT        *op;
572                                          /* check arguments */
# Line 531 | Line 578 | char   *oct, *nam;
578                  error(COMMAND, "missing name");
579                  return(0);
580          }
581 <        if (*nam == '*' | *nam == '-') {
581 >        if ((*nam == '*') | (*nam == '-')) {
582                  error(COMMAND, "illegal name");
583                  return(0);
584          }
585 +        if (getdobj(nam) != NULL) {
586 +                error(COMMAND, "name already taken (clear first)");
587 +                return(0);
588 +        }
589                                          /* get octree path */
590 <        if ((fpp = getpath(oct, getlibpath(), R_OK)) == NULL) {
590 >        if ((fpp = getpath(oct, getrlibpath(), R_OK)) == NULL) {
591                  sprintf(errmsg, "cannot find octree \"%s\"", oct);
592                  error(COMMAND, errmsg);
593                  return(0);
594          }
595          strcpy(fpath, fpp);
545        freedobj(getdobj(nam));         /* free previous use of nam */
596          op = (DOBJECT *)malloc(sizeof(DOBJECT));
597          if (op == NULL)
598                  error(SYSTEM, "out of memory in dobj_load");
# Line 555 | Line 605 | char   *oct, *nam;
605          op->xfav[op->xfac=0] = NULL;
606                                          /* load octree into display list */
607          dolights = 0;
608 <        op->listid = rgl_octlist(fpath, op->center, &op->radius);
608 >        domats = 1;
609 >        op->listid = rgl_octlist(fpath, op->center, &op->radius, &op->nlists);
610                                          /* start rtrace */
611          rtargv[RTARGC-1] = fpath;
612          rtargv[RTARGC] = NULL;
613 <        open_process(op->rtp, rtargv);
613 >        open_process(&(op->rtp), rtargv);
614                                          /* insert into main list */
615          op->next = dobjects;
616          curobj = dobjects = op;
# Line 568 | Line 619 | char   *oct, *nam;
619   }
620  
621  
622 < dobj_unload(nam)                        /* free the named object */
623 < char    *nam;
622 > extern int
623 > dobj_unload(                    /* free the named object */
624 >        char    *nam
625 > )
626   {
627          register DOBJECT        *op;
628  
# Line 583 | Line 636 | char   *nam;
636   }
637  
638  
639 < dobj_cleanup()                          /* free all resources */
639 > extern int
640 > dobj_cleanup(void)                              /* free all resources */
641   {
642          register DLIGHTS        *lp;
643  
# Line 592 | Line 646 | dobj_cleanup()                         /* free all resources */
646          savedxf(curobj = NULL);
647          while ((lp = dlightsets) != NULL) {
648                  dlightsets = lp->next;
649 <                free((char *)lp);
649 >                free((void *)lp);
650          }
651          return(1);
652   }
653  
654  
655 < dobj_xform(nam, add, ac, av)            /* set/add transform for nam */
656 < char    *nam;
657 < int     add, ac;
658 < char    **av;
655 > extern int
656 > dobj_xform(             /* set/add transform for nam */
657 >        char    *nam,
658 >        int     rel,
659 >        int     ac,
660 >        char    **av
661 > )
662   {
663          register DOBJECT        *op;
664 +        FVECT   cent;
665 +        double  rad;
666 +        char    scoord[16];
667 +        int     i;
668  
669          if ((op = getdobj(nam)) == NULL) {
670                  error(COMMAND, "no object");
671                  return(0);
672          }
673 <        if (add) add = op->xfac;
674 <        if (ac + add > MAXAC) {
673 >        if (rel)
674 >                rel = op->xfac + 8;
675 >        if (ac + rel > MAXAC) {
676                  error(COMMAND, "too many transform arguments");
677                  return(0);
678          }
679 <        savedxf(curobj = op);
680 <        if (!add)
679 >        savedxf(curobj = op);           /* remember current transform */
680 >        if (rel && ac == 4 && !strcmp(av[0], "-t"))
681 >                rel = -1;                       /* don't move for translate */
682 >        else {
683 >                getdcent(cent, op);             /* don't move if near orig. */
684 >                rad = getdrad(op);
685 >                if (DOT(cent,cent) < rad*rad)
686 >                        rel = -1;
687 >        }
688 >        if (!rel) {                             /* remove old transform */
689                  while (op->xfac)
690                          freestr(op->xfav[--op->xfac]);
691 +        } else if (rel > 0) {                   /* relative move */
692 +                op->xfav[op->xfac++] = savestr("-t");
693 +                for (i = 0; i < 3; i++) {
694 +                        sprintf(scoord, "%.4e", -cent[i]);
695 +                        op->xfav[op->xfac++] = savestr(scoord);
696 +                }
697 +        }
698          while (ac--)
699                  op->xfav[op->xfac++] = savestr(*av++);
700 +        if (rel > 0) {                          /* move back */
701 +                op->xfav[op->xfac++] = savestr("-t");
702 +                for (i = 0; i < 3; i++) {
703 +                        sprintf(scoord, "%.4e", cent[i]);
704 +                        op->xfav[op->xfac++] = savestr(scoord);
705 +                }
706 +        }
707          op->xfav[op->xfac] = NULL;
708          if (fullxf(&op->xfb, op->xfac, op->xfav) != op->xfac) {
709                  error(COMMAND, "bad transform arguments");
# Line 633 | Line 717 | char   **av;
717   }
718  
719  
720 < dobj_putstats(nam, fp)                  /* put out statistics for nam */
721 < char    *nam;
722 < FILE    *fp;
720 > extern int
721 > dobj_putstats(                  /* put out statistics for nam */
722 >        char    *nam,
723 >        FILE    *fp
724 > )
725   {
726          FVECT   ocent;
727          register DOBJECT        *op;
# Line 655 | Line 741 | FILE   *fp;
741                  error(COMMAND, "unknown object");
742                  return(0);
743          }
744 <        multp3(ocent, op->center, op->xfb.f.xfm);
745 <        fprintf(fp, "%s: %s, center [%f %f %f], radius %f", op->name,
746 <                        op->drawcode==DO_HIDE ? "hid" :
747 <                        op->drawcode==DO_LIGHT && op->ol!=NULL ? "lit" :
744 >        getdcent(ocent, op);
745 >        fprintf(fp, "%s: %s, center [%g %g %g], radius %g", op->name,
746 >                        op->drawcode==DO_HIDE ? "hidden" :
747 >                        op->drawcode==DO_LIGHT && op->ol!=NULL ? "lighted" :
748                          "shown",
749 <                        ocent[0],ocent[1],ocent[2], op->radius*op->xfb.f.sca);
749 >                        ocent[0],ocent[1],ocent[2], getdrad(op));
750          if (op->xfac)
751                  fputs(", (xform", fp);
752          for (i = 0; i < op->xfac; i++) {
# Line 674 | Line 760 | FILE   *fp;
760   }
761  
762  
763 < dobj_unmove()                           /* undo last transform change */
763 > extern int
764 > dobj_unmove(void)                               /* undo last transform change */
765   {
766          int     txfac;
767          char    *txfav[MAXAC+1];
# Line 684 | Line 771 | dobj_unmove()                          /* undo last transform change */
771                  return(0);
772          }
773                                          /* hold last transform */
774 <        bcopy((char *)lastxfav, (char *)txfav,
774 >        memcpy((void *)txfav, (void *)lastxfav,
775                          (txfac=lastxfac)*sizeof(char *));
776                                          /* save this transform */
777 <        bcopy((char *)curobj->xfav, (char *)lastxfav,
777 >        memcpy((void *)lastxfav, (void *)curobj->xfav,
778                          (lastxfac=curobj->xfac)*sizeof(char *));
779                                          /* copy back last transform */
780 <        bcopy((char *)txfav, (char *)curobj->xfav,
780 >        memcpy((void *)curobj->xfav, (void *)txfav,
781                          (curobj->xfac=txfac)*sizeof(char *));
782                                          /* set matrices */
783          fullxf(&curobj->xfb, curobj->xfac, curobj->xfav);
# Line 700 | Line 787 | dobj_unmove()                          /* undo last transform change */
787   }
788  
789  
790 < dobj_dup(oldnm, nam)                    /* duplicate object oldnm as nam */
791 < char    *oldnm, *nam;
790 > extern int
791 > dobj_dup(                       /* duplicate object oldnm as nam */
792 >        char    *oldnm,
793 >        char    *nam
794 > )
795   {
796          register DOBJECT        *op, *opdup;
797                                          /* check arguments */
# Line 713 | Line 803 | char   *oldnm, *nam;
803                  error(COMMAND, "missing name");
804                  return(0);
805          }
806 <        if (*nam == '*' | *nam == '-') {
806 >        if ((*nam == '*') | (*nam == '-')) {
807                  error(COMMAND, "illegal name");
808                  return(0);
809          }
810 +        if (getdobj(nam) != NULL) {
811 +                error(COMMAND, "name already taken (clear first)");
812 +                return(0);
813 +        }
814                                          /* allocate and copy struct */
815          opdup = (DOBJECT *)malloc(sizeof(DOBJECT));
816          if (opdup == NULL)
817                  error(SYSTEM, "out of memory in dobj_dup");
818 <        copystruct(opdup, op);
818 >        *opdup = *op;
819                                          /* rename */
820          strcpy(opdup->name, nam);
821                                          /* get our own copy of transform */
# Line 735 | Line 829 | char   *oldnm, *nam;
829   }
830  
831  
832 < dobj_lighting(nam, cn)          /* set up lighting for display object */
833 < char    *nam;
834 < int     cn;
832 > extern int
833 > dobj_lighting(          /* set up lighting for display object */
834 >        char    *nam,
835 >        int     cn
836 > )
837   {
838          int     i, res[2];
839          VIEW    *dv;
# Line 756 | Line 852 | int    cn;
852          } else if ((op = getdobj(nam)) == NULL) {
853                  error(COMMAND, "unknown object");
854                  return(0);
855 <        } else if ((op->drawcode = cn) == DO_LIGHT)
856 <                getdlights(op, 1);
857 <        else
855 >        } else if ((op->drawcode = cn) == DO_LIGHT) {
856 >                if (!getdlights(op, 1))
857 >                        error(COMMAND, "insufficient samples to light object");
858 >        } else
859                  op->ol = NULL;
860  
861          if (dobj_lightsamp != NULL) {           /* restore beam set */
# Line 768 | Line 865 | int    cn;
865                          beam_view(dv, res[0], res[1]);
866                  beam_sync(1);                   /* update server */
867          }
868 +        return 0; /* XXX not sure if this is the right value */
869   }
870  
871  
872 < double
873 < dobj_trace(rorg, rdir)          /* check for ray intersection with objects */
874 < FVECT   rorg, rdir;
872 > extern double
873 > dobj_trace(     /* check for ray intersection with object(s) */
874 >        char    nm[],
875 >        FVECT  rorg,
876 >        FVECT  rdir
877 > )
878   {
879          register DOBJECT        *op;
880          FVECT   xorg, xdir;
881 <        double  darr[6], mindist = FHUGE;
882 <                                        /* check each visible object */
883 <        for (op = dobjects; op != NULL; op = op->next) {
884 <                if (op->drawcode == DO_HIDE)
885 <                        continue;
886 <                if (op->xfac) {         /* transform ray */
887 <                        multp3(xorg, rorg, op->xfb.b.xfm);
888 <                        multv3(xdir, rdir, op->xfb.b.xfm);
889 <                        VCOPY(darr, xorg); VCOPY(darr+3, xdir);
890 <                } else {
891 <                        VCOPY(darr, rorg); VCOPY(darr+3, rdir);
881 >        double  darr[6];
882 >                                        /* check each visible object? */
883 >        if (nm == NULL || *nm == '*') {
884 >                double  dist, mindist = 1.01*FHUGE;
885 >
886 >                if (nm != NULL) nm[0] = '\0';
887 >                for (op = dobjects; op != NULL; op = op->next) {
888 >                        if (op->drawcode == DO_HIDE)
889 >                                continue;
890 >                        dist = dobj_trace(op->name, rorg, rdir);
891 >                        if (dist < mindist) {
892 >                                if (nm != NULL) strcpy(nm, op->name);
893 >                                mindist = dist;
894 >                        }
895                  }
896 <                                        /* 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];
896 >                return(mindist);
897          }
898 <        return(mindist);
898 >                                        /* else check particular object */
899 >        if ((op = getdobj(nm)) == NULL) {
900 >                error(COMMAND, "unknown object");
901 >                return(FHUGE);
902 >        }
903 >        if (op->xfac) {         /* put ray in local coordinates */
904 >                multp3(xorg, rorg, op->xfb.b.xfm);
905 >                multv3(xdir, rdir, op->xfb.b.xfm);
906 >                VCOPY(darr, xorg); VCOPY(darr+3, xdir);
907 >        } else {
908 >                VCOPY(darr, rorg); VCOPY(darr+3, rdir);
909 >        }
910 >                                /* trace it */
911 >        if (process(&(op->rtp), (char *)darr, (char *)darr, sizeof(double),
912 >                        6*sizeof(double)) != sizeof(double))
913 >                error(SYSTEM, "rtrace communication error");
914 >                                /* return distance */
915 >        if (darr[0] >= .99*FHUGE)
916 >                return(FHUGE);
917 >        return(darr[0]*op->xfb.f.sca);
918   }
919  
920  
921 < dobj_render()                   /* render our objects in OpenGL */
921 > extern int
922 > dobj_render(void)                       /* render our objects in OpenGL */
923   {
924 +        int     nrendered = 0;
925          GLboolean       normalizing;
926          GLfloat vec[4];
927 +        FVECT   v1;
928          register DOBJECT        *op;
929          register int    i;
930                                          /* anything to render? */
# Line 812 | Line 932 | dobj_render()                  /* render our objects in OpenGL */
932                  if (op->drawcode != DO_HIDE)
933                          break;
934          if (op == NULL)
935 <                return(1);
935 >                return(0);
936                                          /* set up general rendering params */
937          glGetBooleanv(GL_NORMALIZE, &normalizing);
938 <        glPushAttrib(GL_LIGHTING_BIT|GL_TRANSFORM_BIT|
939 <                        GL_DEPTH_BUFFER_BIT|GL_POLYGON_BIT);
938 >        glPushAttrib(GL_LIGHTING_BIT|GL_TRANSFORM_BIT|GL_ENABLE_BIT|
939 >                GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_POLYGON_BIT);
940          glDepthFunc(GL_LESS);
941          glEnable(GL_DEPTH_TEST);
942          glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
# Line 836 | Line 956 | dobj_render()                  /* render our objects in OpenGL */
956                  if (op->drawcode == DO_LIGHT && op->ol != NULL) {
957                          BYTE    pval;
958                          double  expval, d;
959 <
959 >                                                /* use computed sources */
960                          if (tmMapPixels(&pval, &op->ol->larb, TM_NOCHROM, 1)
961                                          != TM_E_OK)
962                                  error(CONSISTENCY, "dobj_render w/o tone map");
# Line 862 | Line 982 | dobj_render()                  /* render our objects in OpenGL */
982                                  glLightfv(glightid[i], GL_AMBIENT, vec);
983                                  glEnable(glightid[i]);
984                          }
985 <                } else {
986 <                        vec[0] = vec[1] = vec[2] = 1.; vec[3] = 1.;
985 >                } else {                        /* fake lighting */
986 >                        vec[0] = vec[1] = vec[2] = 0.; vec[3] = 1.;
987                          glLightModelfv(GL_LIGHT_MODEL_AMBIENT, vec);
988 +                        getdcent(v1, op);
989 +                        VSUB(v1, odev.v.vp, v1);
990 +                        if (normalize(v1) <= getdrad(op)) {
991 +                                vec[0] = -odev.v.vdir[0];
992 +                                vec[1] = -odev.v.vdir[1];
993 +                                vec[2] = -odev.v.vdir[2];
994 +                        } else
995 +                                VCOPY(vec, v1);
996 +                        vec[3] = 0.;
997 +                        glLightfv(GL_LIGHT0, GL_POSITION, vec);
998 +                        vec[0] = vec[1] = vec[2] = .7; vec[3] = 1.;
999 +                        glLightfv(GL_LIGHT0, GL_SPECULAR, vec);
1000 +                        glLightfv(GL_LIGHT0, GL_DIFFUSE, vec);
1001 +                        vec[0] = vec[1] = vec[2] = .3; vec[3] = 1.;
1002 +                        glLightfv(GL_LIGHT0, GL_AMBIENT, vec);
1003 +                        glEnable(GL_LIGHT0);
1004                  }
1005                                          /* set up object transform */
1006                  if (op->xfac) {
1007 <                        if (!normalizing && op->xfb.f.sca < 1.-FTINY |
1008 <                                                op->xfb.f.sca > 1.+FTINY)
1007 >                        if (!normalizing && (op->xfb.f.sca < 1.-FTINY) |
1008 >                                                (op->xfb.f.sca > 1.+FTINY))
1009                                  glEnable(GL_NORMALIZE);
1010                          glMatrixMode(GL_MODELVIEW);
1011                          glPushMatrix();
# Line 882 | Line 1018 | dobj_render()                  /* render our objects in OpenGL */
1018                  }
1019                                          /* render the display list */
1020                  glCallList(op->listid);
1021 +                nrendered++;
1022                                          /* restore matrix */
1023                  if (op->xfac) {
1024                          glMatrixMode(GL_MODELVIEW);
# Line 893 | Line 1030 | dobj_render()                  /* render our objects in OpenGL */
1030                  if (op->drawcode == DO_LIGHT && op->ol != NULL)
1031                          for (i = op->ol->nl; i--; )
1032                                  glDisable(glightid[i]);
1033 +                else
1034 +                        glDisable(GL_LIGHT0);
1035                                          /* check errors */
897                rgl_checkerr("rendering object in dobj_render");
1036          }
1037          glPopAttrib();                  /* restore rendering params */
1038 <        return(1);
1038 >        rgl_checkerr("rendering objects in dobj_render");
1039 >        return(nrendered);
1040   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines