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

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

added some statistics stuff, but ssao slower than before (probably because made ssao width and intensity variable and not hardcoded anymore) from >180 frames to < 130 frames!!!

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 int 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.