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

Revision 3232, 4.7 KB checked in by mattausch, 16 years ago (diff)

started dof implementation (not working yet!)

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