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

Revision 3329, 5.4 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
9SampleGenerator::SampleGenerator(int numSamples, float radius):
10mNumSamples(numSamples), mRadius(radius)
11{
12        mHalton = new HaltonSequence(2);
13}
14
15
16SampleGenerator::~SampleGenerator()
17{
18        DEL_PTR(mHalton);
19}
20
21
22PoissonDiscSampleGenerator2D::PoissonDiscSampleGenerator2D(int numSamples, float radius):
23SampleGenerator(numSamples, radius)
24{}
25
26
27void PoissonDiscSampleGenerator2D::Generate(float *samples) const
28{
29        // Poisson disc sampling generator using relaxation
30        // dart-throwing as proposed by McCool et al.
31        // the min distance requirement is relaxed if we are not
32        // able to place any dart for a number of tries
33        // the solution is a possion sampling with respect
34        // to the adjusted min distance
35        // this sampling scheme has the benefit that it is hierarchical
36        int maxTries = 1000;
37        const float f_reduction = 0.95f;
38       
39        float r[2];
40
41        // the maximal possible radius: our radius is a fraction of this radius
42        // this is used as a measure of the quality of distribution of the point samples
43        const float rmax = 2.0f * mRadius * sqrt(1.0f / (2.0f * sqrt(3.0f) * mNumSamples));
44
45        // generates poisson distribution on disc
46        // start with some thresholds: all samples lie on the circumference of circle
47         
48        float minDist = 2.0f * rmax;
49        float sqrMinDist = minDist * minDist;
50
51        int tries = 0;
52
53        //cout << "minDist before= " << minDist << endl;
54        Sample2 *s = (Sample2 *)samples;
55
56        // check if on disc
57        for (int i = 0; i < mNumSamples; ++ i)
58        {
59                // repeat until valid sample was found
60                while (1)
61                {
62                        // q: should we use halton or does it conflict with the poisson disc properties?
63                        r[0] = RandomValue(0, 1); r[1] = RandomValue(0, 1);
64                        //mHalton->GetNext(r);
65
66                        // scale to -1 .. 1
67                        const float rx = r[0] * 2.0f - 1.0f;
68                        const float ry = r[1] * 2.0f - 1.0f;
69
70                        // check if in disk, else exit early
71                        const float distanceSquared = rx * rx + ry * ry;
72
73                        if ((rx * rx + ry * ry > mRadius * mRadius)
74                                // also avoid case that sample exactly in center                       
75                                //|| (distanceSquared <= 1e-3f)
76                                )
77                                continue;
78
79                        bool sampleValid = true;
80
81                        // check poisson property
82                        for (int j = 0; ((j < i) && sampleValid); ++ j)
83                        {
84                                const float dist =
85                                        (s[j].x - rx) * (s[j].x - rx) +
86                                        (s[j].y - ry) * (s[j].y - ry);
87                       
88                                if (dist < sqrMinDist)
89                                        sampleValid = false;
90                        }
91
92                        if (sampleValid)
93                        {
94                                s[i].x = rx;
95                                s[i].y = ry;
96                                break;
97                        }
98
99                        ++ tries;
100
101                        if (tries > maxTries)
102                        {
103                                minDist *= f_reduction;
104                                sqrMinDist = minDist * minDist;
105
106                                maxTries += 1000;
107                        }
108                }
109        }
110
111        //cout << "minDist after= " << (float)minDist / mNumSamples<< " #tries: " << tries << endl;
112}
113
114
115RandomSampleGenerator2D::RandomSampleGenerator2D(int numSamples, float radius):
116SampleGenerator(numSamples, radius)
117{}
118
119
120#if 0
121void RandomSampleGenerator2D::Generate(float *samples) const
122{
123        Sample2 *s = (Sample2 *)samples;
124
125        int numSamples = 0;
126
127        float r[2];
128
129        while (numSamples < mNumSamples)
130        {
131                mHalton->GetNext(r);
132               
133                const float rx = r[0] * 2.0f - 1.0f;
134                const float ry = r[1] * 2.0f - 1.0f;
135
136                // check if in disk, else exit early
137                if (rx * rx + ry * ry > mRadius * mRadius)
138                        continue;
139
140                s[numSamples].x = rx;
141                s[numSamples].y = ry;
142
143                ++ numSamples;
144        }
145}
146
147#else
148
149void RandomSampleGenerator2D::Generate(float *samples) const
150{
151        Sample2 *s = (Sample2 *)samples;
152
153        int numSamples = 0;
154        float x[2];
155
156        static float total1 = 0;
157        static float total2 = 0;
158        static int totalSamples = 0;
159
160        for (int i = 0; i < mNumSamples; ++ i)
161        {
162                //x[0] = RandomValue(0, 1); x[1] = RandomValue(0, 1);
163                mHalton->GetNext(x);
164               
165                const float a = 2.0f * M_PI * x[0];
166                const float r = mRadius * sqrt(x[1]);
167
168                s[i].x = r * cos(a);
169                s[i].y = r * sin(a);
170
171                /*total1 += x[0];
172                total2 += x[1];
173                totalSamples ++;
174
175                if (totalSamples % 1000 == 1)
176                {
177                        float n1 = (float)total1 / totalSamples;
178                        float n2 = (float)total2 / totalSamples;
179
180                        cout << "here3 " << n1 << " " << n2 << endl;
181                }*/
182        }
183}
184
185#endif
186
187SphericalSampleGenerator3D::SphericalSampleGenerator3D(int numSamples, float radius):
188SampleGenerator(numSamples, radius)
189{}
190
191
192void SphericalSampleGenerator3D::Generate(float *samples) const
193{
194        float r[2];
195        Sample3 *s = (Sample3 *)samples;
196
197        for (int i = 0; i < mNumSamples; ++ i)
198        {
199                r[0] = RandomValue(0, 1);
200                r[1] = RandomValue(0, 1);
201
202                const float theta = 2.0f * acos(sqrt(1.0f - r[0]));
203                const float phi = 2.0f * M_PI * r[1];
204 
205                s[i].x = mRadius * sin(theta) * cos(phi);
206                s[i].y = mRadius * sin(theta) * sin(phi);
207                s[i].z = mRadius * cos(theta);
208        }
209}
210
211
212QuadraticDiscSampleGenerator2D::QuadraticDiscSampleGenerator2D(int numSamples, float radius):
213//PoissonDiscSampleGenerator2D(numSamples, radius)
214RandomSampleGenerator2D(numSamples, radius)
215{}
216
217
218void QuadraticDiscSampleGenerator2D::Generate(float *samples) const
219{
220        Sample2 *s = (Sample2 *)samples;
221
222        int numSamples = 0;
223        float x[2];
224
225        static float total1 = 0;
226        static float total2 = 0;
227        static int totalSamples = 0;
228
229        for (int i = 0; i < mNumSamples; ++ i)
230        {
231                //x[0] = RandomValue(0, 1); x[1] = RandomValue(0, 1);
232                mHalton->GetNext(x);
233               
234                const float a = 2.0f * M_PI * x[0];
235                const float r = sqrt(x[1]);
236                //const float rad = mRadius * r * r * r * r;
237                const float rad = mRadius * r;// * r;
238
239                s[i].x = rad * cos(a);
240                s[i].y = rad * sin(a);
241        }
242}
Note: See TracBrowser for help on using the repository browser.