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

Revision 2900, 3.5 KB checked in by mattausch, 16 years ago (diff)

changed to real 3d samples which are then projected to texture space

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(float *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        Sample2 *s = (Sample2 *)samples;
38
39        for (int i = 0; i < mNumSamples; ++ i)
40        {
41                int tries = 0, totalTries = 0;
42
43                // repeat until valid sample was found
44                while (1)
45                {
46                        ++ tries;
47                        ++ totalTries;
48
49                        halton.GetNext(2, r);
50
51                        const float rx = r[0] * 2.0f - 1.0f;
52                        const float ry = r[1] * 2.0f - 1.0f;
53
54                        // check if in disk, else exit early
55                        if (rx * rx + ry * ry > 1)
56                                continue;
57
58                        bool sampleValid = true;
59
60                        // check poisson property
61                        for (int j = 0; ((j < i) && sampleValid); ++ j)
62                        {
63                                const float dist =
64                                        sqrt((s[j].x - rx) * (s[j].x - rx) +
65                                             (s[j].y - ry) * (s[j].y - ry));
66                       
67                                if (dist < minDist)
68                                        sampleValid = false;
69                        }
70
71                        if (sampleValid)
72                        {
73                                s[i].x = rx;
74                                s[i].y = ry;
75                                break;
76                        }
77
78                        if (tries > maxTries)
79                        {
80                                minDist *= f_reduction;
81                                tries = 0;
82                        }
83                }
84               
85                //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;
86        }
87
88        //cout << "minDist after= " << minDist << endl;
89}
90
91
92
93GaussianSampleGenerator::GaussianSampleGenerator(int numSamples, float radius):
94SampleGenerator(numSamples, radius)
95{}
96
97
98void GaussianSampleGenerator::Generate(float *samples) const
99{
100        static HaltonSequence halton;
101        float r[2];
102
103        const float sigma = mRadius;
104
105        Sample2 *s = (Sample2 *)samples;
106
107        const float p0 = 1.0f / (sigma * sqrt(2.0f * M_PI));
108        const float p1 = 1.0f / (sigma * sqrt(2.0f * M_PI));
109
110        for (int i = 0; i < mNumSamples; ++ i)
111        {
112                halton.GetNext(2, r);
113
114                float exp_x = -(r[0] * r[0]) / (2.0f * sigma * sigma);
115                float exp_y = -(r[1] * r[1]) / (2.0f * sigma * sigma);
116
117                s[i].x = p0 * pow(M_E, exp_x);
118                s[i].y = p1 * pow(M_E, exp_y);
119        }
120
121        //cout << "minDist after= " << minDist << endl;
122}
123
124
125SphericalSampleGenerator::SphericalSampleGenerator(int numSamples, float radius):
126SampleGenerator(numSamples, radius)
127{}
128
129
130void SphericalSampleGenerator::Generate(float *samples) const
131{
132        static HaltonSequence halton;
133        float r[2];
134
135        Sample3 *s = (Sample3 *)samples;
136
137        for (int i = 0; i < mNumSamples; ++ i)
138        {
139                halton.GetNext(2, r);
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 = sin(theta) * cos(phi);
146                s[i].y = sin(theta) * sin(phi);
147                s[i].z = cos(theta);
148        }
149}
Note: See TracBrowser for help on using the repository browser.