ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/rxtrace.cpp
Revision: 2.7
Committed: Tue Nov 19 16:29:44 2024 UTC (5 months, 1 week ago) by greg
Branch: MAIN
Changes since 2.6: +3 -3 lines
Log Message:
fix(rxtrace): Compile error fix

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: rxtrace.cpp,v 2.6 2024/11/19 16:28:18 greg Exp $";
3 #endif
4 /*
5 * C++ module for individual ray tracing.
6 */
7
8 /*
9 * Input is in the form:
10 *
11 * xorg yorg zorg xdir ydir zdir
12 *
13 * The direction need not be normalized. Output is flexible.
14 * If the direction vector is (0,0,0), then the output is flushed.
15 * All values default to ascii representation of real
16 * numbers. Binary representations can be selected
17 * with '-ff' for float or '-fd' for double. By default,
18 * radiance is computed. The '-i' or '-I' options indicate that
19 * irradiance values are desired.
20 */
21
22 #include "copyright.h"
23
24 #include "RtraceSimulManager.h"
25 #include "platform.h"
26 #include "otypes.h"
27 #include "otspecial.h"
28 #include "source.h"
29 #include "resolu.h"
30
31 extern int inform; /* input format */
32 extern int outform; /* output format */
33
34 extern char *tralist[]; /* list of modifers to trace (or no) */
35 extern int traincl; /* include == 1, exclude == 0 */
36
37 extern int hresolu; /* horizontal resolution */
38 extern int vresolu; /* vertical resolution */
39
40 extern int castonly; /* only doing ray-casting? */
41
42 extern double (*sens_curve)(SCOLOR scol); /* spectral conversion for 1-channel */
43 extern double out_scalefactor; /* output calibration scale factor */
44 extern RGBPRIMP out_prims; /* output color primitives (NULL if spectral) */
45
46 #ifndef MAXTSET
47 #define MAXTSET 8191 /* maximum number in trace set */
48 #endif
49 OBJECT traset[MAXTSET+1]={0}; /* trace include/exclude set */
50
51 // global simulation manager
52 extern RtraceSimulManager myRTmanager;
53
54 static FILE *inpfp = NULL; /* input stream pointer */
55
56 static FVECT *inp_queue = NULL; /* ray input queue if flushing */
57 static int inp_qpos = 0; /* next ray to return */
58 static int inp_qend = 0; /* number of rays in this work group */
59
60 typedef void putf_t(RREAL *v, int n);
61 static putf_t puta, putd, putf, putrgbe;
62
63 typedef void oputf_t(RAY *r);
64 static oputf_t oputo, oputd, oputv, oputV, oputl, oputL, oputc, oputp,
65 oputr, oputR, oputx, oputX, oputn, oputN, oputs,
66 oputw, oputW, oputm, oputM, oputtilde;
67
68 extern void tranotify(OBJECT obj);
69 static void tabin(RAY *r);
70 static RayReportCall ourtrace;
71
72 RayReportCall printvals; /* print selected ray values */
73
74 void putscolor(COLORV *scol); /* convert/print spectral color */
75
76 static oputf_t *ray_out[32], *every_out[32];
77
78 putf_t *putreal; /* put out real vector */
79
80 void
81 quit( /* quit program */
82 int code
83 )
84 {
85 if (ray_pnprocs < 0)
86 _exit(code); /* avoid flush in child */
87
88 int ec = myRTmanager.Cleanup();
89
90 if (ec) code = ec;
91
92 exit(code);
93 }
94
95 const char *
96 formstr( /* return format identifier */
97 int f
98 )
99 {
100 switch (f) {
101 case 'a': return("ascii");
102 case 'f': return("float");
103 case 'd': return("double");
104 case 'c':
105 if (out_prims == NULL)
106 return(SPECFMT);
107 if (out_prims == xyzprims)
108 return(CIEFMT);
109 return(COLRFMT);
110 }
111 return("unknown");
112 }
113
114 static bool
115 getvec( /* get a vector from fp */
116 FVECT vec,
117 int fmt,
118 FILE *fp
119 )
120 {
121 static char buf[32];
122 float * vf = (float *)buf;
123 double * vd = (double *)buf;
124 int i;
125
126 switch (fmt) {
127 case 'a': /* ascii */
128 for (i = 0; i < 3; i++) {
129 if (fgetword(buf, sizeof(buf), fp) == NULL ||
130 !isflt(buf))
131 return false;
132 vec[i] = atof(buf);
133 }
134 break;
135 #ifdef SMLFLT
136 case 'f': /* binary float */
137 if (getbinary(vec, sizeof(RREAL), 3, fp) != 3)
138 return false;
139 break;
140 case 'd': /* binary double */
141 if (getbinary(vd, sizeof(double), 3, fp) != 3)
142 return false;
143 VCOPY(vec, vd);
144 break;
145 #else
146 case 'f': /* binary float */
147 if (getbinary(vf, sizeof(float), 3, fp) != 3)
148 return false;
149 VCOPY(vec, vf);
150 break;
151 case 'd': /* binary double */
152 if (getbinary(vec, sizeof(RREAL), 3, fp) != 3)
153 return false;
154 break;
155 #endif
156 default:
157 error(CONSISTENCY, "botched input format");
158 }
159 return true;
160 }
161
162 // read ray list from inpfp
163 static int
164 getrays(FVECT org_dir[], int n)
165 {
166 int nread = 0;
167
168 while (n-- > 0) {
169 if (!getvec(org_dir[0], inform, inpfp) ||
170 !getvec(org_dir[1], inform, inpfp))
171 break;
172 ++nread;
173 if (IsZeroVec(org_dir[1]))
174 break;
175 org_dir += 2;
176 }
177 return nread;
178 }
179
180 void
181 rtrace( /* trace rays from stdin or file */
182 char *fname,
183 int nproc
184 )
185 {
186 RNUMBER vcount = (hresolu > 1) ? (RNUMBER)hresolu*vresolu
187 : (RNUMBER)vresolu;
188 const int flushIntvl = (!vresolu | (hresolu <= 1)) * hresolu;
189 FVECT * ivbuf = (FVECT *)malloc(2*sizeof(FVECT) *
190 (flushIntvl + !flushIntvl));
191 if (ivbuf == NULL)
192 error(SYSTEM, "cannot allocate input vector buffer");
193 /* set up input */
194 if (fname == NULL)
195 inpfp = stdin;
196 else if ((inpfp = fopen(fname, "r")) == NULL) {
197 sprintf(errmsg, "cannot open input file \"%s\"", fname);
198 error(SYSTEM, errmsg);
199 }
200 if (inform != 'a')
201 SET_FILE_BINARY(inpfp);
202 /* set up output */
203 if (castonly || every_out[0] != NULL) {
204 nproc = 1; /* don't bother multiprocessing */
205 } else if (nproc <= 0) { // need to get default for system?
206 nproc = myRTmanager.GetNCores() + nproc;
207 if (nproc <= 0) nproc = 1;
208 }
209 if ((flushIntvl > 0) & (nproc > flushIntvl)) {
210 error(WARNING, "reducing number of processes to match flush interval");
211 nproc = flushIntvl;
212 }
213 nproc = myRTmanager.SetThreadCount(nproc);
214 if (ray_out[0])
215 myRTmanager.SetCookedCall(printvals);
216 if (every_out[0])
217 myRTmanager.SetTraceCall(ourtrace);
218 myRTmanager.rtFlags |= RTdoFIFO;
219 #ifdef getc_unlocked
220 flockfile(inpfp); /* avoid lock/unlock overhead */
221 flockfile(stdout);
222 #endif
223 if (hresolu > 0) { // print resolution string if appropriate
224 if (vresolu > 0)
225 fprtresolu(hresolu, vresolu, stdout);
226 else
227 fflush(stdout);
228 }
229 int n; /* process input rays */
230 bool pending = false;
231 while ((n = getrays(ivbuf, flushIntvl + !flushIntvl)) > 0) {
232 if ((vcount > 0) & (n > vcount)) {
233 error(WARNING, "extra ray(s) past end of input");
234 n = vcount;
235 } // put ray(s) into queue
236 if (myRTmanager.EnqueueBundle(ivbuf, n) < n)
237 error(USER, "ray queuing failure");
238 pending |= (n > 1); // time to flush output?
239 bool atZero = IsZeroVec(ivbuf[2*n-1]);
240 if (pending & (atZero | (n == flushIntvl))) {
241 if (myRTmanager.FlushQueue() <= 0)
242 error(USER, "ray flush error");
243 fflush(stdout);
244 pending = false;
245 } else
246 pending |= !atZero;
247 if (ferror(stdout))
248 error(SYSTEM, "write error");
249 if (vcount && !(vcount -= n)) /* check for end */
250 break;
251 }
252 if (vcount)
253 error(WARNING, feof(inpfp) ? "unexpected EOF on input" :
254 "input read error");
255 if (myRTmanager.FlushQueue() < 0 || fflush(stdout) < 0)
256 error(SYSTEM, "final flush error");
257 if (fname != NULL) {
258 fclose(inpfp);
259 inpfp = NULL;
260 }
261 free(ivbuf);
262 }
263
264 int
265 setrtoutput(const char *outvals) /* set up output tables, return #comp */
266 {
267 const char *vs = outvals;
268 oputf_t **table = ray_out;
269 const int nco = (sens_curve != NULL) ? 1 :
270 (out_prims != NULL) ? 3 : NCSAMP;
271 int ncomp = 0;
272
273 if (!*vs)
274 error(USER, "empty output specification");
275
276 switch (outform) { /* make sure (*putreal)() calls someone! */
277 case 'a': putreal = puta; break;
278 case 'f': putreal = putf; break;
279 case 'd': putreal = putd; break;
280 case 'c':
281 if (outvals[1] || !strchr("vrx", outvals[0]))
282 error(USER, "color format only with -ov, -or, -ox");
283 putreal = putrgbe; break;
284 default:
285 error(CONSISTENCY, "botched output format");
286 }
287 castonly = 1; /* sets castonly as side-effect */
288 do
289 switch (*vs) {
290 case 'T': /* trace sources */
291 myRTmanager.rtFlags |= RTtraceSources;
292 /* fall through */
293 case 't': /* trace */
294 if (!vs[1]) break;
295 *table = NULL;
296 table = every_out;
297 castonly = 0;
298 break;
299 case 'o': /* origin */
300 *table++ = oputo;
301 ncomp += 3;
302 break;
303 case 'd': /* direction */
304 *table++ = oputd;
305 ncomp += 3;
306 break;
307 case 'r': /* reflected contrib. */
308 *table++ = oputr;
309 ncomp += nco;
310 castonly = 0;
311 break;
312 case 'R': /* reflected distance */
313 *table++ = oputR;
314 ncomp++;
315 castonly = 0;
316 break;
317 case 'x': /* xmit contrib. */
318 *table++ = oputx;
319 ncomp += nco;
320 castonly = 0;
321 break;
322 case 'X': /* xmit distance */
323 *table++ = oputX;
324 ncomp++;
325 castonly = 0;
326 break;
327 case 'v': /* value */
328 *table++ = oputv;
329 ncomp += nco;
330 castonly = 0;
331 break;
332 case 'V': /* contribution */
333 *table++ = oputV;
334 ncomp += nco;
335 castonly = 0;
336 if (ambounce > 0 && (ambacc > FTINY || ambssamp > 0))
337 error(WARNING,
338 "-otV accuracy depends on -aa 0 -as 0");
339 break;
340 case 'l': /* effective distance */
341 *table++ = oputl;
342 ncomp++;
343 castonly = 0;
344 break;
345 case 'c': /* local coordinates */
346 *table++ = oputc;
347 ncomp += 2;
348 break;
349 case 'L': /* single ray length */
350 *table++ = oputL;
351 ncomp++;
352 break;
353 case 'p': /* point */
354 *table++ = oputp;
355 ncomp += 3;
356 break;
357 case 'n': /* perturbed normal */
358 *table++ = oputn;
359 ncomp += 3;
360 castonly = 0;
361 break;
362 case 'N': /* unperturbed normal */
363 *table++ = oputN;
364 ncomp += 3;
365 break;
366 case 's': /* surface */
367 *table++ = oputs;
368 ncomp++;
369 break;
370 case 'w': /* weight */
371 *table++ = oputw;
372 ncomp++;
373 break;
374 case 'W': /* coefficient */
375 *table++ = oputW;
376 ncomp += nco;
377 castonly = 0;
378 if (ambounce > 0 && (ambacc > FTINY) | (ambssamp > 0))
379 error(WARNING,
380 "-otW accuracy depends on -aa 0 -as 0");
381 break;
382 case 'm': /* modifier */
383 *table++ = oputm;
384 ncomp++;
385 break;
386 case 'M': /* material */
387 *table++ = oputM;
388 ncomp++;
389 break;
390 case '~': /* tilde */
391 *table++ = oputtilde;
392 break;
393 default:
394 sprintf(errmsg, "unrecognized output option '%c'", *vs);
395 error(USER, errmsg);
396 }
397 while (*++vs);
398
399 *table = NULL;
400 if (*every_out != NULL)
401 ncomp = 0;
402 /* compatibility */
403 if ((do_irrad | (myRTmanager.rtFlags & RTimmIrrad)) && castonly)
404 error(USER, "-I+ and -i+ options require some value output");
405 for (table = ray_out; *table != NULL; table++) {
406 if ((*table == oputV) | (*table == oputW))
407 error(WARNING, "-oVW options require trace mode");
408 if ((do_irrad | (myRTmanager.rtFlags & RTimmIrrad)) &&
409 (*table == oputr) | (*table == oputR) |
410 (*table == oputx) | (*table == oputX))
411 error(WARNING, "-orRxX options incompatible with -I+ and -i+");
412 }
413 return(ncomp);
414 }
415
416 int
417 printvals( /* print requested ray values */
418 RAY *r, void *cd
419 )
420 {
421 oputf_t **tp;
422
423 if (ray_out[0] == NULL)
424 return 0;
425 for (tp = ray_out; *tp != NULL; tp++)
426 (**tp)(r);
427 if (outform == 'a')
428 putchar('\n');
429 return 1;
430 }
431
432 void
433 tranotify( /* record new modifier */
434 OBJECT obj
435 )
436 {
437 static int hitlimit = 0;
438 OBJREC *o = objptr(obj);
439 char **tralp;
440
441 if (obj == OVOID) { /* starting over */
442 traset[0] = 0;
443 hitlimit = 0;
444 return;
445 }
446 if (hitlimit || !ismodifier(o->otype))
447 return;
448 for (tralp = tralist; *tralp != NULL; tralp++)
449 if (!strcmp(o->oname, *tralp)) {
450 if (traset[0] >= MAXTSET) {
451 error(WARNING, "too many modifiers in trace list");
452 hitlimit++;
453 return; /* should this be fatal? */
454 }
455 insertelem(traset, obj);
456 return;
457 }
458 }
459
460 static int
461 ourtrace( /* print ray values */
462 RAY *r, void *cd
463 )
464 {
465 oputf_t **tp;
466
467 if (every_out[0] == NULL)
468 return 0;
469 if (r->ro == NULL) {
470 if (traincl == 1)
471 return 0;
472 } else if (traincl != -1 && traincl != inset(traset, r->ro->omod))
473 return 0;
474 tabin(r);
475 for (tp = every_out; *tp != NULL; tp++)
476 (**tp)(r);
477 if (outform == 'a')
478 putchar('\n');
479 return 1;
480 }
481
482 static void
483 tabin( /* tab in appropriate amount */
484 RAY *r
485 )
486 {
487 const RAY *rp;
488
489 for (rp = r->parent; rp != NULL; rp = rp->parent)
490 putchar('\t');
491 }
492
493 static void
494 oputo( /* print origin */
495 RAY *r
496 )
497 {
498 (*putreal)(r->rorg, 3);
499 }
500
501 static void
502 oputd( /* print direction */
503 RAY *r
504 )
505 {
506 (*putreal)(r->rdir, 3);
507 }
508
509 static void
510 oputr( /* print mirrored contribution */
511 RAY *r
512 )
513 {
514 putscolor(r->mcol);
515 }
516
517 static void
518 oputR( /* print mirrored distance */
519 RAY *r
520 )
521 {
522 (*putreal)(&r->rmt, 1);
523 }
524
525 static void
526 oputx( /* print unmirrored contribution */
527 RAY *r
528 )
529 {
530 SCOLOR cdiff;
531
532 copyscolor(cdiff, r->rcol);
533 sopscolor(cdiff, -=, r->mcol);
534
535 putscolor(cdiff);
536 }
537
538 static void
539 oputX( /* print unmirrored distance */
540 RAY *r
541 )
542 {
543 (*putreal)(&r->rxt, 1);
544 }
545
546 static void
547 oputv( /* print value */
548 RAY *r
549 )
550 {
551 putscolor(r->rcol);
552 }
553
554 static void
555 oputV( /* print value contribution */
556 RAY *r
557 )
558 {
559 SCOLOR contr;
560
561 raycontrib(contr, r, PRIMARY);
562 smultscolor(contr, r->rcol);
563 putscolor(contr);
564 }
565
566 static void
567 oputl( /* print effective distance */
568 RAY *r
569 )
570 {
571 RREAL d = raydistance(r);
572
573 (*putreal)(&d, 1);
574 }
575
576 static void
577 oputL( /* print single ray length */
578 RAY *r
579 )
580 {
581 (*putreal)(&r->rot, 1);
582 }
583
584 static void
585 oputc( /* print local coordinates */
586 RAY *r
587 )
588 {
589 (*putreal)(r->uv, 2);
590 }
591
592 static RREAL vdummy[3] = {0.0, 0.0, 0.0};
593
594 static void
595 oputp( /* print intersection point */
596 RAY *r
597 )
598 {
599 (*putreal)(r->rop, 3); /* set to ray origin if distant or no hit */
600 }
601
602 static void
603 oputN( /* print unperturbed normal */
604 RAY *r
605 )
606 {
607 if (r->ro == NULL) { /* zero vector if clipped or no hit */
608 (*putreal)(vdummy, 3);
609 return;
610 }
611 if (r->rflips & 1) { /* undo any flippin' flips */
612 FVECT unrm;
613 unrm[0] = -r->ron[0];
614 unrm[1] = -r->ron[1];
615 unrm[2] = -r->ron[2];
616 (*putreal)(unrm, 3);
617 } else
618 (*putreal)(r->ron, 3);
619 }
620
621 static void
622 oputn( /* print perturbed normal */
623 RAY *r
624 )
625 {
626 FVECT pnorm;
627
628 if (r->ro == NULL) { /* clipped or no hit */
629 (*putreal)(vdummy, 3);
630 return;
631 }
632 raynormal(pnorm, r);
633 (*putreal)(pnorm, 3);
634 }
635
636 static void
637 oputs( /* print name */
638 RAY *r
639 )
640 {
641 if (r->ro != NULL)
642 fputs(r->ro->oname, stdout);
643 else
644 putchar('*');
645 putchar('\t');
646 }
647
648 static void
649 oputw( /* print weight */
650 RAY *r
651 )
652 {
653 RREAL rwt = r->rweight;
654
655 (*putreal)(&rwt, 1);
656 }
657
658 static void
659 oputW( /* print coefficient */
660 RAY *r
661 )
662 {
663 SCOLOR contr;
664 /* shadow ray not on source? */
665 if (r->rsrc >= 0 && source[r->rsrc].so != r->ro)
666 scolorblack(contr);
667 else
668 raycontrib(contr, r, PRIMARY);
669
670 putscolor(contr);
671 }
672
673 static void
674 oputm( /* print modifier */
675 RAY *r
676 )
677 {
678 if (r->ro != NULL)
679 if (r->ro->omod != OVOID)
680 fputs(objptr(r->ro->omod)->oname, stdout);
681 else
682 fputs(VOIDID, stdout);
683 else
684 putchar('*');
685 putchar('\t');
686 }
687
688 static void
689 oputM( /* print material */
690 RAY *r
691 )
692 {
693 OBJREC *mat;
694
695 if (r->ro != NULL) {
696 if ((mat = findmaterial(r->ro)) != NULL)
697 fputs(mat->oname, stdout);
698 else
699 fputs(VOIDID, stdout);
700 } else
701 putchar('*');
702 putchar('\t');
703 }
704
705 static void
706 oputtilde( /* output tilde (spacer) */
707 RAY *r
708 )
709 {
710 fputs("~\t", stdout);
711 }
712
713 static void
714 puta( /* print ascii value(s) */
715 RREAL *v, int n
716 )
717 {
718 if (n == 3) {
719 printf("%e\t%e\t%e\t", v[0], v[1], v[2]);
720 return;
721 }
722 while (n--)
723 printf("%e\t", *v++);
724 }
725
726 static void
727 putd(RREAL *v, int n) /* output binary double(s) */
728 {
729 #ifdef SMLFLT
730 double da[3];
731 int i;
732
733 if (n > 3)
734 error(INTERNAL, "code error in putd()");
735 for (i = n; i--; )
736 da[i] = v[i];
737 putbinary(da, sizeof(double), n, stdout);
738 #else
739 putbinary(v, sizeof(RREAL), n, stdout);
740 #endif
741 }
742
743 static void
744 putf(RREAL *v, int n) /* output binary float(s) */
745 {
746 #ifndef SMLFLT
747 float fa[3];
748 int i;
749
750 if (n > 3)
751 error(INTERNAL, "code error in putf()");
752 for (i = n; i--; )
753 fa[i] = v[i];
754 putbinary(fa, sizeof(float), n, stdout);
755 #else
756 putbinary(v, sizeof(RREAL), n, stdout);
757 #endif
758 }
759
760 static void
761 putrgbe(RREAL *v, int n) /* output RGBE color */
762 {
763 COLR cout;
764
765 if (n != 3)
766 error(INTERNAL, "putrgbe() not called with 3 components");
767 setcolr(cout, v[0], v[1], v[2]);
768 putbinary(cout, sizeof(cout), 1, stdout);
769 }
770
771 void
772 putscolor(COLORV *scol) /* output (spectral) color */
773 {
774 static COLORMAT xyz2myrgbmat;
775 SCOLOR my_scol;
776 COLOR col;
777 /* single channel output? */
778 if (sens_curve != NULL) {
779 RREAL v = (*sens_curve)(scol) * out_scalefactor;
780 (*putreal)(&v, 1);
781 return;
782 }
783 if (out_scalefactor != 1.) { /* apply scalefactor if any */
784 copyscolor(my_scol, scol);
785 scalescolor(my_scol, out_scalefactor);
786 scol = my_scol;
787 }
788 if (out_prims == NULL) { /* full spectral reporting */
789 if (outform == 'c') {
790 SCOLR sclr;
791 scolor_scolr(sclr, scol);
792 putbinary(sclr, LSCOLR, 1, stdout);
793 } else if (sizeof(RREAL) != sizeof(COLORV)) {
794 RREAL sreal[MAXCSAMP];
795 int i = NCSAMP;
796 while (i--) sreal[i] = scol[i];
797 (*putreal)(sreal, NCSAMP);
798 } else
799 (*putreal)((RREAL *)scol, NCSAMP);
800 return;
801 }
802 if (out_prims == xyzprims) {
803 scolor_cie(col, scol);
804 } else if (out_prims == stdprims) {
805 scolor_rgb(col, scol);
806 } else {
807 COLOR xyz;
808 if (xyz2myrgbmat[0][0] == 0)
809 compxyz2rgbWBmat(xyz2myrgbmat, out_prims);
810 scolor_cie(xyz, scol);
811 colortrans(col, xyz2myrgbmat, xyz);
812 clipgamut(col, xyz[CIEY], CGAMUT_LOWER, cblack, cwhite);
813 }
814 if (outform == 'c') {
815 COLR clr;
816 setcolr(clr, colval(col,RED), colval(col,GRN), colval(col,BLU));
817 putbinary(clr, sizeof(COLR), 1, stdout);
818 } else if (sizeof(RREAL) != sizeof(COLORV)) {
819 RREAL creal[3];
820 copycolor(creal, col);
821 (*putreal)(creal, 3);
822 } else
823 (*putreal)((RREAL *)col, 3);
824 }