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

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