| 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" |
| 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 */ |
| 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 |
|
|
| 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) { |
| 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")) |
| 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 "; |
| 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; |
| 219 |
|
} |
| 220 |
|
|
| 221 |
|
/* Parse program parameters (directives) */ |
| 222 |
< |
int |
| 222 |
> |
static int |
| 223 |
|
parse_params(PARAMS *p, char *pargs) |
| 224 |
|
{ |
| 225 |
|
char *cp = 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; |
| 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') { |
| 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; |
| 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); |
| 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; |
| 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; |
| 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; |
| 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; |
| 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; |
| 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; |
| 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] - |
| 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 |
| 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] = { |
| 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! */ |
| 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; |
| 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; |
| 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; |
| 955 |
|
} |
| 956 |
|
|
| 957 |
|
/* Parse a sender object */ |
| 958 |
< |
int |
| 958 |
> |
static int |
| 959 |
|
add_send_object(FILE *fp) |
| 960 |
|
{ |
| 961 |
|
int st; |
| 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; |
| 1087 |
|
} |
| 1088 |
|
|
| 1089 |
|
/* set input/output format */ |
| 1090 |
< |
void |
| 1090 |
> |
static void |
| 1091 |
|
setformat(const char *fmt) |
| 1092 |
|
{ |
| 1093 |
|
switch (fmt[0]) { |
| 1127 |
|
error(USER, errmsg); |
| 1128 |
|
} |
| 1129 |
|
|
| 1130 |
< |
inline double |
| 1130 |
> |
static inline double |
| 1131 |
|
pixjitter() |
| 1132 |
|
{ |
| 1133 |
|
return(0.5 + dstrpix*(frandom()-0.5)); |
| 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, |
| 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; |
| 1260 |
|
} |
| 1261 |
|
|
| 1262 |
|
/* Set overriding options */ |
| 1263 |
< |
void |
| 1263 |
> |
static void |
| 1264 |
|
override_options() |
| 1265 |
|
{ |
| 1266 |
|
shadthresh = 0; |
| 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[]) |
| 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; |
| 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 |
|
; |
| 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]; |
| 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)) |
| 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); |
| 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) |
| 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 |
|
} |
| 1702 |
|
int code |
| 1703 |
|
) |
| 1704 |
|
{ |
| 1705 |
< |
myRCmanager.FlushQueue(); // leave nothing in queue |
| 1705 |
> |
if (!code) |
| 1706 |
> |
myRCmanager.ClearModifiers(); |
| 1707 |
|
|
| 1708 |
|
exit(code); |
| 1709 |
|
} |