source: GTP/trunk/App/Demos/Vis/FriendlyCulling/src/SampleGenerator.cpp @ 3162

Revision 3162, 5.1 KB checked in by mattausch, 16 years ago (diff)

playing around with filter: returning to world space depth difference for filter kernel??

Line 
1#include "SampleGenerator.h"
2#include "common.h"
3
4
5using namespace std;
6using namespace CHCDemoEngine;
7
8HaltonSequence SphericalSampleGenerator3::sHalton;
9HaltonSequence PoissonDiscSampleGenerator2::sHalton;
10HaltonSequence RandomSampleGenerator2::sHalton;
11HaltonSequence QuadraticDiscSampleGenerator2::sHalton;
12
13
14SampleGenerator::SampleGenerator(int numSamples, float radius):
15mNumSamples(numSamples), mRadius(radius)
16{}
17
18
19PoissonDiscSampleGenerator2::PoissonDiscSampleGenerator2(int numSamples, float radius):
20SampleGenerator(numSamples, radius)
21{}
22
23
24void PoissonDiscSampleGenerator2::Generate(float *samples) const
25{
26        // this is a hacky poisson sampling generator which does random dart-throwing on a disc.
27        // as a savety criterium, the min distance requirement is relaxed if we are not
28        // able to place any dart for a number of tries
29        // the solution is a possion sampling with respect to the adjusted min distance
30        // better solutions have been proposed, i.e., using hierarchical sampling
31        const float maxTries = 1000;
32        const float f_reduction = 0.9f;
33
34        //static HaltonSequence halton;
35        float r[2];
36
37        // generates poisson distribution on disc
38        // start with some threshold. best case: all samples lie on the circumference
39        //const float minDist = 2.0f * mRadius / sqrt((float)mNumSamples);
40        const float eps = 0.2f;
41        const float minDist = 2.0f * mRadius * M_PI * (1.0f - eps) / (float)mNumSamples;
42        float sqrMinDist = minDist * minDist;
43
44        //cout << "minDist before= " << minDist << endl;
45        Sample2 *s = (Sample2 *)samples;
46
47        int totalTries = 0;
48
49        // check if on disc
50        for (int i = 0; i < mNumSamples; ++ i)
51        {
52                int tries = 0;
53
54                // repeat until valid sample was found
55                while (1)
56                {
57                        ++ tries;
58                        ++ totalTries;
59
60                        // note: should use halton, but seems somewhat broken
61                        //r[0] = RandomValue(.0f, mRadius);
62                        //r[1] = RandomValue(.0f, mRadius);
63                        sHalton.GetNext(2, r);
64
65                        // scale to -1 .. 1
66                        const float rx = r[0] * 2.0f - 1.0f;
67                        const float ry = r[1] * 2.0f - 1.0f;
68
69                        // check if in disk, else exit early
70                        const float distanceSquared = rx * rx + ry * ry;
71
72                        if ((rx * rx + ry * ry > mRadius * mRadius)
73                                // also avoid case that sample exactly in center                       
74                                || (distanceSquared <= 1e-3f)
75                                )
76                                continue;
77
78                        bool sampleValid = true;
79
80                        // check poisson property
81                        for (int j = 0; ((j < i) && sampleValid); ++ j)
82                        {
83                                const float dist =
84                                        (s[j].x - rx) * (s[j].x - rx) +
85                                        (s[j].y - ry) * (s[j].y - ry);
86                       
87                                if (dist < sqrMinDist)
88                                        sampleValid = false;
89                        }
90
91                        if (sampleValid)
92                        {
93                                s[i].x = rx;
94                                s[i].y = ry;
95                                break;
96                        }
97
98                        if (tries > maxTries)
99                        {
100                                sqrMinDist *= f_reduction;
101                                tries = 0;
102                        }
103                }
104        }
105
106        //cout << "minDist after= " << sqrt(sqrMinDist) << " #tries: " << totalTries << endl;
107}
108
109
110RandomSampleGenerator2::RandomSampleGenerator2(int numSamples, float radius):
111SampleGenerator(numSamples, radius)
112{}
113
114
115void RandomSampleGenerator2::Generate(float *samples) const
116{
117        Sample2 *s = (Sample2 *)samples;
118
119        int numSamples = 0;
120
121        float r[2];
122
123        while (numSamples < mNumSamples)
124        {
125                //r[0] = RandomValue(-mRadius, mRadius);
126                //r[1] = RandomValue(-mRadius, mRadius);
127                sHalton.GetNext(2, r);
128               
129                const float rx = r[0] * 2.0f - 1.0f;
130                const float ry = r[1] * 2.0f - 1.0f;
131
132                // check if in disk, else exit early
133                if (rx * rx + ry * ry > mRadius * mRadius)
134                        continue;
135
136                s[numSamples].x = rx;
137                s[numSamples].y = ry;
138
139                ++ numSamples;
140        }
141}
142
143
144SphericalSampleGenerator3::SphericalSampleGenerator3(int numSamples, float radius):
145SampleGenerator(numSamples, radius)
146{}
147
148
149void SphericalSampleGenerator3::Generate(float *samples) const
150{
151        float r[2];
152        Sample3 *s = (Sample3 *)samples;
153
154        for (int i = 0; i < mNumSamples; ++ i)
155        {
156                r[0] = RandomValue(0, 1);
157                r[1] = RandomValue(0, 1);
158
159                //sHalton.GetNext(2, r);
160
161                // create stratified samples over sphere
162                const float theta = 2.0f * acos(sqrt(1.0f - r[0]));
163                const float phi = 2.0f * M_PI * r[1];
164 
165                s[i].x = mRadius * sin(theta) * cos(phi);
166                s[i].y = mRadius * sin(theta) * sin(phi);
167                s[i].z = mRadius * cos(theta);
168        }
169}
170
171
172QuadraticDiscSampleGenerator2::QuadraticDiscSampleGenerator2(int numSamples, float radius):
173SampleGenerator(numSamples, radius)
174{}
175
176
177void QuadraticDiscSampleGenerator2::Generate(float *samples) const
178{
179#if 0
180        float r[2];
181        Sample2 *s = (Sample2 *)samples;
182
183        for (int i = 0; i < mNumSamples; ++ i)
184        {
185                //r[0] = samples[i * 2];
186                //r[1] = samples[i * 2 + 1];
187                sHalton.GetNext(2, r);
188
189                // create samples over disc: the sample density
190                // decreases quadratically with the distance to the origin
191                s[i].x = mRadius * r[1] * sin(2.0f * M_PI * r[0]);
192                s[i].y = mRadius * r[1] * cos(2.0f * M_PI * r[0]);
193        }
194#else
195
196        PoissonDiscSampleGenerator2 poisson(mNumSamples, 1.0f);
197        poisson.Generate(samples);
198
199        Sample2 *s = (Sample2 *)samples;
200
201        // multiply with lenght to get quadratic dependence on the distance
202        for (int i = 0; i < mNumSamples; ++ i)
203        {
204                Sample2 &spl = s[i];
205
206                float len = sqrt(spl.x * spl.x + spl.y * spl.y);
207                spl.x *= len * mRadius;
208                spl.y *= len * mRadius;
209        }
210#endif
211}
Note: See TracBrowser for help on using the repository browser.