35 |
|
"Unknown error" |
36 |
|
}; |
37 |
|
|
38 |
+ |
/* Pointer to error list in preferred language */ |
39 |
+ |
const char **SDerrorList = SDerrorEnglish; |
40 |
+ |
|
41 |
|
/* Additional information on last error (ASCII English) */ |
42 |
|
char SDerrorDetail[256]; |
43 |
|
|
47 |
|
/* Cache of loaded BSDFs */ |
48 |
|
struct SDCache_s *SDcacheList = NULL; |
49 |
|
|
50 |
< |
/* Retain BSDFs in cache list */ |
50 |
> |
/* Retain BSDFs in cache list? */ |
51 |
|
int SDretainSet = SDretainNone; |
52 |
|
|
53 |
< |
/* Report any error to the indicated stream (in English) */ |
53 |
> |
/* Maximum cache size for any given BSDF? */ |
54 |
> |
unsigned long SDmaxCache = 0; /* 0 == unlimited */ |
55 |
> |
|
56 |
> |
/* Report any error to the indicated stream */ |
57 |
|
SDError |
58 |
< |
SDreportEnglish(SDError ec, FILE *fp) |
58 |
> |
SDreportError(SDError ec, FILE *fp) |
59 |
|
{ |
60 |
|
if (!ec) |
61 |
|
return SDEnone; |
65 |
|
} |
66 |
|
if (fp == NULL) |
67 |
|
return ec; |
68 |
< |
fputs(SDerrorEnglish[ec], fp); |
68 |
> |
fputs(SDerrorList[ec], fp); |
69 |
|
if (SDerrorDetail[0]) { |
70 |
|
fputs(": ", fp); |
71 |
|
fputs(SDerrorDetail, fp); |
202 |
|
} |
203 |
|
wtl = ezxml_child(ezxml_child(fl, "Optical"), "Layer"); |
204 |
|
if (wtl == NULL) { |
205 |
< |
sprintf(SDerrorDetail, "BSDF \"%s\": no optical layers'", |
205 |
> |
sprintf(SDerrorDetail, "BSDF \"%s\": no optical layers", |
206 |
|
sd->name); |
207 |
|
ezxml_free(fl); |
208 |
|
return SDEformat; |
381 |
|
sd->rLambFront.spec.flags = 0; |
382 |
|
sd->rLambBack.cieY = .0; |
383 |
|
sd->rLambBack.spec.flags = 0; |
384 |
< |
sd->tLamb.cieY = .0; |
385 |
< |
sd->tLamb.spec.flags = 0; |
384 |
> |
sd->tLambFront.cieY = .0; |
385 |
> |
sd->tLambFront.spec.flags = 0; |
386 |
> |
sd->tLambBack.cieY = .0; |
387 |
> |
sd->tLambBack.spec.flags = 0; |
388 |
|
} |
389 |
|
|
390 |
|
/* Find writeable BSDF by name, or allocate new cache entry if absent */ |
427 |
|
if (fname == NULL || !*fname) |
428 |
|
return NULL; |
429 |
|
SDerrorDetail[0] = '\0'; |
430 |
+ |
/* PLACE MUTEX LOCK HERE FOR THREAD-SAFE */ |
431 |
|
if ((sd = SDgetCache(fname)) == NULL) { |
432 |
< |
SDreportEnglish(SDEmemory, stderr); |
432 |
> |
SDreportError(SDEmemory, stderr); |
433 |
|
return NULL; |
434 |
|
} |
435 |
|
if (!SDisLoaded(sd) && (ec = SDloadFile(sd, fname))) { |
436 |
< |
SDreportEnglish(ec, stderr); |
436 |
> |
SDreportError(ec, stderr); |
437 |
|
SDfreeCache(sd); |
438 |
< |
return NULL; |
438 |
> |
sd = NULL; |
439 |
|
} |
440 |
+ |
/* END MUTEX LOCK */ |
441 |
|
return sd; |
442 |
|
} |
443 |
|
|
495 |
|
return SDEargument; |
496 |
|
/* get cumulative distribution */ |
497 |
|
VCOPY(inVec, ioVec); |
498 |
+ |
sv->cieY = 0; |
499 |
|
cd = (*sdc->func->getCDist)(inVec, sdc); |
500 |
< |
if (cd == NULL) |
501 |
< |
return SDEmemory; |
502 |
< |
if (cd->cTotal <= 1e-6) { /* anything to sample? */ |
500 |
> |
if (cd != NULL) |
501 |
> |
sv->cieY = cd->cTotal; |
502 |
> |
if (sv->cieY <= 1e-6) { /* nothing to sample? */ |
503 |
|
sv->spec = c_dfcolor; |
504 |
< |
sv->cieY = .0; |
494 |
< |
memset(ioVec, 0, 3*sizeof(double)); |
504 |
> |
memset(ioVec, 0, sizeof(FVECT)); |
505 |
|
return SDEnone; |
506 |
|
} |
497 |
– |
sv->cieY = cd->cTotal; |
507 |
|
/* compute sample direction */ |
508 |
|
ec = (*sdc->func->sampCDist)(ioVec, randX, cd); |
509 |
|
if (ec) |
520 |
|
c_cmix(&sv->spec, d, &sv->spec, coef[n], &sdc->cspec[n]); |
521 |
|
d += coef[n]; |
522 |
|
} |
523 |
< |
/* make sure everything is set */ |
515 |
< |
c_ccvt(&sv->spec, C_CSXY+C_CSSPEC); |
523 |
> |
c_ccvt(&sv->spec, C_CSXY); /* make sure (x,y) is set */ |
524 |
|
return SDEnone; |
525 |
|
} |
526 |
|
|
564 |
|
SDmultiSamp(outVec, 2, randX); |
565 |
|
SDsquare2disk(outVec, outVec[0], outVec[1]); |
566 |
|
outVec[2] = 1. - outVec[0]*outVec[0] - outVec[1]*outVec[1]; |
567 |
< |
if (outVec[2] > 0) /* a bit of paranoia */ |
560 |
< |
outVec[2] = sqrt(outVec[2]); |
567 |
> |
outVec[2] = sqrt(outVec[2]*(outVec[2]>0)); |
568 |
|
if (!outFront) /* going out back? */ |
569 |
|
outVec[2] = -outVec[2]; |
570 |
|
} |
601 |
|
rdf = sd->rb; |
602 |
|
tdf = (sd->tb != NULL) ? sd->tb : sd->tf; |
603 |
|
} |
604 |
< |
if (v2 != NULL) /* bidirectional? */ |
604 |
> |
if (v2 != NULL) { /* bidirectional? */ |
605 |
|
if (v1[2] > 0 ^ v2[2] > 0) |
606 |
|
rdf = NULL; |
607 |
|
else |
608 |
|
tdf = NULL; |
609 |
+ |
} |
610 |
|
ec = SDEdata; /* run through components */ |
611 |
|
for (i = (rdf==NULL) ? 0 : rdf->ncomp; i--; ) { |
612 |
|
ec = (*rdf->comp[i].func->queryProjSA)(projSA, v1, v2, |
624 |
|
projSA[0] = M_PI; |
625 |
|
if (qflags == SDqueryMin+SDqueryMax) |
626 |
|
projSA[1] = M_PI; |
627 |
< |
} |
627 |
> |
} else if (qflags == SDqueryMin+SDqueryMax && projSA[0] > projSA[1]) |
628 |
> |
projSA[0] = projSA[1]; |
629 |
|
return SDEnone; |
630 |
|
} |
631 |
|
|
651 |
|
*sv = sd->rLambBack; |
652 |
|
sdf = sd->rb; |
653 |
|
} else if (inFront) { |
654 |
< |
*sv = sd->tLamb; |
654 |
> |
*sv = sd->tLambFront; |
655 |
|
sdf = (sd->tf != NULL) ? sd->tf : sd->tb; |
656 |
< |
} else /* inBack */ { |
657 |
< |
*sv = sd->tLamb; |
656 |
> |
} else /* outFront & !inFront */ { |
657 |
> |
*sv = sd->tLambBack; |
658 |
|
sdf = (sd->tb != NULL) ? sd->tb : sd->tf; |
659 |
|
} |
660 |
|
sv->cieY *= 1./M_PI; |
669 |
|
sv->cieY += coef[nch]; |
670 |
|
} |
671 |
|
} |
672 |
< |
/* make sure everything is set */ |
664 |
< |
c_ccvt(&sv->spec, C_CSXY+C_CSSPEC); |
672 |
> |
c_ccvt(&sv->spec, C_CSXY); /* make sure (x,y) is set */ |
673 |
|
return SDEnone; |
674 |
|
} |
675 |
|
|
697 |
|
if ((sflags & SDsampDf+SDsampR) != SDsampDf+SDsampR) |
698 |
|
hsum = .0; |
699 |
|
if ((sflags & SDsampDf+SDsampT) == SDsampDf+SDsampT) |
700 |
< |
hsum += sd->tLamb.cieY; |
700 |
> |
hsum += (inVec[2] > 0) ? |
701 |
> |
sd->tLambFront.cieY : sd->tLambBack.cieY; |
702 |
|
/* gather non-diffuse components */ |
703 |
|
i = (((sflags & SDsampSp+SDsampR) == SDsampSp+SDsampR) & |
704 |
|
(rdf != NULL)) ? rdf->ncomp : 0; |
751 |
|
sv->cieY = .0; |
752 |
|
rdiff = sv->cieY; |
753 |
|
if ((sflags & SDsampDf+SDsampT) == SDsampDf+SDsampT) |
754 |
< |
sv->cieY += sd->tLamb.cieY; |
754 |
> |
sv->cieY += inFront ? sd->tLambFront.cieY : sd->tLambBack.cieY; |
755 |
|
/* gather non-diffuse components */ |
756 |
|
i = nr = (((sflags & SDsampSp+SDsampR) == SDsampSp+SDsampR) & |
757 |
|
(rdf != NULL)) ? rdf->ncomp : 0; |
762 |
|
return SDEmemory; |
763 |
|
while (j-- > 0) { /* non-diffuse transmission */ |
764 |
|
cdarr[i+j] = (*tdf->comp[j].func->getCDist)(inVec, &tdf->comp[j]); |
765 |
< |
if (cdarr[i+j] == NULL) { |
766 |
< |
free(cdarr); |
758 |
< |
return SDEmemory; |
759 |
< |
} |
765 |
> |
if (cdarr[i+j] == NULL) |
766 |
> |
cdarr[i+j] = &SDemptyCD; |
767 |
|
sv->cieY += cdarr[i+j]->cTotal; |
768 |
|
} |
769 |
|
while (i-- > 0) { /* non-diffuse reflection */ |
770 |
|
cdarr[i] = (*rdf->comp[i].func->getCDist)(inVec, &rdf->comp[i]); |
771 |
< |
if (cdarr[i] == NULL) { |
772 |
< |
free(cdarr); |
766 |
< |
return SDEmemory; |
767 |
< |
} |
771 |
> |
if (cdarr[i] == NULL) |
772 |
> |
cdarr[i] = &SDemptyCD; |
773 |
|
sv->cieY += cdarr[i]->cTotal; |
774 |
|
} |
775 |
|
if (sv->cieY <= 1e-6) { /* anything to sample? */ |
776 |
|
sv->cieY = .0; |
777 |
< |
memset(ioVec, 0, 3*sizeof(double)); |
777 |
> |
memset(ioVec, 0, sizeof(FVECT)); |
778 |
|
return SDEnone; |
779 |
|
} |
780 |
|
/* scale random variable */ |
787 |
|
randX -= rdiff; |
788 |
|
/* diffuse transmission? */ |
789 |
|
if ((sflags & SDsampDf+SDsampT) == SDsampDf+SDsampT) { |
790 |
< |
if (randX < sd->tLamb.cieY) { |
791 |
< |
sv->spec = sd->tLamb.spec; |
792 |
< |
SDdiffuseSamp(ioVec, !inFront, randX/sd->tLamb.cieY); |
790 |
> |
const SDValue *sdt = inFront ? &sd->tLambFront : &sd->tLambBack; |
791 |
> |
if (randX < sdt->cieY) { |
792 |
> |
sv->spec = sdt->spec; |
793 |
> |
SDdiffuseSamp(ioVec, !inFront, randX/sdt->cieY); |
794 |
|
goto done; |
795 |
|
} |
796 |
< |
randX -= sd->tLamb.cieY; |
796 |
> |
randX -= sdt->cieY; |
797 |
|
} |
798 |
|
/* else one of cumulative dist. */ |
799 |
< |
for (i = 0; i < n && randX < cdarr[i]->cTotal; i++) |
799 |
> |
for (i = 0; i < n && randX >= cdarr[i]->cTotal; i++) |
800 |
|
randX -= cdarr[i]->cTotal; |
801 |
|
if (i >= n) |
802 |
|
return SDEinternal; |
821 |
|
done: |
822 |
|
if (cdarr != NULL) |
823 |
|
free(cdarr); |
824 |
< |
/* make sure everything is set */ |
819 |
< |
c_ccvt(&sv->spec, C_CSXY+C_CSSPEC); |
824 |
> |
c_ccvt(&sv->spec, C_CSXY); /* make sure (x,y) is set */ |
825 |
|
return SDEnone; |
826 |
|
} |
827 |
|
|