ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/ratrace.cpp
Revision: 2.3
Committed: Mon Aug 21 22:39:05 2023 UTC (8 months, 3 weeks ago) by greg
Branch: MAIN
CVS Tags: HEAD
Changes since 2.2: +1 -1 lines
State: FILE REMOVED
Log Message:
Renamed ratrace to rxtrace

File Contents

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