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

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