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

Revision 3229, 5.1 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
[3229]8//HaltonSequence PoissonDiscSampleGenerator2D::sHalton(2);
9//HaltonSequence RandomSampleGenerator2D::sHalton(2);
10//HaltonSequence QuadraticDiscSampleGenerator2D::sHalton(2);
[2853]11
[2901]12
[2853]13SampleGenerator::SampleGenerator(int numSamples, float radius):
14mNumSamples(numSamples), mRadius(radius)
15{}
16
17
[3227]18PoissonDiscSampleGenerator2D::PoissonDiscSampleGenerator2D(int numSamples, float radius):
[3229]19SampleGenerator(numSamples, radius), sHalton(HaltonSequence(2))
[2853]20{}
21
22
[3227]23void PoissonDiscSampleGenerator2D::Generate(float *samples) const
[2853]24{
[2930]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
[2873]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
[3221]30        const int maxTries = 1000;
[2873]31        const float f_reduction = 0.9f;
32
[3227]33
[2853]34        float r[2];
35
36        // generates poisson distribution on disc
[2930]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;
[2853]42
43        //cout << "minDist before= " << minDist << endl;
[2900]44        Sample2 *s = (Sample2 *)samples;
[2853]45
[2930]46        int totalTries = 0;
47
48        // check if on disc
[2853]49        for (int i = 0; i < mNumSamples; ++ i)
50        {
[2930]51                int tries = 0;
[2853]52
53                // repeat until valid sample was found
54                while (1)
55                {
56                        ++ tries;
57                        ++ totalTries;
58
[2930]59                        // note: should use halton, but seems somewhat broken
[3227]60                        sHalton.GetNext(r);
[2853]61
[2930]62                        // scale to -1 .. 1
[2853]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
[3103]67                        const float distanceSquared = rx * rx + ry * ry;
68
69                        if ((rx * rx + ry * ry > mRadius * mRadius)
[3162]70                                // also avoid case that sample exactly in center                       
[3227]71                                //|| (distanceSquared <= 1e-3f)
[3103]72                                )
[2853]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 =
[2930]81                                        (s[j].x - rx) * (s[j].x - rx) +
82                                        (s[j].y - ry) * (s[j].y - ry);
[2853]83                       
[2930]84                                if (dist < sqrMinDist)
[2853]85                                        sampleValid = false;
86                        }
87
88                        if (sampleValid)
89                        {
[2900]90                                s[i].x = rx;
91                                s[i].y = ry;
[2853]92                                break;
93                        }
94
[2873]95                        if (tries > maxTries)
[2853]96                        {
[2930]97                                sqrMinDist *= f_reduction;
[2853]98                                tries = 0;
99                        }
100                }
101        }
102
[2930]103        //cout << "minDist after= " << sqrt(sqrMinDist) << " #tries: " << totalTries << endl;
[2898]104}
105
106
[3227]107RandomSampleGenerator2D::RandomSampleGenerator2D(int numSamples, float radius):
[3229]108SampleGenerator(numSamples, radius), sHalton(HaltonSequence(2))
[2898]109{}
110
111
[3227]112void RandomSampleGenerator2D::Generate(float *samples) const
[2898]113{
[2900]114        Sample2 *s = (Sample2 *)samples;
115
[2903]116        int numSamples = 0;
[2898]117
[2930]118        float r[2];
119
[2903]120        while (numSamples < mNumSamples)
[2898]121        {
[3227]122                sHalton.GetNext(r);
[2930]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
[3227]139SphericalSampleGenerator3D::SphericalSampleGenerator3D(int numSamples, float radius):
[2899]140SampleGenerator(numSamples, radius)
141{}
142
143
[3227]144void SphericalSampleGenerator3D::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
[2899]154                // create stratified samples over sphere
[2900]155                const float theta = 2.0f * acos(sqrt(1.0f - r[0]));
156                const float phi = 2.0f * M_PI * r[1];
[2901]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        }
[2930]162}
[2899]163
[2930]164
[3227]165QuadraticDiscSampleGenerator2D::QuadraticDiscSampleGenerator2D(int numSamples, float radius):
[3229]166PoissonDiscSampleGenerator2D(numSamples, radius)
167//SampleGenerator(numSamples, radius),
168//sHalton(HaltonSequence(2)),
169//mPoisson(PoissonDiscSampleGenerator2D(numSamples, radius))
[2930]170{}
171
172
[3227]173void QuadraticDiscSampleGenerator2D::Generate(float *samples) const
[2930]174{
[2954]175#if 0
[2930]176        float r[2];
177        Sample2 *s = (Sample2 *)samples;
178
179        for (int i = 0; i < mNumSamples; ++ i)
180        {
[3227]181                sHalton.GetNext(r);
[2930]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]);
[2954]187        }
188#else
[2930]189
[3229]190        //static PoissonDiscSampleGenerator2D poisson(mNumSamples, 1.0f);
191        //poisson.Generate(samples);
[2954]192
[3229]193        PoissonDiscSampleGenerator2D::Generate(samples);
194
[2954]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        {
[2955]200                Sample2 &spl = s[i];
[2954]201
202                float len = sqrt(spl.x * spl.x + spl.y * spl.y);
203                spl.x *= len * mRadius;
204                spl.y *= len * mRadius;
[2930]205        }
[2954]206#endif
[2853]207}
Note: See TracBrowser for help on using the repository browser.