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

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