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

Revision 2903, 3.5 KB checked in by mattausch, 16 years ago (diff)
Line 
1#include "SampleGenerator.h"
2#include "common.h"
3
4
5using namespace std;
6using namespace CHCDemoEngine;
7
8HaltonSequence SphericalSampleGenerator::sHalton;
9HaltonSequence PoissonDiscSampleGenerator::sHalton;
10HaltonSequence PseudoRandomGenerator::sHalton;
11
12
13SampleGenerator::SampleGenerator(int numSamples, float radius):
14mNumSamples(numSamples), mRadius(radius)
15{}
16
17
18PoissonDiscSampleGenerator::PoissonDiscSampleGenerator(int numSamples, float radius):
19SampleGenerator(numSamples, radius)
20{}
21
22
23void PoissonDiscSampleGenerator::Generate(float *samples) const
24{
25        // this is a hacky poisson sampling generator which does random dart-throwing
26        // until it is not able to place any dart for a number of tries
27        // in this case, the required min distance is reduced
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
30
31        const float maxTries = 1000;
32        const float f_reduction = 0.9f;
33
34        //static HaltonSequence halton;
35        float r[2];
36
37        // generates poisson distribution on disc
38        float minDist = 2.0f * mRadius / sqrt((float)mNumSamples);
39
40        //cout << "minDist before= " << minDist << endl;
41        Sample2 *s = (Sample2 *)samples;
42
43        for (int i = 0; i < mNumSamples; ++ i)
44        {
45                int tries = 0, totalTries = 0;
46
47                // repeat until valid sample was found
48                while (1)
49                {
50                        ++ tries;
51                        ++ totalTries;
52
53                        r[0] = RandomValue(0, mRadius);
54                        r[1] = RandomValue(0, mRadius);
55                        //halton.GetNext(2, r);
56
57                        const float rx = r[0] * 2.0f - 1.0f;
58                        const float ry = r[1] * 2.0f - 1.0f;
59
60                        // check if in disk, else exit early
61                        if (rx * rx + ry * ry > mRadius * mRadius)
62                                continue;
63
64                        bool sampleValid = true;
65
66                        // check poisson property
67                        for (int j = 0; ((j < i) && sampleValid); ++ j)
68                        {
69                                const float dist =
70                                        sqrt((s[j].x - rx) * (s[j].x - rx) +
71                                             (s[j].y - ry) * (s[j].y - ry));
72                       
73                                if (dist < minDist)
74                                        sampleValid = false;
75                        }
76
77                        if (sampleValid)
78                        {
79                                s[i].x = rx;
80                                s[i].y = ry;
81                                break;
82                        }
83
84                        if (tries > maxTries)
85                        {
86                                minDist *= f_reduction;
87                                tries = 0;
88                        }
89                }
90        }
91
92        //cout << "minDist after= " << minDist << endl;
93}
94
95
96PseudoRandomGenerator::PseudoRandomGenerator(int numSamples, float radius):
97SampleGenerator(numSamples, radius)
98{}
99
100
101void PseudoRandomGenerator::Generate(float *samples) const
102{
103        Sample2 *s = (Sample2 *)samples;
104
105        int numSamples = 0;
106
107        while (numSamples < mNumSamples)
108        {
109                const float rx = RandomValue(-mRadius, +mRadius);
110                const float ry = RandomValue(-mRadius, +mRadius);
111
112                // check if in disk, else exit early
113                if (rx * rx + ry * ry > mRadius * mRadius)
114                        continue;
115
116                s[numSamples].x = rx;
117                s[numSamples].y = ry;
118
119                ++ numSamples;
120        }
121}
122
123
124SphericalSampleGenerator::SphericalSampleGenerator(int numSamples, float radius):
125SampleGenerator(numSamples, radius)
126{}
127
128
129void SphericalSampleGenerator::Generate(float *samples) const
130{
131        float r[2];
132        Sample3 *s = (Sample3 *)samples;
133
134        for (int i = 0; i < mNumSamples; ++ i)
135        {
136                r[0] = RandomValue(0, 1);
137                r[1] = RandomValue(0, 1);
138                //sHalton.GetNext(2, r);
139                //r[0] = pSamples[i].x; r[1] = pSamples[i].y;
140
141                // create stratified samples over sphere
142                const float theta = 2.0f * acos(sqrt(1.0f - r[0]));
143                const float phi = 2.0f * M_PI * r[1];
144 
145                s[i].x = mRadius * sin(theta) * cos(phi);
146                s[i].y = mRadius * sin(theta) * sin(phi);
147                s[i].z = mRadius * cos(theta);
148        }
149
150        //delete [] pSamples;
151}
Note: See TracBrowser for help on using the repository browser.