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

Revision 3247, 5.0 KB checked in by mattausch, 15 years ago (diff)

worked on obj loader
played around with ssao sampling

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
8
9SampleGenerator::SampleGenerator(int numSamples, float radius):
10mNumSamples(numSamples), mRadius(radius)
[3230]11{
12        mHalton = new HaltonSequence(2);
13}
[2853]14
15
[3230]16SampleGenerator::~SampleGenerator()
17{
18        DEL_PTR(mHalton);
19}
20
21
[3227]22PoissonDiscSampleGenerator2D::PoissonDiscSampleGenerator2D(int numSamples, float radius):
[3230]23SampleGenerator(numSamples, radius)
[2853]24{}
25
26
[3227]27void PoissonDiscSampleGenerator2D::Generate(float *samples) const
[2853]28{
[3233]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
[2930]32        // able to place any dart for a number of tries
[3233]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;
[3234]37        const float f_reduction = 0.95f;
[3233]38       
[2853]39        float r[2];
40
[3234]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
[2853]45        // generates poisson distribution on disc
[3234]46        // start with some thresholds: all samples lie on the circumference of circle
[3233]47         
[3234]48        float minDist = 2.0f * rmax;
[2930]49        float sqrMinDist = minDist * minDist;
[2853]50
[3234]51        int tries = 0;
52
[2853]53        //cout << "minDist before= " << minDist << endl;
[2900]54        Sample2 *s = (Sample2 *)samples;
[2853]55
[2930]56        // check if on disc
[2853]57        for (int i = 0; i < mNumSamples; ++ i)
58        {
59                // repeat until valid sample was found
60                while (1)
61                {
[3234]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);
[2853]65
[2930]66                        // scale to -1 .. 1
[2853]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
[3103]71                        const float distanceSquared = rx * rx + ry * ry;
72
73                        if ((rx * rx + ry * ry > mRadius * mRadius)
[3162]74                                // also avoid case that sample exactly in center                       
[3227]75                                //|| (distanceSquared <= 1e-3f)
[3103]76                                )
[2853]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 =
[2930]85                                        (s[j].x - rx) * (s[j].x - rx) +
86                                        (s[j].y - ry) * (s[j].y - ry);
[2853]87                       
[2930]88                                if (dist < sqrMinDist)
[2853]89                                        sampleValid = false;
90                        }
91
92                        if (sampleValid)
93                        {
[2900]94                                s[i].x = rx;
95                                s[i].y = ry;
[2853]96                                break;
97                        }
98
[3234]99                        ++ tries;
100
[2873]101                        if (tries > maxTries)
[2853]102                        {
[3234]103                                minDist *= f_reduction;
104                                sqrMinDist = minDist * minDist;
105
106                                maxTries += 1000;
[2853]107                        }
108                }
109        }
110
[3235]111        //cout << "minDist after= " << (float)minDist / mNumSamples<< " #tries: " << tries << endl;
[2898]112}
113
114
[3227]115RandomSampleGenerator2D::RandomSampleGenerator2D(int numSamples, float radius):
[3230]116SampleGenerator(numSamples, radius)
[2898]117{}
118
119
[3227]120void RandomSampleGenerator2D::Generate(float *samples) const
[2898]121{
[2900]122        Sample2 *s = (Sample2 *)samples;
123
[2903]124        int numSamples = 0;
[2898]125
[2930]126        float r[2];
127
[2903]128        while (numSamples < mNumSamples)
[2898]129        {
[3230]130                mHalton->GetNext(r);
[2930]131               
132                const float rx = r[0] * 2.0f - 1.0f;
133                const float ry = r[1] * 2.0f - 1.0f;
[2898]134
[2903]135                // check if in disk, else exit early
136                if (rx * rx + ry * ry > mRadius * mRadius)
137                        continue;
[2898]138
[2903]139                s[numSamples].x = rx;
140                s[numSamples].y = ry;
[2898]141
[2903]142                ++ numSamples;
143        }
[2899]144}
145
146
[3227]147SphericalSampleGenerator3D::SphericalSampleGenerator3D(int numSamples, float radius):
[2899]148SampleGenerator(numSamples, radius)
149{}
150
151
[3227]152void SphericalSampleGenerator3D::Generate(float *samples) const
[2899]153{
154        float r[2];
[2900]155        Sample3 *s = (Sample3 *)samples;
156
[2899]157        for (int i = 0; i < mNumSamples; ++ i)
158        {
[2903]159                r[0] = RandomValue(0, 1);
160                r[1] = RandomValue(0, 1);
[2930]161
[2899]162                // create stratified samples over sphere
[2900]163                const float theta = 2.0f * acos(sqrt(1.0f - r[0]));
164                const float phi = 2.0f * M_PI * r[1];
[2901]165 
166                s[i].x = mRadius * sin(theta) * cos(phi);
167                s[i].y = mRadius * sin(theta) * sin(phi);
168                s[i].z = mRadius * cos(theta);
169        }
[2930]170}
[2899]171
[2930]172
[3227]173QuadraticDiscSampleGenerator2D::QuadraticDiscSampleGenerator2D(int numSamples, float radius):
[3247]174//PoissonDiscSampleGenerator2D(numSamples, radius)
175RandomSampleGenerator2D(numSamples, radius)
[2930]176{}
177
178
[3227]179void QuadraticDiscSampleGenerator2D::Generate(float *samples) const
[2930]180{
[2954]181#if 0
[2930]182        float r[2];
183        Sample2 *s = (Sample2 *)samples;
184
185        for (int i = 0; i < mNumSamples; ++ i)
186        {
[3230]187                mHalton->GetNext(r);
[2930]188
189                // create samples over disc: the sample density
190                // decreases quadratically with the distance to the origin
191                s[i].x = mRadius * r[1] * sin(2.0f * M_PI * r[0]);
192                s[i].y = mRadius * r[1] * cos(2.0f * M_PI * r[0]);
[2954]193        }
194#else
[2930]195
[3247]196        //PoissonDiscSampleGenerator2D::Generate(samples);
197        RandomSampleGenerator2D::Generate(samples);
[3229]198
[2954]199        Sample2 *s = (Sample2 *)samples;
200
201        // multiply with lenght to get quadratic dependence on the distance
202        for (int i = 0; i < mNumSamples; ++ i)
203        {
[2955]204                Sample2 &spl = s[i];
[2954]205
206                float len = sqrt(spl.x * spl.x + spl.y * spl.y);
207                spl.x *= len * mRadius;
208                spl.y *= len * mRadius;
[2930]209        }
[2954]210#endif
[2853]211}
Note: See TracBrowser for help on using the repository browser.