1 |
|
---|
2 | // Written by Vlastimil Havran, December 2007
|
---|
3 |
|
---|
4 | // This macro allows to use the ray shooting written by
|
---|
5 | // Vlastimil Havran, 2007-2008
|
---|
6 |
|
---|
7 |
|
---|
8 | #include "VssRay.h"
|
---|
9 | #include "KdTree.h"
|
---|
10 | #include "Preprocessor.h"
|
---|
11 | #include "IntersectableWrapper.h"
|
---|
12 |
|
---|
13 | #ifdef USE_HAVRAN_RAYCASTER
|
---|
14 | #include "ktbconf.h"
|
---|
15 | #include "timer.h"
|
---|
16 | #include "ktball.h"
|
---|
17 | #include "ktb.h"
|
---|
18 | #ifdef _USE_HAVRAN_SSE
|
---|
19 |
|
---|
20 | #include "raypack.h"
|
---|
21 | #endif // _USE_HAVRAN_SSE
|
---|
22 | #endif // _USE_HAVRAN_RAYCASTER
|
---|
23 |
|
---|
24 | #include "HavranRayCaster.h"
|
---|
25 |
|
---|
26 | #define DEBUG_RAYCAST 0
|
---|
27 |
|
---|
28 | namespace GtpVisibilityPreprocessor {
|
---|
29 |
|
---|
30 | #ifdef _USE_HAVRAN_SSE
|
---|
31 | // static rays
|
---|
32 | GALIGN16 RayPacket2x2
|
---|
33 | HavranDynRayCaster::raypack_t;
|
---|
34 | #endif // _USE_HAVRAN_SSE
|
---|
35 |
|
---|
36 | HavranDynRayCaster::HavranDynRayCaster(const Preprocessor &preprocessor):
|
---|
37 | HavranRayCaster(preprocessor), mDynKtbtree(0),
|
---|
38 | dynobjects(0), dynamicFlag(false)
|
---|
39 | {
|
---|
40 | #ifdef USE_HAVRAN_RAYCASTER
|
---|
41 | #ifdef _USE_HAVRAN_SSE
|
---|
42 | if ( ((int)(&raypack_t)) & 0xf != 0) {
|
---|
43 | cerr << "The ray pack data type not aligned on 16 Bytes boundary" << endl;
|
---|
44 | cerr << "Address is " << (void*)(&raypack_t) << endl;
|
---|
45 | cerr << "Reorganize your data structure to make it aligned" << endl;
|
---|
46 | abort();
|
---|
47 | }
|
---|
48 | #endif
|
---|
49 | #endif
|
---|
50 | }
|
---|
51 |
|
---|
52 |
|
---|
53 | HavranDynRayCaster::~HavranDynRayCaster()
|
---|
54 | {
|
---|
55 | #ifdef USE_HAVRAN_RAYCASTER
|
---|
56 | DeleteDynamicObjects();
|
---|
57 | #endif // USE_HAVRAN_RAYCASTER
|
---|
58 | }
|
---|
59 |
|
---|
60 | void
|
---|
61 | HavranDynRayCaster::DeleteDynamicObjects()
|
---|
62 | {
|
---|
63 | #ifdef USE_HAVRAN_RAYCASTER
|
---|
64 | delete mDynKtbtree; mDynKtbtree = 0;
|
---|
65 | delete dynobjects; dynobjects = 0;
|
---|
66 | dynamicFlag = false;
|
---|
67 | #endif // USE_HAVRAN_RAYCASTER
|
---|
68 | }
|
---|
69 |
|
---|
70 | void
|
---|
71 | HavranDynRayCaster::AddDynamicObjecs(const ObjectContainer &objects, const Matrix4x4 &m)
|
---|
72 | {
|
---|
73 | #ifdef USE_HAVRAN_RAYCASTER
|
---|
74 | if (dynobjects)
|
---|
75 | DeleteDynamicObjects();
|
---|
76 |
|
---|
77 | dynamicFlag = false;
|
---|
78 |
|
---|
79 | if (objects.size()) {
|
---|
80 | dynamicFlag = true;
|
---|
81 | dynobjects = new ObjectContainer(objects);
|
---|
82 | assert(dynobjects);
|
---|
83 | // kd-tree built over the objects
|
---|
84 | mDynKtbtree = new CKTB;
|
---|
85 | mDynKtbtree->BuildUp(*dynobjects);
|
---|
86 |
|
---|
87 | // The matrix to transform the objects
|
---|
88 | UpdateDynamicObjects(m);
|
---|
89 | }
|
---|
90 | #endif // USE_HAVRAN_RAYCASTER
|
---|
91 | }
|
---|
92 |
|
---|
93 | void
|
---|
94 | HavranDynRayCaster::UpdateDynamicObjects(const Matrix4x4 &m)
|
---|
95 | {
|
---|
96 | #ifdef USE_HAVRAN_RAYCASTER
|
---|
97 | matTr = m;
|
---|
98 | matTr_inv = Invert(matTr);
|
---|
99 | #endif // USE_HAVRAN_RAYCASTER
|
---|
100 | }
|
---|
101 |
|
---|
102 | // Using packet of 4 rays supposing that these are coherent
|
---|
103 | // We give a box to which each ray is clipped to before the
|
---|
104 | // ray shooting is computed !
|
---|
105 | void HavranDynRayCaster::CastRaysPacket4(const Vector3 &minBox,
|
---|
106 | const Vector3 &maxBox,
|
---|
107 | const Vector3 origin4[],
|
---|
108 | const Vector3 direction4[],
|
---|
109 | int result4[],
|
---|
110 | float dist4[])
|
---|
111 | {
|
---|
112 | #ifdef USE_HAVRAN_RAYCASTER
|
---|
113 | #ifdef _USE_HAVRAN_SSE
|
---|
114 | for (int i = 0; i < 4; i++) {
|
---|
115 | result4[i] = -1;
|
---|
116 | result4_t[4] = -1;
|
---|
117 | raypack.SetLoc(i, origin4[i]);
|
---|
118 | raypack.SetDir(i, direction4[i]);
|
---|
119 | }
|
---|
120 |
|
---|
121 | // The same operations for packets of rays, if implemented by
|
---|
122 | // a particular ASDS, otherwise it is emulated by decomposition
|
---|
123 | // of a packet to individual rays and traced individually.
|
---|
124 | mKtbtree->FindNearestI(raypack, minBox, maxBox);
|
---|
125 |
|
---|
126 | for (int i = 0; i < 4; i++) {
|
---|
127 | // if ray intersects an object, we set the pointer to
|
---|
128 | // this object
|
---|
129 | Intersectable* intersectable = raypack.GetObject(i);
|
---|
130 | if (intersectable) {
|
---|
131 | result4[i] = intersectable->mId;
|
---|
132 | dist4[i] = raypack.GetT(i);
|
---|
133 | }
|
---|
134 | }
|
---|
135 |
|
---|
136 | if (dynamicFlag) {
|
---|
137 | // The ray pack to be transformed
|
---|
138 | raypack_t = raypack;
|
---|
139 | raypack_t.ApplyTransform(matTr_inv);
|
---|
140 |
|
---|
141 | mDynKtbtree->FindNearestI(raypack_t, minBox, maxBox);
|
---|
142 |
|
---|
143 | for (int i = 0; i < 4; i++) {
|
---|
144 | // if ray intersects an object, we set the pointer to
|
---|
145 | // this object
|
---|
146 | Intersectable* intersectable = raypack_t.GetObject(i);
|
---|
147 | if (intersectable) {
|
---|
148 | float t = raypack_t.GetT(i);
|
---|
149 | if ( ( (result4[i] != -1) && (t < dist4[i]) ) ||
|
---|
150 | (result4[i] == -1) ) {
|
---|
151 | // update, dynamic object is closer
|
---|
152 | dist4[i] = t;
|
---|
153 | result4[i] = intersectable->mId;
|
---|
154 | }
|
---|
155 | }
|
---|
156 | } // for i
|
---|
157 | } // dynamic flag
|
---|
158 |
|
---|
159 | return;
|
---|
160 | #else // _USE_HAVRAN_SSE
|
---|
161 | // Compute the result ray by ray
|
---|
162 | SimpleRay sray;
|
---|
163 | for (int i = 0; i < 4; i++) {
|
---|
164 | result4[i] = -1; // no intersection
|
---|
165 | sray.mOrigin = origin4[i];
|
---|
166 | sray.mDirection = direction4[i];
|
---|
167 | mKtbtree->FindNearestI(sray, minBox, maxBox);
|
---|
168 | if (SimpleRay::IntersectionRes[0].intersectable) {
|
---|
169 | // This is object ID - is this the triangle index ???
|
---|
170 | result4[i] = SimpleRay::IntersectionRes[0].intersectable->mId;
|
---|
171 | dist4[i] = SimpleRay::IntersectionRes[0].tdist;
|
---|
172 | }
|
---|
173 |
|
---|
174 | if (dynamicFlag) {
|
---|
175 | // Now apply transform
|
---|
176 | ApplyTransform(sray);
|
---|
177 | mDynKtbtree->FindNearestI(sray, minBox, maxBox);
|
---|
178 | Intersectable *objdyn = SimpleRay::IntersectionRes[0].intersectable;
|
---|
179 | if (objdyn) {
|
---|
180 | float t = SimpleRay::IntersectionRes[0].tdist;
|
---|
181 | if ( ((result4[i] != -1) && (t < dist4[i])) ||
|
---|
182 | (result4[i] == -1) ) {
|
---|
183 | // = update, dynamic object is closer
|
---|
184 | dist4[i] = t;
|
---|
185 | result4[i] = objdyn->mId;
|
---|
186 | }
|
---|
187 | }
|
---|
188 | } // dynamic flag
|
---|
189 | } // for i;
|
---|
190 |
|
---|
191 | #endif // _USE_HAVRAN_SSE
|
---|
192 | #endif // USE_HAVRAN_RAYCASTER
|
---|
193 | }
|
---|
194 |
|
---|
195 |
|
---|
196 | int HavranDynRayCaster::CastRay(const SimpleRay &simpleRay,
|
---|
197 | VssRayContainer &vssRays,
|
---|
198 | const AxisAlignedBox3 &box,
|
---|
199 | const bool castDoubleRay,
|
---|
200 | const bool pruneInvalidRays)
|
---|
201 | {
|
---|
202 | #ifdef USE_HAVRAN_RAYCASTER
|
---|
203 |
|
---|
204 | // rays forwards - TESTED 21/1/2008 VH (only for forward rays)
|
---|
205 |
|
---|
206 | int hits = 0;
|
---|
207 | Intersection hitA(simpleRay.mOrigin), hitB(simpleRay.mOrigin);
|
---|
208 |
|
---|
209 | // ray.mFlags &= ~Ray::CULL_BACKFACES;
|
---|
210 | bool result;
|
---|
211 | hitA.mObject = 0;
|
---|
212 | if ((result = mKtbtree->FindNearestI(simpleRay))) {
|
---|
213 | hitA.mObject = SimpleRay::IntersectionRes[0].intersectable;
|
---|
214 | tdist[0] = SimpleRay::IntersectionRes[0].tdist;
|
---|
215 | hitA.mPoint = simpleRay.Extrap(tdist[0]);
|
---|
216 | hitA.mNormal = SimpleRay::IntersectionRes[0].intersectable->GetNormal(0);
|
---|
217 | //hitA.mNormal = (dynamic_cast< TriangleIntersectable *>
|
---|
218 | // (hitA.mObject))->GetNormal(0);
|
---|
219 | }
|
---|
220 |
|
---|
221 | if (dynamicFlag) {
|
---|
222 | bool result2 = false;
|
---|
223 | // For a dynamic object
|
---|
224 | sray_t = simpleRay;
|
---|
225 | // Now apply transform
|
---|
226 | ApplyTransform(sray_t);
|
---|
227 | if (mDynKtbtree->FindNearestI(sray_t)) {
|
---|
228 | float t = SimpleRay::IntersectionRes[0].tdist;
|
---|
229 | if ( ((hitA.mObject) && (t < tdist[0])) ||
|
---|
230 | (!hitA.mObject) ) {
|
---|
231 | result = result2 = true; // dynamic object hit
|
---|
232 | // There is an intersection closer than the previous one
|
---|
233 | hitA.mObject = SimpleRay::IntersectionRes[0].intersectable;
|
---|
234 | tdist[0] = SimpleRay::IntersectionRes[0].tdist;
|
---|
235 | hitA.mPoint = simpleRay.Extrap(tdist[0]);
|
---|
236 | hitA.mNormal = hitA.mObject->GetNormal(0);
|
---|
237 | // We have to transform the normal
|
---|
238 | hitA.mNormal = TransformNormal(matTr_inv, hitA.mNormal);
|
---|
239 | }
|
---|
240 | }
|
---|
241 | if (result && (!result2)) {
|
---|
242 | // We put back the result from hitA.mObject for ray tracing
|
---|
243 | SimpleRay::IntersectionRes[0].intersectable = hitA.mObject;
|
---|
244 | SimpleRay::IntersectionRes[0].tdist = tdist[0];
|
---|
245 | }
|
---|
246 | }
|
---|
247 |
|
---|
248 | bool resultB = false;
|
---|
249 | if (castDoubleRay) {
|
---|
250 | bool result2 = false;
|
---|
251 | // casting rays backward
|
---|
252 | Vector3 *v = (Vector3*)(&simpleRay.mDirection);
|
---|
253 | *v = -(*v);
|
---|
254 | // ray.mFlags &= ~Ray::CULL_BACKFACES;
|
---|
255 | if (mKtbtree->FindNearestI(simpleRay)) {
|
---|
256 | resultB = true;
|
---|
257 | hitB.mObject = SimpleRay::IntersectionRes[0].intersectable;
|
---|
258 | assert(hitB.mObject);
|
---|
259 | float tdist = SimpleRay::IntersectionRes[0].tdist;
|
---|
260 | hitB.mPoint = simpleRay.Extrap(tdist);
|
---|
261 | hitB.mNormal = hitB.mObject->GetNormal(0);
|
---|
262 | }
|
---|
263 |
|
---|
264 | if (dynamicFlag) {
|
---|
265 | // For a dynamic object
|
---|
266 | sray_t = simpleRay;
|
---|
267 | // Now apply transform
|
---|
268 | ApplyTransform(sray_t);
|
---|
269 | bool result2;
|
---|
270 | if ( mDynKtbtree->FindNearestI(sray_t)) {
|
---|
271 | assert(SimpleRay::IntersectionRes[0].intersectable);
|
---|
272 | float t = SimpleRay::IntersectionRes[0].tdist;
|
---|
273 | if ( ((hitB.mObject) && (t < tdist[0])) ||
|
---|
274 | (!hitB.mObject) ) {
|
---|
275 | // There is an intersection closer than the previous one
|
---|
276 | resultB = result2 = true; // dynamic object hit
|
---|
277 | hitB.mObject = SimpleRay::IntersectionRes[0].intersectable;
|
---|
278 | tdist[0] = SimpleRay::IntersectionRes[0].tdist;
|
---|
279 | hitB.mPoint = simpleRay.Extrap(tdist[0]);
|
---|
280 | hitB.mNormal = hitB.mObject->GetNormal(0);
|
---|
281 | // We have to transform the normal
|
---|
282 | hitB.mNormal = TransformNormal(matTr_inv, hitB.mNormal);
|
---|
283 | }
|
---|
284 | }
|
---|
285 | if ((resultB) && (!result2)) {
|
---|
286 | // For visualization
|
---|
287 | SimpleRay::IntersectionRes[0].intersectable = hitB.mObject;
|
---|
288 | SimpleRay::IntersectionRes[0].tdist = tdist[0];
|
---|
289 | }
|
---|
290 | } // dynamicFlag
|
---|
291 |
|
---|
292 | // restore the direction to the original
|
---|
293 | *v = -simpleRay.mDirection;
|
---|
294 | } // castDoubleRay
|
---|
295 |
|
---|
296 | #ifdef _PROCESS_RAY
|
---|
297 | // This code is also in IntelRayCaster.cpp
|
---|
298 | return ProcessRay(
|
---|
299 | simpleRay,
|
---|
300 | hitA,
|
---|
301 | hitB,
|
---|
302 | vssRays,
|
---|
303 | box,
|
---|
304 | castDoubleRay,
|
---|
305 | pruneInvalidRays
|
---|
306 | );
|
---|
307 | #else // _PROCESS_RAY
|
---|
308 | if (castDoubleRay)
|
---|
309 | return resultB;
|
---|
310 | return result;
|
---|
311 | #endif // _PROCESS_RAY
|
---|
312 |
|
---|
313 | #else
|
---|
314 | return 0;
|
---|
315 | #endif // USE_HAVRAN_RAYCASTER
|
---|
316 | }
|
---|
317 |
|
---|
318 | void HavranDynRayCaster::CastRays16(SimpleRayContainer &rays,
|
---|
319 | VssRayContainer &vssRays,
|
---|
320 | const AxisAlignedBox3 &sbox,
|
---|
321 | const bool castDoubleRay,
|
---|
322 | const bool pruneInvalidRays)
|
---|
323 | {
|
---|
324 | CastRays16(rays, 0, vssRays, sbox, castDoubleRay, pruneInvalidRays);
|
---|
325 | }
|
---|
326 |
|
---|
327 |
|
---|
328 | void HavranDynRayCaster::CastRays16(SimpleRayContainer &rays,
|
---|
329 | int offset,
|
---|
330 | VssRayContainer &vssRays,
|
---|
331 | const AxisAlignedBox3 &sbox,
|
---|
332 | const bool castDoubleRays,
|
---|
333 | const bool pruneInvalidRays)
|
---|
334 | {
|
---|
335 | #ifdef USE_HAVRAN_RAYCASTER
|
---|
336 |
|
---|
337 | #if DEBUG_RAYCAST
|
---|
338 | Debug << "C16 " << flush;
|
---|
339 | #endif
|
---|
340 |
|
---|
341 | // Use special algorithm for 16 rays at once
|
---|
342 | if (castDoubleRays) {
|
---|
343 | // Here we decompose shooting into two phases
|
---|
344 |
|
---|
345 | // First we delete the results from casting dynamic objects
|
---|
346 | if (dynamicFlag) {
|
---|
347 | for (int i = 0; i < 32; i++)
|
---|
348 | objI[i] = 0;
|
---|
349 | }
|
---|
350 |
|
---|
351 | // Here we shoot first backward rays and forward ones
|
---|
352 | SimpleRayContainer::iterator sit = rays.begin() + offset;
|
---|
353 | SimpleRayContainer::const_iterator sit_end = rays.begin() + offset + 16;
|
---|
354 | for ( ; sit != sit_end; ++ sit)
|
---|
355 | {
|
---|
356 | (*sit).mDirection = - (*sit).mDirection;
|
---|
357 | }
|
---|
358 | // backward rays to be shot - saving with offset 16
|
---|
359 |
|
---|
360 | #ifdef _USE_HAVRAN_SSE
|
---|
361 | mKtbtree->SetOffset(0);
|
---|
362 | mKtbtree->FindNearestI_16oneDir(rays, offset, 16);
|
---|
363 | #else
|
---|
364 | mKtbtree->SetOffset(16);
|
---|
365 | mKtbtree->FindNearestI_16oneDirNoSSE(rays, offset);
|
---|
366 | #endif // _USE_HAVRAN_SSE
|
---|
367 |
|
---|
368 | if (dynamicFlag) {
|
---|
369 | for (int i = 0; i < 16; i++) {
|
---|
370 | // store the origin and direction of the ray
|
---|
371 | orig[i] = rays[offset+i].mOrigin;
|
---|
372 | dirs[i] = rays[offset+i].mDirection;
|
---|
373 |
|
---|
374 | objI[i+16] = SimpleRay::IntersectionRes[i+16].intersectable;
|
---|
375 | if (objI[i+16])
|
---|
376 | normal[i+16] = objI[i+16]->GetNormal(0);
|
---|
377 | tdist[i+16] = SimpleRay::IntersectionRes[i+16].tdist;
|
---|
378 | ApplyTransform(rays[offset+i]);
|
---|
379 | } // for
|
---|
380 | // Now shoot the ray with dynamic object
|
---|
381 | #ifdef _USE_HAVRAN_SSE
|
---|
382 | mDynKtbtree->SetOffset(0);
|
---|
383 | mDynKtbtree->FindNearestI_16oneDir(rays, offset, 16);
|
---|
384 | #else
|
---|
385 | mDynKtbtree->SetOffset(16);
|
---|
386 | mDynKtbtree->FindNearestI_16oneDirNoSSE(rays, offset);
|
---|
387 | #endif // _USE_HAVRAN_SSE
|
---|
388 | for (int i = 0; i < 16; i++) {
|
---|
389 | Intersectable *intersectable =
|
---|
390 | SimpleRay::IntersectionRes[i+16].intersectable;
|
---|
391 | if (intersectable) {
|
---|
392 | float t = SimpleRay::IntersectionRes[i+16].tdist;
|
---|
393 | if ( ((objI[i+16]) && (t < tdist[i+16])) ||
|
---|
394 | (!objI[i+16]) ) {
|
---|
395 | // There is an intersection closer than the previous one
|
---|
396 | objI[i+16] = intersectable;
|
---|
397 | tdist[i+16] = SimpleRay::IntersectionRes[i+16].tdist;
|
---|
398 | normal[i+16] = intersectable->GetNormal(0);
|
---|
399 | // We have to transform the normal
|
---|
400 | normal[i+16] = TransformNormal(matTr_inv, normal[i+16]);
|
---|
401 | } // if update
|
---|
402 | } // if intersected dynamic object
|
---|
403 | else {
|
---|
404 | // we copy back the static object - only for visualization
|
---|
405 | SimpleRay::IntersectionRes[i+16].intersectable = objI[i+16];
|
---|
406 | SimpleRay::IntersectionRes[i+16].tdist = tdist[i+16];
|
---|
407 | }
|
---|
408 | } // for
|
---|
409 | } // dynamic flag
|
---|
410 |
|
---|
411 | // set the ray direction to original direction
|
---|
412 | if (dynamicFlag) {
|
---|
413 | sit = rays.begin() + offset;
|
---|
414 | int i = 0;
|
---|
415 | for ( ; sit != sit_end; ++sit, ++i)
|
---|
416 | {
|
---|
417 | rays[offset+i].mOrigin = orig[i];
|
---|
418 | rays[offset+i].mDirection = -dirs[i];
|
---|
419 | }
|
---|
420 | }
|
---|
421 | else {
|
---|
422 | // no dynamic objects
|
---|
423 | sit = rays.begin() + offset;
|
---|
424 | for ( ; sit != sit_end; ++ sit)
|
---|
425 | {
|
---|
426 | (*sit).mDirection = - (*sit).mDirection;
|
---|
427 | }
|
---|
428 | }
|
---|
429 | // forward rays to be shot
|
---|
430 | #ifdef _USE_HAVRAN_SSE
|
---|
431 | mKtbtree->SetOffset(0);
|
---|
432 | mKtbtree->FindNearestI_16oneDir(rays, offset, 0);
|
---|
433 | #else
|
---|
434 | mKtbtree->SetOffset(0);
|
---|
435 | mKtbtree->FindNearestI_16oneDirNoSSE(rays, offset);
|
---|
436 | #endif // _USE_HAVRAN_SSE
|
---|
437 |
|
---|
438 | if (dynamicFlag) {
|
---|
439 | for (int i = 0; i < 16; i++) {
|
---|
440 | objI[i] = SimpleRay::IntersectionRes[i].intersectable;
|
---|
441 | if (objI[i])
|
---|
442 | normal[i] = objI[i]->GetNormal(0);
|
---|
443 | tdist[i] = SimpleRay::IntersectionRes[i].tdist;
|
---|
444 | ApplyTransform(rays[offset+i]);
|
---|
445 | } // for
|
---|
446 | // Now shoot the ray with dynamic object
|
---|
447 | #ifdef _USE_HAVRAN_SSE
|
---|
448 | mDynKtbtree->SetOffset(0);
|
---|
449 | mDynKtbtree->FindNearestI_16oneDir(rays, offset, 0);
|
---|
450 | #else
|
---|
451 | mDynKtbtree->SetOffset(0);
|
---|
452 | mDynKtbtree->FindNearestI_16oneDirNoSSE(rays, offset);
|
---|
453 | #endif // _USE_HAVRAN_SSE
|
---|
454 | for (int i = 0; i < 16; i++) {
|
---|
455 | Intersectable *intersectable
|
---|
456 | = SimpleRay::IntersectionRes[i].intersectable;
|
---|
457 | if (intersectable) {
|
---|
458 | float t = SimpleRay::IntersectionRes[i].tdist;
|
---|
459 | if ( ((objI[i]) && (t < tdist[i])) ||
|
---|
460 | (!objI[i]) ) {
|
---|
461 | // There is an intersection closer than the previous one
|
---|
462 | objI[i] = intersectable;
|
---|
463 | tdist[i] = SimpleRay::IntersectionRes[i].tdist;
|
---|
464 | normal[i] = objI[i]->GetNormal(0);
|
---|
465 | // We have to transform the normal
|
---|
466 | normal[i] = TransformNormal(matTr_inv, normal[i]);
|
---|
467 | } // update
|
---|
468 | } // intersection
|
---|
469 | // we have to recover the ray
|
---|
470 | rays[offset+i].mOrigin = orig[i];
|
---|
471 | rays[offset+i].mDirection = -dirs[i];
|
---|
472 | } // for i
|
---|
473 | } // dynamic flag
|
---|
474 | } // cast double rays
|
---|
475 | else {
|
---|
476 | // ONLY forward rays - TESTED 21/1/2007 VH
|
---|
477 |
|
---|
478 | // First we delete the results from casting dynamic objects
|
---|
479 | if (dynamicFlag) {
|
---|
480 | for (int i = 0; i < 16; i++) {
|
---|
481 | objI[i] = 0;
|
---|
482 | orig[i] = rays[offset+i].mOrigin;
|
---|
483 | dirs[i] = rays[offset+i].mDirection;
|
---|
484 | }
|
---|
485 | }
|
---|
486 |
|
---|
487 | // Shoot all 16 rays at the same time using a special algorithm
|
---|
488 | mKtbtree->SetOffset(0);
|
---|
489 | #ifdef _USE_HAVRAN_SSE
|
---|
490 | mKtbtree->FindNearestI_16oneDir(rays, offset, 0);
|
---|
491 | #else
|
---|
492 | mKtbtree->FindNearestI_16oneDirNoSSE(rays, offset);
|
---|
493 | #endif // _USE_HAVRAN_SSE
|
---|
494 |
|
---|
495 | // Here we must add dynamic objects
|
---|
496 | if (dynamicFlag) {
|
---|
497 | for (int i = 0; i < 16; i++) {
|
---|
498 | objI[i] = SimpleRay::IntersectionRes[i].intersectable;
|
---|
499 | if (objI[i])
|
---|
500 | normal[i] = objI[i]->GetNormal(0);
|
---|
501 | tdist[i] = SimpleRay::IntersectionRes[i].tdist;
|
---|
502 | ApplyTransform(rays[offset+i]);
|
---|
503 | } // for
|
---|
504 | // Now shoot the ray with dynamic object
|
---|
505 | #ifdef _USE_HAVRAN_SSE
|
---|
506 | mDynKtbtree->SetOffset(0);
|
---|
507 | mDynKtbtree->FindNearestI_16oneDir(rays, offset, 0);
|
---|
508 | #else
|
---|
509 | mDynKtbtree->SetOffset(0);
|
---|
510 | mDynKtbtree->FindNearestI_16oneDirNoSSE(rays, offset);
|
---|
511 | #endif // _USE_HAVRAN_SSE
|
---|
512 | for (int i = 0; i < 16; i++) {
|
---|
513 | Intersectable *intersectable
|
---|
514 | = SimpleRay::IntersectionRes[i].intersectable;
|
---|
515 | if (intersectable) {
|
---|
516 | float t = SimpleRay::IntersectionRes[i].tdist;
|
---|
517 | if ( ((objI[i]) && (t < tdist[i])) ||
|
---|
518 | (!objI[i]) ) {
|
---|
519 | // There is an intersection closer than the previous one
|
---|
520 | objI[i] = intersectable;
|
---|
521 | tdist[i] = SimpleRay::IntersectionRes[i].tdist;
|
---|
522 | normal[i] = objI[i]->GetNormal(0);
|
---|
523 | // We have to transform the normal
|
---|
524 | normal[i] = TransformNormal(matTr_inv, normal[i]);
|
---|
525 | } // update
|
---|
526 | } // intersection
|
---|
527 | // we have to recover the rays back
|
---|
528 | rays[offset+i].mOrigin = orig[i];
|
---|
529 | rays[offset+i].mDirection = dirs[i];
|
---|
530 | } // for i
|
---|
531 | } // dynamic flag
|
---|
532 | }
|
---|
533 |
|
---|
534 | if (dynamicFlag) {
|
---|
535 | for (int i=0, k=offset; i < 16; i++, k++)
|
---|
536 | {
|
---|
537 | Intersection hitA(rays[k].mOrigin), hitB(rays[k].mOrigin);
|
---|
538 |
|
---|
539 | #if DEBUG_RAYCAST
|
---|
540 | Debug<<"FH\n"<<flush;
|
---|
541 | #endif
|
---|
542 |
|
---|
543 | Intersectable *intersectable = objI[i];
|
---|
544 | // For visualization needs only - forward rays
|
---|
545 | SimpleRay::IntersectionRes[i].intersectable = objI[i];
|
---|
546 | SimpleRay::IntersectionRes[i].tdist = tdist[i];
|
---|
547 | if (intersectable)
|
---|
548 | {
|
---|
549 | hitA.mObject = intersectable;
|
---|
550 | // Get the normal of that face
|
---|
551 | hitA.mNormal = normal[i];
|
---|
552 |
|
---|
553 | //-rays[index+i].mDirection; // $$ temporary
|
---|
554 | hitA.mPoint = rays[k].Extrap(tdist[i]);
|
---|
555 | }
|
---|
556 |
|
---|
557 | #if DEBUG_RAYCAST
|
---|
558 | Debug<<"BH\n"<<flush;
|
---|
559 | #endif
|
---|
560 |
|
---|
561 | if (castDoubleRays)
|
---|
562 | {
|
---|
563 | Intersectable *intersectable = objI[i+16];
|
---|
564 |
|
---|
565 | if (intersectable)
|
---|
566 | {
|
---|
567 | hitB.mObject = intersectable;
|
---|
568 | hitB.mNormal = normal[i+16];
|
---|
569 | hitB.mPoint = rays[k].Extrap(-tdist[i+16]);
|
---|
570 | }
|
---|
571 | }
|
---|
572 |
|
---|
573 | #if DEBUG_RAYCAST
|
---|
574 | Debug<<"PR\n"<<flush;
|
---|
575 | #endif
|
---|
576 |
|
---|
577 | #ifdef _PROCESS_RAY
|
---|
578 | ProcessRay(rays[k],
|
---|
579 | hitA,
|
---|
580 | hitB,
|
---|
581 | vssRays,
|
---|
582 | sbox,
|
---|
583 | castDoubleRays,
|
---|
584 | pruneInvalidRays
|
---|
585 | );
|
---|
586 | #endif
|
---|
587 | } // for
|
---|
588 | }
|
---|
589 | else {
|
---|
590 | // no dynamic objects
|
---|
591 | for (int i=0, k=offset; i < 16; i++, k++)
|
---|
592 | {
|
---|
593 | Intersection hitA(rays[k].mOrigin), hitB(rays[k].mOrigin);
|
---|
594 |
|
---|
595 | #if DEBUG_RAYCAST
|
---|
596 | Debug<<"FH\n"<<flush;
|
---|
597 | #endif
|
---|
598 |
|
---|
599 | Intersectable *intersectable
|
---|
600 | = SimpleRay::IntersectionRes[i].intersectable;
|
---|
601 |
|
---|
602 | if (intersectable)
|
---|
603 | {
|
---|
604 | hitA.mObject = intersectable;
|
---|
605 | // Get the normal of that face
|
---|
606 | hitA.mNormal = intersectable->GetNormal(0);
|
---|
607 |
|
---|
608 | //-rays[index+i].mDirection; // $$ temporary
|
---|
609 | float tdist = SimpleRay::IntersectionRes[i].tdist;
|
---|
610 | hitA.mPoint = rays[k].Extrap(tdist);
|
---|
611 | }
|
---|
612 |
|
---|
613 | #if DEBUG_RAYCAST
|
---|
614 | Debug<<"BH\n"<<flush;
|
---|
615 | #endif
|
---|
616 |
|
---|
617 | if (castDoubleRays)
|
---|
618 | {
|
---|
619 | Intersectable *intersectable =
|
---|
620 | SimpleRay::IntersectionRes[i+16].intersectable;
|
---|
621 |
|
---|
622 | if (intersectable)
|
---|
623 | {
|
---|
624 | hitB.mObject = intersectable;
|
---|
625 | hitB.mNormal = intersectable->GetNormal(0);;
|
---|
626 | float tdist = SimpleRay::IntersectionRes[16+i].tdist;
|
---|
627 | hitB.mPoint = rays[k].Extrap(-tdist);
|
---|
628 | }
|
---|
629 | }
|
---|
630 |
|
---|
631 | #if DEBUG_RAYCAST
|
---|
632 | Debug<<"PR\n"<<flush;
|
---|
633 | #endif
|
---|
634 |
|
---|
635 | #ifdef _PROCESS_RAY
|
---|
636 | ProcessRay(rays[k],
|
---|
637 | hitA,
|
---|
638 | hitB,
|
---|
639 | vssRays,
|
---|
640 | sbox,
|
---|
641 | castDoubleRays,
|
---|
642 | pruneInvalidRays
|
---|
643 | );
|
---|
644 | #endif
|
---|
645 | } // for
|
---|
646 | } // dynamic objects
|
---|
647 |
|
---|
648 |
|
---|
649 | #if DEBUG_RAYCAST
|
---|
650 | Debug<<"C16F\n"<<flush;
|
---|
651 | #endif
|
---|
652 |
|
---|
653 | #endif // USE_HAVRAN_RAYCASTER
|
---|
654 | }
|
---|
655 |
|
---|
656 |
|
---|
657 |
|
---|
658 | void
|
---|
659 | HavranDynRayCaster::CastSimpleForwardRays(
|
---|
660 | SimpleRayContainer &rays,
|
---|
661 | const AxisAlignedBox3 &sbox
|
---|
662 | )
|
---|
663 | {
|
---|
664 | #ifdef USE_HAVRAN_RAYCASTER
|
---|
665 |
|
---|
666 | //int hit_triangles[16];
|
---|
667 | //float dist[16];
|
---|
668 | Vector3 normals[16];
|
---|
669 | Vector3 min = sbox.Min();
|
---|
670 | Vector3 max = sbox.Max();
|
---|
671 |
|
---|
672 | int packets = (int)rays.size() / 16;
|
---|
673 |
|
---|
674 | int i, k = 0;
|
---|
675 | Vector3 dir;
|
---|
676 |
|
---|
677 | // By groups of rays
|
---|
678 | for (i=0; i < packets; i++) {
|
---|
679 | int offset = i * 16;
|
---|
680 | mKtbtree->FindNearestI_16oneDir(rays, offset, 0);
|
---|
681 |
|
---|
682 | if (dynamicFlag) {
|
---|
683 | for (int i = 0; i < 16; i++) {
|
---|
684 | orig[i] = rays[i].mOrigin;
|
---|
685 | dirs[i] = rays[i].mDirection;
|
---|
686 |
|
---|
687 | tdist[i] = SimpleRay::IntersectionRes[i].tdist;
|
---|
688 | objI[i] = SimpleRay::IntersectionRes[i].intersectable;
|
---|
689 | // for dynamic objects
|
---|
690 | ApplyTransform(rays[i]);
|
---|
691 | } // for
|
---|
692 |
|
---|
693 | // shoot the rays against dynamic objects
|
---|
694 | mDynKtbtree->FindNearestI_16oneDir(rays, offset, 0);
|
---|
695 | // and combine the results
|
---|
696 | for (int i = 0; i < 16; i++) {
|
---|
697 | float t = SimpleRay::IntersectionRes[i].tdist;
|
---|
698 | if (SimpleRay::IntersectionRes[i].intersectable) {
|
---|
699 | if ( ((objI[i]) && (t < tdist[i])) ||
|
---|
700 | (!objI[i]) ) {
|
---|
701 | // There is an intersection closer than the previous one
|
---|
702 | objI[i] = SimpleRay::IntersectionRes[i].intersectable;
|
---|
703 | tdist[i] = SimpleRay::IntersectionRes[i].tdist;
|
---|
704 | } // update
|
---|
705 | } // intersection
|
---|
706 | else {
|
---|
707 | // Only for visualization
|
---|
708 | SimpleRay::IntersectionRes[i].intersectable = objI[i];
|
---|
709 | SimpleRay::IntersectionRes[i].tdist = tdist[i];
|
---|
710 | }
|
---|
711 | // recover ray origin and direction
|
---|
712 | rays[i].mOrigin = orig[i];
|
---|
713 | rays[i].mDirection = dirs[i];
|
---|
714 | } // for
|
---|
715 |
|
---|
716 | } // dynamic objects
|
---|
717 |
|
---|
718 | // ??? What to do with the results ? These are
|
---|
719 | // not used at the moment also in IntelRayCaster.cpp
|
---|
720 | } // for
|
---|
721 |
|
---|
722 |
|
---|
723 | i = 0;
|
---|
724 | int k2 = k;
|
---|
725 | for (; k < rays.size(); k++, i++) {
|
---|
726 | //double normal[3];
|
---|
727 | // Intersect with the static scene
|
---|
728 | bool result = mKtbtree->FindNearestI(rays[k]);
|
---|
729 | tdist[i] = SimpleRay::IntersectionRes[0].tdist;
|
---|
730 | objI[i] = SimpleRay::IntersectionRes[0].intersectable;
|
---|
731 |
|
---|
732 | if (dynamicFlag) {
|
---|
733 | orig[i] = rays[k].mOrigin;
|
---|
734 | dirs[i] = rays[k].mDirection;
|
---|
735 |
|
---|
736 | // Intersect with the dynamic object
|
---|
737 | ApplyTransform(rays[k]);
|
---|
738 | bool result2 = false;
|
---|
739 | if (mDynKtbtree->FindNearestI(rays[k])) {
|
---|
740 | float t = SimpleRay::IntersectionRes[0].tdist;
|
---|
741 | if ( ((objI[i]) && (t < tdist[i])) ||
|
---|
742 | (!objI[i]) ) {
|
---|
743 | // There is an intersection closer than the previous one
|
---|
744 | result2 = true;
|
---|
745 | objI[i] = SimpleRay::IntersectionRes[0].intersectable;
|
---|
746 | tdist[i] = t;
|
---|
747 | }
|
---|
748 | }
|
---|
749 |
|
---|
750 | // recover ray origin and direction
|
---|
751 | rays[k].mOrigin = orig[i];
|
---|
752 | rays[k].mDirection = dirs[i];
|
---|
753 | } // dynamic objects
|
---|
754 |
|
---|
755 | // ??? What to do with the results ? These are
|
---|
756 | // not used at the moment also in IntelRayCaster.cpp
|
---|
757 | }
|
---|
758 | // The result will be in the array
|
---|
759 | i = 0;
|
---|
760 | for (; k2 < rays.size(); k2++, i++) {
|
---|
761 | SimpleRay::IntersectionRes[i].intersectable = objI[i];
|
---|
762 | SimpleRay::IntersectionRes[i].tdist = tdist[i];
|
---|
763 | }
|
---|
764 | #endif // USE_HAVRAN_RAYCASTER
|
---|
765 |
|
---|
766 | return;
|
---|
767 | }
|
---|
768 |
|
---|
769 | void HavranDynRayCaster::CastRays(
|
---|
770 | SimpleRayContainer &rays,
|
---|
771 | VssRayContainer &vssRays,
|
---|
772 | const AxisAlignedBox3 &sbox,
|
---|
773 | const bool castDoubleRay,
|
---|
774 | const bool pruneInvalidRays )
|
---|
775 | {
|
---|
776 | int buckets = (int)rays.size()/16;
|
---|
777 | int offset = 0;
|
---|
778 |
|
---|
779 | #if 0
|
---|
780 | int time = GetTime();
|
---|
781 | CastSimpleForwardRays(rays, sbox);
|
---|
782 | cout<<1e-3*2*rays.size()/TimeDiff(time, GetTime())<<" Mrays/sec"<<endl;
|
---|
783 | #endif
|
---|
784 |
|
---|
785 | // Cast only by 16 rays at once
|
---|
786 | for (int i=0; i < buckets; i++, offset+=16) {
|
---|
787 | CastRays16(rays, offset, vssRays, sbox,
|
---|
788 | castDoubleRay, pruneInvalidRays);
|
---|
789 |
|
---|
790 | if ((int)rays.size() > 100000 && i % (100000/16) == 0)
|
---|
791 | cout<<"\r"<<offset<<"/"<<(int)rays.size()<<"\r";
|
---|
792 | }
|
---|
793 |
|
---|
794 | // Cast the rest of the rays
|
---|
795 | for (; offset < (int)rays.size(); offset++)
|
---|
796 | CastRay(rays[offset], vssRays, sbox, castDoubleRay, pruneInvalidRays);
|
---|
797 |
|
---|
798 | return;
|
---|
799 | }
|
---|
800 |
|
---|
801 | #ifdef _USE_HAVRAN_SSE
|
---|
802 | // BUG1 41579 196948 1064111
|
---|
803 | // BUG2 254 1672 10869
|
---|
804 |
|
---|
805 | // Just for testing concept
|
---|
806 | void
|
---|
807 | HavranDynRayCaster::CastRaysPacket2x2(RayPacket2x2 &raysPack,
|
---|
808 | bool castDoubleRay,
|
---|
809 | const bool pruneInvalidRays)
|
---|
810 | {
|
---|
811 | #ifdef USE_HAVRAN_RAYCASTER
|
---|
812 |
|
---|
813 | if (castDoubleRay) {
|
---|
814 | // cast forward rays
|
---|
815 | mKtbtree->FindNearestI(raysPack);
|
---|
816 |
|
---|
817 | if (dynamicFlag) {
|
---|
818 | // The ray pack to be transformed
|
---|
819 | raypack_t = raysPack;
|
---|
820 | raypack.ApplyTransform(matTr_inv);
|
---|
821 |
|
---|
822 | mDynKtbtree->FindNearestI(raypack_t);
|
---|
823 |
|
---|
824 | for (int i = 0; i < 4; i++) {
|
---|
825 | // if ray intersects an object, we set the pointer to
|
---|
826 | // this object
|
---|
827 | Intersectable* intersectable = raypack_t.GetObject(i);
|
---|
828 | if (intersectable) {
|
---|
829 | Intersectable *o = raysPack.GetObject(i);
|
---|
830 | if ( ((o) && (raypack_t.GetT(i) < tdist[i])) ||
|
---|
831 | (!o) ) {
|
---|
832 | // update, dynamic object is closer
|
---|
833 | raysPack.SetT(i, raypack_t.GetT(i));
|
---|
834 | raysPack.SetObject(i, raypack_t.GetObject(i));
|
---|
835 | } // if update is required
|
---|
836 | } // if intersectable
|
---|
837 | } // for i
|
---|
838 | } // dynamic object
|
---|
839 |
|
---|
840 | // Double (=opposite) direction
|
---|
841 | for (int i = 0; i < 4; i++)
|
---|
842 | raysPack.SetDir(i, -raysPack.GetDir(i));
|
---|
843 | // cast backward rays
|
---|
844 | mKtbtree->FindNearestI(raysPack);
|
---|
845 |
|
---|
846 | if (dynamicFlag) {
|
---|
847 |
|
---|
848 | // The ray pack to be transformed
|
---|
849 | raypack_t = raysPack;
|
---|
850 | raypack_t.ApplyTransform(matTr_inv);
|
---|
851 |
|
---|
852 | mDynKtbtree->FindNearestI(raypack_t);
|
---|
853 |
|
---|
854 | for (int i = 0; i < 4; i++) {
|
---|
855 | // if ray intersects an object, we set the pointer to
|
---|
856 | // this object
|
---|
857 | Intersectable* intersectable = raypack_t.GetObject(i);
|
---|
858 | if (intersectable) {
|
---|
859 | Intersectable *o = raysPack.GetObject(i);
|
---|
860 | if ( ((o) && (raypack_t.GetT(i) < tdist[i])) ||
|
---|
861 | (!o) ) {
|
---|
862 | // update, dynamic object is closer
|
---|
863 | raysPack.SetT(i, raypack_t.GetT(i));
|
---|
864 | raysPack.SetObject(i, raypack_t.GetObject(i));
|
---|
865 | } // if update is required
|
---|
866 | } // if intersectable
|
---|
867 | } // for i
|
---|
868 | } // dynamic object
|
---|
869 |
|
---|
870 | // reverse the rays back
|
---|
871 | for (int i = 0; i < 4; i++)
|
---|
872 | raysPack.SetDir(i, -raysPack.GetDir(i));
|
---|
873 | }
|
---|
874 | else {
|
---|
875 | // ONLY forward rays - TESTED 21/1/2007 VH
|
---|
876 |
|
---|
877 | mKtbtree->FindNearestI(raysPack);
|
---|
878 |
|
---|
879 | if (dynamicFlag) {
|
---|
880 | // The ray pack to be transformed
|
---|
881 | raypack_t = raysPack;
|
---|
882 | raypack_t.ApplyTransform(matTr_inv);
|
---|
883 |
|
---|
884 | mDynKtbtree->FindNearestI(raypack_t);
|
---|
885 |
|
---|
886 | for (int i = 0; i < 4; i++) {
|
---|
887 | // if ray intersects an object, we set the pointer to
|
---|
888 | // this object
|
---|
889 | Intersectable* intersectable = raypack_t.GetObject(i);
|
---|
890 | if (intersectable) {
|
---|
891 | Intersectable *o = raysPack.GetObject(i);
|
---|
892 | if ( ((o) && (raypack_t.GetT(i) < tdist[i])) ||
|
---|
893 | (!o) ) {
|
---|
894 | // update, dynamic object is closer
|
---|
895 | raysPack.SetT(i, raypack_t.GetT(i));
|
---|
896 | raysPack.SetObject(i, raypack_t.GetObject(i));
|
---|
897 | } // if update is required
|
---|
898 | } // if intersectable
|
---|
899 | } // for i
|
---|
900 | } // dynamic object
|
---|
901 |
|
---|
902 | #if 0
|
---|
903 | // Only verification of correctness by casting single rays
|
---|
904 | static int cntBugs = 0;
|
---|
905 | SimpleRay ray;
|
---|
906 | int cntErrors = 0, cntDistErrors = 0;
|
---|
907 | bool newBug = false;
|
---|
908 | for (int i = 0; i < 4; i++) {
|
---|
909 | ray.mOrigin = raysPack.GetLoc(i);
|
---|
910 | ray.mDirection = raysPack.GetDir(i);
|
---|
911 | mKtbtree->FindNearestI(ray);
|
---|
912 | if (raysPack.GetObject(i) != SimpleRay::IntersectionRes[0].intersectable) {
|
---|
913 | float dist = (raysPack.GetT(i) - SimpleRay::IntersectionRes[0].tdist);
|
---|
914 | if (fabs(dist) > 0.001f) {
|
---|
915 | cntErrors++; newBug = true;
|
---|
916 | cntBugs++;
|
---|
917 | cout << " BUG1 d= " << dist;
|
---|
918 | }
|
---|
919 | }
|
---|
920 | else {
|
---|
921 | float dist = 0.f;
|
---|
922 | if (raysPack.GetObject(i) && SimpleRay::IntersectionRes[0].intersectable)
|
---|
923 | if (fabs((dist=(fabs (raysPack.GetT(i) - SimpleRay::IntersectionRes[0].tdist)))) > 1.f) {
|
---|
924 | cntDistErrors++; newBug = true; cntBugs++;
|
---|
925 | cout << " BUG2 distdf= " << dist ;
|
---|
926 | }
|
---|
927 | }
|
---|
928 | } // for
|
---|
929 | if (newBug) cout << " CB= " << cntBugs << "\n";
|
---|
930 | #endif
|
---|
931 | }
|
---|
932 |
|
---|
933 | return;
|
---|
934 |
|
---|
935 | #endif // USE_HAVRAN_RAYCASTER
|
---|
936 |
|
---|
937 | }
|
---|
938 | #endif // _USE_HAVRAN_SSE
|
---|
939 |
|
---|
940 |
|
---|
941 | } // the namespace
|
---|
942 |
|
---|