| 11 |  | #include <stdlib.h> | 
| 12 |  | #include "rtio.h" | 
| 13 |  | #include "rtmath.h" | 
| 14 | + | #include "rtprocess.h" | 
| 15 |  | #include "bsdf.h" | 
| 16 |  | #include "bsdf_m.h" | 
| 17 |  | #include "random.h" | 
| 36 |  |  | 
| 37 |  | char            *progname;              /* global argv[0] */ | 
| 38 |  |  | 
| 39 | < | int             verbose = 0;            /* verbose mode? */ | 
| 39 | > | int             verbose = 0;            /* verbose mode (< 0 no warnings) */ | 
| 40 |  |  | 
| 41 |  | char            *rcarg[MAXRCARG+1] = {"rcontrib", "-fo+"}; | 
| 42 |  | int             nrcargs = 2; | 
| 54 |  | char            *khalffn = "klems_half.cal"; | 
| 55 |  | char            *kquarterfn = "klems_quarter.cal"; | 
| 56 |  |  | 
| 57 | < | #define PARAMSTART      "@rfluxmtx"     /* string indicating parameters */ | 
| 57 | > | /* string indicating parameters */ | 
| 58 | > | const char      PARAMSTART[] = "@rfluxmtx"; | 
| 59 |  |  | 
| 60 |  | /* surface type IDs */ | 
| 61 |  | #define ST_NONE         0 | 
| 68 |  | void            *priv;          /* private data (malloc'ed) */ | 
| 69 |  | char            sname[32];      /* surface name */ | 
| 70 |  | FVECT           snrm;           /* surface normal */ | 
| 71 | < | double          area;           /* surface area (or solid angle) */ | 
| 71 | > | double          area;           /* surface area / proj. solid angle */ | 
| 72 |  | short           styp;           /* surface type */ | 
| 73 |  | short           nfargs;         /* number of real arguments */ | 
| 74 |  | double          farg[1];        /* real values (extends struct) */ | 
| 97 |  |  | 
| 98 |  | PARAMS          curparams; | 
| 99 |  | char            curmod[128]; | 
| 100 | + | char            newparams[1024]; | 
| 101 |  |  | 
| 102 |  | typedef int     SURFSAMP(FVECT, SURF *, double); | 
| 103 |  |  | 
| 111 |  | static void | 
| 112 |  | clear_params(PARAMS *p, int reset_only) | 
| 113 |  | { | 
| 111 | – | curmod[0] = '\0'; | 
| 114 |  | while (p->slist != NULL) { | 
| 115 |  | SURF    *sdel = p->slist; | 
| 116 |  | p->slist = sdel->next; | 
| 125 |  | p->outfn = NULL; | 
| 126 |  | return; | 
| 127 |  | } | 
| 128 | < | memset(p, 0, sizeof(curparams)); | 
| 128 | > | memset(p, 0, sizeof(PARAMS)); | 
| 129 |  | } | 
| 130 |  |  | 
| 131 |  | /* Get surface type from name */ | 
| 145 |  | static char * | 
| 146 |  | oconv_command(int ac, char *av[]) | 
| 147 |  | { | 
| 148 | < | static char     oconvbuf[2048] = "!oconv -f"; | 
| 149 | < | char            *cp = oconvbuf + 9; | 
| 150 | < |  | 
| 148 | > | static char     oconvbuf[2048] = "!oconv -f "; | 
| 149 | > | char            *cp = oconvbuf + 10; | 
| 150 | > | char            *recv = *av++; | 
| 151 | > |  | 
| 152 | > | if (ac-- <= 0) | 
| 153 | > | return(NULL); | 
| 154 |  | while (ac-- > 0) { | 
| 155 | + | strcpy(cp, *av++); | 
| 156 | + | while (*cp) cp++; | 
| 157 | + | *cp++ = ' '; | 
| 158 |  | if (cp >= oconvbuf+(sizeof(oconvbuf)-32)) { | 
| 159 |  | fputs(progname, stderr); | 
| 160 |  | fputs(": too many file arguments!\n", stderr); | 
| 161 |  | exit(1); | 
| 162 |  | } | 
| 155 | – | *cp++ = ' '; | 
| 156 | – | strcpy(cp, *av++); | 
| 157 | – | while (*cp) cp++; | 
| 163 |  | } | 
| 164 | < | *cp = '\0'; | 
| 164 | > | strcpy(cp, recv);       /* receiver goes last */ | 
| 165 |  | return(oconvbuf); | 
| 166 |  | } | 
| 167 |  |  | 
| 226 |  | fputs(": command line too long in popen_arglist()\n", stderr); | 
| 227 |  | return(NULL); | 
| 228 |  | } | 
| 229 | < | if (verbose) | 
| 229 | > | if (verbose > 0) | 
| 230 |  | fprintf(stderr, "%s: opening pipe %s: %s\n", | 
| 231 |  | progname, (*mode=='w') ? "to" : "from", cmd); | 
| 232 |  | return(popen(cmd, mode)); | 
| 244 |  | fputs(": command line too long in my_exec()\n", stderr); | 
| 245 |  | return(1); | 
| 246 |  | } | 
| 247 | < | if (verbose) | 
| 247 | > | if (verbose > 0) | 
| 248 |  | fprintf(stderr, "%s: running: %s\n", progname, cmd); | 
| 249 |  | return(system(cmd)); | 
| 250 |  | } | 
| 259 |  | fprintf(stderr, "%s: cannot locate %s\n", progname, av[0]); | 
| 260 |  | return(1); | 
| 261 |  | } | 
| 262 | < | if (verbose) { | 
| 262 | > | if (verbose > 0) { | 
| 263 |  | char    cmd[4096]; | 
| 264 |  | if (!convert_commandline(cmd, sizeof(cmd), av)) | 
| 265 |  | strcpy(cmd, "COMMAND TOO LONG TO SHOW"); | 
| 313 |  |  | 
| 314 |  | /* Parse program parameters (directives) */ | 
| 315 |  | static int | 
| 316 | < | parse_params(char *pargs) | 
| 316 | > | parse_params(PARAMS *p, char *pargs) | 
| 317 |  | { | 
| 318 |  | char    *cp = pargs; | 
| 319 |  | int     nparams = 0; | 
| 320 |  | int     i; | 
| 321 |  |  | 
| 322 | < | for ( ; ; ) | 
| 322 | > | for ( ; ; ) { | 
| 323 |  | switch (*cp++) { | 
| 324 |  | case 'h': | 
| 325 |  | if (*cp++ != '=') | 
| 326 |  | break; | 
| 327 | < | curparams.hsiz = 0; | 
| 327 | > | p->hsiz = 0; | 
| 328 |  | i = 0; | 
| 329 |  | while (*cp && !isspace(*cp)) { | 
| 330 |  | if (isdigit(*cp)) | 
| 331 | < | curparams.hsiz = 10*curparams.hsiz + | 
| 332 | < | *cp - '0'; | 
| 328 | < | curparams.hemis[i++] = *cp++; | 
| 331 | > | p->hsiz = 10*p->hsiz + *cp - '0'; | 
| 332 | > | p->hemis[i++] = *cp++; | 
| 333 |  | } | 
| 334 |  | if (!i) | 
| 335 |  | break; | 
| 336 | < | curparams.hemis[i] = '\0'; | 
| 337 | < | curparams.hsiz += !curparams.hsiz; | 
| 336 | > | p->hemis[i] = '\0'; | 
| 337 | > | p->hsiz += !p->hsiz; | 
| 338 |  | ++nparams; | 
| 339 |  | continue; | 
| 340 |  | case 'u': | 
| 341 |  | if (*cp++ != '=') | 
| 342 |  | break; | 
| 343 | < | if (!get_direction(curparams.vup, cp)) | 
| 343 | > | if (!get_direction(p->vup, cp)) | 
| 344 |  | break; | 
| 345 | + | while (*cp && !isspace(*cp++)) | 
| 346 | + | ; | 
| 347 |  | ++nparams; | 
| 348 |  | continue; | 
| 349 |  | case 'o': | 
| 355 |  | if (!i) | 
| 356 |  | break; | 
| 357 |  | *--cp = '\0'; | 
| 358 | < | curparams.outfn = savqstr(cp-i); | 
| 358 | > | p->outfn = savqstr(cp-i); | 
| 359 |  | *cp++ = ' '; | 
| 360 |  | ++nparams; | 
| 361 |  | continue; | 
| 369 |  | default: | 
| 370 |  | break; | 
| 371 |  | } | 
| 372 | < | fprintf(stderr, "%s: bad parameter string '%s'\n", progname, pargs); | 
| 372 | > | break; | 
| 373 | > | } | 
| 374 | > | fprintf(stderr, "%s: bad parameter string: %s", progname, pargs); | 
| 375 |  | exit(1); | 
| 376 |  | return(-1);     /* pro forma return */ | 
| 377 |  | } | 
| 380 |  | static void | 
| 381 |  | finish_receiver(void) | 
| 382 |  | { | 
| 383 | + | char    sbuf[256]; | 
| 384 | + | int     uniform = 0; | 
| 385 |  | char    *calfn = NULL; | 
| 386 | + | char    *params = NULL; | 
| 387 |  | char    *binv = NULL; | 
| 388 |  | char    *binf = NULL; | 
| 389 |  | char    *nbins = NULL; | 
| 379 | – | char    sbuf[256]; | 
| 390 |  |  | 
| 391 |  | if (!curmod[0]) { | 
| 392 |  | fputs(progname, stderr); | 
| 398 |  | rcarg[nrcargs++] = "-o"; | 
| 399 |  | rcarg[nrcargs++] = curparams.outfn; | 
| 400 |  | } | 
| 401 | < | /* add bin specification */ | 
| 401 | > | /* check arguments */ | 
| 402 |  | if (!curparams.hemis[0]) { | 
| 403 |  | fputs(progname, stderr); | 
| 404 |  | fputs(": missing hemisphere sampling type!\n", stderr); | 
| 409 |  | fputs(": undefined normal for hemisphere sampling\n", stderr); | 
| 410 |  | exit(1); | 
| 411 |  | } | 
| 412 | < | if (normalize(curparams.vup) == 0) | 
| 412 | > | if (normalize(curparams.vup) == 0) { | 
| 413 |  | if (fabs(curparams.nrm[2]) < .7) | 
| 414 |  | curparams.vup[2] = 1; | 
| 415 |  | else | 
| 416 |  | curparams.vup[1] = 1; | 
| 417 | + | } | 
| 418 | + | /* determine sample type/bin */ | 
| 419 |  | if (tolower(curparams.hemis[0]) == 'u' | curparams.hemis[0] == '1') { | 
| 420 | < | binv = "0"; | 
| 420 | > | sprintf(sbuf, "if(-Dx*%g-Dy*%g-Dz*%g,0,-1)", | 
| 421 | > | curparams.nrm[0], curparams.nrm[1], curparams.nrm[2]); | 
| 422 | > | binv = savqstr(sbuf); | 
| 423 | > | nbins = "1";            /* uniform sampling -- one bin */ | 
| 424 | > | uniform = 1; | 
| 425 |  | } else if (tolower(curparams.hemis[0]) == 's' && | 
| 426 |  | tolower(curparams.hemis[1]) == 'c') { | 
| 427 |  | /* assign parameters */ | 
| 430 |  | fputs(": missing size for Shirley-Chiu sampling!\n", stderr); | 
| 431 |  | exit(1); | 
| 432 |  | } | 
| 433 | < | sprintf(sbuf, "SCdim=%d,Nx=%g,Ny=%g,Nz=%g,Ux=%g,Uy=%g,Uz=%g", | 
| 433 | > | calfn = shirchiufn; shirchiufn = NULL; | 
| 434 | > | sprintf(sbuf, "SCdim=%d,rNx=%g,rNy=%g,rNz=%g,Ux=%g,Uy=%g,Uz=%g", | 
| 435 |  | curparams.hsiz, | 
| 436 |  | curparams.nrm[0], curparams.nrm[1], curparams.nrm[2], | 
| 437 |  | curparams.vup[0], curparams.vup[1], curparams.vup[2]); | 
| 438 | < | CHECKARGC(2); | 
| 422 | < | rcarg[nrcargs++] = "-p"; | 
| 423 | < | rcarg[nrcargs++] = savqstr(sbuf); | 
| 424 | < | calfn = shirchiufn; shirchiufn = NULL; | 
| 438 | > | params = savqstr(sbuf); | 
| 439 |  | binv = "scbin"; | 
| 440 |  | nbins = "SCdim*SCdim"; | 
| 441 |  | } else if ((tolower(curparams.hemis[0]) == 'r') | | 
| 442 |  | (tolower(curparams.hemis[0]) == 't')) { | 
| 443 |  | calfn = reinhfn; reinhfn = NULL; | 
| 444 | < | /* XXX Need to set number of divisions */ | 
| 445 | < | binf = "rhbin"; | 
| 446 | < | nbins = "Nrhbins"; | 
| 444 | > | sprintf(sbuf, "MF=%d,rNx=%g,rNy=%g,rNz=%g,Ux=%g,Uy=%g,Uz=%g", | 
| 445 | > | curparams.hsiz, | 
| 446 | > | curparams.nrm[0], curparams.nrm[1], curparams.nrm[2], | 
| 447 | > | curparams.vup[0], curparams.vup[1], curparams.vup[2]); | 
| 448 | > | params = savqstr(sbuf); | 
| 449 | > | binv = "rbin"; | 
| 450 | > | nbins = "Nrbins"; | 
| 451 |  | } else if (tolower(curparams.hemis[0]) == 'k' && | 
| 452 |  | !curparams.hemis[1] | | 
| 453 |  | (tolower(curparams.hemis[1]) == 'f') | | 
| 472 |  | progname, curparams.hemis); | 
| 473 |  | exit(1); | 
| 474 |  | } | 
| 475 | + | if (!uniform & (curparams.slist->styp == ST_SOURCE)) { | 
| 476 | + | SURF    *sp; | 
| 477 | + | for (sp = curparams.slist; sp != NULL; sp = sp->next) | 
| 478 | + | if (fabs(sp->area - PI) > 1e-3) { | 
| 479 | + | fprintf(stderr, "%s: source '%s' must be 180-degrees\n", | 
| 480 | + | progname, sp->sname); | 
| 481 | + | exit(1); | 
| 482 | + | } | 
| 483 | + | } | 
| 484 |  | if (calfn != NULL) {            /* add cal file if needed */ | 
| 485 |  | CHECKARGC(2); | 
| 486 |  | rcarg[nrcargs++] = "-f"; | 
| 487 |  | rcarg[nrcargs++] = calfn; | 
| 488 |  | } | 
| 489 | + | if (params != NULL) {           /* parameters _after_ cal file */ | 
| 490 | + | CHECKARGC(2); | 
| 491 | + | rcarg[nrcargs++] = "-p"; | 
| 492 | + | rcarg[nrcargs++] = params; | 
| 493 | + | } | 
| 494 |  | if (nbins != NULL) {            /* add #bins if set */ | 
| 495 |  | CHECKARGC(2); | 
| 496 |  | rcarg[nrcargs++] = "-bn"; | 
| 497 |  | rcarg[nrcargs++] = nbins; | 
| 498 |  | } | 
| 499 | < | if (binfv != NULL) { | 
| 499 | > | if (binv != NULL) { | 
| 500 |  | CHECKARGC(2);           /* assign bin variable */ | 
| 501 |  | rcarg[nrcargs++] = "-b"; | 
| 502 |  | rcarg[nrcargs++] = binv; | 
| 503 |  | } else if (binf != NULL) { | 
| 504 |  | CHECKARGC(2);           /* assign bin function */ | 
| 505 | + | rcarg[nrcargs++] = "-b"; | 
| 506 |  | sprintf(sbuf, "%s(%g,%g,%g,%g,%g,%g)", binf, | 
| 507 |  | curparams.nrm[0], curparams.nrm[1], curparams.nrm[2], | 
| 508 |  | curparams.vup[0], curparams.vup[1], curparams.vup[2]); | 
| 476 | – | rcarg[nrcargs++] = "-b"; | 
| 509 |  | rcarg[nrcargs++] = savqstr(sbuf); | 
| 510 |  | } | 
| 511 |  | CHECKARGC(2);                           /* modifier argument goes last */ | 
| 519 |  | { | 
| 520 |  | int     i; | 
| 521 |  |  | 
| 522 | < | uva[1][0] = 0.5 - frandom(); | 
| 491 | < | uva[1][1] = 0.5 - frandom(); | 
| 492 | < | uva[1][2] = 0.5 - frandom(); | 
| 493 | < | for (i = 3; i--; ) | 
| 494 | < | if ((-0.6 < nrm[i]) & (nrm[i] < 0.6)) | 
| 495 | < | break; | 
| 496 | < | if (i < 0) { | 
| 522 | > | if (!getperpendicular(uva[0], nrm)) { | 
| 523 |  | fputs(progname, stderr); | 
| 524 |  | fputs(": bad surface normal in make_axes!\n", stderr); | 
| 525 |  | exit(1); | 
| 526 |  | } | 
| 527 | < | uva[1][i] = 1.0; | 
| 502 | < | VCROSS(uva[0], uva[1], nrm); | 
| 503 | < | normalize(uva[0]); | 
| 504 | < | VCROSS(uva[1], nrm, uva[0]); | 
| 527 | > | fcross(uva[1], nrm, uva[0]); | 
| 528 |  | } | 
| 529 |  |  | 
| 530 |  | /* Illegal sender surfaces end up here */ | 
| 556 |  | sp->priv = (void *)uva; | 
| 557 |  | } | 
| 558 |  | SDmultiSamp(samp2, 2, x); | 
| 559 | < | samp2[0] = sp->farg[6] + sqrt(samp2[0]*sp->area*(1./PI)); | 
| 559 | > | samp2[0] = sqrt(samp2[0]*sp->area*(1./PI) + sp->farg[6]*sp->farg[6]); | 
| 560 |  | samp2[1] *= 2.*PI; | 
| 561 |  | uv[0] = samp2[0]*tcos(samp2[1]); | 
| 562 |  | uv[1] = samp2[0]*tsin(samp2[1]); | 
| 609 |  | } | 
| 610 |  | ptp->ntris = 0; | 
| 611 |  | v2l->p = (void *)ptp; | 
| 612 | < | if (!polyTriangulate(v2l, add_triangle)) | 
| 612 | > | if (!polyTriangulate(v2l, add_triangle)) { | 
| 613 | > | fprintf(stderr, | 
| 614 | > | "%s: cannot triangulate polygon '%s'\n", | 
| 615 | > | progname, sp->sname); | 
| 616 |  | return(0); | 
| 617 | + | } | 
| 618 |  | for (i = ptp->ntris; i--; ) { | 
| 619 |  | int     a = ptp->tri[i].vndx[0]; | 
| 620 |  | int     b = ptp->tri[i].vndx[1]; | 
| 663 |  | /* special case for lone surface */ | 
| 664 |  | if (p->nsurfs == 1) { | 
| 665 |  | sp = p->slist; | 
| 666 | < | if (DOT(sp->snrm, rdir) >= -FTINY) | 
| 667 | < | return(0);      /* behind surface! */ | 
| 666 | > | if (DOT(sp->snrm, rdir) >= -FTINY) { | 
| 667 | > | fprintf(stderr, | 
| 668 | > | "%s: internal - sample behind sender '%s'\n", | 
| 669 | > | progname, sp->sname); | 
| 670 | > | return(0); | 
| 671 | > | } | 
| 672 |  | return((*orig_in_surf[sp->styp])(orig, sp, x)); | 
| 673 |  | } | 
| 674 |  | if (p->nsurfs > nall) {         /* (re)allocate surface area cache */ | 
| 682 |  | projsa[i] = -DOT(sp->snrm, rdir) * sp->area; | 
| 683 |  | tarea += projsa[i] *= (double)(projsa[i] > FTINY); | 
| 684 |  | } | 
| 685 | < | if (tarea <= FTINY)             /* wrong side of sender? */ | 
| 685 | > | if (tarea <= FTINY) {           /* wrong side of sender? */ | 
| 686 | > | fputs(progname, stderr); | 
| 687 | > | fputs(": internal - sample behind all sender elements!\n", | 
| 688 | > | stderr); | 
| 689 |  | return(0); | 
| 690 | + | } | 
| 691 |  | tarea *= x;                     /* get surface from list */ | 
| 692 |  | for (i = 0, sp = p->slist; tarea > projsa[i]; sp = sp->next) | 
| 693 |  | tarea -= projsa[i++]; | 
| 760 |  | #define T_NALT  7 | 
| 761 |  | static const int        tnaz[T_NALT] = {30, 30, 24, 24, 18, 12, 6}; | 
| 762 |  | const int               RowMax = T_NALT*p->hsiz + 1; | 
| 763 | < | const double            RAH = (.25*PI)/(RowMax-.5); | 
| 763 | > | const double            RAH = (.5*PI)/(RowMax-.5); | 
| 764 |  | #define rnaz(r)                 (r >= RowMax-1 ? 1 : p->hsiz*tnaz[r/p->hsiz]) | 
| 765 |  | int                     n = sampcnt; | 
| 766 |  | int                     row, col; | 
| 785 |  | SDmultiSamp(samp3, 3, (n+frandom())/sampcnt); | 
| 786 |  | alt = (row+samp3[1])*RAH; | 
| 787 |  | azi = (2.*PI)*(col+samp3[2]-.5)/rnaz(row); | 
| 788 | < | duvw[2] = tcos(alt);    /* measured from horizon */ | 
| 789 | < | duvw[0] = tcos(azi)*duvw[2]; | 
| 790 | < | duvw[1] = tsin(azi)*duvw[2]; | 
| 788 | > | duvw[2] = cos(alt);     /* measured from horizon */ | 
| 789 | > | duvw[0] = tsin(azi)*duvw[2]; | 
| 790 | > | duvw[1] = tcos(azi)*duvw[2]; | 
| 791 |  | duvw[2] = sqrt(1. - duvw[2]*duvw[2]); | 
| 792 |  | for (i = 3; i--; ) | 
| 793 |  | orig_dir[1][i] = -duvw[0]*p->udir[i] - | 
| 838 |  |  | 
| 839 |  | while (n--) {                   /* stratified sampling */ | 
| 840 |  | SDmultiSamp(samp2, 2, (n+frandom())/sampcnt); | 
| 841 | < | if (!bo_getvec(duvw, b+samp2[1], kbasis[bi])) | 
| 841 | > | if (!bi_getvec(duvw, b+samp2[1], kbasis[bi])) | 
| 842 |  | return(0); | 
| 843 |  | for (i = 3; i--; ) | 
| 844 |  | orig_dir[1][i] = duvw[0]*p->udir[i] + | 
| 861 |  | fputs(": no sender surface!\n", stderr); | 
| 862 |  | return(-1); | 
| 863 |  | } | 
| 864 | < | if (curparams.outfn != NULL)    /* misplaced output file spec. */ | 
| 864 | > | /* misplaced output file spec. */ | 
| 865 | > | if ((curparams.outfn != NULL) & (verbose >= 0)) | 
| 866 |  | fprintf(stderr, "%s: warning - ignoring output file in sender ('%s')\n", | 
| 867 |  | progname, curparams.outfn); | 
| 868 |  | /* check/set basis hemisphere */ | 
| 876 |  | fputs(": undefined normal for sender sampling\n", stderr); | 
| 877 |  | return(-1); | 
| 878 |  | } | 
| 879 | < | if (normalize(curparams.vup) == 0) | 
| 879 | > | if (normalize(curparams.vup) == 0) { | 
| 880 |  | if (fabs(curparams.nrm[2]) < .7) | 
| 881 |  | curparams.vup[2] = 1; | 
| 882 |  | else | 
| 883 |  | curparams.vup[1] = 1; | 
| 884 | + | } | 
| 885 |  | VCROSS(curparams.udir, curparams.vup, curparams.nrm); | 
| 886 |  | if (normalize(curparams.udir) == 0) { | 
| 887 |  | fputs(progname, stderr); | 
| 1005 |  | case ST_SOURCE: | 
| 1006 |  | if (snew->nfargs != 4) | 
| 1007 |  | goto badcount; | 
| 1008 | < | VCOPY(snew->snrm, snew->farg); | 
| 1008 | > | for (n = 3; n--; )      /* need to reverse "normal" */ | 
| 1009 | > | snew->snrm[n] = -snew->farg[n]; | 
| 1010 |  | if (normalize(snew->snrm) == 0) | 
| 1011 |  | goto badnorm; | 
| 1012 | < | snew->area = 2.*PI*(1. - cos((PI/180./2.)*snew->farg[3])); | 
| 1012 | > | snew->area = sin((PI/180./2.)*snew->farg[3]); | 
| 1013 | > | snew->area *= PI*snew->area; | 
| 1014 |  | break; | 
| 1015 |  | } | 
| 1016 | < | if (snew->area <= FTINY) { | 
| 1016 | > | if ((snew->area <= FTINY) & (verbose >= 0)) { | 
| 1017 |  | fprintf(stderr, "%s: warning - zero area for surface '%s'\n", | 
| 1018 |  | progname, oname); | 
| 1019 |  | free(snew); | 
| 1025 |  | curparams.nsurfs++; | 
| 1026 |  | return; | 
| 1027 |  | badcount: | 
| 1028 | < | fprintf(stderr, "%s: bad argument count for surface '%s'\n", | 
| 1028 | > | fprintf(stderr, "%s: bad argument count for surface element '%s'\n", | 
| 1029 |  | progname, oname); | 
| 1030 |  | exit(1); | 
| 1031 |  | badnorm: | 
| 1032 | < | fprintf(stderr, "%s: bad orientation for surface '%s'\n", | 
| 1032 | > | fprintf(stderr, "%s: bad orientation for surface element '%s'\n", | 
| 1033 |  | progname, oname); | 
| 1034 |  | exit(1); | 
| 1035 |  | } | 
| 1061 |  | finish_receiver(); | 
| 1062 |  | clear_params(&curparams, 1); | 
| 1063 |  | } | 
| 1064 | + | parse_params(&curparams, newparams); | 
| 1065 | + | newparams[0] = '\0'; | 
| 1066 |  | strcpy(curmod, thismod); | 
| 1067 |  | } | 
| 1068 |  | add_surface(st, oname, fp);     /* read & store surface */ | 
| 1069 |  | return(1); | 
| 1070 |  | } | 
| 1071 |  | /* else skip arguments */ | 
| 1072 | < | if (!fscanf(fp, "%d", &n)) return; | 
| 1072 | > | if (!fscanf(fp, "%d", &n)) return(0); | 
| 1073 |  | while (n-- > 0) fscanf(fp, "%*s"); | 
| 1074 | < | if (!fscanf(fp, "%d", &n)) return; | 
| 1074 | > | if (!fscanf(fp, "%d", &n)) return(0); | 
| 1075 |  | while (n-- > 0) fscanf(fp, "%*d"); | 
| 1076 | < | if (!fscanf(fp, "%d", &n)) return; | 
| 1076 | > | if (!fscanf(fp, "%d", &n)) return(0); | 
| 1077 |  | while (n-- > 0) fscanf(fp, "%*f"); | 
| 1078 |  | return(0); | 
| 1079 |  | } | 
| 1099 |  | fputs(": cannot use source as a sender!\n", stderr); | 
| 1100 |  | return(-1); | 
| 1101 |  | } | 
| 1102 | + | parse_params(&curparams, newparams); | 
| 1103 | + | newparams[0] = '\0'; | 
| 1104 |  | add_surface(st, oname, fp);     /* read & store surface */ | 
| 1105 |  | return(0); | 
| 1106 |  | } | 
| 1107 |  | /* else skip arguments */ | 
| 1108 | < | if (!fscanf(fp, "%d", &n)) return; | 
| 1108 | > | if (!fscanf(fp, "%d", &n)) return(0); | 
| 1109 |  | while (n-- > 0) fscanf(fp, "%*s"); | 
| 1110 | < | if (!fscanf(fp, "%d", &n)) return; | 
| 1110 | > | if (!fscanf(fp, "%d", &n)) return(0); | 
| 1111 |  | while (n-- > 0) fscanf(fp, "%*d"); | 
| 1112 | < | if (!fscanf(fp, "%d", &n)) return; | 
| 1112 | > | if (!fscanf(fp, "%d", &n)) return(0); | 
| 1113 |  | while (n-- > 0) fscanf(fp, "%*f"); | 
| 1114 |  | return(0); | 
| 1115 |  | } | 
| 1144 |  | continue; | 
| 1145 |  | } | 
| 1146 |  | if (c == '#') {         /* parameters/comment */ | 
| 1147 | < | if (fscanf(fp, "%s", inpbuf) == 1 && | 
| 1147 | > | if ((c = getc(fp)) == EOF || ungetc(c,fp) == EOF) | 
| 1148 | > | break; | 
| 1149 | > | if (!isspace(c) && fscanf(fp, "%s", inpbuf) == 1 && | 
| 1150 |  | !strcmp(inpbuf, PARAMSTART)) { | 
| 1151 |  | if (fgets(inpbuf, sizeof(inpbuf), fp) != NULL) | 
| 1152 | < | parse_params(inpbuf); | 
| 1152 | > | strcat(newparams, inpbuf); | 
| 1153 |  | continue; | 
| 1154 |  | } | 
| 1155 | < | while ((c = getc(fp)) != EOF && c != '\n'); | 
| 1155 | > | while ((c = getc(fp)) != EOF && c != '\n') | 
| 1156 |  | ;       /* else skipping comment */ | 
| 1157 |  | continue; | 
| 1158 |  | } | 
| 1176 |  | main(int argc, char *argv[]) | 
| 1177 |  | { | 
| 1178 |  | char    fmtopt[6] = "-faa";     /* default output is ASCII */ | 
| 1179 | + | char    *xrs=NULL, *yrs=NULL, *ldopt=NULL; | 
| 1180 | + | char    *iropt = NULL; | 
| 1181 |  | char    *sendfn; | 
| 1182 |  | char    sampcntbuf[32], nsbinbuf[32]; | 
| 1183 |  | FILE    *rcfp; | 
| 1185 |  | int     a, i; | 
| 1186 |  | /* screen rcontrib options */ | 
| 1187 |  | progname = argv[0]; | 
| 1188 | < | for (a = 1; a < argc-2 && argv[a][0] == '-'; a++) { | 
| 1189 | < | int     na = 1;         /* !! Keep consistent !! */ | 
| 1190 | < | switch (argv[a][1]) { | 
| 1188 | > | for (a = 1; a < argc-2; a++) { | 
| 1189 | > | int     na; | 
| 1190 | > | /* check for argument expansion */ | 
| 1191 | > | while ((na = expandarg(&argc, &argv, a)) > 0) | 
| 1192 | > | ; | 
| 1193 | > | if (na < 0) { | 
| 1194 | > | fprintf(stderr, "%s: cannot expand '%s'\n", | 
| 1195 | > | progname, argv[a]); | 
| 1196 | > | return(1); | 
| 1197 | > | } | 
| 1198 | > | if (argv[a][0] != '-' || !argv[a][1]) | 
| 1199 | > | break; | 
| 1200 | > | na = 1; | 
| 1201 | > | switch (argv[a][1]) {   /* !! Keep consistent !! */ | 
| 1202 |  | case 'v':               /* verbose mode */ | 
| 1203 | < | verbose = !verbose; | 
| 1203 | > | verbose = 1; | 
| 1204 |  | na = 0; | 
| 1205 |  | continue; | 
| 1206 |  | case 'f':               /* special case for -fo, -ff, etc. */ | 
| 1213 |  | case 'f': | 
| 1214 |  | case 'd': | 
| 1215 |  | case 'c': | 
| 1216 | < | if (!(fmtopt[4] = argv[a][3])) | 
| 1217 | < | fmtopt[4] = argv[a][2]; | 
| 1218 | < | fmtopt[3] = argv[a][2]; | 
| 1216 | > | if (!(fmtopt[3] = argv[a][3])) | 
| 1217 | > | fmtopt[3] = argv[a][2]; | 
| 1218 | > | fmtopt[2] = argv[a][2]; | 
| 1219 |  | na = 0; | 
| 1220 |  | continue;       /* will pass later */ | 
| 1221 |  | default: | 
| 1222 |  | goto userr; | 
| 1223 |  | } | 
| 1224 |  | break; | 
| 1225 | + | case 'x':               /* x-resolution */ | 
| 1226 | + | xrs = argv[++a]; | 
| 1227 | + | na = 0; | 
| 1228 | + | continue; | 
| 1229 | + | case 'y':               /* y-resolution */ | 
| 1230 | + | yrs = argv[++a]; | 
| 1231 | + | na = 0; | 
| 1232 | + | continue; | 
| 1233 |  | case 'c':               /* number of samples */ | 
| 1234 | < | sampcnt = atoi(argv[a+1]); | 
| 1234 | > | sampcnt = atoi(argv[++a]); | 
| 1235 |  | if (sampcnt <= 0) | 
| 1236 |  | goto userr; | 
| 1237 |  | na = 0;         /* we re-add this later */ | 
| 1238 |  | continue; | 
| 1239 | < | case 'V':               /* options without arguments */ | 
| 1174 | < | case 'w': | 
| 1175 | < | case 'u': | 
| 1239 | > | case 'I':               /* only for pass-through mode */ | 
| 1240 |  | case 'i': | 
| 1241 | + | iropt = argv[a]; | 
| 1242 | + | na = 0; | 
| 1243 | + | continue; | 
| 1244 | + | case 'w':               /* options without arguments */ | 
| 1245 | + | if (argv[a][2] != '+') verbose = -1; | 
| 1246 | + | case 'V': | 
| 1247 | + | case 'u': | 
| 1248 |  | case 'h': | 
| 1249 | + | case 'r': | 
| 1250 |  | break; | 
| 1251 |  | case 'n':               /* options with 1 argument */ | 
| 1252 |  | case 's': | 
| 1257 |  | if (argv[a][2] != 'v') goto userr; | 
| 1258 |  | break; | 
| 1259 |  | case 'l':               /* special case */ | 
| 1260 | < | if (argv[a][2] == 'd') goto userr; | 
| 1260 | > | if (argv[a][2] == 'd') { | 
| 1261 | > | ldopt = argv[a]; | 
| 1262 | > | na = 0; | 
| 1263 | > | continue; | 
| 1264 | > | } | 
| 1265 |  | na = 2; | 
| 1266 |  | break; | 
| 1267 |  | case 'd':               /* special case */ | 
| 1274 |  | if (!argv[a][2]) goto userr; | 
| 1275 |  | na = (argv[a][2] == 'e') | (argv[a][2] == 'a') ? 4 : 2; | 
| 1276 |  | break; | 
| 1201 | – | case '\0':              /* pass-through mode */ | 
| 1202 | – | goto done_opts; | 
| 1277 |  | default:                /* anything else is verbotten */ | 
| 1278 |  | goto userr; | 
| 1279 |  | } | 
| 1283 |  | while (--na)            /* + arguments if any */ | 
| 1284 |  | rcarg[nrcargs++] = argv[++a]; | 
| 1285 |  | } | 
| 1212 | – | done_opts: | 
| 1286 |  | if (a > argc-2) | 
| 1287 |  | goto userr;             /* check at end of options */ | 
| 1288 |  | sendfn = argv[a++];             /* assign sender & receiver inputs */ | 
| 1289 |  | if (sendfn[0] == '-') {         /* user wants pass-through mode? */ | 
| 1290 |  | if (sendfn[1]) goto userr; | 
| 1291 |  | sendfn = NULL; | 
| 1292 | + | if (iropt) { | 
| 1293 | + | CHECKARGC(1); | 
| 1294 | + | rcarg[nrcargs++] = iropt; | 
| 1295 | + | } | 
| 1296 | + | if (xrs) { | 
| 1297 | + | CHECKARGC(2); | 
| 1298 | + | rcarg[nrcargs++] = "-x"; | 
| 1299 | + | rcarg[nrcargs++] = xrs; | 
| 1300 | + | } | 
| 1301 | + | if (yrs) { | 
| 1302 | + | CHECKARGC(2); | 
| 1303 | + | rcarg[nrcargs++] = "-y"; | 
| 1304 | + | rcarg[nrcargs++] = yrs; | 
| 1305 | + | } | 
| 1306 | + | if (ldopt) { | 
| 1307 | + | CHECKARGC(1); | 
| 1308 | + | rcarg[nrcargs++] = ldopt; | 
| 1309 | + | } | 
| 1310 |  | if (sampcnt <= 0) sampcnt = 1; | 
| 1311 | < | } else {                        /* else FVECT determines input format */ | 
| 1312 | < | fmtopt[3] = (sizeof(RREAL)==sizeof(double)) ? 'd' : 'f'; | 
| 1311 | > | } else {                        /* else in sampling mode */ | 
| 1312 | > | if (iropt) { | 
| 1313 | > | fputs(progname, stderr); | 
| 1314 | > | fputs(": -i, -I supported for pass-through only\n", stderr); | 
| 1315 | > | return(1); | 
| 1316 | > | } | 
| 1317 | > | fmtopt[2] = (sizeof(RREAL)==sizeof(double)) ? 'd' : 'f'; | 
| 1318 |  | if (sampcnt <= 0) sampcnt = 10000; | 
| 1319 |  | } | 
| 1320 |  | sprintf(sampcntbuf, "%d", sampcnt); | 
| 1353 |  | if (verbose) { | 
| 1354 |  | fprintf(stderr, "%s: sampling %d directions", progname, nsbins); | 
| 1355 |  | if (curparams.nsurfs > 1) | 
| 1356 | < | fprintf(stderr, " (%d surfaces)\n", curparams.nsurfs); | 
| 1356 | > | fprintf(stderr, " (%d elements)\n", curparams.nsurfs); | 
| 1357 |  | else | 
| 1358 |  | fputc('\n', stderr); | 
| 1359 |  | } | 
| 1364 |  | userr: | 
| 1365 |  | if (a < argc-2) | 
| 1366 |  | fprintf(stderr, "%s: unsupported option '%s'", progname, argv[a]); | 
| 1367 | < | fprintf(stderr, "Usage: %s [rcontrib options] sender.rad receiver.rad [system.rad ..]\n", | 
| 1367 | > | fprintf(stderr, "Usage: %s [-v][rcontrib options] sender.rad receiver.rad [-i system.oct] [system.rad ..]\n", | 
| 1368 |  | progname); | 
| 1369 |  | return(1); | 
| 1370 |  | } |