ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/bsdf_t.c
Revision: 3.3
Committed: Fri Feb 18 02:41:55 2011 UTC (13 years, 2 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 3.2: +4 -2 lines
Log Message:
Minor fixes and adjustments

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: bsdf_t.c,v 3.2 2011/02/18 00:41:44 greg Exp $";
3 #endif
4 /*
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 #include "rtio.h"
14 #include <stdlib.h>
15 #include <math.h>
16 #include <ctype.h>
17 #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 SDloadTre(SDData *sd, ezxml_t fl)
154 {
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 };