Changeset 2592 for GTP/trunk/Lib/Vis/Preprocessing/src
- Timestamp:
- 01/14/08 15:54:15 (17 years ago)
- Location:
- GTP/trunk/Lib/Vis/Preprocessing/src
- Files:
-
- 20 edited
Legend:
- Unmodified
- Added
- Removed
-
GTP/trunk/Lib/Vis/Preprocessing/src/HavranRayCaster.cpp
r2588 r2592 6 6 7 7 8 #include "HavranRayCaster.h"9 8 #include "VssRay.h" 10 9 #include "KdTree.h" … … 13 12 14 13 #ifdef USE_HAVRAN_RAYCASTER 14 #include "ktbconf.h" 15 15 #include "timer.h" 16 16 #include "ktball.h" 17 17 #include "ktb.h" 18 #ifdef _USE_HAVRAN_SSE 19 18 20 #include "raypack.h" 21 #endif // _USE_HAVRAN_SSE 19 22 #endif // USE_HAVRAN_RAYCASTER 23 #include "HavranRayCaster.h" 20 24 21 25 #define DEBUG_RAYCAST 0 22 26 27 // This macro should be undefined when testing ray tracing 28 // by casting rays from file or using camera 29 #define _PROCESS_RAY 30 23 31 namespace GtpVisibilityPreprocessor { 24 32 25 33 26 34 #ifdef USE_HAVRAN_RAYCASTER 35 #ifdef _USE_HAVRAN_SSE 36 27 37 // static rays 28 38 RayPacket2x2 29 39 HavranRayCaster::raypack; 40 #endif // _USE_HAVRAN_SSE 30 41 #endif // USE_HAVRAN_RAYCASTER 31 42 … … 65 76 } 66 77 67 78 bool 79 HavranRayCaster::ExportBinTree(const string &filename) 80 { 81 return mKtbtree->ExportBinTree(filename); 82 } 83 84 bool 85 HavranRayCaster::ImportBinTree(const string &filename, ObjectContainer &objects) 86 { 87 return mKtbtree->ImportBinTree(filename, objects); 88 } 89 90 68 91 // Using packet of 4 rays supposing that these are coherent 69 92 // We give a box to which each ray is clipped to before the 70 93 // ray shooting is computed ! 71 94 void HavranRayCaster::CastRaysPacket4(Vector3 &boxmax, 72 Vector3 &boxmin, 73 Vector3 origin4[], 74 Vector3 direction4[], 75 int result4[], 76 float dist4[]) 77 { 95 Vector3 &boxmin, 96 Vector3 origin4[], 97 Vector3 direction4[], 98 int result4[], 99 float dist4[]) 100 { 101 #ifdef _USE_HAVRAN_SSE 78 102 #ifdef USE_HAVRAN_RAYCASTER 79 103 for (int i = 0; i < 4; i++) { … … 92 116 // this object 93 117 Intersectable* intersectable; 94 if ( (intersectable = raypack.GetObject(i)) ) 95 // $$JB this is very hacky - > should be replaced with fetching the index of the triangle 96 result4[i] = (int)intersectable; 118 if ( (intersectable = raypack.GetObject(i)) ) { 119 // $$JB this is very hacky - > should be replaced with fetching the index of the triangle 120 result4[i] = intersectable->mId; 121 dist4[i] = raypack.GetT(i); 122 } 97 123 } 98 124 99 125 return; 100 #endif 101 } 126 #endif // USE_HAVRAN_RAYCASTER 127 #else // _USE_HAVRAN_SSE 128 // Compute the result ray by ray 129 SimpleRay sray; 130 for (int i = 0; i < 4; i++) { 131 sray.mOrigin = origin4[i]; 132 sray.mDirection = direction4[i]; 133 mKtbtree->FindNearestI(sray, boxmin, boxmax); 134 if (SimpleRay::IntersectionRes[0].intersectable) { 135 // This is object ID - is this the triangle index ??? 136 result4[i] = SimpleRay::IntersectionRes[0].intersectable->mId; 137 dist4[i] = SimpleRay::IntersectionRes[0].tdist; 138 } 139 else { 140 result4[i] = -1; // no intersection 141 } 142 } // for i; 143 144 #endif // _USE_HAVRAN_SSE 145 } 146 102 147 103 148 int HavranRayCaster::CastRay(const SimpleRay &simpleRay, … … 124 169 125 170 // ray.mFlags &= ~Ray::CULL_BACKFACES; 126 127 if ( mKtbtree->FindNearestI(simpleRay)) {171 bool result; 172 if ((result = mKtbtree->FindNearestI(simpleRay))) { 128 173 hitA.mObject = SimpleRay::IntersectionRes[0].intersectable; 129 174 float tdist = SimpleRay::IntersectionRes[0].tdist; … … 151 196 } 152 197 198 #ifdef _PROCESS_RAY 153 199 // This code is also in IntelRayCaster.cpp 154 200 return ProcessRay( … … 161 207 pruneInvalidRays 162 208 ); 163 #else // USE_HAVRAN_RAYCASTER 209 #else // _PROCESS_RAY 210 return result; 211 #endif // _PROCESS_RAY 212 213 #else 164 214 return 0; 165 #endif 215 #endif // USE_HAVRAN_RAYCASTER 166 216 } 167 217 … … 190 240 191 241 #if 0 192 SimpleRayContainer::const_iterator sit = rays.begin() + offset;193 SimpleRayContainer::const_iterator sit _end = sit + 16;194 242 // This is shooting ray by ray 243 SimpleRayContainer::const_iterator sit, sit_end = rays.end(); 244 195 245 // no acceleration for ray bundles implemented right now 196 246 for (sit = rays.begin(); sit != sit_end; ++ sit) … … 199 249 } 200 250 #else 251 // Use special algorithm for 16 rays at once 201 252 if (castDoubleRays) { 202 #if 0 253 254 #if 0 // ------------------------------------------------ 203 255 // Special routine to cast double sided rays 204 256 mKtbtree->SetOffset(0); 257 #ifdef _USE_HAVRAN_SSE 205 258 mKtbtree->FindNearestI_16twoDir(rays); 206 259 #else 260 mKtbtree->FindNearestI_16twoDirNoSSE(rays); 261 #endif 262 #else // ------------------------------------------------- 207 263 // Here we decompose shooting into two phases 208 #if 1 209 // Here we shoot first forward rays and then backward ones 210 mKtbtree->SetOffset(0); 211 mKtbtree->FindNearestI_16oneDir(rays, offset); 212 SimpleRayContainer::iterator sit = rays.begin() + offset; 213 SimpleRayContainer::const_iterator sit_end = rays.begin() + offset + 16; 214 for (; sit != sit_end; ++ sit) 215 { 216 (*sit).mDirection = - (*sit).mDirection; 217 } 218 // We store the results at different place 219 mKtbtree->SetOffset(16); 220 mKtbtree->FindNearestI_16oneDir(rays, offset); 221 sit = rays.begin() + offset; 222 for ( ; sit != sit_end; ++ sit) 223 { 224 (*sit).mDirection = - (*sit).mDirection; 225 } 226 #else 264 227 265 // Here we shoot first backward rays and forward ones 228 266 SimpleRayContainer::iterator sit = rays.begin() + offset; … … 232 270 (*sit).mDirection = - (*sit).mDirection; 233 271 } 234 // backward rays to be shot 272 // backward rays to be shot - saving with offset 16 273 #ifdef _USE_HAVRAN_SSE 274 mKtbtree->SetOffset(0); 275 mKtbtree->FindNearestI_16oneDir(rays, offset, 16); 276 #else 235 277 mKtbtree->SetOffset(16); 236 mKtbtree->FindNearestI_16oneDir(rays, offset); 278 mKtbtree->FindNearestI_16oneDirNoSSE(rays, offset); 279 #endif // _USE_HAVRAN_SSE 237 280 sit = rays.begin() + offset; 238 281 for ( ; sit != sit_end; ++ sit) … … 241 284 } 242 285 // forward rays to be shot 286 #ifdef _USE_HAVRAN_SSE 243 287 mKtbtree->SetOffset(0); 244 mKtbtree->FindNearestI_16oneDir(rays, offset); 245 #endif 246 #endif 247 } 288 mKtbtree->FindNearestI_16oneDir(rays, offset, 0); 289 #else 290 mKtbtree->SetOffset(0); 291 mKtbtree->FindNearestI_16oneDirNoSSE(rays, offset); 292 #endif // _USE_HAVRAN_SSE 293 #endif // ------------------------------------------------ 294 } // cast double rays 248 295 else { 296 // ONLY single rays 249 297 // Shoot all 16 rays at the same time using a special algorithm 250 298 mKtbtree->SetOffset(0); 251 mKtbtree->FindNearestI_16oneDir(rays, offset); 252 } 253 #endif 254 299 #ifdef _USE_HAVRAN_SSE 300 mKtbtree->FindNearestI_16oneDir(rays, offset, 0); 301 #else 302 mKtbtree->FindNearestI_16oneDirNoSSE(rays, offset); 303 #endif // _USE_HAVRAN_SSE 304 } 305 #endif 306 255 307 256 308 for (int i=0, k=offset; i < 16; i++, k++) … … 282 334 { 283 335 Intersectable *intersect = 284 336 SimpleRay::IntersectionRes[i+16].intersectable; 285 337 286 338 if (intersect) 287 339 { 288 hitB.mObject = intersect; 289 hitB.mNormal = intersect->GetNormal(0); 290 // $$ JB : i -> i+16 291 float tdist = SimpleRay::IntersectionRes[i+16].tdist; 292 hitB.mPoint = rays[k].Extrap(-tdist); 340 hitB.mObject = intersect; 341 hitB.mNormal = intersect->GetNormal(0);; 342 float tdist = SimpleRay::IntersectionRes[16+i].tdist; 343 hitB.mPoint = rays[k].Extrap(-tdist); 293 344 } 294 345 } … … 298 349 #endif 299 350 300 #if 1351 #ifdef _PROCESS_RAY 301 352 ProcessRay(rays[k], 302 303 304 305 306 307 308 353 hitA, 354 hitB, 355 vssRays, 356 sbox, 357 castDoubleRays, 358 pruneInvalidRays 359 ); 309 360 #endif 310 361 } // for … … 340 391 for (i=0; i < packets; i++) { 341 392 int offset = i * 16; 342 mKtbtree->FindNearestI_16oneDir(rays, offset );393 mKtbtree->FindNearestI_16oneDir(rays, offset, 0); 343 394 // ??? What to do with the results ? These are 344 395 // not used at the moment also in IntelRayCaster.cpp … … 372 423 cout<<1e-3*2*rays.size()/TimeDiff(time, GetTime())<<" Mrays/sec"<<endl; 373 424 #endif 374 425 426 // Cast only by 16 rays at once 375 427 for (int i=0; i < buckets; i++, offset+=16) { 376 428 CastRays16(rays, offset, vssRays, sbox, … … 381 433 } 382 434 435 // Cast the rest of the rays 383 436 for (; offset < (int)rays.size(); offset++) 384 437 CastRay(rays[offset], vssRays, sbox, castDoubleRay, pruneInvalidRays); 385 } 386 387 #if 0 438 439 return; 440 } 441 442 #ifdef _USE_HAVRAN_SSE 388 443 // BUG1 41579 196948 1064111 389 444 // BUG2 254 1672 10869 … … 392 447 void 393 448 HavranRayCaster::CastRaysPacket2x2(RayPacket2x2 &raysPack, 394 bool castDoubleRay, 395 const bool pruneInvalidRays) 396 { 397 #ifdef USE_HAVRAN_RAYCASTER 449 bool castDoubleRay, 450 const bool pruneInvalidRays) 451 { 452 #ifdef USE_HAVRAN_RAYCASTER 453 #ifdef _USE_HAVRAN_SSE 398 454 399 455 if (castDoubleRay) { … … 443 499 444 500 return; 501 #endif // _USE_HAVRAN_SSE 445 502 #endif // USE_HAVRAN_RAYCASTER 446 503 } 447 #endif 504 #endif // _USE_HAVRAN_SSE 448 505 449 506 -
GTP/trunk/Lib/Vis/Preprocessing/src/HavranRayCaster.h
r2582 r2592 5 5 #include "Containers.h" 6 6 #include <string> 7 #include " havran/raypack.h"8 7 #include "ktbconf.h" 8 #include "raypack.h" 9 9 10 10 namespace GtpVisibilityPreprocessor { … … 15 15 class KdTree; 16 16 class Ray; 17 class RayPacket2x2;18 17 class SimpleRayContainer; 19 18 class AxisAlignedBox3; … … 38 37 39 38 int Type() const { return HAVRAN_RAYCASTER; } 40 41 // Using packet of 4 rays supposing that these are coherent42 // We give a box to which each ray is clipped to before the43 // ray shooting is computed !44 virtual void CastRaysPacket4(Vector3 &minBox,45 Vector3 &maxBox,46 Vector3 origin4[],47 Vector3 direction4[],48 int result4[],49 float dist4[]);50 39 51 40 virtual int CastRay( … … 82 71 const bool castDoubleRay, 83 72 const bool pruneInvalidRays = true); 73 74 // Using packet of 4 rays supposing that these are coherent 75 // We give a box to which each ray is clipped to before the 76 // ray shooting is computed ! 77 virtual void CastRaysPacket4(Vector3 &minBox, 78 Vector3 &maxBox, 79 Vector3 origin4[], 80 Vector3 direction4[], 81 int result4[], 82 float dist4[]); 83 84 #ifdef _USE_HAVRAN_SSE 85 // Just for testing concept 86 virtual void CastRaysPacket2x2(RayPacket2x2 &raysPack, 87 bool castDoubleRay, 88 const bool pruneInvalidRays = true); 89 #endif 90 91 bool ExportBinTree(const string &filename); 92 bool ImportBinTree(const string &filename, ObjectContainer &objects); 93 84 94 protected: 85 95 CKTB *mKtbtree; -
GTP/trunk/Lib/Vis/Preprocessing/src/Makefile
r2589 r2592 1 1 ############################################################################# 2 2 # Makefile for building: preprocessor 3 # Generated by qmake (2.00a) (Qt 4.1.2) on: ?t 10. I 13:25:3820083 # Generated by qmake (2.00a) (Qt 4.1.2) on: po 14. I 15:10:11 2008 4 4 # Project: preprocessor.pro 5 5 # Template: app … … 63 63 $(MAKE) -f $(MAKEFILE).Debug uninstall 64 64 65 Makefile: preprocessor.pro C:/Qt/4.1.2/mkspecs/win32-msvc 2005\qmake.conf C:/Qt/4.1.2/mkspecs/qconfig.pri \65 Makefile: preprocessor.pro C:/Qt/4.1.2/mkspecs/win32-msvc.net\qmake.conf C:/Qt/4.1.2/mkspecs/qconfig.pri \ 66 66 C:\Qt\4.1.2\mkspecs\features\qt_config.prf \ 67 67 C:\Qt\4.1.2\mkspecs\features\exclusive_builds.prf \ -
GTP/trunk/Lib/Vis/Preprocessing/src/Mutation.cpp
r2590 r2592 94 94 95 95 Intersectable *oldObject = mRays[vssRays[i]->mGeneratorId].mRay->mTerminationObject; 96 96 // the ray generated a contribution although it hits the same object 97 // mark this using a counter 97 98 if (oldObject == newObject) 98 99 dummyCMutations++; … … 106 107 mRays.push_back(RayEntry(newRay)); 107 108 } else { 108 // unref the old ray 109 // unref the old ray and add the new ray into the mutation buffer 109 110 *mRays[mBufferStart].mRay = *vssRays[i]; 110 111 mRays[mBufferStart].mMutations = 0; … … 117 118 } 118 119 } else { 120 // the ray did not generate any contribution 119 121 if (vssRays[i]->mDistribution == MUTATION_BASED_DISTRIBUTION && 120 122 vssRays[i]->mGeneratorId != -1 121 123 ) { 122 124 // check whether not to store a new backward mutation candidate 125 // this happens if the new ray is occluded significantly closer than 126 // the generator ray 123 127 VssRay *oldRay = mRays[vssRays[i]->mGeneratorId].mRay; 124 128 VssRay *newRay = vssRays[i]; 125 129 126 127 130 Intersectable *oldObject = oldRay->mTerminationObject; 128 129 131 132 // only allow one reverse mutation per generator ray 130 133 if (!mRays[newRay->mGeneratorId].HasReverseMutation()) { 131 134 if (DotProd(oldRay->GetDir(), newRay->GetDir()) > 0.0f) { … … 149 152 Intersectable *newObject = vssRays[i]->mTerminationObject; 150 153 151 152 154 if (oldObject == newObject) 153 155 dummyNcMutations++; … … 163 165 cout<<"Dummy NC mutations ratio:"<<100.0f*dummyNcMutations/(float)mutationRays<<"%"<<endl; 164 166 cout<<"Dummy C mutations ratio:"<<100.0f*dummyCMutations/(float)mutationRays<<"%"<<endl; 165 cout<<"Reverse candidates:"<< reverseCandidates<<endl;167 cout<<"Reverse candidates:"<<100.0f*reverseCandidates/(float)mutationRays<<endl; 166 168 } 167 169 168 170 float pContributingRays = contributingRays/(float)vssRays.size(); 169 171 170 cout<<" Percentageof contributing rays:"<<pContributingRays<<endl;172 cout<<"Ratio of contributing rays:"<<pContributingRays<<endl; 171 173 172 174 if (mUseUnsuccCountImportance) { … … 233 235 ) 234 236 { 235 #if 0236 Vector3 v;237 if (d.DrivingAxis() == 0)238 v = Vector3(0, r[0]-0.5f, r[1]-0.5f);239 else240 if (d.DrivingAxis() == 1)241 v = Vector3(r[0]-0.5f, 0, r[1]-0.5f);242 else243 v = Vector3(r[0]-0.5f, r[1]-0.5f, 0);244 return v*(2*radius);245 #endif246 237 #if 0 247 238 return (U*(r[0] - 0.5f) + V*(r[1] - 0.5f))*(2*radius); … … 339 330 340 331 AxisAlignedBox3 box = occluder->GetBox(); 332 // consider slightly larger neighborhood of the occluder 333 // in search for unocclude reverse ray 341 334 box.Scale(2.0f); 342 335 … … 430 423 } 431 424 425 return true; 432 426 #else 433 427 cerr << "warning: reverse mutation not supported!" << endl; 434 #endif 435 436 return true;428 return false; 429 #endif 430 437 431 438 432 // now the origin and termination is swapped compred to the generator ray … … 510 504 511 505 #else 512 513 506 //cerr << "warning: shiluette mutation not supported" << endl; 507 return Vector3(0, 0, 0); 514 508 #endif 515 509 … … 523 517 if (mRays.size() == 0) { 524 518 float rr[5]; 525 // use direction based distribution 519 // use direction based distribution until we have some mutation candidates 526 520 Vector3 origin, direction; 527 521 … … 532 526 Vector3(rr[0], rr[1], rr[2])); 533 527 534 528 535 529 direction = UniformRandomVector(rr[3], rr[4]); 536 530 … … 538 532 sray = SimpleRay(origin, direction, MUTATION_BASED_DISTRIBUTION, pdf); 539 533 sray.mGeneratorId = -1; 540 534 541 535 return true; 542 } 536 } 543 537 544 538 int index; … … 552 546 if ( 553 547 mRays[index].GetSamplingFactor() >= mRays[mLastIndex].GetSamplingFactor()) { 554 // make another round 548 // make another round to equalize the oversampling factor 555 549 556 550 // cout<<"R2"<<endl; … … 666 660 667 661 if (mUseSilhouetteSamples && a < mSilhouetteProb) { 668 669 662 termination += ComputeSilhouetteTerminationMutation(*ray, 670 663 origin, … … 692 685 693 686 // shift the origin a little bit 687 #if 1 694 688 origin += direction*0.5f; 689 #else 690 // $$JB - 14.1. 2008 increase shift to test HavranRayCaster 691 origin = 0.5f*(origin + termination); 692 #endif 695 693 696 694 direction.Normalize(); … … 718 716 mRays[index].mMutations++; 719 717 mRays[index].mUnsuccessfulMutations++; 720 721 718 return true; 722 719 } -
GTP/trunk/Lib/Vis/Preprocessing/src/Preprocessor.cpp
r2590 r2592 1230 1230 if ( 1231 1231 rays.size() > 10000) 1232 {1232 { 1233 1233 1234 1234 mRayCaster->SortRays(rays); 1235 //cout<<"Rays sorted in "<<TimeDiff(t1, GetTime())<<" ms."<<endl;1235 cout<<"Rays sorted in "<<TimeDiff(t1, GetTime())<<" ms."<<endl; 1236 1236 } 1237 1237 -
GTP/trunk/Lib/Vis/Preprocessing/src/RayCaster.cpp
r2583 r2592 178 178 //const int batchsize = 16384; 179 179 const int batchsize = 8192; 180 // const int batchsize = 1024; 180 181 //const int batchsize = 128; 181 182 -
GTP/trunk/Lib/Vis/Preprocessing/src/default.env
r2588 r2592 53 53 useGlDebugger false 54 54 # 0 = INTERNAL 1 = MLRT 2 = HAVRAN 55 rayCastMethod 155 rayCastMethod 2 56 56 57 57 # type sampling -
GTP/trunk/Lib/Vis/Preprocessing/src/havran/configh.h
r2582 r2592 59 59 60 60 #ifdef _MSC_VER 61 #define __SSE__ 61 62 // disable some Microsoft Visual Compiler warnings if necessary 62 63 #pragma warning( disable:4305 ) -
GTP/trunk/Lib/Vis/Preprocessing/src/havran/ktb.cpp
r2582 r2592 61 61 float tclosest = Limits::Infinity; 62 62 int intersected = 0; 63 // rayIndex += rayOffset; 63 64 // iterate the whole list and find out the nearest intersection 64 65 for (ObjectContainer::iterator sc = list->begin(); sc != sc_end; sc++) { … … 352 353 } 353 354 355 // Set the pointers to children for the interior node 356 void 357 CKTBAllocMan::SetInteriorNodeLeft(SKTBNodeT *node, 358 SKTBNodeT *leftChild) 359 { 360 leftChild = leftChild; // to satisfy the compiler 361 362 // Check on correctness of DFS order 363 assert( (node+1 == leftChild) || (node+2 == leftChild) || (node+4 == leftChild) ); 364 } 365 366 // Set the pointers to children for the interior node 367 void 368 CKTBAllocMan::SetInteriorNodeRight(SKTBNodeT *node, 369 SKTBNodeT *rightChild) 370 { 371 node->right = rightChild; 372 } 373 374 354 375 // Create the representation of the leaf. Note that possibly there 355 376 // can be special cases, such as 0, 1, 2, or 3 objects, or in general -
GTP/trunk/Lib/Vis/Preprocessing/src/havran/ktb.h
r2582 r2592 156 156 #endif 157 157 158 // init the stack of auxiliary variables from min to max159 virtual void InitAux(int min, int max, int maxItemsAtOnce);160 161 158 // the direction of traversal through CKTB tree 162 159 enum EDirection { LEFT = 0, RIGHT = 1, NOWHERE = 2 }; … … 180 177 virtual ~CKTBAllocMan() { } 181 178 179 // init the stack of auxiliary variables from min to max 180 virtual void InitAux(int min, int max, int maxItemsAtOnce); 181 182 182 // forget the content that is created by previous kd-tree construction 183 183 // or just init for the first use. … … 224 224 void SetInteriorNodeLinks(SKTBNodeT *node, 225 225 SKTBNodeT *leftChild, 226 SKTBNodeT *rightChild); 227 void SetInteriorNodeLeft(SKTBNodeT *node, 228 SKTBNodeT *leftChild); 229 void SetInteriorNodeRight(SKTBNodeT *node, 226 230 SKTBNodeT *rightChild); 227 231 -
GTP/trunk/Lib/Vis/Preprocessing/src/havran/ktb8b.cpp
r2582 r2592 63 63 float tclosest = Limits::Infinity; 64 64 int intersected = 0; 65 //indexRay += rayOffset;65 indexRay += rayOffset; 66 66 // iterate the whole list and find out the nearest intersection 67 67 for (ObjectContainer::iterator sc = list->begin(); sc != sc_end; sc++) { … … 76 76 return intersected; 77 77 } 78 79 78 80 79 // test all objects in the leaf for intersection with ray … … 244 243 CKTB8BAllocMan::AllocInteriorNodeWithBox(int axis, float position, 245 244 int cntLeft, int cntRight, 246 const SBBox &tsbox, SKTBNodeT* prevMinBoxNode, 245 const SBBox &tsbox, 246 SKTBNodeT* prevMinBoxNode, 247 247 int depthStore) 248 248 { … … 354 354 leftChild = leftChild; // to satisfy the compiler 355 355 356 #if 1 357 if (! ((node+1 == leftChild) || (node+2 == leftChild) || 358 (node+5 == leftChild))) { 359 360 cout << "Problem with left node linking " << endl; 361 } 362 363 #endif 356 364 // Check on correctness of DFS order 357 365 assert( (node+1 == leftChild) || (node+2 == leftChild) || (node+5 == leftChild) ); … … 390 398 } 391 399 400 // Set the pointers to children for the interior node 401 void 402 CKTB8BAllocMan::SetInteriorNodeLeft(SKTBNodeT *node, 403 SKTBNodeT *leftChild) 404 { 405 leftChild = leftChild; // to satisfy the compiler 406 407 #if 1 408 if (! ((node+1 == leftChild) || (node+2 == leftChild) || 409 (node+5 == leftChild))) { 410 411 cout << "Problem with left node linking " << endl; 412 abort(); 413 } 414 415 #endif 416 // Check on correctness of DFS order 417 assert( (node+1 == leftChild) || (node+2 == leftChild) || (node+5 == leftChild) ); 418 419 // Nothing to do - left link is linked automatically 420 return; 421 } 422 423 // Set the pointers to children for the interior node 424 void 425 CKTB8BAllocMan::SetInteriorNodeRight(SKTBNodeT *node, 426 SKTBNodeT *rightChild) 427 { 428 assert(node->offset <= CKTBAxes::EE_Z_axisBox); 429 //assert(node->offset >= 0); 430 //(unsigned long)node->offset |= (unsigned long)rightChild; 431 node->offset = node->offset | (unsigned int)rightChild; 432 #ifdef _DEBUG 433 // Compute right child 434 SKTBNodeT *p = GetRight(node); 435 if (p != rightChild) { 436 cerr << "Problem with implementation of setting right child" << endl; 437 abort();; 438 } 439 #endif 440 441 return; 442 } 443 444 392 445 // Create the representation of the leaf. Note that possibly there 393 446 // can be special cases, such as 0, 1, 2, or 3 objects, or in general -
GTP/trunk/Lib/Vis/Preprocessing/src/havran/ktb8b.h
r2582 r2592 161 161 #endif 162 162 163 // init the stack of auxiliary variables from min to max164 void InitAux(int min, int max, int maxItemsAtOnce);165 166 163 // the direction of traversal through CKTB tree 167 164 enum EDirection { LEFT = 0, RIGHT = 1, NOWHERE = 2 }; … … 185 182 ~CKTB8BAllocMan() { } 186 183 184 // init the stack of auxiliary variables from min to max 185 void InitAux(int min, int max, int maxItemsAtOnce); 186 187 187 // forget the content that is created by previous kd-tree construction 188 188 // or just init for the first use. … … 232 232 void SetInteriorNodeLinks(SKTBNodeT *node, 233 233 SKTBNodeT *leftChild, 234 SKTBNodeT *rightChild); 235 236 void SetInteriorNodeLeft(SKTBNodeT *node, 237 SKTBNodeT *leftChild); 238 void SetInteriorNodeRight(SKTBNodeT *node, 234 239 SKTBNodeT *rightChild); 235 240 … … 275 280 void DecDepth() {_currDepth--;} 276 281 282 277 283 // -------------------------------------------------------------- 278 284 // Statistics … … 300 306 float _sumSurfaceAreaInteriorNodes; 301 307 #endif 302 308 303 309 // General statistics on the depth of current node 304 310 // the depth of the currently accessed node during building up -
GTP/trunk/Lib/Vis/Preprocessing/src/havran/ktbai.cpp
r2582 r2592 1221 1221 if (objlist.size() == 0) 1222 1222 return 0; // nothing 1223 cerr<<"hh44"<<endl;1223 // cerr<<"hh44"<<endl; 1224 1224 // initialize the whole box of the kd-tree and sort 1225 1225 // the boundary entries 1226 1226 SInputData *d = Init(&objlist, box); 1227 1227 1228 cerr<<"hh45"<<endl;1228 //cerr<<"hh45"<<endl; 1229 1229 1230 1230 // copy verbose to be used consistenly further on -
GTP/trunk/Lib/Vis/Preprocessing/src/havran/ktball.cpp
r2582 r2592 22 22 #include <fstream> 23 23 #include <iomanip> 24 #include <stack> 24 25 25 26 namespace GtpVisibilityPreprocessor { … … 96 97 const int size1D = 150; 97 98 98 cerr<<"th1"<<endl;99 // cerr<<"th1"<<endl; 99 100 // $$JB tmp 100 101 size2D = 1; 101 cerr<<"size2d="<<size2D<<endl;102 // cerr<<"size2d="<<size2D<<endl; 102 103 // initial index 103 104 index2D = 0; 104 105 AllocBuffer(size2D, size1D); 105 cerr<<"th2"<<endl;106 // cerr<<"th2"<<endl; 106 107 107 108 #if 0 … … 117 118 } 118 119 #else 119 cerr<<"th3"<<endl;120 // cerr<<"th3"<<endl; 120 121 121 122 traversalClass = new CKTBTraversal; … … 308 309 #endif // _DEBUG 309 310 310 cerr<<"hh2"<<endl;311 // cerr<<"hh2"<<endl; 311 312 // possibly remove the old building class 312 313 // and allocate the class for CKTB building up … … 315 316 buildClass = AllocBuildClass(); 316 317 317 cerr<<"hh3"<<endl;318 // cerr<<"hh3"<<endl; 318 319 319 320 // and for traversal 320 321 AllocTraversalClass(); 321 cerr<<"hh4"<<endl;322 // cerr<<"hh4"<<endl; 322 323 323 324 if (boxToBoundObjects) { … … 330 331 bbox.Include(*boxToInclude); 331 332 332 cerr<<"hh5"<<endl;333 // cerr<<"hh5"<<endl; 333 334 334 335 // build up the CKTB tree and make setup for traversal 335 336 SKTBNodeT *rootNode = 336 337 buildClass->BuildUp(objlist, bbox, verbose); 337 cerr<<"hh6"<<endl;338 // cerr<<"hh6"<<endl; 338 339 339 340 traversalClass->Setup(bbox, rootNode); 340 cerr<<"hh7"<<endl;341 // cerr<<"hh7"<<endl; 341 342 342 343 #ifdef _DEBUG … … 400 401 } 401 402 403 int 404 CKTB::FindNearestI(const SimpleRay &ray, Vector3 &boxmin, Vector3 &boxmax) 405 { 406 const AxisAlignedBox3 localbox(boxmin, boxmax); 407 return traversalClass->FindNearestI(ray, localbox); 408 } 409 410 411 #ifdef _USE_HAVRAN_SSE 412 402 413 #ifdef __SSE__ 403 414 // -------------------------------------------------------------- … … 420 431 421 432 #endif // __SSE__ 433 434 #endif // _USE_HAVRAN_SSE 435 422 436 423 437 void … … 752 766 SKTBNodeT* 753 767 CKTB::ImportBinLeaf(IN_STREAM &stream, 754 SKTBNodeT * parent,768 SKTBNodeT **nodeToLink, 755 769 const ObjectContainer &objects) 756 770 { … … 764 778 // since for 765 779 SKTBNodeT* leaf = buildClass->AllocLeaf(0); 780 *nodeToLink = buildClass->nodeToLink; 766 781 return leaf; 767 782 } … … 769 784 MeshInstance dummyInst(NULL); 770 785 SKTBNodeT* leaf = buildClass->AllocLeaf(size); 786 *nodeToLink = buildClass->nodeToLink; 771 787 772 788 ObjectContainer *newobjlist = new ObjectContainer; … … 809 825 810 826 SKTBNodeT * 811 CKTB::ImportBinInterior(IN_STREAM &stream, SKTBNodeT * parent)827 CKTB::ImportBinInterior(IN_STREAM &stream, SKTBNodeT **nodeToLink) 812 828 { 813 829 int axis; … … 819 835 SKTBNodeT *interiorNode = 820 836 buildClass->AllocInteriorNode(axis, pos, 0, 0); 837 *nodeToLink = buildClass->nodeToLink; 821 838 822 839 return interiorNode; … … 830 847 if (!stream.is_open()) return false; 831 848 832 // DEBUG << "CKTB::GatherStats called" << endl; 833 struct EDir { 834 SKTBNodeT *node; 835 int depth; 836 AxisAlignedBox3 bbox; 837 }; 838 EDir stack[CKTBTraversal::MAX_TRAVERSAL_HEIGHT]; 839 int stackTop = 0; // pointer to the stack 840 stack[stackTop].node = 0; 841 stack[stackTop].depth = 0; 842 stack[stackTop].bbox = bbox; 843 int tmpdir; 849 int startMark = 0xf0f0; 850 stream.write(reinterpret_cast<char *>(&startMark), sizeof(int)); 844 851 845 852 // export binary version of mesh 846 queue<SKTBNodeT *> tStack; 847 // start from the root node 848 SKTBNodeT *currNode = buildClass->GetRootNode(); 849 850 // copy the box over the scene objects 851 AxisAlignedBox3 bwbox = this->bbox; 852 int currDepth = 0; 853 854 // traverse through whole CKTB tree 855 do { 856 CKTBAxes::Axes nodeType = buildClass->GetNodeType(currNode); 857 if (nodeType == CKTBAxes::EE_Link) { 858 // just relink 859 currNode = buildClass->GetLinkNode(currNode); 860 // cout << "Link node was accessed" << endl; 861 continue; 853 std::stack<SKTBNodeT *> tStack; 854 tStack.push(buildClass->GetRootNode()); 855 int cntSaves = 0, cntSavesLeaf = 0, cntSavesIN = 0; 856 857 while(!tStack.empty()) 858 { 859 SKTBNodeT *node = tStack.top(); 860 tStack.pop(); 861 862 int nodeType = buildClass->GetNodeType(node); 863 864 if (nodeType == CKTBAxes::EE_Link) 865 { 866 tStack.push(buildClass->GetLinkNode(node)); 862 867 } 863 864 if ( (nodeType == CKTBAxes::EE_X_axis)|| 865 (nodeType == CKTBAxes::EE_Y_axis)|| 866 (nodeType == CKTBAxes::EE_Z_axis)|| 867 (nodeType == CKTBAxes::EE_X_axisBox)|| 868 (nodeType == CKTBAxes::EE_Y_axisBox)|| 869 (nodeType == CKTBAxes::EE_Z_axisBox) 870 ) { 871 872 // push onto the stack 873 AxisAlignedBox3 rightBox = bwbox; 874 float value = currNode->splitPlane; 875 switch(nodeType) { 876 case CKTBAxes:: EE_X_axisBox: { 877 rightBox.SetMin(0, value); 878 bwbox.SetMax(0, value); 879 break; 880 } 881 case CKTBAxes:: EE_X_axis: { 882 rightBox.SetMin(0, value); 883 bwbox.SetMax(0, value); 884 break; 885 } 886 case CKTBAxes:: EE_Y_axisBox: { 887 rightBox.SetMin(0, value); 888 bwbox.SetMax(0, value); 889 break; 890 } 891 case CKTBAxes:: EE_Y_axis: { 892 rightBox.SetMin(1, value); 893 bwbox.SetMax(1, value); 894 break; 895 } 896 case CKTBAxes:: EE_Z_axisBox: { 897 rightBox.SetMin(0, value); 898 bwbox.SetMax(0, value); 899 break; 900 } 901 case CKTBAxes:: EE_Z_axis: { 902 rightBox.SetMin(2, value); 903 bwbox.SetMax(2, value); 904 break; 905 } 906 } // switch 907 908 // Exporting interior node 909 ExportBinInterior(stream, currNode); 910 911 stack[stackTop].node = buildClass->GetRight(currNode); 912 stack[stackTop].depth = currDepth + 1; 913 stack[stackTop].bbox = rightBox; 914 stackTop++; 915 // where to go 916 if ( (nodeType == CKTBAxes:: EE_X_axisBox)|| 917 (nodeType == CKTBAxes:: EE_Y_axisBox)|| 918 (nodeType == CKTBAxes:: EE_Z_axisBox) ) 919 currNode = buildClass->GetLeftMinBox(currNode); 868 else 869 if (nodeType == CKTBAxes::EE_Leaf) 870 { 871 //Debug << "l"; 872 ExportBinLeaf(stream, node); 873 cntSavesLeaf++; cntSaves++; 874 } 875 else 876 { // interior node 877 //Debug << "i"; 878 ExportBinInterior(stream, node); 879 cntSavesIN++; cntSaves++; 880 881 tStack.push(buildClass->GetRight(node)); 882 if (nodeType >= CKTBAxes::EE_X_axisBox) 883 tStack.push(buildClass->GetLeftLong(node)); 920 884 else 921 currNode = buildClass->GetLeft(currNode); 922 // the box was already set 923 currDepth++; 924 925 continue; 926 } // interior nodes 927 928 assert(nodeType == CKTBAxes::EE_Leaf); 929 930 while ( (nodeType == CKTBAxes::EE_Leaf) && currDepth) { 931 ObjectContainer *olist = buildClass->GetObjList(currNode); 932 // Exporting leaf node 933 ExportBinLeaf(stream, static_cast<SKTBNodeT *>(currNode)); 934 935 // traverse up the tree 936 stackTop--; 937 if (stackTop < 0) 938 goto FINISH; 939 // pop the node from the stack 940 currNode = stack[stackTop].node; 941 currDepth = stack[stackTop].depth; 942 bwbox = stack[stackTop].bbox; 943 944 nodeType = buildClass->GetNodeType(currNode); 945 946 } // while is a leaf 947 } 948 while (stackTop >= 0); 949 950 FINISH: 951 // close the stream 885 tStack.push(buildClass->GetLeft(node)); 886 } 887 } // while 888 889 int endMark = 0xf0ff; 890 stream.write(reinterpret_cast<char *>(&endMark), sizeof(int)); 891 892 cout << "Writes " << cntSaves << " cntLeafs " 893 << cntSavesLeaf << " cntIN " << cntSavesIN << endl; 894 952 895 stream.close(); 953 954 return true; 955 } 956 957 #if 0 958 KdNode *KdTree::ImportNextNode(IN_STREAM &stream, 959 KdInterior *parent, 960 const ObjectContainer &objects) 961 { 962 int nodeType; 963 stream.read(reinterpret_cast<char *>(&nodeType), sizeof(int)); 964 965 if (nodeType == TYPE_LEAF) 966 return ImportBinLeaf(stream, static_cast<KdInterior *>(parent), objects); 967 968 if (nodeType == TYPE_INTERIOR) 969 return ImportBinInterior(stream, static_cast<KdInterior *>(parent)); 970 971 Debug << "error! loading failed!" << endl; 972 return NULL; 973 } 974 975 976 bool KdTree::ImportBinTree(const string &filename, ObjectContainer &objects) 977 { 978 // export binary version of mesh 979 queue<TraversalData> tStack; 896 return true; // saved 897 } 898 899 900 SKTBNodeT * 901 CKTB::ImportNextNode(IN_STREAM &stream, 902 SKTBNodeT **nodeToLink, 903 const ObjectContainer &objects) 904 { 905 int nodeType; 906 stream.read(reinterpret_cast<char *>(&nodeType), sizeof(int)); 907 908 if (nodeType == TYPE_LEAF) 909 return ImportBinLeaf(stream, nodeToLink, objects); 910 911 if (nodeType == TYPE_INTERIOR) 912 return ImportBinInterior(stream, nodeToLink); 913 914 Debug << "error! loading failed!" << endl; 915 return NULL; 916 } 917 918 919 // creates the ASDS according to the file description 920 bool 921 CKTB::ImportBinTree(const string &filename, ObjectContainer &objects) 922 { 923 // open the stream in text mode 980 924 IN_STREAM stream(filename.c_str(), IN_BIN_MODE); 981 982 if (!stream.is_open()) return false; 983 984 // sort objects by their id 925 926 if (!stream.is_open()) { 927 cerr << "Kd-tree description file (.kbt) cannot be opened for reading\n"; 928 return true; // error 929 } 930 931 int mark; 932 stream.read(reinterpret_cast<char *>(&mark), sizeof(int)); 933 if (mark != 0xf0f0) { 934 cout << "Something wrong with the tree - heading" << endl; 935 abort(); 936 } 937 938 // sort objects by their id to allow list creation in kd-tree leaves 985 939 // if (!is_sorted(objects.begin(), objects.end(), ilt)) 986 940 sort(objects.begin(), objects.end(), ilt); 987 941 988 mBox.Initialize(); 989 ObjectContainer::const_iterator oit, oit_end = objects.end(); 990 991 /////////////////////////// 992 //-- compute bounding box of object space 993 994 for (oit = objects.begin(); oit != oit_end; ++ oit) 995 { 996 const AxisAlignedBox3 box = (*oit)->GetBox(); 997 mBox.Include(box); 998 } 999 1000 // hack: we make a new root 1001 DEL_PTR(mRoot); 1002 1003 mRoot = ImportNextNode(stream, NULL, objects); 1004 1005 tStack.push(TraversalData(mRoot, mBox, 0)); 1006 mStat.Reset(); 1007 mStat.nodes = 1; 1008 942 // remove all the data in the current data structure 943 CKTBAllocManPredecessor *bc = GetBuildClass(); 944 if (!bc) 945 bc = buildClass = AllocBuildClass(); 946 else 947 bc->Remove(); 948 949 // How many items can be allocated at once 950 int maxItemsAtOnce = 1; 951 if (makeMinBoxes) { 952 #ifdef _KTB8Bytes 953 // We need to allocate for boxes the memory in a row 954 maxItemsAtOnce = 5; // 8x5=40 = 16+24; 955 #else 956 maxItemsAtOnce = 4; // 12x4=48 = 24+24; 957 #endif // _KTB8Bytes 958 } 959 960 bc->InitAux(0, CKTBNodeAbstract::MAX_HEIGHT - 1, maxItemsAtOnce); 961 962 // Compute the box from all objects 963 bbox.Initialize(); 964 for (ObjectContainer::iterator sc = objects.begin(); 965 sc != objects.end(); sc++) { 966 AxisAlignedBox3 abox = (*sc)->GetBox(); 967 bbox.Include(abox); 968 } // for 969 970 // initialize the root node 971 SKTBNodeT *node; 972 973 bc->root = ImportNextNode(stream, &node, objects); 974 assert(bc->root == node); 975 976 std::stack<STraversalData> tStack; 977 tStack.push(STraversalData(bc->root, 1, 0)); 978 tStack.push(STraversalData(bc->root, 0, 0)); 979 int depth, lastDepth; 980 981 //int cntReads = 1, cntReadsLeaf = 0, cntReadsIN = 1; 1009 982 while(!tStack.empty()) 1010 { 1011 TraversalData tData = tStack.front();983 { 984 STraversalData tData = tStack.top(); 1012 985 tStack.pop(); 1013 986 1014 KdNode *node = tData.mNode; 987 node = tData.mNode; 988 lastDepth = depth = tData.depth; 989 //int nodeType = bc->GetNodeType(node); 990 //cout << "nodeType = " << nodeType << " adr = " << (void*)node << endl; 991 992 SKTBNodeT *childNodeLink = 0; 993 SKTBNodeT *childNode = ImportNextNode(stream, &childNodeLink, objects); 994 // cout << "childNode = " << (void*)childNode 995 // << " linkNode = " << (void*)childNodeLink << endl; 996 997 if (tData.dir) 998 bc->SetInteriorNodeRight(node, childNodeLink); 999 else 1000 bc->SetInteriorNodeLeft(node, childNodeLink); 1015 1001 1016 if (!node->IsLeaf()) 1002 //cntReads++; 1003 if (!bc->IsLeaf_(childNode)) 1017 1004 { 1018 mStat.nodes += 2; 1019 1020 //Debug << "i" ; 1021 KdInterior *interior = static_cast<KdInterior *>(node); 1022 interior->mBox = tData.mBox; 1023 1024 KdNode *front = ImportNextNode(stream, interior, objects); 1025 KdNode *back = ImportNextNode(stream, interior, objects); 1026 1027 interior->SetupChildLinks(back, front); 1028 1029 ++ mStat.splits[interior->mAxis]; 1030 1031 // compute new bounding box 1032 AxisAlignedBox3 frontBox, backBox; 1033 1034 tData.mBox.Split(interior->mAxis, 1035 interior->mPosition, 1036 frontBox, 1037 backBox); 1038 1039 tStack.push(TraversalData(front, frontBox, tData.mDepth + 1)); 1040 tStack.push(TraversalData(back, backBox, tData.mDepth + 1)); 1005 //cntReadsIN++; 1006 tStack.push(STraversalData(childNode, 1, depth+1)); 1007 tStack.push(STraversalData(childNode, 0, depth+1)); 1041 1008 } 1042 else 1043 { 1044 EvaluateLeafStats(tData); 1045 //cout << "l"; 1046 } 1047 } 1048 1049 float area = GetBox().SurfaceArea()*mKdPvsArea; 1050 1051 SetPvsTerminationNodes(area); 1052 1053 Debug << mStat << endl; 1054 1055 return true; 1056 } 1057 #endif 1058 1009 //else { 1010 // cntReadsLeaf++; 1011 // //cout << "leaf" << endl; 1012 // } 1013 } // while 1014 1015 //cout << "Last depth = " << lastDepth << endl; 1016 //cout << "Reads " << cntReads << " cntLeafs " 1017 // << cntReadsLeaf << " cntIN " << cntReadsIN << endl; 1018 1019 stream.read(reinterpret_cast<char *>(&mark), sizeof(int)); 1020 if (mark != 0xf0ff) { 1021 cout << "Something wrong with the kd-tree in the file" 1022 << endl; 1023 abort(); 1024 } 1025 1026 if (!traversalClass) 1027 AllocTraversalClass(); 1028 1029 // Make setup for traversal 1030 traversalClass->Setup(bbox, bc->GetRootNode()); 1031 // Handles unbounded objects in traversal class 1032 // traversalClass->Setup2(0); 1033 1034 stream.close(); 1035 1036 // now the tree is surely well constructed 1037 builtUp = true; 1038 1039 return false; // OK 1040 } 1059 1041 1060 1042 void -
GTP/trunk/Lib/Vis/Preprocessing/src/havran/ktball.h
r2582 r2592 174 174 175 175 int FindNearestI(const SimpleRay &ray); 176 int FindNearestI(const SimpleRay &ray, Vector3 &boxmin, Vector3 &boxmax); 176 177 void SetOffset(int offset) { traversalClass->SetOffset(offset); } 177 int FindNearestI_16oneDir(SimpleRayContainer &rays ) {178 return traversalClass->FindNearestI_16oneDir(rays );179 } 180 int FindNearestI_16oneDir (SimpleRayContainer &rays, int offset) {181 return traversalClass->FindNearestI_16oneDir (rays, offset);178 int FindNearestI_16oneDir(SimpleRayContainer &rays, int offset, int copyOffset) { 179 return traversalClass->FindNearestI_16oneDir(rays, offset, copyOffset); 180 } 181 int FindNearestI_16oneDirNoSSE(SimpleRayContainer &rays, int offset) { 182 return traversalClass->FindNearestI_16oneDirNoSSE(rays, offset); 182 183 } 183 184 int FindNearestI_16twoDir(SimpleRayContainer &rays) { … … 186 187 187 188 #ifdef __SSE__ 189 #ifdef _USE_HAVRAN_SSE 188 190 // The same operations for packets of rays, if implemented by 189 191 // a particular ASDS, otherwise it is emulated by decomposition … … 191 193 void FindNearestI(RayPacket2x2 &raypack); 192 194 void FindNearestI(RayPacket2x2 &raypack, Vector3 &boxmin, Vector3 &boxmax); 195 #endif 193 196 #else 194 197 void FindNearestI(RayPacket2x2 &raypack) { } … … 199 202 void ExportBinLeaf(OUT_STREAM &stream, SKTBNodeT *leaf); 200 203 SKTBNodeT* ImportBinLeaf(IN_STREAM &stream, 201 SKTBNodeT * parent,204 SKTBNodeT **nodeToLink, 202 205 const ObjectContainer &objects); 206 203 207 void ExportBinInterior(OUT_STREAM &stream, SKTBNodeT *interior); 204 SKTBNodeT* ImportBinInterior(IN_STREAM &stream, 205 SKTBNodeT *parent); 208 SKTBNodeT *ImportBinInterior(IN_STREAM &stream, 209 SKTBNodeT **nodeToLink); 210 211 SKTBNodeT * ImportNextNode(IN_STREAM &stream, 212 SKTBNodeT **nodeToLink, 213 const ObjectContainer &objects); 214 206 215 bool ExportBinTree(const string &filename); 216 bool ImportBinTree(const string &filename, ObjectContainer &objects); 217 207 218 208 219 protected: … … 211 222 int sizeBuffer, size1D; 212 223 void AllocBuffer(int size2D, int size1Dv); 224 225 struct STraversalData 226 { 227 SKTBNodeT *mNode; 228 int dir; 229 int depth; 230 STraversalData() {} 231 232 STraversalData(SKTBNodeT *n): mNode(n) 233 { } 234 235 STraversalData(SKTBNodeT *n, int ndir, int ndepth): 236 mNode(n), dir(ndir), depth(ndepth) { } 237 }; 213 238 }; 214 239 -
GTP/trunk/Lib/Vis/Preprocessing/src/havran/ktbconf.h
r2582 r2592 22 22 #include <xmmintrin.h> 23 23 #endif 24 25 // If we support the use of SSE instructions for ray shooting 26 #define _USE_HAVRAN_SSE 24 27 25 28 namespace GtpVisibilityPreprocessor { -
GTP/trunk/Lib/Vis/Preprocessing/src/havran/ktbftrav.cpp
r2583 r2592 20 20 #ifdef TRV00F 21 21 22 #if 0 23 // the depth of traversal when kd-trees are nested. The global (the highest 24 // level) kd-tree is at the depth 0. 25 int 26 CKTBTraversal::traversalDepth = 0; 27 28 // sets the stack pointers that are used for the traversal. 29 void 30 CKTBTraversal::GetStackPointers(struct SStackElem *&entryPointer, 31 struct SStackElem *&exitPointer) 32 { 33 assert(traversalDepth < MAX_NESTING); 34 35 int index = traversalDepth * MAX_HEIGHT; 36 entryPointer = &(stack[index]); 37 exitPointer = &(stack[index + 1]); 38 39 traversalDepth++; 40 return; 41 } 42 43 // sets the stack pointers that are used for the traversal. 44 void 45 CKTBTraversal::RestoreStackPointers() 46 { 47 assert(traversalDepth >= 0); 48 traversalDepth--; 49 return; 50 } 51 52 53 // default constructor 54 CKTBTraversal::CKTBTraversal() 55 { 56 bbox = AxisAlignedBox3(Vector3(MAXFLOAT), 57 Vector3(-MAXFLOAT)); 58 root = 0; 59 epsilon = 0; 60 61 #ifdef __TRAVERSAL_STATISTICS 62 _allNodesTraversed = 0L; 63 _fullLeavesTraversed = 0L; 64 _emptyLeavesTraversed = 0L; 65 #endif 66 } 67 68 // Here we find the node (preferably minbox node) containing 69 // the point 70 const SKTBNodeT* 71 CKTBTraversal::Locate(const Vector3 &position) 72 { 73 const SKTBNodeT *current, *next = root; 74 const SKTBNodeT *returnNode = 0; 75 76 do { 77 current = next; 78 switch (GetNodeType(current)) { 79 // ------------------------------------------------- 80 case CKTBAxes::EE_X_axis: { 81 if (position[CKTBAxes::EE_X_axis] < current->splitPlane) 82 next = GetLeft(current); 83 else 84 next = GetRight(current); 85 break; 86 } 87 case CKTBAxes::EE_Y_axis: { 88 if (position[CKTBAxes::EE_Y_axis] < current->splitPlane) 89 next = GetLeft(current); 90 else 91 next = GetRight(current); 92 break; 93 } 94 case CKTBAxes::EE_Z_axis: { 95 if (position[CKTBAxes::EE_Z_axis] < current->splitPlane) 96 next = GetLeft(current); 97 else 98 next = GetRight(current); 99 break; 100 } 101 case CKTBAxes::EE_X_axisBox: { 102 if (position[CKTBAxes::EE_X_axis] < current->splitPlane) 103 next = GetLeft(current); 104 else 105 next = GetRight(current); 106 returnNode = current; 107 break; 108 } 109 case CKTBAxes::EE_Y_axisBox: { 110 if (position[CKTBAxes::EE_Y_axis] < current->splitPlane) 111 next = GetLeft(current); 112 else 113 next = GetRight(current); 114 returnNode = current; 115 break; 116 } 117 case CKTBAxes::EE_Z_axisBox: { 118 if (position[CKTBAxes::EE_Z_axis] < current->splitPlane) 119 next = GetLeft(current); 120 else 121 next = GetRight(current); 122 returnNode = current; 123 break; 124 } 125 case CKTBAxes::EE_Leaf: { 126 next = 0; // finishing 127 break; 128 } 129 case CKTBAxes::EE_Link:{ 130 next = GetLinkNode(current); 131 // cout << "Link node was accessed" << endl; 132 break; 133 } 134 } // switch 135 } 136 while (next != NULL); 137 138 if (returnNode) 139 return returnNode; 140 141 // return the last (leaf node) visited on the path 142 return current; 143 } 144 #endif 145 146 147 #if 1 22 // -------------------------------------------------------------- 23 // Shooting a single ray without SSE 148 24 int 149 25 CKTBTraversal::FindNearestI(const SimpleRay &ray) … … 162 38 // passing through parameters 163 39 float tmin, tmax; 40 SimpleRay::IntersectionRes[0].intersectable = 0; 164 41 165 42 // test if the whole CKTB tree is missed by the input ray 166 43 if ( (!root) || 167 44 (!bbox.ComputeMinMaxT(ray.mOrigin, ray.mDirection, &tmin, &tmax)) || 168 (tmax < =tmin) ||45 (tmax < tmin) || 169 46 (tmax <= 0.f) ) { 170 SimpleRay::IntersectionRes[0].intersectable = 0;171 47 return 0; // no object can be intersected 172 48 } … … 185 61 186 62 Vector3 invertedDir; 187 invertedDir.x = 1.0f / ray.mDirection.x;188 invertedDir.y = 1.0f / ray.mDirection.y;189 invertedDir.z = 1.0f / ray.mDirection.z;63 invertedDir.x = 1.0f / (ray.mDirection.x - 1e-25f); 64 invertedDir.y = 1.0f / (ray.mDirection.y - 1e-25f); 65 invertedDir.z = 1.0f / (ray.mDirection.z - 1e-25f); 190 66 191 67 // start from the root node … … 216 92 } 217 93 #endif 94 95 CONTINUE_LINK: 96 97 assert(tmin <= tmax); 98 #ifdef __TRAVERSAL_STATISTICS 99 allNodesTraversed++; 100 #endif // __TRAVERSAL_STATISTICS 101 102 register const int nodeType = GetNodeType(currNode); 103 104 // cout << " tmin = " << tmin << " tmax = " << tmax << " nodeType = " << (int)nodeType << endl; 218 105 219 assert(tmin <= tmax);220 221 #ifdef __TRAVERSAL_STATISTICS222 allNodesTraversed++;223 #endif // __TRAVERSAL_STATISTICS224 register const int nodeType = GetNodeType(currNode);225 226 106 if (nodeType < CKTBAxes::EE_Leaf) { 227 107 float tval = (GetSplitValue(currNode) - ray.mOrigin[nodeType]); … … 265 145 // test the objects in the full leaf against the ray 266 146 267 SimpleRay::IntersectionRes[0].maxt = stack3[index].tmax; 147 SimpleRay::IntersectionRes[0].maxt = 148 stack3[index].tmax + Limits::Small; 268 149 #if 0 269 150 // using subroutine … … 320 201 cout << "Link " << endl; 321 202 #endif 322 stack3[index].nodep = GetLinkNode(currNode);323 203 // cout << "Link node was accessed" << endl; 324 continue; 204 currNode = GetLinkNode(currNode); 205 goto CONTINUE_LINK; 325 206 } 326 207 } … … 336 217 return 0; 337 218 } // FindNearestI - single ray 338 #endif 339 340 #if 1 219 220 221 // Shooting a single ray without SSE with prespecified box of the scene, assuming 222 // to be contained in the scene box!!! 341 223 int 342 224 CKTBTraversal::FindNearestI(const SimpleRay &ray, const AxisAlignedBox3 &localbox) … … 355 237 // passing through parameters 356 238 float tmin, tmax; 239 SimpleRay::IntersectionRes[0].intersectable = 0; 357 240 358 241 // test if the whole CKTB tree is missed by the input ray … … 361 244 (tmax <= tmin) || 362 245 (tmax <= 0.f) ) { 363 SimpleRay::IntersectionRes[0].intersectable = 0;364 246 return 0; // no object can be intersected 365 247 } … … 378 260 379 261 Vector3 invertedDir; 380 invertedDir.x = 1.0f / ray.mDirection.x;381 invertedDir.y = 1.0f / ray.mDirection.y;382 invertedDir.z = 1.0f / ray.mDirection.z;262 invertedDir.x = 1.0f / (ray.mDirection.x - 1e-25f); 263 invertedDir.y = 1.0f / (ray.mDirection.y - 1e-25f); 264 invertedDir.z = 1.0f / (ray.mDirection.z - 1e-25f); 383 265 384 266 // start from the root node … … 409 291 } 410 292 #endif 411 293 294 CONTINUE_LINK: 412 295 assert(tmin <= tmax); 413 296 414 297 #ifdef __TRAVERSAL_STATISTICS 415 298 allNodesTraversed++; 416 299 #endif // __TRAVERSAL_STATISTICS 300 417 301 register const int nodeType = GetNodeType(currNode); 418 302 if (nodeType < CKTBAxes::EE_Leaf) { … … 457 341 // test the objects in the full leaf against the ray 458 342 459 SimpleRay::IntersectionRes[0].maxt = stack3[index].tmax; 343 SimpleRay::IntersectionRes[0].maxt = 344 stack3[index].tmax + Limits::Small; 460 345 #if 0 461 346 // using subroutine … … 512 397 cout << "Link " << endl; 513 398 #endif 514 stack3[index].nodep = GetLinkNode(currNode);515 399 // cout << "Link node was accessed" << endl; 516 continue; 400 currNode = GetLinkNode(currNode); 401 goto CONTINUE_LINK; 517 402 } 518 403 } … … 528 413 return 0; 529 414 } // FindNearestI - single ray 530 #endif 531 532 533 // --------------------------------------------------------------------------- 534 // This is an attempt using SSE instructions - not successfull 31/12/2007 535 #if 0 536 int 537 CKTBTraversal::FindNearestI(const SimpleRay &ray) 538 { 539 #if 0 540 static int counter = 0; 541 counter++; 542 bool debug = false; 543 if (counter == 530) { 544 debug = true; 545 cout << "COUNTER = " << counter << endl; 546 cout << "DEBUG starts" << endl; 547 } 548 #endif 549 550 // passing through parameters 551 float tmin, tmax; 552 553 // test if the whole CKTB tree is missed by the input ray 554 if ( (!root) || 555 (!bbox.ComputeMinMaxT(ray.mOrigin, ray.mDirection, &tmin, &tmax)) || 556 (tmax <= tmin) || 557 (tmax <= 0.f) ) { 558 SimpleRay::IntersectionRes[0].intersectable = 0; 559 return 0; // no object can be intersected 560 } 561 562 //#define _DEBUGKTB 563 #ifdef _DEBUGKTB 564 int ib = 0; 565 int depth = 0; 566 #endif 567 568 #ifdef __TRAVERSAL_STATISTICS 569 int allNodesTraversed = 0L; 570 int fullLeavesTraversed = 0L; 571 int emptyLeavesTraversed = 0L; 572 #endif // __TRAVERSAL_STATISTICS 573 574 Vector3 invertedDir; 575 invertedDir.x = 1.0f / ray.mDirection.x; 576 invertedDir.y = 1.0f / ray.mDirection.y; 577 invertedDir.z = 1.0f / ray.mDirection.z; 578 579 // start from the root node 580 if (tmin < 0.f) 581 tmin = 0.f; 582 583 int index = 1; 584 stack3[1].nodep = root; 585 stack3[1].tmax = tmax; 586 tmax = tmin; 587 SKTBNodeT * childNodes[2]; 588 int RayDirs[3]; 589 RayDirs[0] = ray.mDirection.x < 0.f ? 1 : 0; 590 RayDirs[1] = ray.mDirection.y < 0.f ? 1 : 0; 591 RayDirs[2] = ray.mDirection.z < 0.f ? 1 : 0; 592 593 // we have to check the node 594 // current node is not the leaf, empty leaves are NULL pointers 595 while (index) { 596 SKTBNodeT *currNode = stack3[index].nodep; 597 tmin = tmax; 598 tmax = stack3[index].tmax; 599 #if 0 600 if (debug) { 601 cout << "node = " << (void*)currNode 602 << " tmin = " << tmin << " tmax = " << tmax 603 << endl; 604 } 605 #endif 606 607 assert(tmin <= tmax); 608 609 #ifdef __TRAVERSAL_STATISTICS 610 allNodesTraversed++; 611 #endif // __TRAVERSAL_STATISTICS 612 const unsigned int nodeType = GetNodeType(currNode); 613 if (nodeType < CKTBAxes::EE_Leaf) { 614 float tval = (GetSplitValue(currNode) - ray.mOrigin[nodeType]); 615 tval *= invertedDir[nodeType]; 616 SKTBNodeT *near, *far; 617 childNodes[0] = GetLeft(currNode); 618 childNodes[1] = GetRight(currNode); 619 int rayDir = RayDirs[nodeType]; 620 near = childNodes[rayDir]; 621 far = childNodes[rayDir ^ 0x1]; 622 // This code is slower than above !!!!! 623 stack3[index].nodep = far; 624 // stack3[index].tmax = tmax; // this is already there, not necessary! 625 __m128 tsim = _mm_set_ss(tval); 626 // index += tval < tmax ? 1 : 0; 627 __m128 tother = _mm_set_ss(tmax); 628 index += _mm_ucomilt_ss(tsim, tother); 629 stack3[index].nodep = near; 630 // stack3[index].tmax = Min(tval, tmax); 631 _mm_store_ss(&(stack3[index].tmax), _mm_min_ps(tsim, tother)); 632 tmax = tmin; 633 // index += tval < tmin ? -1 : 0; 634 __m128 tother2 = _mm_set_ss(tmin); 635 index -= _mm_ucomilt_ss(tsim, tother2); 636 } 637 else { 638 if (nodeType == CKTBAxes::EE_Leaf) { 639 // test objects for intersection 640 #ifdef _DEBUGKTB 641 cout << "Leaf " << endl; 642 depth++; 643 #endif 644 #ifdef _DEBUGKTB 645 DEBUG << "currNode = " << currNode << " entp.t = " << entp->t 646 << " extp.t = " << extp->t << endl; 647 #endif 648 if (!IsEmptyLeaf_(currNode)) { 649 #ifdef _DEBUGKTB 650 cout << "Full leaf at depth= " << depth << endl; 651 #endif 652 653 #ifdef __TRAVERSAL_STATISTICS 654 fullLeavesTraversed++; 655 #endif // __TRAVERSAL_STATISTICS 656 // test the objects in the full leaf against the ray 657 658 SimpleRay::IntersectionRes[0].maxt = stack3[index].tmax; 659 if (TestFullLeaf(ray, currNode)) { 660 #ifdef _DEBUGKTB 661 cout << "Full leaf HIT " << endl; 662 #endif 663 664 #ifdef __TRAVERSAL_STATISTICS 665 _allNodesTraversed += allNodesTraversed; 666 _fullLeavesTraversed += fullLeavesTraversed; 667 _emptyLeavesTraversed += emptyLeavesTraversed; 668 #endif // __TRAVERSAL_STATISTICS 669 670 // signed distance should be already set in TestFullLeaf 671 // the first object intersected was found 672 return 1; 673 } 674 } // full leaf 675 #ifdef __TRAVERSAL_STATISTICS 676 else { 677 #ifdef _DEBUGKTB 678 cout << "Empty leaf at depth= " << depth << endl; 679 #endif 680 emptyLeavesTraversed++; 681 } 682 #endif // __TRAVERSAL_STATISTICS 683 684 #ifdef _DEBUGKTB 685 cout << "Pop the node" << endl; 686 #endif 687 688 // pop farChild from the stack 689 // restore the current values 690 index--; 691 continue; 692 } 693 else { 694 assert(nodeType == CKTBAxes::EE_Link); 695 #ifdef _DEBUGKTB 696 cout << "Link " << endl; 697 #endif 698 stack3[index].nodep = GetLinkNode(currNode); 699 // cout << "Link node was accessed" << endl; 700 continue; 701 } 702 } 703 } // while current node is not the leaf 704 705 #ifdef __TRAVERSAL_STATISTICS 706 _allNodesTraversed += allNodesTraversed; 707 _fullLeavesTraversed += fullLeavesTraversed; 708 _emptyLeavesTraversed += emptyLeavesTraversed; 709 #endif // __TRAVERSAL_STATISTICS 710 711 // no objects found along the ray path 712 return 0; 713 } // FindNearestI - single ray 714 #endif 715 716 #if 0 415 416 717 417 // Reasonably fast - about 101,500 rays per second for single dir! 718 // It allows fast switching context from one ray to the next ray so it i t418 // It allows fast switching context from one ray to the next ray so it is 719 419 // virtually independent of memory latency ! 720 420 int 721 CKTBTraversal::FindNearestI_16oneDir (SimpleRayContainer &rays, int offset)421 CKTBTraversal::FindNearestI_16oneDirNoSSE(SimpleRayContainer &rays, int offset) 722 422 { 723 423 // passing through parameters … … 742 442 float tmin, tmax; 743 443 for (int i = 0; i < cntMaxRays; i++) { 744 // test if the whole CKTB tree is missed by the input ray 444 // Setting zero intersection as original result 445 SimpleRay::IntersectionRes[i+rayOffset].intersectable = 0; 446 // test if the whole CKTB tree is missed by the input ray 745 447 if ((!bbox.ComputeMinMaxT(rays[i+offset].mOrigin, 746 448 rays[i+offset].mDirection, … … 748 450 (tmax <= tmin) || 749 451 (tmax <= 0.f) ) { 750 SimpleRay::IntersectionRes[i].intersectable = 0;751 452 } 752 453 else { … … 756 457 rayOrig[indexR + 2] = rays[i+offset].mOrigin.z; 757 458 //rayOrig[indexR + 3] = 0.f; 758 invertedDir[indexR + 0] = 1.0f / (rays[i+offset].mDirection.x );759 invertedDir[indexR + 1] = 1.0f / (rays[i+offset].mDirection.y );760 invertedDir[indexR + 2] = 1.0f / (rays[i+offset].mDirection.z );459 invertedDir[indexR + 0] = 1.0f / (rays[i+offset].mDirection.x - 1e-25f); 460 invertedDir[indexR + 1] = 1.0f / (rays[i+offset].mDirection.y - 1e-25f); 461 invertedDir[indexR + 2] = 1.0f / (rays[i+offset].mDirection.z - 1e-25f); 761 462 //invertedDir[indexR + 2] = 0.f; 762 463 rayDirs[indexR + 0] = rays[i+offset].mDirection.x < 0.f ? 1 : 0; … … 819 520 } 820 521 #endif 821 assert(tmin <= tmax);822 522 823 523 #ifdef __TRAVERSAL_STATISTICS … … 876 576 // which ray is processed 877 577 int indexR = indexRay[indexA]; 878 SimpleRay::IntersectionRes[indexR].maxt = tmax; 578 SimpleRay::IntersectionRes[indexR + rayOffset].maxt = 579 tmax + Limits::Small; 879 580 if (TestFullLeaf(rays[indexR+offset], currNode, indexR)) { 880 581 … … 934 635 #endif 935 636 stackA[indexSA].nodep = GetLinkNode(currNode); 637 GPREFETCH(stackA[indexSA].nodep, PREF_DEFAULT); 936 638 // cout << "Link node was accessed" << endl; 937 639 continue; … … 950 652 return cntHits; 951 653 } 952 #endif953 954 #ifdef __SSE__955 956 #if 1957 // Even faster - about 125,500 rays per second for single dir and 164 rps958 // for double dir !959 int960 CKTBTraversal::FindNearestI_16oneDir(SimpleRayContainer &rays, int offset)961 {962 static RayPacket2x2 raypack;963 struct SResultI {964 Intersectable *intersectable;965 float tdist;966 };967 static SResultI results[16];968 969 for (int i = 0; i < 4; i++) {970 int k = i * 4 + offset;971 for (int j = 0; j < 4; j++, k++) {972 raypack.SetLoc(j, rays[k].mOrigin);973 raypack.SetDir(j, rays[k].mDirection);974 }975 // Here either use ray packet traversal or976 // casting individual rays977 FindNearestI(raypack);978 k = i * 4;979 for (int j = 0; j < 4; j++, k++) {980 results[k].intersectable = raypack.GetObject(j);981 results[k].tdist = raypack.GetT(j);982 } // for j983 } // for i984 985 // Copy the results to the output array986 for (int i = 0; i < 16; i++) {987 SimpleRay::IntersectionRes[i].intersectable =988 results[i].intersectable;989 SimpleRay::IntersectionRes[i].tdist =990 results[i].tdist;991 } // for i992 return 0;993 }994 #endif995 996 #if 0997 // This code works well 1/1/2008 - 11:00998 // The same operations for packets of rays for the same signs,999 // otherwise it is emulated by decomposition1000 // of a packet to individual rays and traced individually.1001 void1002 CKTBTraversal::FindNearestI(RayPacket2x2 &rp)1003 {1004 int m1 = _mm_movemask_ps(rp.dx4);1005 if ((m1 == 0)||(m1 == 15)) {1006 m1 = _mm_movemask_ps(rp.dy4);1007 if ((m1 == 0)||(m1 == 15)) {1008 m1 = _mm_movemask_ps(rp.dz4);1009 if ((m1 == 0)||(m1 == 15)) {1010 rp.Init();1011 // all the signs for 4 rays are the same, use1012 // ray packet traversal1013 // Compute min and max distances1014 GALIGN16 union { float tmin4[4]; __m128 tmin_4; };1015 GALIGN16 union { float tmax4[4]; __m128 tmax_4; };1016 SimpleRay sray[4];1017 int maxIntersections = 4;1018 GALIGN16 union { int inters[4]; __m128 inters_4; };1019 inters[0] = inters[1] = inters[2] = inters[3] = 1;1020 unsigned int inters32 = 0xf;1021 for (int i = 0; i < 4; i++) {1022 bbox.ComputeMinMaxT(rp.GetLoc(i), rp.GetDir(i), &(tmin4[i]), &(tmax4[i]));1023 if ( (tmin4[i] >= tmax4[i]) ||1024 (tmax4[i] < 0.f) ) {1025 inters[i] = 0; // finished1026 inters32 &= ~(1 << i); // bit zero when ray is invalid1027 maxIntersections--;1028 }1029 if (tmin4[i] < 0.f)1030 tmin4[i] = 0.f;1031 sray[i].mOrigin = rp.GetLoc(i);1032 sray[i].mDirection = rp.GetDir(i);1033 } // for i1034 if (maxIntersections == 0)1035 return;1036 1037 SKTBNodeT * childNodes[2];1038 int RayDirs[3];1039 RayDirs[0] = (rp.dx[0] > 0.f) ? 1 : 0;1040 RayDirs[1] = (rp.dy[0] > 0.f) ? 1 : 0;1041 RayDirs[2] = (rp.dz[0] > 0.f) ? 1 : 0;1042 //int activeMask=_mm_movemask_ps(_mm_cmplt_ps( tmin_4, tmax_4 ))&inters32;1043 int activeMask = inters32;1044 int indexStack = 0;1045 SKTBNodeT *currNode = root;1046 unsigned int k = GetNodeType(currNode);1047 for (;;) {1048 while (k < CKTBAxes::EE_Leaf) {1049 // the 3 operations below can be brought down to 3 simple float1050 // calculations by precomputing min/max of the inverse dir1051 const __m128 node_split = _mm_set_ps1(GetSplitValue(currNode));1052 const __m128 t4 =1053 _mm_mul_ps(_mm_sub_ps(node_split, rp.orig[k]), rp.idir[k]);1054 childNodes[0] = GetLeft(currNode);1055 childNodes[1] = GetRight(currNode);1056 int rayDir = RayDirs[k];1057 SKTBNodeT *far = childNodes[rayDir];1058 if (!(_mm_movemask_ps(_mm_cmpgt_ps(t4, tmin_4)) & activeMask))1059 {1060 currNode = far;1061 k = GetNodeType(currNode);1062 continue;1063 }1064 currNode = childNodes[rayDir ^ 0x1]; // this is near node1065 k = GetNodeType(currNode);1066 if (! (_mm_movemask_ps(_mm_cmplt_ps( t4, tmax_4)) & activeMask))1067 continue;1068 1069 // pop far node to the stack1070 stack4[indexStack].nodep = far;1071 stack4[indexStack].tmax_4 = tmax_4;1072 stack4[indexStack].tmin_4 = _mm_max_ps(t4, tmin_4);1073 // stack4[indexStack].mask = activeMask;1074 indexStack++;1075 1076 tmax_4 = _mm_min_ps(t4, tmax_4);1077 activeMask &= _mm_movemask_ps(_mm_cmplt_ps( tmin_4, tmax_4 ));1078 } // while this is an interior node1079 1080 // either a leaf or a link1081 if (k == CKTBAxes::EE_Leaf) {1082 // test objects for intersection1083 if (!IsEmptyLeaf_(currNode)) {1084 // cout << "Full leaf" << endl;1085 1086 // test the objects in the full leaf against the ray1087 for (int i = 0; i < 4; i++) {1088 if (inters[i] ) {1089 // no intersection so far !1090 SimpleRay::IntersectionRes[i].maxt = tmax4[i];1091 // Test only rays that were not finished1092 if (TestFullLeaf(sray[i], currNode, i)) {1093 // intersection for this ray found1094 inters[i] = 0;1095 inters32 &= ~(1 << i);1096 rp.SetT(i, SimpleRay::IntersectionRes[0].maxt);1097 rp.SetObject(i, SimpleRay::IntersectionRes[0].intersectable);1098 // signed distance should be already set in TestFullLeaf1099 // the first object intersected was found1100 if (--maxIntersections == 0)1101 return;1102 }1103 } // if this ray did not hit the triangle so far1104 } // for all 4 rays1105 } // full leaf1106 // pop farChild from the stack1107 // restore the current values1108 // update the minimum distance since we traverse to the next one1109 1110 if (indexStack == 0)1111 return;1112 indexStack--;1113 currNode = stack4[indexStack].nodep;1114 k = GetNodeType(currNode);1115 tmin_4 = stack4[indexStack].tmin_4;1116 tmax_4 = stack4[indexStack].tmax_4;1117 activeMask = _mm_movemask_ps(_mm_cmple_ps( tmin_4, tmax_4 )) & inters32;1118 continue;1119 }1120 // cout << "Link node was accessed" << endl;1121 assert(k == CKTBAxes::EE_Link);1122 currNode = GetLinkNode(currNode);1123 k = GetNodeType(currNode);1124 } // for1125 return;1126 }}}1127 1128 // Trace ray by ray1129 SimpleRay ray;1130 for (int i = 0; i < 4; i++) {1131 ray.mOrigin = rp.GetLoc(i);1132 ray.mDirection = rp.GetDir(i);1133 FindNearestI(ray);1134 rp.SetObject(i, SimpleRay::IntersectionRes[0].intersectable);1135 rp.SetT(i, SimpleRay::IntersectionRes[0].tdist);1136 // SimpleRay::IntersectionRes[0].intersectable->GetNormal(0);1137 } // for1138 }1139 #endif1140 1141 1142 #if 11143 // This code also works well 1/1/2008 - 14:001144 // Using mask of 128-bits width - the code works as well, only a bit1145 // faster than the code above1146 void1147 CKTBTraversal::FindNearestI(RayPacket2x2 &rp)1148 {1149 int m1 = _mm_movemask_ps(rp.dx4);1150 if ((m1 == 0)||(m1 == 15)) {1151 m1 = _mm_movemask_ps(rp.dy4);1152 if ((m1 == 0)||(m1 == 15)) {1153 m1 = _mm_movemask_ps(rp.dz4);1154 if ((m1 == 0)||(m1 == 15)) {1155 rp.Init();1156 // all the signs for 4 rays are the same, use1157 // ray packet traversal1158 // Compute min and max distances1159 GALIGN16 union { float tmin4[4]; __m128 tmin_4; };1160 GALIGN16 union { float tmax4[4]; __m128 tmax_4; };1161 GALIGN16 union { float activeMask[4]; __m128 activeMask_4; };1162 GALIGN16 union { float liveMask[4]; __m128 liveMask_4; };1163 liveMask[0] = liveMask[1] = liveMask[2] = liveMask[3] = 0xffffffff;1164 1165 GALIGN16 SimpleRay sray[4];1166 int maxIntersections = 4;1167 // unsigned int inters32 = 0xf;1168 for (int i = 0; i < 4; i++) {1169 rp.SetObject(i, 0);1170 bbox.ComputeMinMaxT(rp.GetLoc(i), rp.GetDir(i), &(tmin4[i]), &(tmax4[i]));1171 if ( (tmin4[i] >= tmax4[i]) ||1172 (tmax4[i] < 0.f) ) {1173 liveMask[i] = 0; // finished1174 // inters32 &= ~(1 << i); // bit zero when ray is invalid1175 maxIntersections--;1176 }1177 if (tmin4[i] < 0.f)1178 tmin4[i] = 0.f;1179 sray[i].mOrigin = rp.GetLoc(i);1180 sray[i].mDirection = rp.GetDir(i);1181 } // for i1182 if (maxIntersections == 0)1183 return;1184 1185 // This is the mask 128 bits witdth1186 //activeMask_4 =1187 // _mm_and_ps(_mm_cmple_ps(tmin_4, tmax_4),1188 // _mm_cmplt_ps(tmax_4, _mm_setzero_ps()));1189 activeMask_4 = liveMask_4;1190 1191 SKTBNodeT * childNodes[2];1192 int RayDirs[4];1193 RayDirs[0] = (rp.dx[0] > 0.f) ? 1 : 0;1194 RayDirs[1] = (rp.dy[0] > 0.f) ? 1 : 0;1195 RayDirs[2] = (rp.dz[0] > 0.f) ? 1 : 0;1196 int indexStack = 0;1197 SKTBNodeT *currNode = root;1198 unsigned int k = GetNodeType(currNode);1199 for (;;) {1200 // traverse until we find a leaf1201 while (k < CKTBAxes::EE_Leaf) {1202 // the 3 operations below can be brought down to 3 simple float1203 // calculations by precomputing min/max of the inverse dir1204 // const __m128 node_split = ;1205 const __m128 t4 =1206 _mm_mul_ps(_mm_sub_ps(_mm_set_ps1(GetSplitValue(currNode)),1207 rp.orig[k]), rp.idir[k]);1208 childNodes[0] = GetLeft(currNode);1209 childNodes[1] = GetRight(currNode);1210 int rayDir = RayDirs[k];1211 SKTBNodeT *far = childNodes[rayDir];1212 if (_mm_movemask_ps(_mm_and_ps(_mm_cmpge_ps(t4, tmin_4),1213 activeMask_4))) {1214 currNode = far;1215 k = GetNodeType(currNode);1216 continue;1217 }1218 1219 currNode = childNodes[rayDir ^ 0x1]; // this is near node1220 k = GetNodeType(currNode);1221 if (_mm_movemask_ps(_mm_and_ps(_mm_cmple_ps(t4, tmax_4),1222 activeMask_4)))1223 continue;1224 1225 // pop far node to the stack1226 stack4[indexStack].nodep = far;1227 stack4[indexStack].tmax_4 = tmax_4;1228 1229 // Uncomenting this macro is unsafe!1230 // Not convinced if for packet of 4 rays we can say that since when1231 // one ray is different than the others, it could bring to wrong state1232 // It is surely true for one ray when tmin < t < tmax, but for a packet1233 // of rays this condition can be true only for a single ray1234 // tmin4 = max(t4, tmin4) = min(t4, tmax4)1235 //#define _NOT_STORE_MINT1236 1237 #ifdef _NOT_STORE_MINT1238 #else1239 // store mint onto the stack1240 stack4[indexStack].tmin_4 = _mm_max_ps(t4, tmin_4);1241 #endif1242 // stack4[indexStack].mask = activeMask;1243 indexStack++;1244 1245 tmax_4 = _mm_min_ps(t4, tmax_4);1246 activeMask_4 = _mm_cmplt_ps( tmin_4, tmax_4 );1247 } // while this is an interior node1248 1249 // either a leaf or a link1250 if (k == CKTBAxes::EE_Leaf) {1251 // test objects for intersection1252 if (!IsEmptyLeaf_(currNode)) {1253 // cout << "Full leaf" << endl;1254 1255 // test the objects in the full leaf against the ray1256 for (int i = 0; i < 4; i++) {1257 if (liveMask[i] ) {1258 // no intersection so far !1259 SimpleRay::IntersectionRes[i].maxt = tmax4[i];1260 #if 01261 // Using subroutine1262 // Test only rays that were not finished1263 if (TestFullLeaf(sray[i], currNode, i))1264 #else1265 // avoiding one call1266 const ObjectContainer * const list = GetObjList(currNode);1267 int intersected = 0;1268 // iterate the whole list and find out the nearest intersection1269 ObjectContainer::const_iterator sc_end = list->end();1270 for (ObjectContainer::const_iterator sc = list->begin(); sc != sc_end; sc++) {1271 // if the intersection realy lies in the node1272 intersected |= ((*sc)->CastSimpleRay(sray[i], i));1273 } // for all objects1274 if (intersected)1275 #endif1276 {1277 rp.SetT(i, SimpleRay::IntersectionRes[0].maxt);1278 rp.SetObject(i, SimpleRay::IntersectionRes[0].intersectable);1279 // signed distance should be already set in TestFullLeaf1280 // the first object intersected was found1281 if (--maxIntersections == 0)1282 return;1283 // inters32 &= ~(1 << i);1284 liveMask[i] = 0;1285 }1286 } // if this ray did not hit the triangle so far1287 } // for all 4 rays1288 } // full leaf1289 1290 // pop farChild from the stack1291 // restore the current values1292 // update the minimum distance since we traverse to the next one1293 do {1294 if (indexStack == 0)1295 return;1296 indexStack--;1297 currNode = stack4[indexStack].nodep;1298 k = GetNodeType(currNode);1299 #ifdef _NOT_STORE_MINT1300 // this is an attempt !1301 tmin_4 = tmax_4;1302 #else1303 // This surrely works1304 tmin_4 = stack4[indexStack].tmin_4;1305 #endif1306 tmax_4 = stack4[indexStack].tmax_4;1307 activeMask_4 = _mm_and_ps(_mm_cmple_ps( tmin_4, tmax_4 ), liveMask_4);1308 }1309 while (_mm_movemask_ps(activeMask_4) == 0);1310 }1311 else {1312 // cout << "Link node was accessed" << endl;1313 assert(k == CKTBAxes::EE_Link);1314 currNode = GetLinkNode(currNode);1315 k = GetNodeType(currNode);1316 }1317 } // for(;;)1318 return;1319 }}}1320 1321 // Trace ray by ray1322 SimpleRay ray;1323 for (int i = 0; i < 4; i++) {1324 ray.mOrigin = rp.GetLoc(i);1325 ray.mDirection = rp.GetDir(i);1326 FindNearestI(ray);1327 rp.SetObject(i, SimpleRay::IntersectionRes[0].intersectable);1328 rp.SetT(i, SimpleRay::IntersectionRes[0].tdist);1329 // SimpleRay::IntersectionRes[0].intersectable->GetNormal(0);1330 } // for1331 }1332 #endif1333 1334 #if 11335 // This code also works well 1/1/2008 - 14:001336 // Using mask of 128-bits width - the code works as well, only a bit1337 // faster than the code above1338 void1339 CKTBTraversal::FindNearestI(RayPacket2x2 &rp, Vector3 &boxmin, Vector3 &boxmax)1340 {1341 1342 static AxisAlignedBox3 localbox;1343 localbox.SetMin(boxmin);1344 localbox.SetMax(boxmax);1345 1346 #define USE_SIMPLE_VERSION 11347 1348 #if !USE_SIMPLE_VERSION1349 int m1 = _mm_movemask_ps(rp.dx4);1350 if ((m1 == 0)||(m1 == 15)) {1351 m1 = _mm_movemask_ps(rp.dy4);1352 if ((m1 == 0)||(m1 == 15)) {1353 m1 = _mm_movemask_ps(rp.dz4);1354 if ((m1 == 0)||(m1 == 15)) {1355 rp.Init();1356 1357 // all the signs for 4 rays are the same, use1358 // ray packet traversal1359 // Compute min and max distances1360 GALIGN16 union { float tmin4[4]; __m128 tmin_4; };1361 GALIGN16 union { float tmax4[4]; __m128 tmax_4; };1362 GALIGN16 union { float activeMask[4]; __m128 activeMask_4; };1363 GALIGN16 union { float liveMask[4]; __m128 liveMask_4; };1364 liveMask[0] = liveMask[1] = liveMask[2] = liveMask[3] = 0xffffffff;1365 1366 GALIGN16 SimpleRay sray[4];1367 int maxIntersections = 4;1368 // unsigned int inters32 = 0xf;1369 for (int i = 0; i < 4; i++) {1370 rp.SetObject(i, 0);1371 localbox.ComputeMinMaxT(rp.GetLoc(i), rp.GetDir(i), &(tmin4[i]), &(tmax4[i]));1372 if ( (tmin4[i] >= tmax4[i]) ||1373 (tmax4[i] < 0.f) ) {1374 liveMask[i] = 0; // finished1375 // inters32 &= ~(1 << i); // bit zero when ray is invalid1376 maxIntersections--;1377 }1378 if (tmin4[i] < 0.f)1379 tmin4[i] = 0.f;1380 sray[i].mOrigin = rp.GetLoc(i);1381 sray[i].mDirection = rp.GetDir(i);1382 } // for i1383 if (maxIntersections == 0)1384 return;1385 1386 // This is the mask 128 bits witdth1387 //activeMask_4 =1388 // _mm_and_ps(_mm_cmple_ps(tmin_4, tmax_4),1389 // _mm_cmplt_ps(tmax_4, _mm_setzero_ps()));1390 activeMask_4 = liveMask_4;1391 1392 SKTBNodeT * childNodes[2];1393 int RayDirs[4];1394 RayDirs[0] = (rp.dx[0] > 0.f) ? 1 : 0;1395 RayDirs[1] = (rp.dy[0] > 0.f) ? 1 : 0;1396 RayDirs[2] = (rp.dz[0] > 0.f) ? 1 : 0;1397 int indexStack = 0;1398 SKTBNodeT *currNode = root;1399 unsigned int k = GetNodeType(currNode);1400 for (;;) {1401 // traverse until we find a leaf1402 while (k < CKTBAxes::EE_Leaf) {1403 // the 3 operations below can be brought down to 3 simple float1404 // calculations by precomputing min/max of the inverse dir1405 // const __m128 node_split = ;1406 const __m128 t4 =1407 _mm_mul_ps(_mm_sub_ps(_mm_set_ps1(GetSplitValue(currNode)),1408 rp.orig[k]), rp.idir[k]);1409 childNodes[0] = GetLeft(currNode);1410 childNodes[1] = GetRight(currNode);1411 int rayDir = RayDirs[k];1412 SKTBNodeT *far = childNodes[rayDir];1413 if (_mm_movemask_ps(_mm_and_ps(_mm_cmpge_ps(t4, tmin_4),1414 activeMask_4))) {1415 currNode = far;1416 k = GetNodeType(currNode);1417 continue;1418 }1419 1420 currNode = childNodes[rayDir ^ 0x1]; // this is near node1421 k = GetNodeType(currNode);1422 if (_mm_movemask_ps(_mm_and_ps(_mm_cmple_ps(t4, tmax_4),1423 activeMask_4)))1424 continue;1425 1426 // pop far node to the stack1427 stack4[indexStack].nodep = far;1428 stack4[indexStack].tmax_4 = tmax_4;1429 1430 // Uncomenting this macro is unsafe!1431 // Not convinced if for packet of 4 rays we can say that since when1432 // one ray is different than the others, it could bring to wrong state1433 // It is surely true for one ray when tmin < t < tmax, but for a packet1434 // of rays this condition can be true only for a single ray1435 // tmin4 = max(t4, tmin4) = min(t4, tmax4)1436 //#define _NOT_STORE_MINT1437 1438 #ifdef _NOT_STORE_MINT1439 #else1440 // store mint onto the stack1441 stack4[indexStack].tmin_4 = _mm_max_ps(t4, tmin_4);1442 #endif1443 // stack4[indexStack].mask = activeMask;1444 indexStack++;1445 1446 tmax_4 = _mm_min_ps(t4, tmax_4);1447 activeMask_4 = _mm_cmplt_ps( tmin_4, tmax_4 );1448 } // while this is an interior node1449 1450 // either a leaf or a link1451 if (k == CKTBAxes::EE_Leaf) {1452 // test objects for intersection1453 if (!IsEmptyLeaf_(currNode)) {1454 // cout << "Full leaf" << endl;1455 1456 // test the objects in the full leaf against the ray1457 for (int i = 0; i < 4; i++) {1458 if (liveMask[i] ) {1459 // no intersection so far !1460 SimpleRay::IntersectionRes[i].maxt = tmax4[i];1461 #if 01462 // Using subroutine1463 // Test only rays that were not finished1464 if (TestFullLeaf(sray[i], currNode, i))1465 #else1466 // avoiding one call1467 const ObjectContainer * const list = GetObjList(currNode);1468 int intersected = 0;1469 // iterate the whole list and find out the nearest intersection1470 ObjectContainer::const_iterator sc_end = list->end();1471 for (ObjectContainer::const_iterator sc = list->begin(); sc != sc_end; sc++) {1472 // if the intersection realy lies in the node1473 intersected |= ((*sc)->CastSimpleRay(sray[i], i));1474 } // for all objects1475 if (intersected)1476 #endif1477 {1478 rp.SetT(i, SimpleRay::IntersectionRes[0].maxt);1479 rp.SetObject(i, SimpleRay::IntersectionRes[0].intersectable);1480 // signed distance should be already set in TestFullLeaf1481 // the first object intersected was found1482 if (--maxIntersections == 0)1483 return;1484 // inters32 &= ~(1 << i);1485 liveMask[i] = 0;1486 }1487 } // if this ray did not hit the triangle so far1488 } // for all 4 rays1489 } // full leaf1490 1491 // pop farChild from the stack1492 // restore the current values1493 // update the minimum distance since we traverse to the next one1494 do {1495 if (indexStack == 0)1496 return;1497 indexStack--;1498 currNode = stack4[indexStack].nodep;1499 k = GetNodeType(currNode);1500 #ifdef _NOT_STORE_MINT1501 // this is an attempt !1502 tmin_4 = tmax_4;1503 #else1504 // This surrely works1505 tmin_4 = stack4[indexStack].tmin_4;1506 #endif1507 tmax_4 = stack4[indexStack].tmax_4;1508 activeMask_4 = _mm_and_ps(_mm_cmple_ps( tmin_4, tmax_4 ), liveMask_4);1509 }1510 while (_mm_movemask_ps(activeMask_4) == 0);1511 }1512 else {1513 // cout << "Link node was accessed" << endl;1514 assert(k == CKTBAxes::EE_Link);1515 currNode = GetLinkNode(currNode);1516 k = GetNodeType(currNode);1517 }1518 } // for(;;)1519 return;1520 }}}1521 #endif1522 // Trace ray by ray1523 SimpleRay ray;1524 for (int i = 0; i < 4; i++) {1525 ray.mOrigin = rp.GetLoc(i);1526 ray.mDirection = rp.GetDir(i);1527 FindNearestI(ray, localbox);1528 rp.SetObject(i, SimpleRay::IntersectionRes[0].intersectable);1529 rp.SetT(i, SimpleRay::IntersectionRes[0].tdist);1530 // SimpleRay::IntersectionRes[0].intersectable->GetNormal(0);1531 } // for1532 }1533 #endif1534 1535 #endif // __SSE__1536 654 1537 655 #endif // TRV00F -
GTP/trunk/Lib/Vis/Preprocessing/src/havran/ktbtrav.h
r2583 r2592 30 30 31 31 namespace GtpVisibilityPreprocessor { 32 33 class RayPacket2x2;34 32 35 33 //#define TRV000 … … 136 134 public: 137 135 virtual int FindNearestI(const SimpleRay &ray) { return 0; } 136 virtual int FindNearestI(const SimpleRay &ray, const AxisAlignedBox3 &localbox) { return 0;} 138 137 void SetOffset(int offset) { rayOffset = offset; } 139 138 virtual int FindNearestI_16oneDir(SimpleRayContainer &rays) { return 0; } 140 virtual int FindNearestI_16oneDir(SimpleRayContainer &rays, int offset) 141 { return 0; } 139 virtual int FindNearestI_16oneDir(SimpleRayContainer &rays, 140 int offset, int copyOffset) { return 0; } 141 virtual int FindNearestI_16oneDirNoSSE(SimpleRayContainer &rays, int offset) { return 0; } 142 142 virtual int FindNearestI_16twoDir(SimpleRayContainer &rays) { return 0; } 143 143 … … 145 145 enum { MAX_NESTING = 2}; 146 146 147 #ifdef _USE_HAVRAN_SSE 147 148 // The same operations for packets of rays, if implemented by 148 149 // a particular ASDS, otherwise it is emulated by decomposition … … 150 151 virtual void FindNearestI(RayPacket2x2 &raypack) { } 151 152 virtual void FindNearestI(RayPacket2x2 &raypack, Vector3 &boxmin, Vector3 &boxmax) { } 152 153 #endif 154 153 155 virtual void PrintStatsTR(ostream &) { } 154 156 virtual void DynamicStatsReset() { } … … 306 308 virtual int FindNearestI(const SimpleRay &ray); 307 309 virtual int FindNearestI(const SimpleRay &ray, const AxisAlignedBox3 &localbox); 308 309 virtual int FindNearestI_16oneDir(SimpleRayContainer &rays) { 310 return FindNearestI_16oneDir(rays, 0); 311 } 312 // $$JB correction 313 virtual int FindNearestI_16oneDir(SimpleRayContainer &rays, int offset); 310 virtual int FindNearestI_16oneDir(SimpleRayContainer &rays, 311 int offset, int copyOffset) 312 #ifdef _USE_HAVRAN_SSE 313 ; // this is implemented with SSE in ktbftrav.cpp ! 314 #else 315 { return 0;} 316 #endif 317 318 virtual int FindNearestI_16oneDirNoSSE(SimpleRayContainer &rays, int offset); 314 319 315 320 int PrecomputeData(SimpleRayContainer &rays); … … 317 322 virtual int FindNearestI_16twoDir(SimpleRayContainer &rays); 318 323 324 #ifdef _USE_HAVRAN_SSE 319 325 #ifdef __SSE__ 320 326 // The same operations for packets of rays, if implemented by … … 324 330 virtual void FindNearestI(RayPacket2x2 &raypack, Vector3 &boxmin, Vector3 &boxmax); 325 331 #endif // __SSE__ 326 332 #endif // _USE_HAVRAN_SSE 333 327 334 virtual void PrintStatsTR(ostream &) { } 328 335 … … 408 415 virtual int FindNearestI(SimpleRay &ray); 409 416 417 #ifdef _USE_HAVRAN_SSE 410 418 #ifdef __SSE__ 411 419 // The same operations for packets of rays, if implemented by … … 415 423 virtual void FindNearestI(RayPacket2x2 &raypack, Vector3 &boxmin, Vector3 &boxmax); 416 424 #endif // __SSE__ 425 #endif // _USE_HAVRAN_SSE 417 426 418 427 virtual void DynamicStatsReset(); -
GTP/trunk/Lib/Vis/Preprocessing/src/havran/raypack.h
r2583 r2592 21 21 22 22 #include "Vector3.h" 23 #include "ktbconf.h" 24 25 #ifdef _USE_HAVRAN_SSE 23 26 24 27 #ifdef __SSE__ … … 337 340 // initialize inverted dir ? 338 341 #ifdef _USE_INVDIR_RP 339 // inverted dir - maybe an overkill for SSE340 // to be checked !341 idx[0] = 1.0f / dx[0];342 idx[1] = 1.0f / dx[1];343 idx[2] = 1.0f / dx[2];344 idx[3] = 1.0f / dx[3];345 346 idy[0] = 1.0f / dy[0];347 idy[1] = 1.0f / dy[1];348 idy[2] = 1.0f / dy[2];349 idy[3] = 1.0f / dy[3];350 351 idz[0] = 1.0f / dz[0];352 idz[1] = 1.0f / dz[1];353 idz[2] = 1.0f / dz[2];354 idz[3] = 1.0f / dz[3];342 // 343 const float epsAdd = -1e-25; 344 idx[0] = 1.0f / (dx[0] + epsAdd); 345 idx[1] = 1.0f / (dx[1] + epsAdd); 346 idx[2] = 1.0f / (dx[2] + epsAdd); 347 idx[3] = 1.0f / (dx[3] + epsAdd); 348 349 idy[0] = 1.0f / (dy[0] + epsAdd); 350 idy[1] = 1.0f / (dy[1] + epsAdd); 351 idy[2] = 1.0f / (dy[2] + epsAdd); 352 idy[3] = 1.0f / (dy[3] + epsAdd); 353 354 idz[0] = 1.0f / (dz[0] + epsAdd); 355 idz[1] = 1.0f / (dz[1] + epsAdd); 356 idz[2] = 1.0f / (dz[2] + epsAdd); 357 idz[3] = 1.0f / (dz[3] + epsAdd); 355 358 #endif 356 359 } … … 430 433 tmax[i] = tmaxnew; 431 434 } 432 #else // __SSE__433 434 // ? What to do here435 //#error "AAA"436 437 435 #endif // __SSE__ 438 436 437 #endif // _USE_HAVRAN_SSE 438 439 439 } // namespace 440 440 -
GTP/trunk/Lib/Vis/Preprocessing/src/preprocessor.pro
r2583 r2592 129 129 SOURCES += havran/allocgo2.cpp havran/ktbai.cpp havran/ktbtrav.cpp \ 130 130 havran/ktb.cpp havran/ktball.cpp havran/sbbox.cpp \ 131 havran/ktb8b.cpp havran/ktbftrav.cpp havran/ timer.cpp131 havran/ktb8b.cpp havran/ktbftrav.cpp havran/ktbf2trv.cpp havran/timer.cpp 132 132 133 133
Note: See TracChangeset
for help on using the changeset viewer.