ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/src/rt/rxfluxmtx.cpp
(Generate patch)

Comparing src/rt/rxfluxmtx.cpp (file contents):
Revision 2.1 by greg, Wed Oct 22 02:38:27 2025 UTC vs.
Revision 2.7 by greg, Fri Oct 24 19:58:19 2025 UTC

# Line 12 | Line 12 | static const char RCSid[] = "$Id$";
12  
13   #include <ctype.h>
14   #include <signal.h>
15 + #include <time.h>
16   #include "RcontribSimulManager.h"
17   #include "bsdf.h"
18   #include "bsdf_m.h"
# Line 34 | Line 35 | const char     *sigerr[NSIG];          /* signal error messages */
35   int     inpfmt = 'a';                   /* input format */
36   int     outfmt = 'f';                   /* output format */
37  
38 + int     report_intvl = 0;               /* reporting interval (seconds) */
39 +
40   RcontribSimulManager    myRCmanager;    // global rcontrib simulation manager
41  
42   #define PARAMSNAME      "rfluxmtx"      /* string indicating parameters */
# Line 79 | Line 82 | struct PARAMS {
82          int             (*sample_basis)(PARAMS *p, int b, FVECT orig_dir[]);
83   };
84  
85 < PARAMS          curparams;
86 < char            curmod[MAXSTR];
87 < char            newparams[1024];
85 > static PARAMS           curparams;
86 > static char             curmod[MAXSTR];
87 > static char             newparams[1024];
88  
89   typedef int     SURFSAMP(FVECT, SURF *, double);
90  
91 < SURFSAMP        ssamp_bad, ssamp_poly, ssamp_ring;
91 > static SURFSAMP ssamp_bad, ssamp_poly, ssamp_ring;
92  
93 < SURFSAMP        *orig_in_surf[4] = {
93 > static SURFSAMP *orig_in_surf[4] = {
94                  ssamp_bad, ssamp_poly, ssamp_ring, ssamp_bad
95          };
96  
# Line 96 | Line 99 | double         dstrpix = 0;            // pixel jitter
99   double          dblur = 0;              // depth-of-field
100  
101   /* Clear parameter set */
102 < void
102 > static void
103   clear_params(PARAMS *p, bool reset_only = true)
104   {
105          while (p->slist != NULL) {
# Line 116 | Line 119 | clear_params(PARAMS *p, bool reset_only = true)
119   }
120  
121   /* Get surface type from name */
122 < int
122 > static int
123   surf_type(const char *otype)
124   {
125          if (!strcmp(otype, "polygon"))
# Line 129 | Line 132 | surf_type(const char *otype)
132   }
133  
134   /* Add arguments to oconv command */
135 < char *
135 > static char *
136   oconv_command(int ac, char *av[])
137   {
138          static char     oconvbuf[4096] = "!oconv -f ";
# Line 176 | Line 179 | overrun:
179   }
180  
181   /* Get normalized direction vector from string specification */
182 < int
182 > static int
183   get_direction(FVECT dv, const char *s)
184   {
185          int     sign = 1;
# Line 216 | Line 219 | nextchar:
219   }
220  
221   /* Parse program parameters (directives) */
222 < int
222 > static int
223   parse_params(PARAMS *p, char *pargs)
224   {
225          char    *cp = pargs;
# Line 295 | Line 298 | parse_params(PARAMS *p, char *pargs)
298   }
299  
300   /* Add receiver modifier and associated parameters */
301 < void
301 > static void
302   finish_receiver()
303   {
304          bool            uniform = false;
305          const char      *calfn = NULL;
306 <        char            binv[64] = "";
306 >        char            binv[64] = "0";
307          char            params[128] = "";
308          const char      *binf = NULL;
309          const char      *nbins = NULL;
# Line 321 | Line 324 | finish_receiver()
324          }
325                                          /* determine sample type/bin */
326          if ((tolower(curparams.hemis[0]) == 'u') | (curparams.hemis[0] == '1')) {
327 <                sprintf(binv, "if(-Dx*%g-Dy*%g-Dz*%g,0,-1)",
328 <                        curparams.nrm[0], curparams.nrm[1], curparams.nrm[2]);
327 >                if (curparams.slist->styp != ST_SOURCE)
328 >                        sprintf(binv, "if(-Dx*%g-Dy*%g-Dz*%g,0,-1)",
329 >                                curparams.nrm[0], curparams.nrm[1], curparams.nrm[2]);
330                  uniform = true;         /* uniform sampling -- one bin */
331          } else if (tolower(curparams.hemis[0]) == 's' &&
332                                  tolower(curparams.hemis[1]) == 'c') {
# Line 408 | Line 412 | finish_receiver()
412   }
413  
414   /* Make randomly oriented tangent plane axes for given normal direction */
415 < void
415 > static void
416   make_axes(FVECT uva[2], const FVECT nrm)
417   {
418          int     i;
# Line 419 | Line 423 | make_axes(FVECT uva[2], const FVECT nrm)
423   }
424  
425   /* Illegal sender surfaces end up here */
426 < int
426 > static int
427   ssamp_bad(FVECT orig, SURF *sp, double x)
428   {
429          sprintf(errmsg, "illegal sender surface '%s'", sp->sname);
# Line 428 | Line 432 | ssamp_bad(FVECT orig, SURF *sp, double x)
432   }
433  
434   /* Generate origin on ring surface from uniform random variable */
435 < int
435 > static int
436   ssamp_ring(FVECT orig, SURF *sp, double x)
437   {
438          FVECT   *uva = (FVECT *)sp->priv;
# Line 456 | Line 460 | ssamp_ring(FVECT orig, SURF *sp, double x)
460   }
461  
462   /* Add triangle to polygon's list (call-back function) */
463 < int
463 > static int
464   add_triangle(const Vert2_list *tp, int a, int b, int c)
465   {
466          POLYTRIS        *ptp = (POLYTRIS *)tp->p;
# Line 469 | Line 473 | add_triangle(const Vert2_list *tp, int a, int b, int c
473   }
474  
475   /* Generate origin on polygon surface from uniform random variable */
476 < int
476 > static int
477   ssamp_poly(FVECT orig, SURF *sp, double x)
478   {
479          POLYTRIS        *ptp = (POLYTRIS *)sp->priv;
# Line 541 | Line 545 | memerr:
545   }
546  
547   /* Compute sample origin based on projected areas of sender subsurfaces */
548 < int
548 > static int
549   sample_origin(PARAMS *p, FVECT orig, const FVECT rdir, double x)
550   {
551          static double   *projsa;
# Line 582 | Line 586 | sample_origin(PARAMS *p, FVECT orig, const FVECT rdir,
586   }
587  
588   /* Uniform sample generator */
589 < int
589 > static int
590   sample_uniform(PARAMS *p, int b, FVECT orig_dir[])
591   {
592          int     n = myRCmanager.accum;
# Line 609 | Line 613 | sample_uniform(PARAMS *p, int b, FVECT orig_dir[])
613   }
614  
615   /* Shirly-Chiu sample generator */
616 < int
616 > static int
617   sample_shirchiu(PARAMS *p, int b, FVECT orig_dir[])
618   {
619          int     n = myRCmanager.accum;
# Line 622 | Line 626 | sample_shirchiu(PARAMS *p, int b, FVECT orig_dir[])
626  
627          while (n--) {                   /* stratified sampling */
628                  SDmultiSamp(samp3, 3, (n+frandom())/myRCmanager.accum);
629 <                square2disk(duvw, (b/p->hsiz + samp3[1])/curparams.hsiz,
630 <                                (b%p->hsiz + samp3[2])/curparams.hsiz);
629 >                square2disk(duvw, (b/p->hsiz + samp3[1])/p->hsiz,
630 >                                (b%p->hsiz + samp3[2])/p->hsiz);
631                  duvw[2] = sqrt(1. - duvw[0]*duvw[0] - duvw[1]*duvw[1]);
632                  for (i = 3; i--; )
633                          orig_dir[1][i] = -duvw[0]*p->udir[i] -
# Line 637 | Line 641 | sample_shirchiu(PARAMS *p, int b, FVECT orig_dir[])
641   }
642  
643   /* Reinhart/Tregenza sample generator */
644 < int
644 > static int
645   sample_reinhart(PARAMS *p, int b, FVECT orig_dir[])
646   {
647   #define T_NALT  7
# Line 687 | Line 691 | sample_reinhart(PARAMS *p, int b, FVECT orig_dir[])
691   }
692  
693   /* Klems sample generator */
694 < int
694 > static int
695   sample_klems(PARAMS *p, int b, FVECT orig_dir[])
696   {
697          static const char       bname[4][20] = {
# Line 735 | Line 739 | sample_klems(PARAMS *p, int b, FVECT orig_dir[])
739   }
740  
741   /* Prepare hemisphere basis sampler that will send rays to rcontrib */
742 < int
742 > static int
743   prepare_sampler(PARAMS *p)
744   {
745          if (p->slist == NULL) {         /* missing sample surface! */
# Line 817 | Line 821 | unrecognized:
821   }
822  
823   /* Compute normal and area for polygon */
824 < int
824 > static int
825   finish_polygon(SURF *p)
826   {
827          const int       nv = p->nfargs / 3;
# Line 839 | Line 843 | finish_polygon(SURF *p)
843   }
844  
845   /* Add a surface to our current parameters */
846 < void
846 > static void
847   add_surface(int st, const char *oname, FILE *fp)
848   {
849          SURF    *snew;
# Line 915 | Line 919 | badnorm:
919   }
920  
921   /* Parse a receiver object (look for modifiers to add) */
922 < int
922 > static int
923   add_recv_object(FILE *fp)
924   {
925          int             st;
# Line 951 | Line 955 | add_recv_object(FILE *fp)
955   }
956  
957   /* Parse a sender object */
958 < int
958 > static int
959   add_send_object(FILE *fp)
960   {
961          int             st;
# Line 991 | Line 995 | add_send_object(FILE *fp)
995   }
996  
997   /* Load a Radiance scene using the given callback function for objects */
998 < int
998 > static int
999   load_scene(const char *inspec, int (*ocb)(FILE *))
1000   {
1001          int     rv = 0;
# Line 1083 | Line 1087 | eputs(                         /* put string to stderr */
1087   }
1088  
1089   /* set input/output format */
1090 < void
1090 > static void
1091   setformat(const char *fmt)
1092   {
1093          switch (fmt[0]) {
# Line 1123 | Line 1127 | fmterr:
1127          error(USER, errmsg);
1128   }
1129  
1130 < inline double
1130 > static inline double
1131   pixjitter()
1132   {
1133          return(0.5 + dstrpix*(frandom()-0.5));
# Line 1131 | Line 1135 | pixjitter()
1135  
1136   // Compute a set of view rays for the given pixel accumulator
1137   bool
1138 < viewRays(FVECT orig_dir[], int x, int y)
1138 > viewRayBundle(FVECT orig_dir[], int x, int y)
1139   {
1140          for (int n = 0; n < myRCmanager.accum; orig_dir += 2, n++) {
1141                  const double    d = viewray(orig_dir[0], orig_dir[1], &ourview,
# Line 1154 | Line 1158 | viewRays(FVECT orig_dir[], int x, int y)
1158          return true;
1159   }
1160  
1161 < // Load a set of rays for accumulation (do not normalize direction)
1162 < int
1163 < getRays(FVECT orig_dir[])
1161 > // skip specified number of bytes, return false if EOF
1162 > static bool
1163 > skipBytes(size_t n2skip)
1164   {
1165 <        int     n;
1165 >        while (n2skip--)
1166 >                if (getchar() == EOF)
1167 >                        return false;
1168 >        return true;
1169 > }
1170 >
1171 > // skip specified number of whitespace-separated words, return false if EOF
1172 > static bool
1173 > skipWords(int n2skip)
1174 > {
1175 >        int     c;
1176 >
1177 >        while (n2skip--) {
1178 >                do {
1179 >                        c = getchar();
1180 >                } while (isspace(c));
1181 >                do {
1182 >                        if (c == EOF) return false;
1183 >                        c = getchar();
1184 >                } while (!isspace(c));
1185 >        }
1186 >        return true;
1187 > }
1188 >
1189 > // Skip a set of input rays
1190 > bool
1191 > skipRayBundle()
1192 > {
1193 >        switch (inpfmt) {
1194 >        case 'd':
1195 >                return skipBytes(sizeof(double)*6*myRCmanager.accum);
1196 >        case 'f':
1197 >                return skipBytes(sizeof(float)*6*myRCmanager.accum);
1198 >        case 'a':
1199 >                return skipWords(6*myRCmanager.accum);
1200 >        }
1201 >        error(INTERNAL, "unsupported input format");
1202 >        return false;
1203 > }
1204 >
1205 > // Load a set of rays for accumulation (do not normalize directions)
1206 > bool
1207 > getRayBundle(FVECT orig_dir[])
1208 > {
1209                                                  // read directly if possible
1210          if (inpfmt == "_fd"[sizeof(RREAL)/sizeof(float)])
1211 <                return(getbinary(orig_dir[0], sizeof(FVECT)*2,
1212 <                                        myRCmanager.accum, stdin));
1211 >                return (getbinary(orig_dir[0], sizeof(FVECT)*2,
1212 >                                myRCmanager.accum, stdin) == myRCmanager.accum);
1213  
1214 <        for (n = 0; n < myRCmanager.accum; orig_dir += 2, n++) {
1214 >        for (int n = 0; n < myRCmanager.accum; orig_dir += 2, n++)
1215                  switch (inpfmt) {
1216   #ifdef SMLFLT
1217                  case 'd': { double      dvin[6];
1218                          if (getbinary(dvin, sizeof(dvin), 1, stdin) != 1)
1219 <                                break;
1219 >                                return false;
1220                          for (int i = 6; i--; ) orig_dir[0][i] = dvin[i];
1221 <                        } continue;
1221 >                        } break;
1222   #else
1223                  case 'f': { float       fvin[6];
1224                          if (getbinary(fvin, sizeof(fvin), 1, stdin) != 1)
1225 <                                break;
1225 >                                return false;
1226                          for (int i = 6; i--; ) orig_dir[0][i] = fvin[i];
1227 <                        } continue;
1227 >                        } break;
1228   #endif
1229                  case 'a':
1230                          if (scanf(FVFORMAT, &orig_dir[0][0], &orig_dir[0][1],
1231                                          &orig_dir[0][2]) != 3)
1232 <                                break;
1232 >                                return false;
1233                          if (scanf(FVFORMAT, &orig_dir[1][0], &orig_dir[1][1],
1234                                          &orig_dir[1][2]) != 3)
1235 <                                break;
1236 <                        continue;
1235 >                                return false;
1236 >                        break;
1237 >                default:
1238 >                        error(INTERNAL, "unsupported input format");
1239                  }
1240 <                break;
1241 <        }
1193 <        return(n);
1240 >
1241 >        return true;
1242   }
1243  
1244   /* Set default options */
1245 < void
1245 > static void
1246   default_options()
1247   {
1248          rand_samp = 1;
# Line 1212 | Line 1260 | default_options()
1260   }
1261  
1262   /* Set overriding options */
1263 < void
1263 > static void
1264   override_options()
1265   {
1266          shadthresh = 0;
# Line 1251 | Line 1299 | sigdie(                        /* set fatal signal */
1299          sigerr[signo] = msg;
1300   }
1301  
1302 + // report progress
1303 + void
1304 + report_progress(bool force = false)
1305 + {
1306 +        static time_t   last_report=0, tstart=time(0);
1307 +        time_t          tnow;
1308 +
1309 +        if (!force & (report_intvl <= 0))
1310 +                return;
1311 +
1312 +        tnow = time(0);
1313 +        if (!force & (tnow < last_report + report_intvl))
1314 +                return;
1315 +
1316 +        sprintf(errmsg, "%.2f%% done after %.3f hours\n",
1317 +                        100. * myRCmanager.GetRowFinished() /
1318 +                                (double)myRCmanager.GetRowMax(),
1319 +                        (tnow - tstart)*(1./3600.));
1320 +        eputs(errmsg);
1321 +        last_report = tnow;
1322 + }
1323 +
1324   /* Run rfluxmtx equivalent without leaning on r[x]contrib */
1325   int
1326   main(int argc, char *argv[])
# Line 1261 | Line 1331 | main(int argc, char *argv[])
1331   #define  check_bool(olen,var)           switch (argv[a][olen]) { \
1332                                  case '\0': var = !var; break; \
1333                                  case 'y': case 'Y': case 't': case 'T': \
1334 <                                case '+': case '1': var = 1; break; \
1334 >                                case '+': case '1': var = true; break; \
1335                                  case 'n': case 'N': case 'f': case 'F': \
1336 <                                case '-': case '0': var = 0; break; \
1336 >                                case '-': case '0': var = false; break; \
1337                                  default: goto userr; }
1338 +        bool            force_open = false;
1339 +        bool            recover = false;
1340          bool            gotView = false;
1341          double          pixaspect = 1.;
1342          int             nproc = 1;
# Line 1287 | Line 1359 | main(int argc, char *argv[])
1359                                          /* set rcontrib defaults */
1360          default_options();
1361                                          /* get command-line options */
1362 <        for (a = 1; a < argc-2; a++) {
1362 >        for (a = 1; a < argc; a++) {
1363                                          /* check for argument expansion */
1364                  while ((rval = expandarg(&argc, &argv, a)) > 0)
1365                          ;
# Line 1381 | Line 1453 | main(int argc, char *argv[])
1453                          check_bool(2,rval);
1454                          myRCmanager.SetFlag(RTimmIrrad, rval);
1455                          break;
1456 <                case 'f':                       /* format */
1457 <                        if (argv[a][2] == 'o')
1458 <                                goto userr;     /* -fo is not optional */
1456 >                case 'f':                       /* format or force overwrite */
1457 >                        if (argv[a][2] == 'o') {
1458 >                                check_bool(3,force_open);
1459 >                                break;
1460 >                        }
1461                          setformat(argv[a]+2);
1388                        myRCmanager.SetDataFormat(outfmt);
1462                          break;
1463 +                case 'r':                       // recover flag
1464 +                        check_bool(2,recover);
1465 +                        break;
1466                  case 'o':                       /* output file */
1467                          check(2,"s");
1468                          outfn = argv[++a];
# Line 1395 | Line 1471 | main(int argc, char *argv[])
1471                          check(2,"i");
1472                          myRCmanager.accum = atoi(argv[++a]);
1473                          break;
1474 +                case 't':                       /* reporting interval */
1475 +                        check(2,"i");
1476 +                        report_intvl = atoi(argv[++a]);
1477 +                        break;
1478                  default:                /* anything else is verbotten */
1479                          goto userr;
1480                  }
1481          }
1482 <        if (a > argc-2)
1482 >        if (a > argc-1)
1483                  goto userr;
1484  
1485          override_options();             /* override critical options */
1486  
1487 <        if (!gotView)
1487 >        if (!gotView) {
1488                  sendfn = argv[a++];
1489 <        else if (argv[a][0] == '-')
1489 >                if (a > argc-1)
1490 >                        goto userr;
1491 >        } else if (argv[a][0] == '-')
1492                  error(USER, "view specification incompatible with pass-through mode");
1493                                          /* assign sender & receiver inputs */
1494          if (gotView) {                  // picture output?
1495                  const char *    err = setview(&ourview);
1496                  if (err != NULL)
1497                          error(USER, err);
1498 +                if (myRCmanager.HasFlag(RTimmIrrad))
1499 +                        error(USER, "-I+ not allowed in view generation mode");
1500                  normaspect(viewaspect(&ourview), &pixaspect,
1501                                  &myRCmanager.xres, &myRCmanager.yres);
1502                  if ((myRCmanager.xres <= 0) | (myRCmanager.yres <= 0))
# Line 1427 | Line 1511 | main(int argc, char *argv[])
1511                          myRCmanager.accum = 1;
1512          } else {                        // else surface sampling
1513                  if (do_irrad | myRCmanager.HasFlag(RTimmIrrad))
1514 <                        error(USER, "-i, -I not allowed in surface-sampling mode");
1514 >                        error(USER, "-i+, -I+ not allowed in surface-sampling mode");
1515                  myRCmanager.SetFlag(RTlimDist, false);
1516                  if (load_scene(sendfn, add_send_object) < 0)
1517                          quit(1);
# Line 1480 | Line 1564 | main(int argc, char *argv[])
1564                          if (strlen(buf) > VIEWSTRL+3)
1565                                  myRCmanager.AddHeader(buf);
1566                  }
1567 <                if ((pixaspect > .005) && (pixaspect < .995) |
1568 <                                        (pixaspect > 1.005)) {
1567 >                if ((pixaspect > .005) & ((pixaspect < .995) |
1568 >                                          (pixaspect > 1.005))) {
1569                          sprintf(buf, "%s%f", ASPECTSTR, pixaspect);
1570                          myRCmanager.AddHeader(buf);
1571                  }
1572          }
1573 +                                        // set output format
1574 +        myRCmanager.SetDataFormat(outfmt);
1575                                          /* assign receiver modifiers */
1576          if (load_scene(argv[a], add_recv_object) < 0)
1577                  quit(1);
1578          finish_receiver();              // makes final AddModifier() call
1579 <                                        // prepare output(s)
1580 <        myRCmanager.outOp = RCOforce;   // mandatory rcontrib -fo+ mode
1581 <        if (myRCmanager.PrepOutput() < 0)
1582 <                error(USER, "issue creating output file(s)");
1583 <        if (verby)                      // get output file count?
1579 >                                        // prepare output files
1580 >        if (recover) {
1581 >                if (force_open) {
1582 >                        error(WARNING, "-r+ mode overrides -fo+");
1583 >                        force_open = false;
1584 >                }
1585 >                myRCmanager.outOp = RCOrecover;
1586 >        } else if (force_open)
1587 >                myRCmanager.outOp = RCOforce;
1588 >        else
1589 >                myRCmanager.outOp = RCOnew;
1590 >                                        // rval = # rows recovered
1591 >        rval = myRCmanager.PrepOutput();
1592 >        if (rval < 0)                   // PrepOutput() failure?
1593 >                error(USER, "issue loading or creating output");
1594 >                                        // in case output is complete
1595 >        if (rval >= myRCmanager.GetRowMax()) {
1596 >                error(WARNING, "nothing left to compute");
1597 >                quit(0);
1598 >        }
1599 >        if (verby) {                    // get output file count?
1600 >                if (rval > 0) {
1601 >                        sprintf(errmsg, "recovered %d of %d rows\n",
1602 >                                        rval, myRCmanager.GetRowMax());
1603 >                        eputs(errmsg);
1604 >                }
1605                  for (const RcontribOutput *op = myRCmanager.GetOutput();
1606                                  op != NULL; op = op->Next())
1607                          ++nout;
1608 +        }
1609          if (nproc > 1) {                // set #processes
1610 <                if (verby)
1611 <                        fprintf(stderr, "%s: starting %d subprocesses\n", progname, nproc);
1610 >                if (verby) {
1611 >                        sprintf(errmsg, "starting %d subprocesses\n", nproc);
1612 >                        eputs(errmsg);
1613 >                }
1614                  myRCmanager.SetThreadCount(nproc);
1615          }
1616          if (gotView) {                  // picture generation mode?
1617 +                i = myRCmanager.GetRowCount();
1618                  if (verby) {
1619 <                        fprintf(stderr, "%s: computing %d %dx%d pictures",
1620 <                                        progname, nout, myRCmanager.xres, myRCmanager.yres);
1619 >                        sprintf(errmsg, "%s %d %dx%d pictures\n",
1620 >                                        i ? "completing" : "computing",
1621 >                                        nout, myRCmanager.xres, myRCmanager.yres);
1622                          if (myRCmanager.accum > 1)
1623 <                                fprintf(stderr, " with %d samples/pixel\n", myRCmanager.accum);
1624 <                        else
1625 <                                fputc('\n', stderr);
1623 >                                sprintf(errmsg+strlen(errmsg)-1, " with %d samples/pixel\n",
1624 >                                                myRCmanager.accum);
1625 >                        eputs(errmsg);
1626                  }
1627 <                for (i = myRCmanager.yres; i--; )       // from the top!
1628 <                        for (int x = 0; x < myRCmanager.xres; x++) {
1629 <                                if (!viewRays(rayarr, x, i))
1627 >                i /= myRCmanager.xres;
1628 >                int     xstart = myRCmanager.GetRowCount() - i*myRCmanager.xres;
1629 >                i = myRCmanager.yres - i;
1630 >                while (i--) {           // compute pixel rows from top down
1631 >                        for (int x = xstart; x < myRCmanager.xres; x++) {
1632 >                                report_progress();
1633 >                                if (!viewRayBundle(rayarr, x, i))
1634                                          quit(1);
1635                                  if (myRCmanager.ComputeRecord(rayarr) != myRCmanager.accum)
1636                                          error(USER, "failed call to ComputeRecord()");
1637                          }
1638 +                        xstart = 0;     // all rows after first start at x=0
1639 +                }
1640          } else if (sendfn == NULL) {    // pass-through mode?
1641   #ifdef getc_unlocked
1642                  flockfile(stdin);
1643   #endif
1644 <                if (verby)
1645 <                        fprintf(stderr,
1646 <                                "%s: computing %d rows in %d matrices with %d samples/row\n",
1647 <                                progname, myRCmanager.GetRowMax(), nout, myRCmanager.accum);
1648 <                for (i = myRCmanager.GetRowMax(); i-- > 0; ) {
1649 <                        if (getRays(rayarr) != myRCmanager.accum) {
1650 <                                sprintf(errmsg, "ray read error after %d of %d",
1651 <                                                myRCmanager.GetRowCount(),
1652 <                                                myRCmanager.GetRowMax());
1644 >                                        // skip completed rows
1645 >                for (i = 0; i < myRCmanager.GetRowCount(); i++)
1646 >                        if (!skipRayBundle()) {
1647 >                                sprintf(errmsg, "read error from stdin at row %d", i);
1648 >                                error(SYSTEM, errmsg);
1649 >                        }
1650 >                if (verby) {
1651 >                        sprintf(errmsg, "computing %d%s rows in %d matrices\n",
1652 >                                        myRCmanager.GetRowMax()-i, i ? " remaining" : "", nout);
1653 >                        if (myRCmanager.accum > 1)
1654 >                                sprintf(errmsg+strlen(errmsg)-1, " with %d samples/row\n",
1655 >                                                myRCmanager.accum);
1656 >                        eputs(errmsg);
1657 >                }
1658 >                for ( ; i < myRCmanager.GetRowMax(); i++) {
1659 >                        report_progress();
1660 >                        if (!getRayBundle(rayarr)) {
1661 >                                sprintf(errmsg, "read error from stdin at row %d of %d",
1662 >                                                i, myRCmanager.GetRowMax());
1663                                  error(USER, errmsg);
1664                          }
1665                          if (myRCmanager.ComputeRecord(rayarr) != myRCmanager.accum)
1666                                  error(USER, "failed call to ComputeRecord()");
1667                  }
1668          } else {                        // else surface-sampling mode
1669 +                i = myRCmanager.GetRowCount();
1670                  if (verby) {
1671 <                        fprintf(stderr,
1672 <                                "%s: sampling %d directions in %d matrices with %d samples/direction",
1673 <                                        progname, myRCmanager.yres, nout, myRCmanager.accum);
1671 >                        sprintf(errmsg, "sampling %d%s directions in %d matrices with %d samples/direction\n",
1672 >                                        myRCmanager.yres-i, i ? " remaining" : "",
1673 >                                        nout, myRCmanager.accum);
1674                          if (sendparams.nsurfs > 1)
1675 <                                fprintf(stderr, " (%d surface elements)\n", sendparams.nsurfs);
1676 <                        else
1548 <                                fputc('\n', stderr);
1675 >                                sprintf(errmsg+strlen(errmsg)-1, " (%d surface elements)\n", sendparams.nsurfs);
1676 >                        eputs(errmsg);
1677                  }
1678 <                for (i = 0; i < myRCmanager.yres; i++) {
1678 >                for ( ; i < myRCmanager.yres; i++) {
1679 >                        report_progress();
1680                          if (!(*sendparams.sample_basis)(&sendparams, i, rayarr))
1681                                  quit(1);
1682                          if (myRCmanager.ComputeRecord(rayarr) != myRCmanager.accum)
# Line 1556 | Line 1685 | main(int argc, char *argv[])
1685                  clear_params(&sendparams);
1686          }
1687          delete [] rayarr;
1688 <        quit(0);                        /* flushes and waits on children */
1688 >        myRCmanager.FlushQueue();
1689 >        report_progress((report_intvl > 0) | verby);
1690 >        quit(0);                        /* waits on any children */
1691   userr:
1692 <        if (a < argc-2)
1693 <                fprintf(stderr, "%s: unsupported option '%s'", progname, argv[a]);
1694 <        fprintf(stderr, "Usage: %s [-W] [rxcontrib options] { sender.rad | view | - } receiver.rad [-i system.oct] [system.rad ..]\n",
1692 >        if (a < argc && argv[a][0] == '-')
1693 >                fprintf(stderr, "%s: unsupported/misplaced option '%s'\n", progname, argv[a]);
1694 >        fprintf(stderr, "Usage: %s [-W] [rcontrib options] { sender.rad | view | - } receiver.rad [-i system.oct] [system.rad ..]\n",
1695                                  progname);
1696          quit(1);
1697   }
# Line 1571 | Line 1702 | quit(
1702          int  code
1703   )
1704   {
1705 <        myRCmanager.FlushQueue();       // leave nothing in queue
1705 >        if (!code)
1706 >                myRCmanager.ClearModifiers();
1707  
1708          exit(code);
1709   }

Diff Legend

Removed lines
+ Added lines
< Changed lines (old)
> Changed lines (new)