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, 3 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

# Content
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 };