1 |
+ |
#ifndef lint |
2 |
+ |
static const char RCSid[] = "$Id$"; |
3 |
+ |
#endif |
4 |
|
/* |
5 |
|
================================================================== |
6 |
|
Photon map support routines for emission from light sources |
10 |
|
(c) Lucerne University of Applied Sciences and Arts, |
11 |
|
supported by the Swiss National Science Foundation (SNSF, #147053) |
12 |
|
================================================================== |
13 |
< |
|
11 |
< |
$Id$ |
13 |
> |
|
14 |
|
*/ |
15 |
|
|
16 |
|
|
20 |
|
#include "pmaprand.h" |
21 |
|
#include "otypes.h" |
22 |
|
|
23 |
< |
|
24 |
< |
|
25 |
< |
SRCREC *photonPorts = NULL; /* Photon port list */ |
23 |
> |
/* List of photon port modifier names */ |
24 |
> |
char *photonPortList [MAXSET + 1] = {NULL}; |
25 |
> |
/* Photon port objects (with modifiers in photonPortMods) */ |
26 |
> |
SRCREC *photonPorts = NULL; |
27 |
|
unsigned numPhotonPorts = 0; |
28 |
|
|
29 |
|
void (*photonPartition [NUMOTYPE]) (EmissionMap*); |
30 |
|
void (*photonOrigin [NUMOTYPE]) (EmissionMap*); |
31 |
|
|
29 |
– |
extern OBJECT ambset []; |
30 |
– |
|
32 |
|
|
33 |
|
|
34 |
|
static int flatPhotonPartition2 (EmissionMap* emap, unsigned long mp, |
520 |
|
|
521 |
|
|
522 |
|
|
523 |
< |
void getPhotonPorts () |
524 |
< |
/* Find geometry declared as photon ports */ |
523 |
> |
void getPhotonPorts (char **portList) |
524 |
> |
/* Find geometry declared as photon ports from modifiers in portList */ |
525 |
|
{ |
526 |
|
OBJECT i; |
527 |
< |
OBJREC* obj; |
527 |
> |
OBJREC *obj, *mat; |
528 |
> |
char **lp; |
529 |
|
|
530 |
|
/* Check for missing port modifiers */ |
531 |
< |
if (!ambset [0]) |
532 |
< |
error(USER, "no photon ports found"); |
531 |
> |
if (!portList [0]) |
532 |
> |
error(USER, "no photon ports"); |
533 |
|
|
534 |
|
for (i = 0; i < nobjects; i++) { |
535 |
|
obj = objptr(i); |
536 |
+ |
mat = findmaterial(obj); |
537 |
|
|
538 |
< |
if (inset(ambset, obj -> omod)) { |
539 |
< |
/* Add photon port */ |
540 |
< |
photonPorts = (SRCREC*)realloc(photonPorts, |
541 |
< |
(numPhotonPorts + 1) * |
542 |
< |
sizeof(SRCREC)); |
540 |
< |
if (!photonPorts) |
541 |
< |
error(USER, "can't allocate photon ports"); |
542 |
< |
|
543 |
< |
photonPorts [numPhotonPorts].so = obj; |
544 |
< |
photonPorts [numPhotonPorts].sflags = 0; |
538 |
> |
/* Check if object is a surface and NOT a light source (duh) and |
539 |
> |
* resolve its material via any aliases, then check for inclusion in |
540 |
> |
* modifier list */ |
541 |
> |
if (issurface(obj -> otype) && mat && !islight(mat -> otype)) { |
542 |
> |
for (lp = portList; *lp && strcmp(mat -> oname, *lp); lp++); |
543 |
|
|
544 |
< |
if (!sfun [obj -> otype].of || !sfun[obj -> otype].of -> setsrc) |
545 |
< |
objerror(obj, USER, "illegal photon port"); |
544 |
> |
if (*lp) { |
545 |
> |
/* Add photon port */ |
546 |
> |
photonPorts = (SRCREC*)realloc(photonPorts, |
547 |
> |
(numPhotonPorts + 1) * |
548 |
> |
sizeof(SRCREC)); |
549 |
> |
if (!photonPorts) |
550 |
> |
error(USER, "can't allocate photon ports"); |
551 |
|
|
552 |
< |
setsource(photonPorts + numPhotonPorts, obj); |
553 |
< |
numPhotonPorts++; |
552 |
> |
photonPorts [numPhotonPorts].so = obj; |
553 |
> |
photonPorts [numPhotonPorts].sflags = 0; |
554 |
> |
|
555 |
> |
if (!sfun [obj -> otype].of || !sfun[obj -> otype].of -> setsrc) |
556 |
> |
objerror(obj, USER, "illegal photon port"); |
557 |
> |
|
558 |
> |
setsource(photonPorts + numPhotonPorts, obj); |
559 |
> |
numPhotonPorts++; |
560 |
> |
} |
561 |
|
} |
562 |
|
} |
563 |
+ |
|
564 |
+ |
if (!numPhotonPorts) |
565 |
+ |
error(USER, "no valid photon ports found"); |
566 |
|
} |
567 |
|
|
568 |
|
|
605 |
|
unsigned i, t, p; |
606 |
|
double phi, cosTheta, sinTheta, du, dv, dOmega, thetaScale; |
607 |
|
EmissionSample* sample; |
608 |
< |
const OBJREC* mod = objptr(emap -> src -> so -> omod); |
608 |
> |
const OBJREC* mod = findmaterial(emap -> src -> so); |
609 |
|
static RAY r; |
610 |
|
#if 0 |
611 |
|
static double lastCosNorm = FHUGE; |
612 |
|
static SRCREC *lastSrc = NULL, *lastPort = NULL; |
613 |
|
#endif |
614 |
|
|
615 |
+ |
setcolor(emap -> partFlux, 0, 0, 0); |
616 |
+ |
|
617 |
|
photonOrigin [emap -> src -> so -> otype] (emap); |
618 |
|
cosTheta = DOT(emap -> ws, emap -> wh); |
619 |
|
|
636 |
|
#endif |
637 |
|
|
638 |
|
/* Need to recompute flux & PDF */ |
624 |
– |
setcolor(emap -> partFlux, 0, 0, 0); |
639 |
|
emap -> cdf = 0; |
640 |
|
emap -> numSamples = 0; |
641 |
|
|
684 |
|
|
685 |
|
VCOPY(r.rorg, emap -> photonOrg); |
686 |
|
VCOPY(r.rop, emap -> photonOrg); |
687 |
< |
r.rmax = FHUGE; |
687 |
> |
r.rmax = 0; |
688 |
|
|
689 |
|
for (t = 0; t < emap -> numTheta; t++) { |
690 |
|
for (p = 0; p < emap -> numPhi; p++) { |
754 |
|
unsigned long i, lo, hi; |
755 |
|
const EmissionSample* sample = emap -> samples; |
756 |
|
RREAL du, dv, cosTheta, cosThetaSqr, sinTheta, phi; |
757 |
< |
const OBJREC* mod = objptr(emap -> src -> so -> omod); |
757 |
> |
const OBJREC* mod = findmaterial(emap -> src -> so); |
758 |
|
|
759 |
|
/* Choose a new origin within current partition for every |
760 |
|
emitted photon to break up clustering artifacts */ |
761 |
|
photonOrigin [emap -> src -> so -> otype] ((EmissionMap*)emap); |
762 |
+ |
/* If we have a local glow source with a maximum radius, then |
763 |
+ |
restrict our photon to the specified distance, otherwise we set |
764 |
+ |
the limit imposed by photonMaxDist (or no limit if 0) */ |
765 |
+ |
if (mod -> otype == MAT_GLOW && !(emap -> src -> sflags & SDISTANT) |
766 |
+ |
&& mod -> oargs.farg[3] > FTINY) |
767 |
+ |
ray -> rmax = mod -> oargs.farg[3]; |
768 |
+ |
else |
769 |
+ |
ray -> rmax = photonMaxDist; |
770 |
|
rayorigin(ray, PRIMARY, NULL, NULL); |
749 |
– |
ray -> rmax = FHUGE; |
771 |
|
|
772 |
|
if (!emap -> numSamples) { |
773 |
|
/* Source is unmodified and has no port, and either local with |