ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/bsdf_t.c
Revision: 3.1
Committed: Fri Feb 18 00:40:25 2011 UTC (13 years, 2 months ago) by greg
Content type: text/plain
Branch: MAIN
Log Message:
Major code reorg, moving mgflib to common and introducing BSDF material

File Contents

# User Rev Content
1 greg 3.1 /*
2     * bsdf_t.c
3     *
4     * Definitions for variable-resolution BSDF trees
5     *
6     * Created by Greg Ward on 2/2/11.
7     *
8     */
9    
10     #include <stdio.h>
11     #include <stdlib.h>
12     #include "ezxml.h"
13     #include "bsdf.h"
14     #include "bsdf_t.h"
15    
16     /* Allocate a new scattering distribution node */
17     static SDNode *
18     SDnewNode(int nd, int lg)
19     {
20     SDNode *st;
21    
22     if (nd <= 0) {
23     strcpy(SDerrorDetail, "Zero dimension BSDF node request");
24     return NULL;
25     }
26     if (nd > SD_MAXDIM) {
27     sprintf(SDerrorDetail, "Illegal BSDF dimension (%d > %d)",
28     nd, SD_MAXDIM);
29     return NULL;
30     }
31     if (lg < 0) {
32     st = (SDNode *)malloc(sizeof(SDNode) +
33     ((1<<nd) - 1)*sizeof(st->u.t[0]));
34     if (st != NULL)
35     memset(st->u.t, 0, (1<<nd)*sizeof(st->u.t[0]));
36     } else
37     st = (SDNode *)malloc(sizeof(SDNode) +
38     ((1 << nd*lg) - 1)*sizeof(st->u.v[0]));
39    
40     if (st == NULL) {
41     if (lg < 0)
42     sprintf(SDerrorDetail,
43     "Cannot allocate %d branch BSDF tree", nd);
44     else
45     sprintf(SDerrorDetail,
46     "Cannot allocate %d BSDF leaves", 1 << nd*lg);
47     return NULL;
48     }
49     st->ndim = nd;
50     st->log2GR = lg;
51     return st;
52     }
53    
54     /* Free an SD tree */
55     static void
56     SDfreeTree(void *p)
57     {
58     SDNode *st = (SDNode *)p;
59     int i;
60    
61     if (st == NULL)
62     return;
63     for (i = (st->log2GR < 0) << st->ndim; i--; )
64     SDfreeTree(st->u.t[i]);
65     free((void *)st);
66     }
67    
68     /* Add up N-dimensional hypercube array values over the given box */
69     static double
70     SDiterSum(const float *va, int nd, int siz, const int *imin, const int *imax)
71     {
72     double sum = .0;
73     unsigned skipsiz = 1;
74     int i;
75    
76     for (i = nd; --i > 0; )
77     skipsiz *= siz;
78     if (skipsiz == 1)
79     for (i = *imin; i < *imax; i++)
80     sum += va[i];
81     else
82     for (i = *imin; i < *imax; i++)
83     sum += SDiterSum(va + i*skipsiz,
84     nd-1, siz, imin+1, imax+1);
85     return sum;
86     }
87    
88     /* Average BSDF leaves over an orthotope defined by the unit hypercube */
89     static double
90     SDavgBox(const SDNode *st, const double *bmin, const double *bmax)
91     {
92     int imin[SD_MAXDIM], imax[SD_MAXDIM];
93     unsigned n;
94     int i;
95    
96     if (!st)
97     return .0;
98     /* check box limits */
99     for (i = st->ndim; i--; ) {
100     if (bmin[i] >= 1.)
101     return .0;
102     if (bmax[i] <= .0)
103     return .0;
104     if (bmin[i] >= bmax[i])
105     return .0;
106     }
107     if (st->log2GR < 0) { /* iterate on subtree */
108     double sum = .0, wsum = 1e-20;
109     double sbmin[SD_MAXDIM], sbmax[SD_MAXDIM], w;
110    
111     for (n = 1 << st->ndim; n--; ) {
112     w = 1.;
113     for (i = st->ndim; i--; ) {
114     sbmin[i] = 2.*bmin[i];
115     sbmax[i] = 2.*bmax[i];
116     if (n & 1<<i) {
117     sbmin[i] -= 1.;
118     sbmax[i] -= 1.;
119     }
120     if (sbmin[i] < .0) sbmin[i] = .0;
121     if (sbmax[i] > 1.) sbmax[i] = 1.;
122     w *= sbmax[i] - sbmin[i];
123     }
124     if (w > 1e-10) {
125     sum += w * SDavgBox(st->u.t[n], sbmin, sbmax);
126     wsum += w;
127     }
128     }
129     return sum / wsum;
130     }
131     n = 1; /* iterate over leaves */
132     for (i = st->ndim; i--; ) {
133     imin[i] = (bmin[i] <= .0) ? 0
134     : (int)((1 << st->log2GR)*bmin[i]);
135     imax[i] = (bmax[i] >= 1.) ? (1 << st->log2GR)
136     : (int)((1 << st->log2GR)*bmax[i] + .999999);
137     n *= imax[i] - imin[i];
138     }
139     if (!n)
140     return .0;
141    
142     return SDiterSum(st->u.v, st->ndim, 1 << st->log2GR, imin, imax) /
143     (double)n;
144     }
145    
146     /* Load a variable-resolution BSDF tree from an open XML file */
147     SDError
148     SDloadTre(SDData *sd, ezxml_t fl)
149     {
150     return SDEsupport;
151     }
152    
153     /* Variable resolution BSDF methods */
154     const SDFunc SDhandleTre = {
155     NULL,
156     NULL,
157     NULL,
158     NULL,
159     &SDfreeTree,
160     };