ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/bsdf_t.c
Revision: 3.4
Committed: Sat Feb 19 01:48:59 2011 UTC (13 years, 2 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 3.3: +2 -2 lines
Log Message:
Minor changes and fixes -- first working version of BSDF material

File Contents

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