| 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       5.0             /* source threshold w.r.t. mean */ | 
| 34 |  | #define NALT            11              /* # sampling altitude angles */ | 
| 35 |  | #endif | 
| 36 |  | #ifndef NAZI | 
| 37 | < | #define NAZI            ((int)(PI/2.*NALT+.5)) | 
| 37 | > | #define NAZI            17 | 
| 38 |  | #endif | 
| 39 |  |  | 
| 40 |  | typedef struct dlights { | 
| 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 */ | 
| 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 |  |  | 
| 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; | 
| 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) | 
| 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; | 
| 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 |  |  | 
| 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) */ | 
| 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; | 
| 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; | 
| 302 |  | nsamps += ssamp[alt][azi].nsamp; | 
| 303 |  | ncells++; | 
| 304 |  | } | 
| 305 | < | if (dlightsets == NULL | ncells < NALT*NAZI/4) { | 
| 305 | > | if ((dlightsets == NULL) | (ncells < NALT*NAZI/4)) { | 
| 306 |  | ncells = 0; | 
| 307 |  | goto done; | 
| 308 |  | } | 
| 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) | 
| 323 | > | if (tmCvColors(tmGlobal, &dlightsets->larb, | 
| 324 | > | TM_NOCHROM, &csum, 1) != TM_E_OK) | 
| 325 |  | error(CONSISTENCY, "tone mapping problem in ssph_compute"); | 
| 326 |  | /* greedy light source clustering */ | 
| 327 |  | while (dlightsets->nl < MAXLIGHTS) { | 
| 342 |  | continue;               /* too dim */ | 
| 343 |  | ssph_direc(v, alt, azi);        /* else add it in */ | 
| 344 |  | VSUM(ls->direc, ls->direc, v, d); | 
| 345 | < | ls->omega++; | 
| 345 | > | ls->omega += 1.; | 
| 346 |  | addcolor(ls->val, ssamp[alt][azi].val); | 
| 347 | + | /* remove from list */ | 
| 348 |  | setcolor(ssamp[alt][azi].val, 0., 0., 0.); | 
| 349 | + | ssamp[alt][azi].nsamp = 0; | 
| 350 |  | } | 
| 351 |  | d = 1./ls->omega;                       /* avg. brightness */ | 
| 352 |  | scalecolor(ls->val, d); | 
| 361 |  | d = 1.0/ncells; | 
| 362 |  | scalecolor(dlightsets->lamb, d); | 
| 363 |  | done:                                   /* clear sphere sample array */ | 
| 364 | < | bzero((char *)ssamp, sizeof(ssamp)); | 
| 364 | > | memset((void *)ssamp, '\0', sizeof(ssamp)); | 
| 365 |  | return(ncells); | 
| 366 |  | } | 
| 367 |  |  | 
| 368 |  |  | 
| 369 | < | static | 
| 370 | < | getdlights(op, force)           /* get lights for display object */ | 
| 371 | < | register DOBJECT        *op; | 
| 372 | < | int     force; | 
| 369 | > | static int | 
| 370 | > | getdlights(             /* get lights for display object */ | 
| 371 | > | register DOBJECT        *op, | 
| 372 | > | int     force | 
| 373 | > | ) | 
| 374 |  | { | 
| 375 |  | double  d2, mind2 = FHUGE*FHUGE; | 
| 376 |  | FVECT   ocent; | 
| 395 |  | if (!force) | 
| 396 |  | return(0); | 
| 397 |  | /* need to compute new light set */ | 
| 398 | < | copystruct(&cvw, &stdview); | 
| 398 | > | cvw = stdview; | 
| 399 |  | cvw.type = VT_PER; | 
| 400 |  | VCOPY(cvw.vp, ocent); | 
| 401 |  | cvw.vup[0] = 1.; cvw.vup[1] = cvw.vup[2] = 0.; | 
| 429 |  | quit(0); | 
| 430 |  | if (!ssph_compute()) {          /* compute light sources from sphere */ | 
| 431 |  | dlightsets = dl->next; | 
| 432 | < | free((char *)dl); | 
| 432 | > | free((void *)dl); | 
| 433 |  | return(0); | 
| 434 |  | } | 
| 435 |  | op->ol = dl; | 
| 436 |  | return(1); | 
| 437 |  | memerr: | 
| 438 |  | error(SYSTEM, "out of memory in getdlights"); | 
| 439 | + | return 0; /* pro forma return */ | 
| 440 |  | } | 
| 441 |  |  | 
| 442 |  |  | 
| 443 | < | static int | 
| 444 | < | cmderror(cn, err)               /* report command error */ | 
| 445 | < | int     cn; | 
| 446 | < | char    *err; | 
| 443 | > | static void | 
| 444 | > | cmderror(               /* report command error */ | 
| 445 | > | int     cn, | 
| 446 | > | char    *err | 
| 447 | > | ) | 
| 448 |  | { | 
| 449 |  | sprintf(errmsg, "%s: %s", rhdcmd[cn], err); | 
| 450 |  | error(COMMAND, errmsg); | 
| 424 | – | return(cn); | 
| 451 |  | } | 
| 452 |  |  | 
| 453 |  |  | 
| 454 | < | int | 
| 455 | < | dobj_command(cmd, args)         /* run object display command */ | 
| 456 | < | char    *cmd; | 
| 457 | < | register char   *args; | 
| 454 | > | extern int | 
| 455 | > | dobj_command(           /* run object display command */ | 
| 456 | > | char    *cmd, | 
| 457 | > | register char   *args | 
| 458 | > | ) | 
| 459 |  | { | 
| 460 | < | int     cn, na, doxfm; | 
| 460 | > | int     somechange = 0; | 
| 461 | > | int     cn, na; | 
| 462 |  | register int    nn; | 
| 463 |  | char    *alist[MAXAC+1], *nm; | 
| 464 |  | /* find command */ | 
| 485 |  | dobj_load(alist[0], alist[0]); | 
| 486 |  | else if (na == 2) | 
| 487 |  | dobj_load(alist[0], alist[1]); | 
| 488 | < | else | 
| 489 | < | return(cmderror(cn, "need octree [name]")); | 
| 488 | > | else { | 
| 489 | > | cmderror(cn, "need octree [name]"); | 
| 490 | > | return(0); | 
| 491 | > | } | 
| 492 |  | break; | 
| 493 | < | case DO_UNLOAD:                         /* unload an object */ | 
| 493 | > | case DO_UNLOAD:                         /* clear an object */ | 
| 494 |  | if (na > 1) goto toomany; | 
| 495 |  | if (na && alist[0][0] == '*') | 
| 496 | < | dobj_cleanup(); | 
| 496 | > | somechange += dobj_cleanup(); | 
| 497 |  | else | 
| 498 | < | dobj_unload(na ? alist[0] : curname); | 
| 498 | > | somechange += dobj_unload(na ? alist[0] : curname); | 
| 499 |  | break; | 
| 500 |  | case DO_XFORM:                          /* transform object */ | 
| 501 |  | case DO_MOVE: | 
| 504 |  | } else { | 
| 505 |  | nm = curname; nn = 0; | 
| 506 |  | } | 
| 507 | < | if (cn == DO_MOVE && nn >= na) | 
| 508 | < | return(cmderror(cn, "missing transform")); | 
| 509 | < | dobj_xform(nm, cn==DO_MOVE, na-nn, alist+nn); | 
| 507 | > | if (cn == DO_MOVE && nn >= na) { | 
| 508 | > | cmderror(cn, "missing transform"); | 
| 509 | > | return(0); | 
| 510 | > | } | 
| 511 | > | somechange += dobj_xform(nm, cn==DO_MOVE, na-nn, alist+nn); | 
| 512 |  | break; | 
| 513 |  | case DO_UNMOVE:                         /* undo last transform */ | 
| 514 | < | dobj_unmove(); | 
| 514 | > | somechange += dobj_unmove(); | 
| 515 |  | break; | 
| 516 |  | case DO_OBJECT:                         /* print object statistics */ | 
| 517 |  | if (dobj_putstats(na ? alist[0] : curname, sstdout)) | 
| 518 | < | if (na && alist[0][0] != '*' && | 
| 519 | < | strcmp(alist[0], curname)) | 
| 518 | > | if (na && alist[0][0] != '*' && (curobj == NULL || | 
| 519 | > | strcmp(alist[0], curobj->name))) | 
| 520 |  | savedxf(curobj = getdobj(alist[0])); | 
| 521 |  | break; | 
| 522 |  | case DO_DUP:                            /* duplicate object */ | 
| 525 |  | break; | 
| 526 |  | switch (nn) { | 
| 527 |  | case 0: | 
| 528 | < | return(cmderror(cn, "need new object name")); | 
| 528 | > | cmderror(cn, "need new object name"); | 
| 529 | > | return(0); | 
| 530 |  | case 1: | 
| 531 |  | nm = curname; | 
| 532 |  | break; | 
| 539 |  | if (!dobj_dup(nm, alist[nn-1])) | 
| 540 |  | break; | 
| 541 |  | if (na > nn) | 
| 542 | < | dobj_xform(curname, 1, na-nn, alist+nn); | 
| 542 | > | somechange += dobj_xform(curname, 1, na-nn, alist+nn); | 
| 543 |  | else | 
| 544 |  | curobj->drawcode = DO_HIDE; | 
| 545 |  | savedxf(curobj); | 
| 549 |  | case DO_HIDE: | 
| 550 |  | if (na > 1) goto toomany; | 
| 551 |  | dobj_lighting(na ? alist[0] : curname, cn); | 
| 552 | + | somechange++; | 
| 553 |  | break; | 
| 554 |  | default: | 
| 555 |  | error(CONSISTENCY, "bad command id in dobj_command"); | 
| 556 |  | } | 
| 557 | < | dev_view(&odev.v);                      /* redraw */ | 
| 524 | < | return(cn); | 
| 557 | > | return(somechange); | 
| 558 |  | toomany: | 
| 559 | < | return(cmderror(cn, "too many arguments")); | 
| 559 | > | cmderror(cn, "too many arguments"); | 
| 560 | > | return(-1); | 
| 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 |  | { | 
| 533 | – | extern char     *getlibpath(), *getpath(); | 
| 570 |  | char    *fpp, fpath[128]; | 
| 571 |  | register DOBJECT        *op; | 
| 572 |  | /* check arguments */ | 
| 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 (unload first)"); | 
| 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); | 
| 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; | 
| 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 |  |  | 
| 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 |  |  | 
| 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"); | 
| 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; | 
| 742 |  | return(0); | 
| 743 |  | } | 
| 744 |  | getdcent(ocent, op); | 
| 745 | < | fprintf(fp, "%s: %s, center [%f %f %f], radius %f", op->name, | 
| 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", | 
| 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]; | 
| 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); | 
| 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 */ | 
| 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 (unload first)"); | 
| 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 */ | 
| 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; | 
| 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 */ | 
| 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(nm, rorg, rdir)      /* check for ray intersection with object(s) */ | 
| 874 | < | char    nm[]; | 
| 875 | < | 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; | 
| 908 |  | VCOPY(darr, rorg); VCOPY(darr+3, rdir); | 
| 909 |  | } | 
| 910 |  | /* trace it */ | 
| 911 | < | if (process(op->rtp, darr, darr, sizeof(double), | 
| 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 */ | 
| 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; | 
| 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); | 
| 954 |  | continue; | 
| 955 |  | /* set up lighting */ | 
| 956 |  | if (op->drawcode == DO_LIGHT && op->ol != NULL) { | 
| 957 | < | BYTE    pval; | 
| 957 | > | uby8    pval; | 
| 958 |  | double  expval, d; | 
| 959 |  | /* use computed sources */ | 
| 960 | < | if (tmMapPixels(&pval, &op->ol->larb, TM_NOCHROM, 1) | 
| 961 | < | != TM_E_OK) | 
| 960 | > | if (tmMapPixels(tmGlobal, &pval, &op->ol->larb, | 
| 961 | > | TM_NOCHROM, 1) != TM_E_OK) | 
| 962 |  | error(CONSISTENCY, "dobj_render w/o tone map"); | 
| 963 |  | expval = pval * (WHTEFFICACY/256.) / | 
| 964 |  | tmLuminance(op->ol->larb); | 
| 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(); | 
| 1018 |  | } | 
| 1019 |  | /* render the display list */ | 
| 1020 |  | glCallList(op->listid); | 
| 1021 | + | nrendered++; | 
| 1022 |  | /* restore matrix */ | 
| 1023 |  | if (op->xfac) { | 
| 1024 |  | glMatrixMode(GL_MODELVIEW); | 
| 1036 |  | } | 
| 1037 |  | glPopAttrib();                  /* restore rendering params */ | 
| 1038 |  | rgl_checkerr("rendering objects in dobj_render"); | 
| 1039 | < | return(1); | 
| 1039 | > | return(nrendered); | 
| 1040 |  | } |