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

# User Rev Content
1 greg 3.2 #ifndef lint
2     static const char RCSid[] = "$Id$";
3     #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     #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     };