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.2 by greg, Thu Oct 23 01:26:48 2025 UTC vs.
Revision 2.8 by greg, Fri Nov 14 23:51:42 2025 UTC

# Line 82 | 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 99 | 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 119 | 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 132 | 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 179 | 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 219 | 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 298 | 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;
# Line 412 | 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 423 | 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 432 | 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 460 | 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 473 | 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 545 | 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 586 | 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 613 | 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 641 | 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 691 | 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 739 | 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 821 | 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 843 | 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 919 | 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 955 | 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 995 | 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 1087 | 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 1127 | 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 1135 | 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 1158 | 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 <        }
1197 <        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 1216 | Line 1260 | default_options()
1260   }
1261  
1262   /* Set overriding options */
1263 < void
1263 > static void
1264   override_options()
1265   {
1266          shadthresh = 0;
# Line 1287 | 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 1298 | Line 1344 | main(int argc, char *argv[])
1344          char            *outfn = NULL;
1345          FVECT           *rayarr = NULL;
1346          const char      *sendfn = "";
1347 +        double          binjitter = 0;
1348          PARAMS          sendparams;
1349          int             rval;
1350          int             a, i;
# Line 1338 | Line 1385 | main(int argc, char *argv[])
1385                  case 'W':                       /* verbose mode */
1386                          check_bool(2,verby);
1387                          break;
1388 +                case 'b':                       /* bin jitter? */
1389 +                        if (argv[a][2] != 'j')
1390 +                                goto userr;
1391 +                        check(3,"f");
1392 +                        binjitter = atof(argv[++a]);
1393 +                        break;
1394                  case 'v':                       // view file
1395                          if (argv[a][2] != 'f')
1396                                  goto userr;
# Line 1407 | Line 1460 | main(int argc, char *argv[])
1460                          check_bool(2,rval);
1461                          myRCmanager.SetFlag(RTimmIrrad, rval);
1462                          break;
1463 <                case 'f':                       /* format */
1464 <                        if (argv[a][2] == 'o')
1465 <                                goto userr;     /* -fo is not optional */
1463 >                case 'f':                       /* format or force overwrite */
1464 >                        if (argv[a][2] == 'o') {
1465 >                                check_bool(3,force_open);
1466 >                                break;
1467 >                        }
1468                          setformat(argv[a]+2);
1414                        myRCmanager.SetDataFormat(outfmt);
1469                          break;
1470 +                case 'r':                       // recover flag
1471 +                        check_bool(2,recover);
1472 +                        break;
1473                  case 'o':                       /* output file */
1474                          check(2,"s");
1475                          outfn = argv[++a];
# Line 1445 | Line 1502 | main(int argc, char *argv[])
1502                  const char *    err = setview(&ourview);
1503                  if (err != NULL)
1504                          error(USER, err);
1505 +                if (myRCmanager.HasFlag(RTimmIrrad))
1506 +                        error(USER, "-I+ not allowed in view generation mode");
1507                  normaspect(viewaspect(&ourview), &pixaspect,
1508                                  &myRCmanager.xres, &myRCmanager.yres);
1509                  if ((myRCmanager.xres <= 0) | (myRCmanager.yres <= 0))
# Line 1459 | Line 1518 | main(int argc, char *argv[])
1518                          myRCmanager.accum = 1;
1519          } else {                        // else surface sampling
1520                  if (do_irrad | myRCmanager.HasFlag(RTimmIrrad))
1521 <                        error(USER, "-i, -I not allowed in surface-sampling mode");
1521 >                        error(USER, "-i+, -I+ not allowed in surface-sampling mode");
1522                  myRCmanager.SetFlag(RTlimDist, false);
1523                  if (load_scene(sendfn, add_send_object) < 0)
1524                          quit(1);
# Line 1512 | Line 1571 | main(int argc, char *argv[])
1571                          if (strlen(buf) > VIEWSTRL+3)
1572                                  myRCmanager.AddHeader(buf);
1573                  }
1574 <                if ((pixaspect > .005) && (pixaspect < .995) |
1575 <                                        (pixaspect > 1.005)) {
1574 >                if ((pixaspect > .005) & ((pixaspect < .995) |
1575 >                                          (pixaspect > 1.005))) {
1576                          sprintf(buf, "%s%f", ASPECTSTR, pixaspect);
1577                          myRCmanager.AddHeader(buf);
1578                  }
1579          }
1580 +                                        // set output format
1581 +        myRCmanager.SetDataFormat(outfmt);
1582                                          /* assign receiver modifiers */
1583          if (load_scene(argv[a], add_recv_object) < 0)
1584                  quit(1);
1585          finish_receiver();              // makes final AddModifier() call
1586 <                                        // prepare output(s)
1587 <        myRCmanager.outOp = RCOforce;   // mandatory rcontrib -fo+ mode
1588 <        if (myRCmanager.PrepOutput() < 0)
1589 <                error(USER, "issue creating output file(s)");
1590 <        if (verby)                      // get output file count?
1586 >        if (binjitter > FTINY)          // global bin jitter?
1587 >                varset(const_cast<char *>("JTR"), '=', binjitter);
1588 >                                        // prepare output files
1589 >        if (recover) {
1590 >                if (force_open) {
1591 >                        error(WARNING, "-r+ mode overrides -fo+");
1592 >                        force_open = false;
1593 >                }
1594 >                myRCmanager.outOp = RCOrecover;
1595 >        } else if (force_open)
1596 >                myRCmanager.outOp = RCOforce;
1597 >        else
1598 >                myRCmanager.outOp = RCOnew;
1599 >                                        // rval = # rows recovered
1600 >        rval = myRCmanager.PrepOutput();
1601 >        if (rval < 0)                   // PrepOutput() failure?
1602 >                error(USER, "issue loading or creating output");
1603 >                                        // in case output is complete
1604 >        if (rval >= myRCmanager.GetRowMax()) {
1605 >                error(WARNING, "nothing left to compute");
1606 >                quit(0);
1607 >        }
1608 >        if (verby) {                    // get output file count?
1609 >                if (rval > 0) {
1610 >                        sprintf(errmsg, "recovered %d of %d rows\n",
1611 >                                        rval, myRCmanager.GetRowMax());
1612 >                        eputs(errmsg);
1613 >                }
1614                  for (const RcontribOutput *op = myRCmanager.GetOutput();
1615                                  op != NULL; op = op->Next())
1616                          ++nout;
1617 +        }
1618          if (nproc > 1) {                // set #processes
1619                  if (verby) {
1620                          sprintf(errmsg, "starting %d subprocesses\n", nproc);
# Line 1538 | Line 1623 | main(int argc, char *argv[])
1623                  myRCmanager.SetThreadCount(nproc);
1624          }
1625          if (gotView) {                  // picture generation mode?
1626 +                i = myRCmanager.GetRowCount();
1627                  if (verby) {
1628 <                        sprintf(errmsg, "computing %d %dx%d pictures\n",
1628 >                        sprintf(errmsg, "%s %d %dx%d pictures\n",
1629 >                                        i ? "completing" : "computing",
1630                                          nout, myRCmanager.xres, myRCmanager.yres);
1631                          if (myRCmanager.accum > 1)
1632                                  sprintf(errmsg+strlen(errmsg)-1, " with %d samples/pixel\n",
1633                                                  myRCmanager.accum);
1634                          eputs(errmsg);
1635                  }
1636 <                for (i = myRCmanager.yres; i--; )       // from the top!
1637 <                        for (int x = 0; x < myRCmanager.xres; x++) {
1636 >                i /= myRCmanager.xres;
1637 >                int     xstart = myRCmanager.GetRowCount() - i*myRCmanager.xres;
1638 >                i = myRCmanager.yres - i;
1639 >                while (i--) {           // compute pixel rows from top down
1640 >                        for (int x = xstart; x < myRCmanager.xres; x++) {
1641                                  report_progress();
1642 <                                if (!viewRays(rayarr, x, i))
1642 >                                if (!viewRayBundle(rayarr, x, i))
1643                                          quit(1);
1644                                  if (myRCmanager.ComputeRecord(rayarr) != myRCmanager.accum)
1645                                          error(USER, "failed call to ComputeRecord()");
1646                          }
1647 +                        xstart = 0;     // all rows after first start at x=0
1648 +                }
1649          } else if (sendfn == NULL) {    // pass-through mode?
1650   #ifdef getc_unlocked
1651                  flockfile(stdin);
1652   #endif
1653 +                                        // skip completed rows
1654 +                for (i = 0; i < myRCmanager.GetRowCount(); i++)
1655 +                        if (!skipRayBundle()) {
1656 +                                sprintf(errmsg, "read error from stdin at row %d", i);
1657 +                                error(SYSTEM, errmsg);
1658 +                        }
1659                  if (verby) {
1660 <                        sprintf(errmsg, "computing %d rows in %d matrices\n",
1661 <                                        myRCmanager.GetRowMax(), nout);
1660 >                        sprintf(errmsg, "computing %d%s rows in %d matrices\n",
1661 >                                        myRCmanager.GetRowMax()-i, i ? " remaining" : "", nout);
1662                          if (myRCmanager.accum > 1)
1663                                  sprintf(errmsg+strlen(errmsg)-1, " with %d samples/row\n",
1664                                                  myRCmanager.accum);
1665                          eputs(errmsg);
1666                  }
1667 <                for (i = 0; i < myRCmanager.GetRowMax(); i++) {
1667 >                for ( ; i < myRCmanager.GetRowMax(); i++) {
1668                          report_progress();
1669 <                        if (getRays(rayarr) != myRCmanager.accum) {
1670 <                                sprintf(errmsg, "ray read error after %d of %d",
1671 <                                                myRCmanager.GetRowCount(),
1574 <                                                myRCmanager.GetRowMax());
1669 >                        if (!getRayBundle(rayarr)) {
1670 >                                sprintf(errmsg, "read error from stdin at row %d of %d",
1671 >                                                i, myRCmanager.GetRowMax());
1672                                  error(USER, errmsg);
1673                          }
1674                          if (myRCmanager.ComputeRecord(rayarr) != myRCmanager.accum)
1675                                  error(USER, "failed call to ComputeRecord()");
1676                  }
1677          } else {                        // else surface-sampling mode
1678 +                i = myRCmanager.GetRowCount();
1679                  if (verby) {
1680 <                        sprintf(errmsg, "sampling %d directions in %d matrices with %d samples/direction\n",
1681 <                                        myRCmanager.yres, nout, myRCmanager.accum);
1680 >                        sprintf(errmsg, "sampling %d%s directions in %d matrices with %d samples/direction\n",
1681 >                                        myRCmanager.yres-i, i ? " remaining" : "",
1682 >                                        nout, myRCmanager.accum);
1683                          if (sendparams.nsurfs > 1)
1684                                  sprintf(errmsg+strlen(errmsg)-1, " (%d surface elements)\n", sendparams.nsurfs);
1685                          eputs(errmsg);
1686                  }
1687 <                for (i = 0; i < myRCmanager.yres; i++) {
1687 >                for ( ; i < myRCmanager.yres; i++) {
1688                          report_progress();
1689                          if (!(*sendparams.sample_basis)(&sendparams, i, rayarr))
1690                                  quit(1);
# Line 1597 | Line 1696 | main(int argc, char *argv[])
1696          delete [] rayarr;
1697          myRCmanager.FlushQueue();
1698          report_progress((report_intvl > 0) | verby);
1699 <        quit(0);                        /* waits on children */
1699 >        quit(0);                        /* waits on any children */
1700   userr:
1701 <        if (a < argc-2)
1702 <                fprintf(stderr, "%s: unsupported option '%s'\n", progname, argv[a]);
1703 <        fprintf(stderr, "Usage: %s [-W] [rxcontrib options] { sender.rad | view | - } receiver.rad [-i system.oct] [system.rad ..]\n",
1701 >        if (a < argc && argv[a][0] == '-')
1702 >                fprintf(stderr, "%s: unsupported/misplaced option '%s'\n", progname, argv[a]);
1703 >        fprintf(stderr, "Usage: %s [-W][-bj frac] [rcontrib options] { sender.rad | view | - } receiver.rad [-i system.oct] [system.rad ..]\n",
1704                                  progname);
1705          quit(1);
1706   }

Diff Legend

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