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

Revision 2902, 4.1 KB checked in by mattausch, 16 years ago (diff)
RevLine 
[2853]1#include "common.h"
2#include "SampleGenerator.h"
3
[2901]4
[2853]5using namespace std;
6
[2901]7HaltonSequence SphericalSampleGenerator::sHalton;
8HaltonSequence PoissonDiscSampleGenerator::sHalton;
9HaltonSequence GaussianSampleGenerator::sHalton;
[2902]10HaltonSequence PseudoRandomGenerator::sHalton;
[2853]11
[2901]12
[2853]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
[2900]23void PoissonDiscSampleGenerator::Generate(float *samples) const
[2853]24{
[2873]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
[2853]34        static HaltonSequence halton;
35        float r[2];
36
37        // generates poisson distribution on disc
[2873]38        float minDist = 2.0f / sqrt((float)mNumSamples);
[2853]39
40        //cout << "minDist before= " << minDist << endl;
[2900]41        Sample2 *s = (Sample2 *)samples;
[2853]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 =
[2900]68                                        sqrt((s[j].x - rx) * (s[j].x - rx) +
69                                             (s[j].y - ry) * (s[j].y - ry));
[2853]70                       
71                                if (dist < minDist)
72                                        sampleValid = false;
73                        }
74
75                        if (sampleValid)
76                        {
[2900]77                                s[i].x = rx;
78                                s[i].y = ry;
[2853]79                                break;
80                        }
81
[2873]82                        if (tries > maxTries)
[2853]83                        {
[2873]84                                minDist *= f_reduction;
[2853]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;
[2898]93}
94
95
96
97GaussianSampleGenerator::GaussianSampleGenerator(int numSamples, float radius):
98SampleGenerator(numSamples, radius)
99{}
100
101
[2900]102void GaussianSampleGenerator::Generate(float *samples) const
[2898]103{
104        float r[2];
105
106        const float sigma = mRadius;
107
[2900]108        Sample2 *s = (Sample2 *)samples;
109
[2898]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        {
[2901]115                sHalton.GetNext(2, r);
[2898]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
[2900]120                s[i].x = p0 * pow(M_E, exp_x);
121                s[i].y = p1 * pow(M_E, exp_y);
[2898]122        }
123
124        //cout << "minDist after= " << minDist << endl;
[2899]125}
126
127
[2902]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
[2899]139SphericalSampleGenerator::SphericalSampleGenerator(int numSamples, float radius):
140SampleGenerator(numSamples, radius)
141{}
142
143
[2900]144void SphericalSampleGenerator::Generate(float *samples) const
[2899]145{
146        float r[2];
[2900]147        Sample3 *s = (Sample3 *)samples;
[2902]148/*     
149        // idea: use poisson distribution to generate samples
[2900]150
[2901]151        PoissonDiscSampleGenerator poisson(mNumSamples, 1.0f);
152        Sample2 *pSamples = new Sample2[mNumSamples];
153        poisson.Generate((float *)pSamples);
[2902]154*/
[2899]155        for (int i = 0; i < mNumSamples; ++ i)
156        {
[2902]157                sHalton.GetNext(2, r);
158                //r[0] = pSamples[i].x; r[1] = pSamples[i].y;
[2899]159
160                // create stratified samples over sphere
[2900]161                const float theta = 2.0f * acos(sqrt(1.0f - r[0]));
162                const float phi = 2.0f * M_PI * r[1];
[2901]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        }
[2899]168
[2902]169        //delete [] pSamples;
[2853]170}
Note: See TracBrowser for help on using the repository browser.