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

Revision 2902, 4.1 KB checked in by mattausch, 16 years ago (diff)
Line 
1#include "common.h"
2#include "SampleGenerator.h"
3
4
5using namespace std;
6
7HaltonSequence SphericalSampleGenerator::sHalton;
8HaltonSequence PoissonDiscSampleGenerator::sHalton;
9HaltonSequence GaussianSampleGenerator::sHalton;
10HaltonSequence PseudoRandomGenerator::sHalton;
11
12
13SampleGenerator::SampleGenerator(int numSamples, float radius):
14mNumSamples(numSamples), mRadius(radius)
15{}
16
17
18PoissonDiscSampleGenerator::PoissonDiscSampleGenerator(int numSamples, float radius):
19SampleGenerator(numSamples, radius)
20{}
21
22
23void PoissonDiscSampleGenerator::Generate(float *samples) const
24{
25        // this is a hacky poisson sampling generator which does random dart-throwing
26        // until it is not able to place any dart for a number of tries
27        // in this case, the required min distance is reduced
28        // the solution is a possion sampling with respect to the adjusted min distance
29        // better solutions have been proposed, i.e., using hierarchical sampling
30
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        float minDist = 2.0f / sqrt((float)mNumSamples);
39
40        //cout << "minDist before= " << minDist << endl;
41        Sample2 *s = (Sample2 *)samples;
42
43        for (int i = 0; i < mNumSamples; ++ i)
44        {
45                int tries = 0, totalTries = 0;
46
47                // repeat until valid sample was found
48                while (1)
49                {
50                        ++ tries;
51                        ++ totalTries;
52
53                        halton.GetNext(2, r);
54
55                        const float rx = r[0] * 2.0f - 1.0f;
56                        const float ry = r[1] * 2.0f - 1.0f;
57
58                        // check if in disk, else exit early
59                        if (rx * rx + ry * ry > 1)
60                                continue;
61
62                        bool sampleValid = true;
63
64                        // check poisson property
65                        for (int j = 0; ((j < i) && sampleValid); ++ j)
66                        {
67                                const float dist =
68                                        sqrt((s[j].x - rx) * (s[j].x - rx) +
69                                             (s[j].y - ry) * (s[j].y - ry));
70                       
71                                if (dist < minDist)
72                                        sampleValid = false;
73                        }
74
75                        if (sampleValid)
76                        {
77                                s[i].x = rx;
78                                s[i].y = ry;
79                                break;
80                        }
81
82                        if (tries > maxTries)
83                        {
84                                minDist *= f_reduction;
85                                tries = 0;
86                        }
87                }
88               
89                //cout << "sample: " << samples[i].x << " " << i << " " << samples[i].y << " r: " << sqrt(samples[i].x * samples[i].x  + samples[i].y * samples[i].y) << " tries: " << totalTries << endl;
90        }
91
92        //cout << "minDist after= " << minDist << endl;
93}
94
95
96
97GaussianSampleGenerator::GaussianSampleGenerator(int numSamples, float radius):
98SampleGenerator(numSamples, radius)
99{}
100
101
102void GaussianSampleGenerator::Generate(float *samples) const
103{
104        float r[2];
105
106        const float sigma = mRadius;
107
108        Sample2 *s = (Sample2 *)samples;
109
110        const float p0 = 1.0f / (sigma * sqrt(2.0f * M_PI));
111        const float p1 = 1.0f / (sigma * sqrt(2.0f * M_PI));
112
113        for (int i = 0; i < mNumSamples; ++ i)
114        {
115                sHalton.GetNext(2, r);
116
117                float exp_x = -(r[0] * r[0]) / (2.0f * sigma * sigma);
118                float exp_y = -(r[1] * r[1]) / (2.0f * sigma * sigma);
119
120                s[i].x = p0 * pow(M_E, exp_x);
121                s[i].y = p1 * pow(M_E, exp_y);
122        }
123
124        //cout << "minDist after= " << minDist << endl;
125}
126
127
128PseudoRandomGenerator::PseudoRandomGenerator(int numSamples, float radius):
129SampleGenerator(numSamples, radius)
130{}
131
132
133void PseudoRandomGenerator::Generate(float *samples) const
134{
135        sHalton.GetNext(2 * mNumSamples, samples);
136}
137
138
139SphericalSampleGenerator::SphericalSampleGenerator(int numSamples, float radius):
140SampleGenerator(numSamples, radius)
141{}
142
143
144void SphericalSampleGenerator::Generate(float *samples) const
145{
146        float r[2];
147        Sample3 *s = (Sample3 *)samples;
148/*     
149        // idea: use poisson distribution to generate samples
150
151        PoissonDiscSampleGenerator poisson(mNumSamples, 1.0f);
152        Sample2 *pSamples = new Sample2[mNumSamples];
153        poisson.Generate((float *)pSamples);
154*/
155        for (int i = 0; i < mNumSamples; ++ i)
156        {
157                sHalton.GetNext(2, r);
158                //r[0] = pSamples[i].x; r[1] = pSamples[i].y;
159
160                // create stratified samples over sphere
161                const float theta = 2.0f * acos(sqrt(1.0f - r[0]));
162                const float phi = 2.0f * M_PI * r[1];
163 
164                s[i].x = mRadius * sin(theta) * cos(phi);
165                s[i].y = mRadius * sin(theta) * sin(phi);
166                s[i].z = mRadius * cos(theta);
167        }
168
169        //delete [] pSamples;
170}
Note: See TracBrowser for help on using the repository browser.