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

Revision 3372, 5.9 KB checked in by mattausch, 15 years ago (diff)

reverted but now a good version

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
[3343]43        //const float rmax = 2.0f * mRadius * sqrt(1.0f / (2.0f * sqrt(3.0f) * mNumSamples));
44        float rmax = 0.5f; //mRadius * sqrt(1.0f / (2.0f * sqrt(3.0f) * mNumSamples));
[3234]45
[2853]46        // generates poisson distribution on disc
[3234]47        // start with some thresholds: all samples lie on the circumference of circle
[3233]48         
[3343]49        //float minDist = 2.0f * rmax;
50        float minDist = rmax;
[2930]51        float sqrMinDist = minDist * minDist;
[2853]52
[3234]53        int tries = 0;
54
[3343]55        //cout << "minDist before= " << minDist / rmax << endl;
56        cout << "minDist before= " << rmax << endl;
57
[2900]58        Sample2 *s = (Sample2 *)samples;
[2853]59
[2930]60        // check if on disc
[2853]61        for (int i = 0; i < mNumSamples; ++ i)
62        {
63                // repeat until valid sample was found
64                while (1)
65                {
[3234]66                        // q: should we use halton or does it conflict with the poisson disc properties?
[3355]67                        //r[0] = RandomValue(0, 1); r[1] = RandomValue(0, 1);
68                        mHalton->GetNext(r);
[2853]69
[3338]70#if 0
[2930]71                        // scale to -1 .. 1
[2853]72                        const float rx = r[0] * 2.0f - 1.0f;
73                        const float ry = r[1] * 2.0f - 1.0f;
74
75                        // check if in disk, else exit early
[3103]76                        const float distanceSquared = rx * rx + ry * ry;
[3338]77                        if (rx * rx + ry * ry > mRadius * mRadius)
78                                // also avoid case that sample exactly in center
[3227]79                                //|| (distanceSquared <= 1e-3f)
[3338]80                        {
[2853]81                                continue;
[3338]82                        }
83#else
84                        const float rx = r[0];
85                        const float ry = r[1];
86#endif
[2853]87
88                        bool sampleValid = true;
89
90                        // check poisson property
91                        for (int j = 0; ((j < i) && sampleValid); ++ j)
92                        {
93                                const float dist =
[2930]94                                        (s[j].x - rx) * (s[j].x - rx) +
95                                        (s[j].y - ry) * (s[j].y - ry);
[2853]96                       
[3339]97                                if (dist < sqrMinDist) sampleValid = false;
[2853]98                        }
99
100                        if (sampleValid)
101                        {
[2900]102                                s[i].x = rx;
103                                s[i].y = ry;
[2853]104                                break;
105                        }
106
[3234]107                        ++ tries;
108
[2873]109                        if (tries > maxTries)
[2853]110                        {
[3234]111                                minDist *= f_reduction;
112                                sqrMinDist = minDist * minDist;
113
114                                maxTries += 1000;
[2853]115                        }
116                }
117        }
118
[3338]119        for (int i = 0; i < mNumSamples; ++ i)
120        {
121                const float a = 2.0f * M_PI * s[i].x;
122                const float r = sqrt(s[i].y);
123               
124                const float rad = mRadius * r;
125
126                s[i].x = rad * cos(a);
127                s[i].y = rad * sin(a);
128        }
129
[3343]130        rmax = mRadius * sqrt(1.0f / (2.0f * sqrt(3.0f) * mNumSamples));
131        cout << "minDist after= " << (float)minDist * mNumSamples << " #tries: " << tries << " samples: " << mNumSamples << endl;
132        cout << "minDist after= " << (float)minDist / rmax << " #tries: " << tries << endl;
[2898]133}
134
135
[3227]136RandomSampleGenerator2D::RandomSampleGenerator2D(int numSamples, float radius):
[3230]137SampleGenerator(numSamples, radius)
[2898]138{}
139
140
[3322]141#if 0
[3227]142void RandomSampleGenerator2D::Generate(float *samples) const
[2898]143{
[2900]144        Sample2 *s = (Sample2 *)samples;
145
[2903]146        int numSamples = 0;
[2898]147
[2930]148        float r[2];
149
[2903]150        while (numSamples < mNumSamples)
[2898]151        {
[3230]152                mHalton->GetNext(r);
[2930]153               
154                const float rx = r[0] * 2.0f - 1.0f;
155                const float ry = r[1] * 2.0f - 1.0f;
[2898]156
[2903]157                // check if in disk, else exit early
158                if (rx * rx + ry * ry > mRadius * mRadius)
159                        continue;
[2898]160
[2903]161                s[numSamples].x = rx;
162                s[numSamples].y = ry;
[2898]163
[2903]164                ++ numSamples;
165        }
[2899]166}
167
[3322]168#else
[2899]169
[3322]170void RandomSampleGenerator2D::Generate(float *samples) const
171{
172        Sample2 *s = (Sample2 *)samples;
173
174        int numSamples = 0;
175        float x[2];
176
177        static float total1 = 0;
178        static float total2 = 0;
179        static int totalSamples = 0;
180
181        for (int i = 0; i < mNumSamples; ++ i)
182        {
[3371]183                //x[0] = RandomValue(0, 1); x[1] = RandomValue(0, 1);
184                mHalton->GetNext(x);
[3322]185               
186                const float a = 2.0f * M_PI * x[0];
187                const float r = mRadius * sqrt(x[1]);
188
189                s[i].x = r * cos(a);
190                s[i].y = r * sin(a);
191
[3323]192                /*total1 += x[0];
[3322]193                total2 += x[1];
194                totalSamples ++;
195
196                if (totalSamples % 1000 == 1)
197                {
198                        float n1 = (float)total1 / totalSamples;
199                        float n2 = (float)total2 / totalSamples;
200
201                        cout << "here3 " << n1 << " " << n2 << endl;
[3323]202                }*/
[3322]203        }
204}
205
206#endif
207
[3227]208SphericalSampleGenerator3D::SphericalSampleGenerator3D(int numSamples, float radius):
[2899]209SampleGenerator(numSamples, radius)
210{}
211
212
[3227]213void SphericalSampleGenerator3D::Generate(float *samples) const
[2899]214{
215        float r[2];
[2900]216        Sample3 *s = (Sample3 *)samples;
217
[2899]218        for (int i = 0; i < mNumSamples; ++ i)
219        {
[2903]220                r[0] = RandomValue(0, 1);
221                r[1] = RandomValue(0, 1);
[2930]222
[2900]223                const float theta = 2.0f * acos(sqrt(1.0f - r[0]));
224                const float phi = 2.0f * M_PI * r[1];
[2901]225 
226                s[i].x = mRadius * sin(theta) * cos(phi);
227                s[i].y = mRadius * sin(theta) * sin(phi);
228                s[i].z = mRadius * cos(theta);
229        }
[2930]230}
[2899]231
[2930]232
[3343]233QuadraticDiscSampleGenerator2D::QuadraticDiscSampleGenerator2D(int numSamples,
234                                                                                                                           float radius):
[3313]235//PoissonDiscSampleGenerator2D(numSamples, radius)
236RandomSampleGenerator2D(numSamples, radius)
[3343]237{
238}
[2930]239
240
[3227]241void QuadraticDiscSampleGenerator2D::Generate(float *samples) const
[2930]242{
243        Sample2 *s = (Sample2 *)samples;
244
[3329]245        int numSamples = 0;
246        float x[2];
[2930]247
[2954]248        for (int i = 0; i < mNumSamples; ++ i)
249        {
[3372]250                //x[0] = RandomValue(0, 1); x[1] = RandomValue(0, 1);
251                mHalton->GetNext(x);
[3329]252               
253                const float a = 2.0f * M_PI * x[0];
254                const float r = sqrt(x[1]);
[3372]255               
256                const float rad = mRadius * r;
[2954]257
[3329]258                s[i].x = rad * cos(a);
259                s[i].y = rad * sin(a);
[2930]260        }
[2853]261}
Note: See TracBrowser for help on using the repository browser.