ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/bsdf_t.c
Revision: 3.2
Committed: Fri Feb 18 00:41:44 2011 UTC (13 years, 3 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 3.1: +3 -0 lines
Log Message:
Added missing RCS tags

File Contents

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