77 |
|
|
78 |
|
/* Load geometric dimensions and description (if any) */ |
79 |
|
static SDError |
80 |
< |
SDloadGeometry(SDData *dp, ezxml_t wdb) |
80 |
> |
SDloadGeometry(SDData *sd, ezxml_t wdb) |
81 |
|
{ |
82 |
|
ezxml_t geom; |
83 |
|
double cfact; |
84 |
|
const char *fmt, *mgfstr; |
85 |
|
|
86 |
< |
sprintf(SDerrorDetail, "Negative size in \"%s\"", dp->name); |
87 |
< |
dp->dim[0] = dp->dim[1] = dp->dim[2] = .0; |
86 |
> |
if (wdb == NULL) /* no geometry section? */ |
87 |
> |
return SDEnone; |
88 |
> |
sd->dim[0] = sd->dim[1] = sd->dim[2] = .0; |
89 |
|
if ((geom = ezxml_child(wdb, "Width")) != NULL) |
90 |
< |
dp->dim[0] = atof(ezxml_txt(geom)) * |
90 |
> |
sd->dim[0] = atof(ezxml_txt(geom)) * |
91 |
|
to_meters(ezxml_attr(geom, "unit")); |
92 |
|
if ((geom = ezxml_child(wdb, "Height")) != NULL) |
93 |
< |
dp->dim[1] = atof(ezxml_txt(geom)) * |
93 |
> |
sd->dim[1] = atof(ezxml_txt(geom)) * |
94 |
|
to_meters(ezxml_attr(geom, "unit")); |
95 |
|
if ((geom = ezxml_child(wdb, "Thickness")) != NULL) |
96 |
< |
dp->dim[2] = atof(ezxml_txt(geom)) * |
96 |
> |
sd->dim[2] = atof(ezxml_txt(geom)) * |
97 |
|
to_meters(ezxml_attr(geom, "unit")); |
98 |
< |
if ((dp->dim[0] < .0) | (dp->dim[1] < .0) | (dp->dim[2] < .0)) |
98 |
> |
if ((sd->dim[0] < .0) | (sd->dim[1] < .0) | (sd->dim[2] < .0)) { |
99 |
> |
sprintf(SDerrorDetail, "Negative size in \"%s\"", sd->name); |
100 |
|
return SDEdata; |
101 |
+ |
} |
102 |
|
if ((geom = ezxml_child(wdb, "Geometry")) == NULL || |
103 |
|
(mgfstr = ezxml_txt(geom)) == NULL) |
104 |
|
return SDEnone; |
106 |
|
strcasecmp(fmt, "MGF")) { |
107 |
|
sprintf(SDerrorDetail, |
108 |
|
"Unrecognized geometry format '%s' in \"%s\"", |
109 |
< |
fmt, dp->name); |
109 |
> |
fmt, sd->name); |
110 |
|
return SDEsupport; |
111 |
|
} |
112 |
|
cfact = to_meters(ezxml_attr(geom, "unit")); |
113 |
< |
dp->mgf = (char *)malloc(strlen(mgfstr)+32); |
114 |
< |
if (dp->mgf == NULL) { |
113 |
> |
sd->mgf = (char *)malloc(strlen(mgfstr)+32); |
114 |
> |
if (sd->mgf == NULL) { |
115 |
|
strcpy(SDerrorDetail, "Out of memory in SDloadGeometry"); |
116 |
|
return SDEmemory; |
117 |
|
} |
118 |
|
if (cfact < 0.99 || cfact > 1.01) |
119 |
< |
sprintf(dp->mgf, "xf -s %.5f\n%s\nxf\n", cfact, mgfstr); |
119 |
> |
sprintf(sd->mgf, "xf -s %.5f\n%s\nxf\n", cfact, mgfstr); |
120 |
|
else |
121 |
< |
strcpy(dp->mgf, mgfstr); |
121 |
> |
strcpy(sd->mgf, mgfstr); |
122 |
|
return SDEnone; |
123 |
|
} |
124 |
|
|
122 |
– |
|
125 |
|
/* Load a BSDF struct from the given file (free first and keep name) */ |
126 |
|
SDError |
127 |
|
SDloadFile(SDData *sd, const char *fname) |
128 |
|
{ |
129 |
|
SDError lastErr; |
130 |
< |
ezxml_t fl; |
130 |
> |
ezxml_t fl, wtl; |
131 |
|
|
132 |
|
if ((sd == NULL) | (fname == NULL || !*fname)) |
133 |
|
return SDEargument; |
144 |
|
ezxml_free(fl); |
145 |
|
return SDEformat; |
146 |
|
} |
147 |
+ |
if (strcmp(ezxml_name(fl), "WindowElement")) { |
148 |
+ |
sprintf(SDerrorDetail, |
149 |
+ |
"BSDF \"%s\": top level node not 'WindowElement'", |
150 |
+ |
sd->name); |
151 |
+ |
ezxml_free(fl); |
152 |
+ |
return SDEformat; |
153 |
+ |
} |
154 |
+ |
wtl = ezxml_child(ezxml_child(fl, "Optical"), "Layer"); |
155 |
+ |
if (wtl == NULL) { |
156 |
+ |
sprintf(SDerrorDetail, "BSDF \"%s\": no optical layer'", |
157 |
+ |
sd->name); |
158 |
+ |
ezxml_free(fl); |
159 |
+ |
return SDEformat; |
160 |
+ |
} |
161 |
|
/* load geometry if present */ |
162 |
< |
if ((lastErr = SDloadGeometry(sd, fl))) |
162 |
> |
lastErr = SDloadGeometry(sd, ezxml_child(wtl, "Material")); |
163 |
> |
if (lastErr) |
164 |
|
return lastErr; |
165 |
|
/* try loading variable resolution data */ |
166 |
< |
lastErr = SDloadTre(sd, fl); |
166 |
> |
lastErr = SDloadTre(sd, wtl); |
167 |
|
/* check our result */ |
168 |
|
switch (lastErr) { |
169 |
|
case SDEformat: |
170 |
|
case SDEdata: |
171 |
|
case SDEsupport: /* possibly we just tried the wrong format */ |
172 |
< |
lastErr = SDloadMtx(sd, fl); |
172 |
> |
lastErr = SDloadMtx(sd, wtl); |
173 |
|
break; |
174 |
|
default: /* variable res. OK else serious error */ |
175 |
|
break; |
176 |
|
} |
177 |
|
/* done with XML file */ |
178 |
|
ezxml_free(fl); |
179 |
< |
/* return success or failure */ |
180 |
< |
return lastErr; |
179 |
> |
|
180 |
> |
if (lastErr) { /* was there a load error? */ |
181 |
> |
SDfreeBSDF(sd); |
182 |
> |
return lastErr; |
183 |
> |
} |
184 |
> |
/* remove any insignificant components */ |
185 |
> |
if (sd->rf != NULL && sd->rf->maxHemi <= .001) { |
186 |
> |
SDfreeSpectralDF(sd->rf); sd->rf = NULL; |
187 |
> |
} |
188 |
> |
if (sd->rb != NULL && sd->rb->maxHemi <= .001) { |
189 |
> |
SDfreeSpectralDF(sd->rb); sd->rb = NULL; |
190 |
> |
} |
191 |
> |
if (sd->tf != NULL && sd->tf->maxHemi <= .001) { |
192 |
> |
SDfreeSpectralDF(sd->tf); sd->tf = NULL; |
193 |
> |
} |
194 |
> |
/* return success */ |
195 |
> |
return SDEnone; |
196 |
|
} |
197 |
|
|
198 |
|
/* Allocate new spectral distribution function */ |
251 |
|
|
252 |
|
/* Shorten file path to useable BSDF name, removing suffix */ |
253 |
|
void |
254 |
< |
SDclipName(char res[SDnameLn], const char *fname) |
254 |
> |
SDclipName(char *res, const char *fname) |
255 |
|
{ |
256 |
|
const char *cp, *dot = NULL; |
257 |
|
|
298 |
|
sd->tf = NULL; |
299 |
|
} |
300 |
|
sd->rLambFront.cieY = .0; |
301 |
< |
sd->rLambFront.spec.clock = 0; |
301 |
> |
sd->rLambFront.spec.flags = 0; |
302 |
|
sd->rLambBack.cieY = .0; |
303 |
< |
sd->rLambBack.spec.clock = 0; |
303 |
> |
sd->rLambBack.spec.flags = 0; |
304 |
|
sd->tLamb.cieY = .0; |
305 |
< |
sd->tLamb.spec.clock = 0; |
305 |
> |
sd->tLamb.spec.flags = 0; |
306 |
|
} |
307 |
|
|
308 |
|
/* Find writeable BSDF by name, or allocate new cache entry if absent */ |
451 |
|
bitmask_t ndx, coord[MS_MAXDIM]; |
452 |
|
|
453 |
|
while (n > MS_MAXDIM) /* punt for higher dimensions */ |
454 |
< |
t[--n] = drand48(); |
454 |
> |
t[--n] = rand()*(1./(RAND_MAX+.5)); |
455 |
|
nBits = (8*sizeof(bitmask_t) - 1) / n; |
456 |
|
ndx = randX * (double)((bitmask_t)1 << (nBits*n)); |
457 |
|
/* get coordinate on Hilbert curve */ |
459 |
|
/* convert back to [0,1) range */ |
460 |
|
scale = 1. / (double)((bitmask_t)1 << nBits); |
461 |
|
while (n--) |
462 |
< |
t[n] = scale * ((double)coord[n] + drand48()); |
462 |
> |
t[n] = scale * ((double)coord[n] + rand()*(1./(RAND_MAX+.5))); |
463 |
|
} |
464 |
|
|
465 |
|
#undef MS_MAXDIM |
489 |
|
if ((projSA == NULL) | (vec == NULL) | (sd == NULL)) |
490 |
|
return SDEargument; |
491 |
|
/* initialize extrema */ |
492 |
< |
switch (qflags & SDqueryMin+SDqueryMax) { |
492 |
> |
switch (qflags) { |
493 |
|
case SDqueryMax: |
494 |
|
projSA[0] = .0; |
495 |
|
break; |
519 |
|
if (ec) |
520 |
|
return ec; |
521 |
|
} |
522 |
< |
return ec; |
522 |
> |
if (ec) { /* all diffuse? */ |
523 |
> |
projSA[0] = M_PI; |
524 |
> |
if (qflags == SDqueryMin+SDqueryMax) |
525 |
> |
projSA[1] = M_PI; |
526 |
> |
} |
527 |
> |
return SDEnone; |
528 |
|
} |
529 |
|
|
530 |
|
/* Return BSDF for the given incident and scattered ray vectors */ |
1114 |
|
break; |
1115 |
|
} |
1116 |
|
if (i < 0) { |
1117 |
< |
sprintf(errmsg, "undefined RowAngleBasis '%s'", cbasis); |
1117 |
> |
sprintf(errmsg, "undefined RowAngleBasis '%s'", rbasis); |
1118 |
|
error(WARNING, errmsg); |
1119 |
|
return; |
1120 |
|
} |