62 |
|
int ntotal; /* surfaces+subsurfaces */ |
63 |
|
IDF_OBJECT *pfirst; /* first matching object */ |
64 |
|
IDF_OBJECT *plast; /* last before subsurfaces */ |
65 |
+ |
float *area_redu; /* subsurface area per surf. */ |
66 |
|
} ZONE; /* a list of collected zone surfaces */ |
67 |
|
|
68 |
|
ZONE *zone_list = NULL; /* our list of zones */ |
99 |
|
znew->next = zone_list; |
100 |
|
znew->pfirst = znew->plast = param; |
101 |
|
znew->ntotal = znew->nsurf = 1; |
102 |
+ |
znew->area_redu = NULL; |
103 |
|
return(zone_list = znew); |
104 |
|
} |
105 |
|
|
299 |
|
} |
300 |
|
|
301 |
|
/* Convert subsurface to Radiance with modifier based on unique name */ |
302 |
< |
static int |
302 |
> |
static double |
303 |
|
rad_subsurface(IDF_OBJECT *param, FILE *ofp) |
304 |
|
{ |
305 |
|
const char *sname = idf_getfield(param,NAME_FLD)->val; |
306 |
|
SURFACE *surf = get_surface(idf_getfield(param,SS_VERT_FLD)); |
307 |
+ |
double area; |
308 |
|
int i; |
309 |
|
|
310 |
|
if (surf == NULL) { |
311 |
|
fprintf(stderr, "%s: bad subsurface '%s'\n", progname, sname); |
312 |
< |
return(0); |
312 |
> |
return(-1.); |
313 |
|
} |
314 |
|
fprintf(ofp, "\nvoid glow '%s'\n0\n0\n4 1 1 1 0\n", sname); |
315 |
|
fprintf(ofp, "\n'%s' polygon 'ss_%s'\n0\n0\n%d\n", |
319 |
|
VSUM(vert, surf->vl[i], surf->norm, 2.*SURF_EPS); |
320 |
|
fprintf(ofp, "\t%.12f %.12f %.12f\n", vert[0], vert[1], vert[2]); |
321 |
|
} |
322 |
+ |
area = surf->area; |
323 |
|
free(surf); |
324 |
< |
return(!ferror(ofp)); |
324 |
> |
if (ferror(ofp)) |
325 |
> |
return(-1.); |
326 |
> |
return(area); |
327 |
|
} |
328 |
|
|
329 |
|
/* Start rcontrib process */ |
339 |
|
FILE *ofp; |
340 |
|
IDF_OBJECT *pptr; |
341 |
|
IDF_FIELD *fptr; |
342 |
< |
int i, n; |
342 |
> |
int i, j, n; |
343 |
|
/* start oconv command */ |
344 |
|
sprintf(cbuf, "oconv - > '%s'", temp_octree); |
345 |
|
if ((ofp = popen(cbuf, "w")) == NULL) { |
369 |
|
av[i++] = fptr->val; |
370 |
|
} |
371 |
|
/* now subsurfaces */ |
372 |
+ |
if (zp->ntotal > zp->nsurf) { |
373 |
+ |
if (zp->area_redu != NULL) |
374 |
+ |
memset(zp->area_redu, 0, sizeof(float)*zp->nsurf); |
375 |
+ |
else if ((zp->area_redu = (float *)calloc(zp->nsurf, |
376 |
+ |
sizeof(float))) == NULL) |
377 |
+ |
return(0); |
378 |
+ |
} |
379 |
|
for ( ; n < zp->ntotal; n++, pptr = pptr->dnext) { |
380 |
+ |
double ssarea; |
381 |
+ |
const char *bname; |
382 |
+ |
IDF_OBJECT *pptr1; |
383 |
|
fptr = idf_getfield(pptr,NAME_FLD); |
384 |
|
if (fptr == NULL || !fptr->val[0]) { |
385 |
|
fputs(progname, stderr); |
386 |
|
fputs(": missing name for subsurface object\n", stderr); |
387 |
|
return(0); |
388 |
|
} |
389 |
< |
if (!rad_subsurface(pptr, ofp)) /* add surface to octree */ |
389 |
> |
/* add subsurface to octree */ |
390 |
> |
if ((ssarea = rad_subsurface(pptr, ofp)) < 0) |
391 |
|
return(0); |
392 |
+ |
/* mark area for subtraction */ |
393 |
+ |
bname = idf_getfield(pptr,SS_BASE_FLD)->val; |
394 |
+ |
for (j = 0, pptr1 = zp->pfirst; |
395 |
+ |
j < zp->nsurf; j++, pptr1 = pptr1->dnext) |
396 |
+ |
if (!strcmp(idf_getfield(pptr1,NAME_FLD)->val, bname)) { |
397 |
+ |
zp->area_redu[j] += ssarea; |
398 |
+ |
break; |
399 |
+ |
} |
400 |
|
av[i++] = "-m"; |
401 |
|
av[i++] = fptr->val; |
402 |
|
} |
517 |
|
} |
518 |
|
|
519 |
|
/* Sample the given surface */ |
520 |
< |
static int |
520 |
> |
static double |
521 |
|
sample_surface(IDF_OBJECT *param, int wd) |
522 |
|
{ |
523 |
|
POLYSAMP psamp; |
524 |
+ |
double area; |
525 |
|
int nv; |
526 |
|
Vert2_list *vlist2; |
527 |
|
/* set up our polygon sampler */ |
529 |
|
fprintf(stderr, "%s: bad polygon %s '%s'\n", |
530 |
|
progname, param->pname, |
531 |
|
idf_getfield(param,NAME_FLD)->val); |
532 |
< |
return(0); |
532 |
> |
return(-1.); |
533 |
|
} |
534 |
|
psamp.samp_left = nsamps; /* assign samples & destination */ |
535 |
|
psamp.wd = wd; |
536 |
|
/* hack for subsurface sampling */ |
537 |
|
psamp.poff += 2.*SURF_EPS * !strcmp(param->pname, SUBSURF_PNAME); |
538 |
+ |
|
539 |
+ |
area = psamp.area_left; /* remember starting surface area */ |
540 |
|
/* sample each subtriangle */ |
541 |
|
if (!polyTriangulate(vlist2, &sample_triangle)) |
542 |
< |
return(0); |
542 |
> |
return(-1.); |
543 |
|
polyFree(vlist2); /* clean up and return */ |
544 |
< |
return(1); |
544 |
> |
return(area); |
545 |
|
} |
546 |
|
|
547 |
|
/* Compute User View Factors using open rcontrib process */ |
573 |
|
/* UVFs from each surface */ |
574 |
|
for (n = 0, pptr = zp->pfirst; n < zp->ntotal; n++, pptr = pptr->dnext) { |
575 |
|
double vfsum = 0; |
576 |
+ |
double adj_factor; |
577 |
|
/* send samples to rcontrib */ |
578 |
< |
if (!sample_surface(pptr, pd->w)) |
578 |
> |
if ((adj_factor = sample_surface(pptr, pd->w)) < 0) |
579 |
|
return(0); |
580 |
+ |
if (zp->area_redu == NULL) |
581 |
+ |
adj_factor = 1.; |
582 |
+ |
else /* comp. for subsurface area */ |
583 |
+ |
adj_factor /= adj_factor - zp->area_redu[n]; |
584 |
|
/* read results */ |
585 |
|
if (readbuf(pd->r, (char *)uvfa, sizeof(float)*3*zp->ntotal) != |
586 |
|
sizeof(float)*3*zp->ntotal) { |
591 |
|
/* append UVF fields */ |
592 |
|
for (m = 0, pptr1 = zp->pfirst; |
593 |
|
m < zp->ntotal; m++, pptr1 = pptr1->dnext) { |
594 |
< |
vfsum += uvfa[3*m + 1]; |
595 |
< |
if (pptr1 == pptr && uvfa[3*m + 1] > .001) |
594 |
> |
const double uvf = uvfa[3*m + 1] * adj_factor; |
595 |
> |
vfsum += uvf; |
596 |
> |
if (pptr1 == pptr && uvf > .001) |
597 |
|
fprintf(stderr, |
598 |
|
"%s: warning - non-zero self-VF (%.1f%%) for surface '%s'\n", |
599 |
< |
progname, 100.*uvfa[3*m + 1], |
599 |
> |
progname, 100.*uvf, |
600 |
|
idf_getfield(pptr,NAME_FLD)->val); |
601 |
< |
sprintf(uvfbuf, "%.4f", uvfa[3*m + 1]); |
601 |
> |
sprintf(uvfbuf, "%.4f", uvf); |
602 |
|
if (!idf_addfield(pout, |
603 |
|
idf_getfield(pptr,NAME_FLD)->val, NULL) || |
604 |
|
!idf_addfield(pout, |