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

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