1 | #include "Environment.h"
|
---|
2 | #include "GvsPreprocessor.h"
|
---|
3 | #include "GlRenderer.h"
|
---|
4 | #include "VssRay.h"
|
---|
5 | #include "ViewCellsManager.h"
|
---|
6 | #include "Triangle3.h"
|
---|
7 | #include "IntersectableWrapper.h"
|
---|
8 |
|
---|
9 |
|
---|
10 | namespace GtpVisibilityPreprocessor
|
---|
11 | {
|
---|
12 |
|
---|
13 |
|
---|
14 | GvsPreprocessor::GvsPreprocessor(): Preprocessor(), mSamplingType(0)
|
---|
15 | {
|
---|
16 | Environment::GetSingleton()->GetIntValue("GvsPreprocessor.totalSamples", mTotalSamples);
|
---|
17 | Environment::GetSingleton()->GetIntValue("GvsPreprocessor.initialSamples", mInitialSamples);
|
---|
18 | Environment::GetSingleton()->GetIntValue("GvsPreprocessor.samplesPerPass", mSamplesPerPass);
|
---|
19 | Environment::GetSingleton()->GetFloatValue("GvsPreprocessor.epsilon", mEps);
|
---|
20 |
|
---|
21 |
|
---|
22 | Debug << "Gvs preprocessor options" << endl;
|
---|
23 | Debug << "number of total samples: " << mTotalSamples << endl;
|
---|
24 | Debug << "number of initial samples: " << mInitialSamples << endl;
|
---|
25 | Debug << "number of samples per pass: " << mSamplesPerPass << endl;
|
---|
26 |
|
---|
27 | mStats.open("gvspreprocessor.log");
|
---|
28 | }
|
---|
29 |
|
---|
30 |
|
---|
31 | const bool GvsPreprocessor::DiscontinuityFound(const VssRay &ray,
|
---|
32 | const VssRay &oldRay) const
|
---|
33 | {
|
---|
34 | //const Plane3 plane = tri->GetPlane();
|
---|
35 | return false;
|
---|
36 | }
|
---|
37 |
|
---|
38 |
|
---|
39 | int GvsPreprocessor::HandleRay(const GvsRayInfo &gvsRay)
|
---|
40 | {
|
---|
41 | VssRay *ray = gvsRay.mRay;
|
---|
42 |
|
---|
43 | if (!mViewCellsManager->ComputeSampleContribution(*ray, true, false))
|
---|
44 | return 1;
|
---|
45 |
|
---|
46 | if (gvsRay.mFoundDiscontinuity)
|
---|
47 | {
|
---|
48 | return ReverseSampling(*ray);
|
---|
49 | }
|
---|
50 | else
|
---|
51 | {
|
---|
52 | return AdaptiveBorderSampling(*ray);
|
---|
53 | }
|
---|
54 | }
|
---|
55 |
|
---|
56 | /** Hepler function for adaptive border sampling. It finds
|
---|
57 | new sample points around a triangle in a eps environment
|
---|
58 | */
|
---|
59 | static void CreateNewSamples(VertexContainer &samples,
|
---|
60 | const Triangle3 &hitTriangle,
|
---|
61 | const VssRay &ray,
|
---|
62 | const int index,
|
---|
63 | const float eps)
|
---|
64 | {
|
---|
65 | const int indexU = (index + 1) % 3;
|
---|
66 | const int indexL = (index == 0) ? 2 : index - 1;
|
---|
67 |
|
---|
68 | const Vector3 a = hitTriangle.mVertices[index] - ray.GetDir();
|
---|
69 | const Vector3 b = hitTriangle.mVertices[indexU] - hitTriangle.mVertices[index];
|
---|
70 | const Vector3 c = hitTriangle.mVertices[index] - hitTriangle.mVertices[indexL];
|
---|
71 | const float len = Magnitude(a);
|
---|
72 |
|
---|
73 | // compute the new three hit points
|
---|
74 | // pi, i + 1
|
---|
75 | const Vector3 dir1 = CrossProd(a, b); //N((pi-xp)×(pi+1- pi));
|
---|
76 | const Vector3 pt1 = hitTriangle.mVertices[index] + eps * len * dir1; //pi+ e·|pi-xp|·di, j
|
---|
77 | samples.push_back(pt1);
|
---|
78 |
|
---|
79 | // pi, i - 1
|
---|
80 | const Vector3 dir2 = CrossProd(a, c); // N((pi-xp)×(pi- pi-1))
|
---|
81 | const Vector3 pt2 = hitTriangle.mVertices[index] + eps * len * dir2; //pi+ e·|pi-xp|·di, j
|
---|
82 | samples.push_back(pt2);
|
---|
83 |
|
---|
84 | // pi, i
|
---|
85 | const Vector3 dir3 = DotProd(dir1, dir2) > 0 ?
|
---|
86 | Normalize(dir2 + dir1) : Normalize(CrossProd(a, dir2) + CrossProd(dir1, a)); // N((pi-xp)×di,i-1+di,i+1×(pi-xp))
|
---|
87 | const Vector3 pt3 = hitTriangle.mVertices[index] + eps * len * dir3; //pi+ e·|pi-xp|·di, j
|
---|
88 | samples.push_back(pt3);
|
---|
89 | }
|
---|
90 |
|
---|
91 |
|
---|
92 | /** Generate rays from sample points.
|
---|
93 | */
|
---|
94 | static void CreateRays(VssRayContainer &rays,
|
---|
95 | const VertexContainer &samples)
|
---|
96 | {
|
---|
97 | VertexContainer::const_iterator vit, vit_end = samples.end();
|
---|
98 |
|
---|
99 | for (vit = samples.begin(); vit != vit_end; ++ vit)
|
---|
100 | {
|
---|
101 | const Vector3 currentSample = *vit;
|
---|
102 | VssRay *ray;// = new VssRay(ray->mOrigin, currentSample);
|
---|
103 | }
|
---|
104 | }
|
---|
105 |
|
---|
106 |
|
---|
107 | int GvsPreprocessor::AdaptiveBorderSampling(const VssRay &prevRay)
|
---|
108 | {
|
---|
109 | cout << "a";
|
---|
110 | Intersectable *tObj = prevRay.mTerminationObject;
|
---|
111 | Triangle3 hitTriangle;
|
---|
112 |
|
---|
113 | // other types not implemented yet
|
---|
114 | if (tObj->Type() == Intersectable::TRIANGLE_INTERSECTABLE)
|
---|
115 | {
|
---|
116 | hitTriangle = dynamic_cast<TriangleIntersectable *>(tObj)->GetItem();
|
---|
117 | }
|
---|
118 |
|
---|
119 | VertexContainer samples;
|
---|
120 | samples.reserve(9);
|
---|
121 |
|
---|
122 | CreateNewSamples(samples, hitTriangle, prevRay, 0, mEps);
|
---|
123 | CreateNewSamples(samples, hitTriangle, prevRay, 1, mEps);
|
---|
124 | CreateNewSamples(samples, hitTriangle, prevRay, 2, mEps);
|
---|
125 |
|
---|
126 | VssRayContainer vssRays;
|
---|
127 | CreateRays(vssRays, samples);
|
---|
128 |
|
---|
129 | VssRayContainer::const_iterator rit, rit_end = vssRays.end();
|
---|
130 |
|
---|
131 | for (rit = vssRays.begin(); rit != rit_end; ++ rit)
|
---|
132 | {
|
---|
133 | VssRay *ray = *rit;
|
---|
134 |
|
---|
135 | // discontinuity found?
|
---|
136 | // schedule for reverse sampling or adaptive border sampling
|
---|
137 | const bool gap = DiscontinuityFound(*ray, prevRay);
|
---|
138 | mRayQueue.push(GvsRayInfo(ray, gap));
|
---|
139 | }
|
---|
140 |
|
---|
141 | return 9;
|
---|
142 | }
|
---|
143 |
|
---|
144 |
|
---|
145 | int GvsPreprocessor::ReverseSampling(const VssRay &ray)
|
---|
146 | {
|
---|
147 | cout << "r" << endl;
|
---|
148 | // TODO
|
---|
149 | return 1;
|
---|
150 | }
|
---|
151 |
|
---|
152 |
|
---|
153 | int GvsPreprocessor::CastInitialSamples(const int numSamples,
|
---|
154 | const int sampleType)
|
---|
155 | {
|
---|
156 | const long startTime = GetTime();
|
---|
157 |
|
---|
158 | // generate simple rays
|
---|
159 | SimpleRayContainer simpleRays;
|
---|
160 | GenerateRays(numSamples, sampleType, simpleRays);
|
---|
161 |
|
---|
162 | // generate vss rays
|
---|
163 | VssRayContainer samples;
|
---|
164 | CastRays(simpleRays, samples);
|
---|
165 |
|
---|
166 | // add to ray queue
|
---|
167 | EnqueueSamples(samples);
|
---|
168 |
|
---|
169 | Debug << "generated " << numSamples << " samples in " << TimeDiff(startTime, GetTime()) * 1e-3 << " secs" << endl;
|
---|
170 |
|
---|
171 | return (int)samples.size();
|
---|
172 | }
|
---|
173 |
|
---|
174 |
|
---|
175 | void GvsPreprocessor::EnqueueSamples(VssRayContainer &samples, VssRay *oldRay)
|
---|
176 | {
|
---|
177 | // add samples to ray queue
|
---|
178 | VssRayContainer::const_iterator vit, vit_end = samples.end();
|
---|
179 | for (vit = samples.begin(); vit != vit_end; ++ vit)
|
---|
180 | {
|
---|
181 | /// if there is no old ray, no discontinuity
|
---|
182 | const bool gap = oldRay ? DiscontinuityFound(*(*vit), *oldRay) : false;
|
---|
183 | mRayQueue.push(GvsRayInfo(*vit, gap));
|
---|
184 | }
|
---|
185 |
|
---|
186 | }
|
---|
187 |
|
---|
188 |
|
---|
189 | int GvsPreprocessor::Pass()
|
---|
190 | {
|
---|
191 | int castSamples = 0;
|
---|
192 | const int mSampleType = 0;
|
---|
193 | while (castSamples < mSamplesPerPass)
|
---|
194 | {
|
---|
195 | // Ray queue empty =>
|
---|
196 | // cast a number of uniform samples to fill ray Queue
|
---|
197 | CastInitialSamples(mInitialSamples, mSampleType);
|
---|
198 |
|
---|
199 | const int gvsSamples = ProcessQueue();
|
---|
200 | castSamples += gvsSamples;
|
---|
201 | //cout << "\ncast " << castSamples << " of " << mSamplesPerPass << endl;
|
---|
202 | }
|
---|
203 |
|
---|
204 | return castSamples;
|
---|
205 | }
|
---|
206 |
|
---|
207 |
|
---|
208 | int GvsPreprocessor::ProcessQueue()
|
---|
209 | {
|
---|
210 | int castSamples = 0;
|
---|
211 |
|
---|
212 | while (!mRayQueue.empty())
|
---|
213 | {
|
---|
214 | // handle next ray
|
---|
215 | GvsRayInfo rayInfo = mRayQueue.top();
|
---|
216 | mRayQueue.pop();
|
---|
217 |
|
---|
218 | castSamples += HandleRay(rayInfo);
|
---|
219 | }
|
---|
220 |
|
---|
221 | return castSamples;
|
---|
222 | }
|
---|
223 |
|
---|
224 |
|
---|
225 | bool GvsPreprocessor::ComputeVisibility()
|
---|
226 | {
|
---|
227 | Randomize(0);
|
---|
228 | const long startTime = GetTime();
|
---|
229 |
|
---|
230 | mViewSpaceBox = mKdTree->GetBox();
|
---|
231 | cout << "Gvs Preprocessor started\n" << flush;
|
---|
232 |
|
---|
233 | if (!mLoadViewCells)
|
---|
234 | { /// construct the view cells from the scratch
|
---|
235 | ConstructViewCells(mViewSpaceBox);
|
---|
236 | cout << "view cells loaded" << endl;
|
---|
237 | }
|
---|
238 |
|
---|
239 | int castSamples = 0;
|
---|
240 |
|
---|
241 | while (castSamples < mTotalSamples)
|
---|
242 | {
|
---|
243 | const int passSamples = Pass();
|
---|
244 | castSamples += passSamples;
|
---|
245 |
|
---|
246 | /////////////
|
---|
247 | // -- stats
|
---|
248 | cout << "+";
|
---|
249 | cout << "\nsamples cast " << passSamples << " (=" << castSamples << " of " << mTotalSamples << ")" << endl;
|
---|
250 | //mVssRays.PrintStatistics(mStats);
|
---|
251 | mStats << "#Time\n" << TimeDiff(startTime, GetTime())*1e-3 << endl
|
---|
252 | << "#TotalSamples\n" << castSamples << endl;
|
---|
253 |
|
---|
254 | mViewCellsManager->PrintPvsStatistics(mStats);
|
---|
255 | // ComputeRenderError();
|
---|
256 | }
|
---|
257 |
|
---|
258 | return true;
|
---|
259 | }
|
---|
260 |
|
---|
261 | }
|
---|