- Timestamp:
- 11/14/05 11:12:38 (19 years ago)
- Location:
- trunk/VUT/GtpVisibilityPreprocessor
- Files:
-
- 2 edited
- 2 moved
Legend:
- Unmodified
- Added
- Removed
-
trunk/VUT/GtpVisibilityPreprocessor/scripts/Preprocessor.vcproj
r406 r408 291 291 </File> 292 292 <File 293 RelativePath="..\src\V iewCellKd.cpp">294 </File> 295 <File 296 RelativePath="..\src\V iewCellKd.h">293 RelativePath="..\src\VspKdTree.cpp"> 294 </File> 295 <File 296 RelativePath="..\src\VspKdTree.h"> 297 297 </File> 298 298 <File -
trunk/VUT/GtpVisibilityPreprocessor/src/Environment.cpp
r406 r408 1322 1322 1323 1323 1324 RegisterOption("VssTree.maxDepth", optInt, "kd_depth=", "12"); 1324 RegisterOption("VspKdTree.maxDepth", optInt, "kd_depth=", "12"); 1325 RegisterOption("VspKdTree.minPvs", optInt, "kd_minpvs=", "1"); 1326 RegisterOption("VspKdTree.minRays", optInt, "kd_minrays=", "10"); 1327 RegisterOption("VspKdTree.maxCostRatio", optFloat, "maxcost=", "0.95"); 1328 RegisterOption("VspKdTree.maxRayContribution", optFloat, "maxraycontrib=", "0.5"); 1329 1330 RegisterOption("VspKdTree.epsilon", optFloat, "kd_eps=", "1e-6"); 1331 RegisterOption("VspKdTree.ct_div_ci", optFloat, "kd_ctdivci=", "1.0"); 1332 RegisterOption("VspKdTree.randomize", optBool, "randomize", "false"); 1333 RegisterOption("VspKdTree.splitType", optString, "split=", "queries"); 1334 RegisterOption("VspKdTree.numberOfEndPointDomains", optInt, "endpoints=", "10000"); 1335 1336 RegisterOption("VspKdTree.minSize", optFloat, "minsize=", "0.001"); 1337 1338 RegisterOption("VspKdTree.maxTotalMemory", optFloat, "mem=", "60.0"); 1339 RegisterOption("VspKdTree.maxStaticMemory", optFloat, "statmem=", "8.0"); 1340 1341 RegisterOption("VspKdTree.queryType", optString, "qtype=", "static"); 1342 1343 RegisterOption("VspKdTree.queryPosWeight", optFloat, "qposweight=", "0.0"); 1344 RegisterOption("VspKdTree.useRefDirSplits", optBool, "refdir", "false"); 1345 RegisterOption("VspKdTree.refDirAngle", optFloat, "refangle=", "10"); 1346 RegisterOption("VspKdTree.refDirBoxMaxSize", optFloat, "refboxsize=", "0.1"); 1347 RegisterOption("VspKdTree.accessTimeThreshold", optInt, "accesstime=", "1000"); 1348 RegisterOption("VspKdTree.minCollapseDepth", optInt, "colldepth=", "4"); 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 RegisterOption("VssTree.maxDepth", optInt, "kd_depth=", "12"); 1325 1360 RegisterOption("VssTree.minPvs", optInt, "kd_minpvs=", "1"); 1326 1361 RegisterOption("VssTree.minRays", optInt, "kd_minrays=", "10"); … … 1347 1382 RegisterOption("VssTree.accessTimeThreshold", optInt, "accesstime=", "1000"); 1348 1383 RegisterOption("VssTree.minCollapseDepth", optInt, "colldepth=", "4"); 1349 1350 1384 } 1351 1385 -
trunk/VUT/GtpVisibilityPreprocessor/src/VspKdTree.cpp
r406 r408 1 2 // ================================================================ 3 // $Id: lsds_kdtree.cpp,v 1.18 2005/04/16 09:34:21 bittner Exp $ 4 // **************************************************************** 5 /** 6 The KD tree based LSDS 7 */ 8 // Initial coding by 9 /** 10 @author Jiri Bittner 11 */ 12 13 // Standard headers 1 14 #include <stack> 15 #include <queue> 2 16 #include <algorithm> 3 #include <queue> 17 #include <fstream> 18 #include <string> 19 20 #include "VspKdTree.h" 21 4 22 #include "Environment.h" 5 #include "Mesh.h" 6 #include "ViewCellKd.h" 7 8 9 int ViewCellKdNode::mailID = 1; 10 11 12 ViewCellKdNode::ViewCellKdNode(ViewCellKdInterior *parent):mParent(parent), mailbox(0) 13 { 14 if (parent) 15 mDepth = parent->mDepth+1; 23 #include "VssRay.h" 24 #include "Intersectable.h" 25 #include "Ray.h" 26 27 28 #define DEBUG_DIR_SPLIT 0 29 30 31 32 // Static variables 33 int 34 VspKdTreeLeaf::mailID = 0; 35 36 inline void 37 AddObject2Pvs(Intersectable *object, 38 const int side, 39 int &pvsBack, 40 int &pvsFront) 41 { 42 43 if (!object) 44 return; 45 46 if (side <= 0) { 47 if (!object->Mailed() && !object->Mailed(2)) { 48 pvsBack++; 49 if (object->Mailed(1)) 50 object->Mail(2); 51 else 52 object->Mail(); 53 } 54 } 55 56 if (side >= 0) { 57 if (!object->Mailed(1) && !object->Mailed(2)) { 58 pvsFront++; 59 if (object->Mailed()) 60 object->Mail(2); 61 else 62 object->Mail(1); 63 } 64 } 65 } 66 67 68 // Constructor 69 VspKdTree::VspKdTree() 70 { 71 environment->GetIntValue("VspKdTree.maxDepth", termMaxDepth); 72 environment->GetIntValue("VspKdTree.minPvs", termMinPvs); 73 environment->GetIntValue("VspKdTree.minRays", termMinRays); 74 environment->GetFloatValue("VspKdTree.maxRayContribution", termMaxRayContribution); 75 environment->GetFloatValue("VspKdTree.maxCostRatio", termMaxCostRatio); 76 77 environment->GetFloatValue("VspKdTree.minSize", termMinSize); 78 termMinSize = sqr(termMinSize); 79 80 environment->GetFloatValue("VspKdTree.refDirBoxMaxSize", refDirBoxMaxSize); 81 refDirBoxMaxSize = sqr(refDirBoxMaxSize); 82 83 environment->GetFloatValue("VspKdTree.epsilon", epsilon); 84 environment->GetFloatValue("VspKdTree.ct_div_ci", ct_div_ci); 85 86 environment->GetFloatValue("VspKdTree.maxTotalMemory", maxTotalMemory); 87 environment->GetFloatValue("VspKdTree.maxStaticMemory", maxStaticMemory); 88 89 90 91 92 float refDirAngle; 93 environment->GetFloatValue("VspKdTree.refDirAngle", refDirAngle); 94 95 environment->GetIntValue("VspKdTree.accessTimeThreshold", accessTimeThreshold); 96 //= 1000; 97 environment->GetIntValue("VspKdTree.minCollapseDepth", minCollapseDepth); 98 // int minCollapseDepth = 4; 99 100 // pRefDirThresh = cos(0.5*M_PI - M_PI*refDirAngle/180.0); 101 // cosRefDir = cos(M_PI*refDirAngle/180.0); 102 // sinRefDir = sin(M_PI*refDirAngle/180.0); 103 104 105 // split type 106 char sname[128]; 107 environment->GetStringValue("VspKdTree.splitType", sname); 108 string name(sname); 109 110 if (name.compare("regular") == 0) 111 splitType = ESplitRegular; 16 112 else 17 mDepth = 0; 18 } 19 20 ViewCellKd::ViewCellKd() 21 { 22 mRoot = new ViewCellKdLeaf(NULL, 0); 23 environment->GetIntValue("ViewCellKd.Termination.maxDepth", mTermMaxDepth); 24 environment->GetIntValue("ViewCellKd.Termination.minCost", mTermMinCost); 25 environment->GetFloatValue("ViewCellKd.Termination.maxCostRatio", mMaxCostRatio); 26 environment->GetFloatValue("ViewCellKd.Termination.ct_div_ci", mCt_div_ci); 27 environment->GetFloatValue("ViewCellKd.splitBorder", mSplitBorder); 28 29 environment->GetBoolValue("ViewCellKd.sahUseFaces", mSahUseFaces); 30 31 char splitType[64]; 32 environment->GetStringValue("ViewCellKd.splitMethod", splitType); 33 34 mSplitMethod = SPLIT_SPATIAL_MEDIAN; 35 if (strcmp(splitType, "spatialMedian") == 0) 36 mSplitMethod = SPLIT_SPATIAL_MEDIAN; 37 else 38 if (strcmp(splitType, "objectMedian") == 0) 39 mSplitMethod = SPLIT_OBJECT_MEDIAN; 40 else 41 if (strcmp(splitType, "SAH") == 0) 42 mSplitMethod = SPLIT_SAH; 43 else { 44 cerr<<"Wrong kd split type "<<splitType<<endl; 45 exit(1); 46 } 47 splitCandidates = NULL; 48 } 49 50 bool 51 ViewCellKd::Construct() 52 { 53 if (!splitCandidates) 113 if (name.compare("heuristic") == 0) 114 splitType = ESplitHeuristic; 115 else { 116 cerr<<"Invalid VspKdTree split type "<<name<<endl; 117 exit(1); 118 } 119 120 environment->GetBoolValue("VspKdTree.randomize", randomize); 121 122 root = NULL; 123 124 splitCandidates = new vector<SortableEntry>; 125 } 126 127 128 VspKdTree::~VspKdTree() 129 { 130 if (root) 131 delete root; 132 } 133 134 135 136 137 void 138 VspKdStatistics::Print(ostream &app) const 139 { 140 app << "===== VspKdTree statistics ===============\n"; 141 142 app << "#N_RAYS ( Number of rays )\n" 143 << rays <<endl; 144 145 app << "#N_INITPVS ( Initial PVS size )\n" 146 << initialPvsSize <<endl; 147 148 app << "#N_NODES ( Number of nodes )\n" << nodes << "\n"; 149 150 app << "#N_LEAVES ( Number of leaves )\n" << Leaves() << "\n"; 151 152 app << "#N_SPLITS ( Number of splits in axes x y z dx dy dz \n"; 153 for (int i=0; i<7; i++) 154 app << splits[i] <<" "; 155 app <<endl; 156 157 app << "#N_RAYREFS ( Number of rayRefs )\n" << 158 rayRefs << "\n"; 159 160 app << "#N_RAYRAYREFS ( Number of rayRefs / ray )\n" << 161 rayRefs/(double)rays << "\n"; 162 163 app << "#N_LEAFRAYREFS ( Number of rayRefs / leaf )\n" << 164 rayRefs/(double)Leaves() << "\n"; 165 166 app << "#N_MAXRAYREFS ( Max number of rayRefs / leaf )\n" << 167 maxRayRefs << "\n"; 168 169 170 // app << setprecision(4); 171 172 app << "#N_PMAXDEPTHLEAVES ( Percentage of leaves at maxdepth )\n"<< 173 maxDepthNodes*100/(double)Leaves()<<endl; 174 175 app << "#N_PMINPVSLEAVES ( Percentage of leaves with minCost )\n"<< 176 minPvsNodes*100/(double)Leaves()<<endl; 177 178 app << "#N_PMINRAYSLEAVES ( Percentage of leaves with minCost )\n"<< 179 minRaysNodes*100/(double)Leaves()<<endl; 180 181 app << "#N_PMINSIZELEAVES ( Percentage of leaves with minSize )\n"<< 182 minSizeNodes*100/(double)Leaves()<<endl; 183 184 app << "#N_PMAXRAYCONTRIBLEAVES ( Percentage of leaves with maximal ray contribution )\n"<< 185 maxRayContribNodes*100/(double)Leaves()<<endl; 186 187 app << "#N_ADDED_RAYREFS (Number of dynamically added ray references )\n"<< 188 addedRayRefs<<endl; 189 190 app << "#N_REMOVED_RAYREFS (Number of dynamically removed ray references )\n"<< 191 removedRayRefs<<endl; 192 193 // app << setprecision(4); 194 195 app << "#N_CTIME ( Construction time [s] )\n" 196 << Time() << " \n"; 197 198 app << "===== END OF VspKdTree statistics ==========\n"; 199 200 } 201 202 203 void 204 VspKdTreeLeaf::UpdatePvsSize() 205 { 206 if (!mValidPvs) { 207 Intersectable::NewMail(); 208 int pvsSize = 0; 209 for(VspKdTreeNode::RayInfoContainer::iterator ri = rays.begin(); 210 ri != rays.end(); 211 ri++) 212 if ((*ri).mRay->IsActive()) { 213 Intersectable *object; 214 #if BIDIRECTIONAL_RAY 215 object = (*ri).mRay->mOriginObject; 216 if (object && !object->Mailed()) { 217 pvsSize++; 218 object->Mail(); 219 } 220 #endif 221 object = (*ri).mRay->mTerminationObject; 222 if (object && !object->Mailed()) { 223 pvsSize++; 224 object->Mail(); 225 } 226 } 227 mPvsSize = pvsSize; 228 mValidPvs = true; 229 } 230 } 231 232 233 void 234 VspKdTree::Construct( 235 VssRayContainer &rays, 236 AxisAlignedBox3 *forcedBoundingBox 237 ) 238 { 239 stat.Start(); 240 241 maxMemory = maxStaticMemory; 242 243 if (root) 244 delete root; 245 246 root = new VspKdTreeLeaf(NULL, rays.size()); 247 // first construct a leaf that will get subdivide 248 VspKdTreeLeaf *leaf = (VspKdTreeLeaf *) root; 249 250 stat.nodes = 1; 251 252 bbox.Initialize(); 253 dirBBox.Initialize(); 254 255 for(VssRayContainer::const_iterator ri = rays.begin(); 256 ri != rays.end(); 257 ri++) { 258 leaf->AddRay(VspKdTreeNode::RayInfo(*ri)); 259 260 bbox.Include((*ri)->GetOrigin()); 261 bbox.Include((*ri)->GetTermination()); 262 263 264 dirBBox.Include(Vector3( 265 (*ri)->GetDirParametrization(0), 266 (*ri)->GetDirParametrization(1), 267 0 268 ) 269 ); 270 } 271 272 273 if ( forcedBoundingBox ) 274 bbox = *forcedBoundingBox; 275 276 cout<<"Bbox = "<<bbox<<endl; 277 cout<<"Dirr Bbox = "<<dirBBox<<endl; 278 279 stat.rays = leaf->rays.size(); 280 leaf->UpdatePvsSize(); 281 stat.initialPvsSize = leaf->GetPvsSize(); 282 // Subdivide(); 283 root = Subdivide(TraversalData(leaf, bbox, 0)); 284 285 if (splitCandidates) { 286 // force realease of this vector 287 delete splitCandidates; 54 288 splitCandidates = new vector<SortableEntry>; 55 56 // first construct a leaf that will get subdivide 57 ViewCellKdLeaf *leaf = (ViewCellKdLeaf *) mRoot; 58 59 mStat.nodes = 1; 60 61 mBox.Initialize(); 62 63 ObjectContainer::const_iterator mi; 64 for ( mi = leaf->mObjects.begin(); 65 mi != leaf->mObjects.end(); 66 mi++) { 67 mBox.Include((*mi)->GetBox()); 68 } 69 70 cout <<"ViewCellKd Root Box:"<< mBox<<endl; 71 mRoot = Subdivide(TraversalData(leaf, mBox, 0)); 72 73 // remove the allocated array 74 delete splitCandidates; 75 76 return true; 77 } 78 79 ViewCellKdNode * 80 ViewCellKd::Subdivide(const TraversalData &tdata) 81 { 82 83 ViewCellKdNode *result = NULL; 289 } 290 291 stat.Stop(); 292 293 stat.Print(cout); 294 cout<<"#Total memory="<<GetMemUsage()<<endl; 295 296 } 297 298 299 300 VspKdTreeNode * 301 VspKdTree::Subdivide(const TraversalData &tdata) 302 { 303 VspKdTreeNode *result = NULL; 84 304 85 305 priority_queue<TraversalData> tStack; 86 // stack< STraversalData> tStack;306 // stack<TraversalData> tStack; 87 307 88 308 tStack.push(tdata); 89 AxisAlignedBox3 backBox, frontBox; 90 91 309 310 AxisAlignedBox3 backBox; 311 AxisAlignedBox3 frontBox; 312 313 314 int lastMem = 0; 92 315 while (!tStack.empty()) { 93 316 94 #if 0 95 if ( GetMemUsage() > maxMemory ) { 317 float mem = GetMemUsage(); 318 319 if ( lastMem/10 != ((int)mem)/10) { 320 cout<<mem<<" MB"<<endl; 321 } 322 lastMem = (int)mem; 323 324 if ( mem > maxMemory ) { 96 325 // count statistics on unprocessed leafs 97 326 while (!tStack.empty()) { 98 EvaluateLeafStats(tStack.top());99 tStack.pop();327 EvaluateLeafStats(tStack.top()); 328 tStack.pop(); 100 329 } 101 330 break; 102 331 } 103 #endif 104 332 105 333 TraversalData data = tStack.top(); 106 334 tStack.pop(); 107 335 108 V iewCellKdNode *node = SubdivideNode((ViewCellKdLeaf *) data.mNode,109 data.mBox,110 111 112 336 VspKdTreeNode *node = SubdivideNode((VspKdTreeLeaf *) data.node, 337 data.bbox, 338 backBox, 339 frontBox 340 ); 113 341 if (result == NULL) 114 342 result = node; 115 343 116 344 if (!node->IsLeaf()) { 117 118 V iewCellKdInterior *interior = (ViewCellKdInterior *) node;345 346 VspKdTreeInterior *interior = (VspKdTreeInterior *) node; 119 347 // push the children on the stack 120 tStack.push(TraversalData(interior-> mBack, backBox, data.mDepth+1));121 tStack.push(TraversalData(interior-> mFront, frontBox, data.mDepth+1));122 348 tStack.push(TraversalData(interior->back, backBox, data.depth+1)); 349 tStack.push(TraversalData(interior->front, frontBox, data.depth+1)); 350 123 351 } else { 124 352 EvaluateLeafStats(data); 125 353 } 126 354 } 127 355 128 356 return result; 129 130 } 131 132 133 134 bool 135 ViewCellKd::TerminationCriteriaMet(const ViewCellKdLeaf *leaf) 136 { 137 // cerr<<"\n OBJECTS="<<leaf->mObjects.size()<<endl; 138 return 139 (leaf->mObjects.size() <= mTermMinCost) || 140 (leaf->mDepth >= mTermMaxDepth); 141 142 } 143 144 357 } 358 359 360 // returns selected plane for subdivision 145 361 int 146 ViewCellKd::SelectPlane(ViewCellKdLeaf *leaf, 147 const AxisAlignedBox3 &box, 148 float &position 149 ) 150 { 151 int axis = -1; 152 153 switch (mSplitMethod) 154 { 155 case SPLIT_SPATIAL_MEDIAN: { 156 axis = box.Size().DrivingAxis(); 157 position = (box.Min()[axis] + box.Max()[axis])*0.5f; 158 break; 362 VspKdTree::SelectPlane( 363 VspKdTreeLeaf *leaf, 364 const AxisAlignedBox3 &box, 365 float &position, 366 int &raysBack, 367 int &raysFront, 368 int &pvsBack, 369 int &pvsFront 370 ) 371 { 372 373 int minDirDepth = 6; 374 int axis; 375 float costRatio; 376 377 if (splitType == ESplitRegular) { 378 costRatio = BestCostRatioRegular(leaf, 379 axis, 380 position, 381 raysBack, 382 raysFront, 383 pvsBack, 384 pvsFront 385 ); 386 387 } else { 388 if (splitType == ESplitHeuristic) 389 costRatio = BestCostRatioHeuristic(leaf, 390 axis, 391 position, 392 raysBack, 393 raysFront, 394 pvsBack, 395 pvsFront 396 ); 397 else { 398 cerr<<"VspKdTree: Unknown split heuristics\n"; 399 exit(1); 400 } 401 } 402 403 if (costRatio > termMaxCostRatio) { 404 // cout<<"Too big cost ratio "<<costRatio<<endl; 405 return -1; 406 } 407 408 #if 0 409 cout<< 410 "pvs="<<leaf->mPvsSize<< 411 " rays="<<leaf->rays.size()<< 412 " rc="<<leaf->GetAvgRayContribution()<< 413 " axis="<<axis<<endl; 414 #endif 415 416 return axis; 417 } 418 419 420 421 422 float 423 VspKdTree::EvalCostRatio( 424 VspKdTreeLeaf *leaf, 425 const int axis, 426 const float position, 427 int &raysBack, 428 int &raysFront, 429 int &pvsBack, 430 int &pvsFront 431 ) 432 { 433 raysBack = 0; 434 raysFront = 0; 435 pvsFront = 0; 436 pvsBack = 0; 437 438 float newCost; 439 440 Intersectable::NewMail(3); 441 442 // eval pvs size 443 int pvsSize = leaf->GetPvsSize(); 444 445 Intersectable::NewMail(3); 446 447 if (axis <= VspKdTreeNode::SPLIT_Z) { 448 // this is the main ray classification loop! 449 for(VspKdTreeNode::RayInfoContainer::iterator ri = leaf->rays.begin(); 450 ri != leaf->rays.end(); 451 ri++) 452 if ((*ri).mRay->IsActive()) { 453 454 // determine the side of this ray with respect to the plane 455 int side = (*ri).ComputeRayIntersection(axis, position, (*ri).mRay->mT); 456 // (*ri).mRay->mSide = side; 457 458 if (side <= 0) 459 raysBack++; 460 461 if (side >= 0) 462 raysFront++; 463 464 AddObject2Pvs((*ri).mRay->mTerminationObject, side, pvsBack, pvsFront); 465 } 466 467 AxisAlignedBox3 box = GetBBox(leaf); 468 469 float minBox = box.Min(axis); 470 float maxBox = box.Max(axis); 471 float sizeBox = maxBox - minBox; 472 473 // float sum = raysBack*(position - minBox) + raysFront*(maxBox - position); 474 float sum = pvsBack*(position - minBox) + pvsFront*(maxBox - position); 475 476 newCost = ct_div_ci + sum/sizeBox; 477 478 } else { 479 480 // directional split 481 for(VspKdTreeNode::RayInfoContainer::iterator ri = leaf->rays.begin(); 482 ri != leaf->rays.end(); 483 ri++) 484 if ((*ri).mRay->IsActive()) { 485 486 // determine the side of this ray with respect to the plane 487 int side; 488 if ((*ri).mRay->GetDirParametrization(axis - 3) > position) 489 side = 1; 490 else 491 side = -1; 492 493 if (side <= 0) 494 raysBack++; 495 496 if (side >= 0) 497 raysFront++; 498 499 // (*ri).mRay->mSide = side; 500 AddObject2Pvs((*ri).mRay->mTerminationObject, side, pvsBack, pvsFront); 501 502 } 503 504 AxisAlignedBox3 box = GetDirBBox(leaf); 505 506 float minBox = box.Min(axis-3); 507 float maxBox = box.Max(axis-3); 508 float sizeBox = maxBox - minBox; 509 510 // float sum = raysBack*(position - minBox) + raysFront*(maxBox - position); 511 float sum = 512 pvsBack*(position - minBox) + 513 pvsFront*(maxBox - position); 514 // float sum = pvsBack + pvsFront; 515 newCost = ct_div_ci + sum/sizeBox; 516 } 517 518 // cout<<axis<<" "<<pvsSize<<" "<<pvsBack<<" "<<pvsFront<<endl; 519 // float oldCost = leaf->rays.size(); 520 float oldCost = pvsSize; 521 float ratio = newCost/oldCost; 522 // cout<<"ratio="<<ratio<<endl; 523 return ratio; 524 } 525 526 float 527 VspKdTree::BestCostRatioRegular( 528 VspKdTreeLeaf *leaf, 529 int &axis, 530 float &position, 531 int &raysBack, 532 int &raysFront, 533 int &pvsBack, 534 int &pvsFront 535 ) 536 { 537 int nRaysBack[6], nRaysFront[6]; 538 int nPvsBack[6], nPvsFront[6]; 539 float nPosition[6]; 540 float nCostRatio[6]; 541 int bestAxis = -1; 542 543 AxisAlignedBox3 sBox = GetBBox(leaf); 544 AxisAlignedBox3 dBox = GetDirBBox(leaf); 545 // int sAxis = box.Size().DrivingAxis(); 546 int sAxis = sBox.Size().DrivingAxis(); 547 int dAxis = dBox.Size().DrivingAxis() + 3; 548 549 bool onlyDrivingAxis = true; 550 551 for (axis = 0; axis < 6; axis++) { 552 if (!onlyDrivingAxis || axis == sAxis || axis == dAxis) { 553 if (axis < 3) 554 nPosition[axis] = (sBox.Min()[axis] + sBox.Max()[axis])*0.5f; 555 else 556 nPosition[axis] = (dBox.Min()[axis-3] + dBox.Max()[axis-3])*0.5f; 557 558 nCostRatio[axis] = EvalCostRatio(leaf, 559 axis, 560 nPosition[axis], 561 nRaysBack[axis], 562 nRaysFront[axis], 563 nPvsBack[axis], 564 nPvsFront[axis] 565 ); 566 567 if ( bestAxis == -1) 568 bestAxis = axis; 569 else 570 if ( nCostRatio[axis] < nCostRatio[bestAxis] ) 571 bestAxis = axis; 572 } 573 } 574 575 axis = bestAxis; 576 position = nPosition[bestAxis]; 577 578 raysBack = nRaysBack[bestAxis]; 579 raysFront = nRaysFront[bestAxis]; 580 581 pvsBack = nPvsBack[bestAxis]; 582 pvsFront = nPvsFront[bestAxis]; 583 584 return nCostRatio[bestAxis]; 585 } 586 587 float 588 VspKdTree::BestCostRatioHeuristic( 589 VspKdTreeLeaf *leaf, 590 int &axis, 591 float &position, 592 int &raysBack, 593 int &raysFront, 594 int &pvsBack, 595 int &pvsFront 596 ) 597 { 598 AxisAlignedBox3 box = GetBBox(leaf); 599 // AxisAlignedBox3 dirBox = GetDirBBox(node); 600 601 axis = box.Size().DrivingAxis(); 602 603 SortSplitCandidates(leaf, axis); 604 605 // go through the lists, count the number of objects left and right 606 // and evaluate the following cost funcion: 607 // C = ct_div_ci + (ql*rl + qr*rr)/queries 608 609 int rl=0, rr = leaf->rays.size(); 610 int pl=0, pr = leaf->GetPvsSize(); 611 float minBox = box.Min(axis); 612 float maxBox = box.Max(axis); 613 float sizeBox = maxBox - minBox; 614 615 float minBand = minBox + 0.1*(maxBox - minBox); 616 float maxBand = minBox + 0.9*(maxBox - minBox); 617 618 float sum = rr*sizeBox; 619 float minSum = 1e20; 620 621 Intersectable::NewMail(); 622 // set all object as belonging to the fron pvs 623 for(VspKdTreeNode::RayInfoContainer::iterator ri = leaf->rays.begin(); 624 ri != leaf->rays.end(); 625 ri++) 626 if ((*ri).mRay->IsActive()) { 627 Intersectable *object = (*ri).mRay->mTerminationObject; 628 if (object) 629 if (!object->Mailed()) { 630 object->Mail(); 631 object->mCounter = 1; 632 } else 633 object->mCounter++; 634 } 635 636 Intersectable::NewMail(); 637 638 for(vector<SortableEntry>::const_iterator ci = splitCandidates->begin(); 639 ci < splitCandidates->end(); 640 ci++) { 641 VssRay *ray; 642 switch ((*ci).type) { 643 case SortableEntry::ERayMin: { 644 rl++; 645 ray = (VssRay *) (*ci).data; 646 Intersectable *object = ray->mTerminationObject; 647 if (object && !object->Mailed()) { 648 object->Mail(); 649 pl++; 650 } 651 break; 652 } 653 case SortableEntry::ERayMax: { 654 rr--; 655 ray = (VssRay *) (*ci).data; 656 Intersectable *object = ray->mTerminationObject; 657 if (object) { 658 if (--object->mCounter == 0) 659 pr--; 660 } 661 break; 662 } 663 } 664 if ((*ci).value > minBand && (*ci).value < maxBand) { 665 666 sum = pl*((*ci).value - minBox) + pr*(maxBox - (*ci).value); 667 668 // cout<<"pos="<<(*ci).value<<"\t q=("<<ql<<","<<qr<<")\t r=("<<rl<<","<<rr<<")"<<endl; 669 // cout<<"cost= "<<sum<<endl; 670 671 if (sum < minSum) { 672 minSum = sum; 673 position = (*ci).value; 674 675 raysBack = rl; 676 raysFront = rr; 677 678 pvsBack = pl; 679 pvsFront = pr; 680 681 } 159 682 } 160 case SPLIT_SAH: { 161 int objectsBack, objectsFront; 162 float costRatio; 163 bool mOnlyDrivingAxis = false; 164 if (mOnlyDrivingAxis) { 165 axis = box.Size().DrivingAxis(); 166 costRatio = BestCostRatio(leaf, 167 box, 168 axis, 169 position, 170 objectsBack, 171 objectsFront); 172 } else { 173 costRatio = MAX_FLOAT; 174 for (int i=0; i < 3; i++) { 175 float p; 176 float r = BestCostRatio(leaf, 177 box, 178 i, 179 p, 180 objectsBack, 181 objectsFront); 182 if (r < costRatio) { 183 costRatio = r; 184 axis = i; 185 position = p; 186 } 187 } 188 } 189 190 if (costRatio > mMaxCostRatio) { 191 // cout<<"Too big cost ratio "<<costRatio<<endl; 192 axis = -1; 193 } 194 break; 195 } 196 197 } 198 return axis; 199 } 200 201 ViewCellKdNode * 202 ViewCellKd::SubdivideNode( 203 ViewCellKdLeaf *leaf, 204 const AxisAlignedBox3 &box, 205 AxisAlignedBox3 &backBBox, 206 AxisAlignedBox3 &frontBBox 207 ) 208 { 209 210 if (TerminationCriteriaMet(leaf)) 211 return leaf; 212 213 float position; 214 215 // select subdivision axis 216 int axis = SelectPlane( leaf, box, position ); 217 218 if (axis == -1) { 219 return leaf; 220 } 221 222 mStat.nodes+=2; 223 mStat.splits[axis]++; 224 225 // add the new nodes to the tree 226 ViewCellKdInterior *node = new ViewCellKdInterior(leaf->mParent); 227 228 node->mAxis = axis; 229 node->mPosition = position; 230 node->mBox = box; 231 232 backBBox = box; 233 frontBBox = box; 234 235 // first count ray sides 236 int objectsBack = 0; 237 int objectsFront = 0; 238 239 backBBox.SetMax(axis, position); 240 frontBBox.SetMin(axis, position); 241 242 ObjectContainer::const_iterator mi; 243 244 for ( mi = leaf->mObjects.begin(); 245 mi != leaf->mObjects.end(); 246 mi++) { 247 // determine the side of this ray with respect to the plane 248 AxisAlignedBox3 box = (*mi)->GetBox(); 249 if (box.Max(axis) > position ) 250 objectsFront++; 251 252 if (box.Min(axis) < position ) 253 objectsBack++; 254 } 255 256 257 ViewCellKdLeaf *back = new ViewCellKdLeaf(node, objectsBack); 258 ViewCellKdLeaf *front = new ViewCellKdLeaf(node, objectsFront); 259 260 // replace a link from node's parent 261 if ( leaf->mParent ) 262 leaf->mParent->ReplaceChildLink(leaf, node); 263 264 // and setup child links 265 node->SetupChildLinks(back, front); 266 267 for (mi = leaf->mObjects.begin(); 268 mi != leaf->mObjects.end(); 269 mi++) { 270 // determine the side of this ray with respect to the plane 271 AxisAlignedBox3 box = (*mi)->GetBox(); 272 273 if (box.Max(axis) >= position ) 274 front->mObjects.push_back(*mi); 275 276 if (box.Min(axis) < position ) 277 back->mObjects.push_back(*mi); 278 279 mStat.objectRefs -= (int)leaf->mObjects.size(); 280 mStat.objectRefs += objectsBack + objectsFront; 281 } 282 283 delete leaf; 284 return node; 285 } 286 287 683 } 684 685 float oldCost = leaf->GetPvsSize(); 686 float newCost = ct_div_ci + minSum/sizeBox; 687 float ratio = newCost/oldCost; 688 689 // cout<<"===================="<<endl; 690 // cout<<"costRatio="<<ratio<<" pos="<<position<<" t="<<(position - minBox)/(maxBox - minBox) 691 // <<"\t q=("<<queriesBack<<","<<queriesFront<<")\t r=("<<raysBack<<","<<raysFront<<")"<<endl; 692 return ratio; 693 } 288 694 289 695 void 290 ViewCellKdTreeStatistics::Print(ostream &app) const 291 { 292 app << "===== ViewCellKd statistics ===============\n"; 293 294 app << "#N_RAYS Number of rays )\n" 295 << rays <<endl; 296 app << "#N_DOMAINS ( Number of query domains )\n" 297 << queryDomains <<endl; 298 299 app << "#N_NODES ( Number of nodes )\n" << nodes << "\n"; 300 301 app << "#N_LEAVES ( Number of leaves )\n" << Leaves() << "\n"; 302 303 app << "#N_SPLITS ( Number of splits in axes x y z dx dy dz \n"; 304 for (int i=0; i<7; i++) 305 app << splits[i] <<" "; 306 app <<endl; 307 308 app << "#N_RAYREFS ( Number of rayRefs )\n" << 309 rayRefs << "\n"; 310 311 app << "#N_RAYRAYREFS ( Number of rayRefs / ray )\n" << 312 rayRefs/(double)rays << "\n"; 313 314 app << "#N_LEAFRAYREFS ( Number of rayRefs / leaf )\n" << 315 rayRefs/(double)Leaves() << "\n"; 316 317 app << "#N_MAXOBJECTREFS ( Max number of rayRefs / leaf )\n" << 318 maxObjectRefs << "\n"; 319 320 app << "#N_NONEMPTYRAYREFS ( Number of rayRefs in nonEmpty leaves / non empty leaf )\n" << 321 rayRefsNonZeroQuery/(double)(Leaves() - zeroQueryNodes) << "\n"; 322 323 app << "#N_LEAFDOMAINREFS ( Number of query domain Refs / leaf )\n" << 324 objectRefs/(double)Leaves() << "\n"; 325 326 // app << setprecision(4); 327 328 app << "#N_PEMPTYLEAVES ( Percentage of leaves with zero query domains )\n"<< 329 zeroQueryNodes*100/(double)Leaves()<<endl; 330 331 app << "#N_PMAXDEPTHLEAVES ( Percentage of leaves at maxdepth )\n"<< 332 maxDepthNodes*100/(double)Leaves()<<endl; 333 334 app << "#N_PMINCOSTLEAVES ( Percentage of leaves with minCost )\n"<< 335 minCostNodes*100/(double)Leaves()<<endl; 336 337 app << "#N_ADDED_RAYREFS (Number of dynamically added ray references )\n"<< 338 addedRayRefs<<endl; 339 340 app << "#N_REMOVED_RAYREFS (Number of dynamically removed ray references )\n"<< 341 removedRayRefs<<endl; 342 343 // app << setprecision(4); 344 345 // app << "#N_CTIME ( Construction time [s] )\n" 346 // << Time() << " \n"; 347 348 app << "===== END OF ViewCellKd statistics ==========\n"; 349 350 } 351 352 353 354 void 355 ViewCellKd::EvaluateLeafStats(const TraversalData &data) 356 { 357 358 // the node became a leaf -> evaluate stats for leafs 359 ViewCellKdLeaf *leaf = (ViewCellKdLeaf *)data.mNode; 360 361 if (data.mDepth > mTermMaxDepth) 362 mStat.maxDepthNodes++; 363 364 if ( (int)(leaf->mObjects.size()) < mTermMinCost) 365 mStat.minCostNodes++; 366 367 368 if ( (int)(leaf->mObjects.size()) > mStat.maxObjectRefs) 369 mStat.maxObjectRefs = (int)leaf->mObjects.size(); 370 371 } 372 373 374 375 void 376 ViewCellKd::SortSplitCandidates( 377 ViewCellKdLeaf *node, 378 const int axis 379 ) 380 { 696 VspKdTree::SortSplitCandidates( 697 VspKdTreeLeaf *node, 698 const int axis 699 ) 700 { 701 381 702 splitCandidates->clear(); 382 703 383 int requestedSize = 2 * (int)node->mObjects.size();704 int requestedSize = 2*(node->rays.size()); 384 705 // creates a sorted split candidates array 385 706 if (splitCandidates->capacity() > 500000 && 386 707 requestedSize < (int)(splitCandidates->capacity()/10) ) { 708 387 709 delete splitCandidates; 388 710 splitCandidates = new vector<SortableEntry>; … … 390 712 391 713 splitCandidates->reserve(requestedSize); 392 714 393 715 // insert all queries 394 for(ObjectContainer::const_iterator mi = node->mObjects.begin(); 395 mi != node->mObjects.end(); 396 mi++) { 397 AxisAlignedBox3 box = (*mi)->GetBox(); 398 399 splitCandidates->push_back(SortableEntry(SortableEntry::BOX_MIN, 400 box.Min(axis), 401 *mi) 402 ); 716 for(VspKdTreeNode::RayInfoContainer::const_iterator ri = node->rays.begin(); 717 ri < node->rays.end(); 718 ri++) { 719 bool positive = (*ri).mRay->HasPosDir(axis); 720 splitCandidates->push_back(SortableEntry(positive ? SortableEntry::ERayMin : 721 SortableEntry::ERayMax, 722 (*ri).ExtrapOrigin(axis), 723 (void *)&*ri) 724 ); 725 726 splitCandidates->push_back(SortableEntry(positive ? SortableEntry::ERayMax : 727 SortableEntry::ERayMin, 728 (*ri).ExtrapTermination(axis), 729 (void *)&*ri) 730 ); 731 } 732 733 stable_sort(splitCandidates->begin(), splitCandidates->end()); 734 } 735 736 737 void 738 VspKdTree::EvaluateLeafStats(const TraversalData &data) 739 { 740 741 // the node became a leaf -> evaluate stats for leafs 742 VspKdTreeLeaf *leaf = (VspKdTreeLeaf *)data.node; 743 744 if (data.depth >= termMaxDepth) 745 stat.maxDepthNodes++; 746 747 // if ( (int)(leaf->rays.size()) < termMinCost) 748 // stat.minCostNodes++; 749 if ( leaf->GetPvsSize() < termMinPvs) 750 stat.minPvsNodes++; 751 752 if ( leaf->GetPvsSize() < termMinRays) 753 stat.minRaysNodes++; 754 755 if (0 && leaf->GetAvgRayContribution() > termMaxRayContribution ) 756 stat.maxRayContribNodes++; 757 758 if (SqrMagnitude(data.bbox.Size()) <= termMinSize) { 759 stat.minSizeNodes++; 760 } 761 762 if ( (int)(leaf->rays.size()) > stat.maxRayRefs) 763 stat.maxRayRefs = leaf->rays.size(); 764 765 } 766 767 768 769 VspKdTreeNode * 770 VspKdTree::SubdivideNode( 771 VspKdTreeLeaf *leaf, 772 const AxisAlignedBox3 &box, 773 AxisAlignedBox3 &backBBox, 774 AxisAlignedBox3 &frontBBox 775 ) 776 { 777 778 if ( (leaf->GetPvsSize() < termMinPvs) || 779 (leaf->rays.size() < termMinRays) || 780 // (leaf->GetAvgRayContribution() > termMaxRayContribution ) || 781 (leaf->depth >= termMaxDepth) || 782 SqrMagnitude(box.Size()) <= termMinSize ) { 783 784 #if 0 785 if (leaf->depth >= termMaxDepth) { 786 cout<<"Warning: max depth reached depth="<<(int)leaf->depth<<" rays="<<leaf->rays.size()<<endl; 787 cout<<"Bbox: "<<GetBBox(leaf)<<" dirbbox:"<<GetDirBBox(leaf)<<endl; 788 } 789 #endif 790 791 return leaf; 792 } 793 794 float position; 795 796 // first count ray sides 797 int raysBack; 798 int raysFront; 799 int pvsBack; 800 int pvsFront; 801 802 // select subdivision axis 803 int axis = SelectPlane( leaf, box, position, raysBack, raysFront, pvsBack, pvsFront); 804 805 // cout<<"rays back="<<raysBack<<" rays front="<<raysFront<<" pvs back="<<pvsBack<<" pvs front="<< 806 // pvsFront<<endl; 807 808 if (axis == -1) { 809 return leaf; 810 } 811 812 stat.nodes+=2; 813 stat.splits[axis]++; 814 815 // add the new nodes to the tree 816 VspKdTreeInterior *node = new VspKdTreeInterior(leaf->parent); 817 818 node->axis = axis; 819 node->position = position; 820 node->bbox = box; 821 node->dirBBox = GetDirBBox(leaf); 822 823 backBBox = box; 824 frontBBox = box; 825 826 VspKdTreeLeaf *back = new VspKdTreeLeaf(node, raysBack); 827 back->SetPvsSize(pvsBack); 828 VspKdTreeLeaf *front = new VspKdTreeLeaf(node, raysFront); 829 front->SetPvsSize(pvsFront); 830 831 // replace a link from node's parent 832 if ( leaf->parent ) 833 leaf->parent->ReplaceChildLink(leaf, node); 834 // and setup child links 835 node->SetupChildLinks(back, front); 836 837 if (axis <= VspKdTreeNode::SPLIT_Z) { 838 backBBox.SetMax(axis, position); 839 frontBBox.SetMin(axis, position); 840 841 for(VspKdTreeNode::RayInfoContainer::iterator ri = leaf->rays.begin(); 842 ri != leaf->rays.end(); 843 ri++) { 844 if ((*ri).mRay->IsActive()) { 845 846 // first unref ray from the former leaf 847 (*ri).mRay->Unref(); 848 849 // determine the side of this ray with respect to the plane 850 int side = node->ComputeRayIntersection(*ri, (*ri).mRay->mT); 851 852 if (side == 0) { 853 if ((*ri).mRay->HasPosDir(axis)) { 854 back->AddRay(VspKdTreeNode::RayInfo((*ri).mRay, 855 (*ri).mMinT, 856 (*ri).mRay->mT) 857 ); 858 front->AddRay(VspKdTreeNode::RayInfo((*ri).mRay, 859 (*ri).mRay->mT, 860 (*ri).mMaxT)); 861 } else { 862 back->AddRay(VspKdTreeNode::RayInfo((*ri).mRay, 863 (*ri).mRay->mT, 864 (*ri).mMaxT)); 865 front->AddRay(VspKdTreeNode::RayInfo((*ri).mRay, 866 (*ri).mMinT, 867 (*ri).mRay->mT)); 868 } 869 } else 870 if (side == 1) 871 front->AddRay(*ri); 872 else 873 back->AddRay(*ri); 874 } else 875 (*ri).mRay->Unref(); 876 } 877 } else { 878 // rays front/back 403 879 404 880 405 splitCandidates->push_back(SortableEntry(SortableEntry::BOX_MAX, 406 box.Max(axis), 407 *mi) 408 ); 409 } 410 411 stable_sort(splitCandidates->begin(), splitCandidates->end()); 412 } 413 414 415 float 416 ViewCellKd::BestCostRatio( 417 ViewCellKdLeaf *node, 418 const AxisAlignedBox3 &box, 419 const int axis, 420 float &position, 421 int &objectsBack, 422 int &objectsFront 423 ) 424 { 425 426 SortSplitCandidates(node, axis); 427 428 // go through the lists, count the number of objects left and right 429 // and evaluate the following cost funcion: 430 // C = ct_div_ci + (ol + or)/queries 431 432 float totalIntersections = 0.0f; 433 vector<SortableEntry>::const_iterator ci; 434 435 for(ci = splitCandidates->begin(); 436 ci < splitCandidates->end(); 437 ci++) 438 if ((*ci).type == SortableEntry::BOX_MIN) { 439 totalIntersections += (*ci).intersectable->IntersectionComplexity(); 881 for(VspKdTreeNode::RayInfoContainer::iterator ri = leaf->rays.begin(); 882 ri != leaf->rays.end(); 883 ri++) { 884 if ((*ri).mRay->IsActive()) { 885 // first unref ray from the former leaf 886 (*ri).mRay->Unref(); 887 888 int side; 889 if ((*ri).mRay->GetDirParametrization(axis - 3) > position) 890 side = 1; 891 else 892 side = -1; 893 894 if (side == 1) 895 front->AddRay(*ri); 896 else 897 back->AddRay(*ri); 898 899 } else 900 (*ri).mRay->Unref(); 440 901 } 441 442 float intersectionsLeft = 0; 443 float intersectionsRight = totalIntersections;444 445 int objectsLeft = 0, objectsRight = (int)node->mObjects.size();446 447 float minBox = box.Min(axis);448 float maxBox = box.Max(axis);449 float boxArea = box.SurfaceArea();450 451 float minBand = minBox + mSplitBorder*(maxBox - minBox); 452 float maxBand = minBox + (1.0f - mSplitBorder)*(maxBox - minBox); 453 454 float minSum = 1e20; 455 456 for(ci = splitCandidates->begin(); 457 ci < splitCandidates->end(); 458 ci++) { 459 switch ((*ci).type){460 case SortableEntry::BOX_MIN:461 objectsLeft++;462 intersectionsLeft += (*ci).intersectable->IntersectionComplexity();463 break;464 case SortableEntry::BOX_MAX:465 objectsRight--; 466 intersectionsRight -= (*ci).intersectable->IntersectionComplexity();467 break; 468 }469 470 if ((*ci).value > minBand && (*ci).value < maxBand) {471 AxisAlignedBox3 lbox = box;472 AxisAlignedBox3 rbox = box;473 lbox.SetMax(axis, (*ci).value);474 rbox.SetMin(axis, (*ci).value);475 476 float sum;477 if (mSahUseFaces) 478 sum = intersectionsLeft*lbox.SurfaceArea() + intersectionsRight*rbox.SurfaceArea();479 else 480 sum = objectsLeft*lbox.SurfaceArea() + objectsRight*rbox.SurfaceArea(); 902 } 903 904 // update stats 905 stat.rayRefs -= leaf->rays.size(); 906 stat.rayRefs += raysBack + raysFront; 907 908 909 delete leaf; 910 return node; 911 } 912 913 914 915 916 917 918 int 919 VspKdTree::ReleaseMemory(const int time) 920 { 921 stack<VspKdTreeNode *> tstack; 922 923 // find a node in the tree which subtree will be collapsed 924 int maxAccessTime = time - accessTimeThreshold; 925 int released; 926 927 tstack.push(root); 928 929 while (!tstack.empty()) { 930 VspKdTreeNode *node = tstack.top(); 931 tstack.pop(); 932 933 934 if (!node->IsLeaf()) { 935 VspKdTreeInterior *in = (VspKdTreeInterior *)node; 936 // cout<<"depth="<<(int)in->depth<<" time="<<in->lastAccessTime<<endl; 937 if (in->depth >= minCollapseDepth && 938 in->lastAccessTime <= maxAccessTime) { 939 released = CollapseSubtree(node, time); 940 break; 941 } 481 942 482 // cout<<"pos="<<(*ci).value<<"\t q=("<<ql<<","<<qr<<")\t r=("<<rl<<","<<rr<<")"<<endl; 483 // cout<<"cost= "<<sum<<endl; 484 485 if (sum < minSum) { 486 minSum = sum; 487 position = (*ci).value; 488 489 objectsBack = objectsLeft; 490 objectsFront = objectsRight; 943 if (in->back->GetAccessTime() < 944 in->front->GetAccessTime()) { 945 tstack.push(in->front); 946 tstack.push(in->back); 947 } else { 948 tstack.push(in->back); 949 tstack.push(in->front); 491 950 } 492 951 } 493 952 } 494 495 float oldCost = mSahUseFaces ? totalIntersections : node->mObjects.size(); 496 float newCost = mCt_div_ci + minSum/boxArea; 497 float ratio = newCost/oldCost; 498 499 #if 0 500 cout<<"===================="<<endl; 501 cout<<"costRatio="<<ratio<<" pos="<<position<<" t="<<(position - minBox)/(maxBox - minBox) 502 <<"\t o=("<<objectsBack<<","<<objectsFront<<")"<<endl; 953 954 while (tstack.empty()) { 955 // could find node to collaps... 956 // cout<<"Could not find a node to release "<<endl; 957 break; 958 } 959 960 return released; 961 } 962 963 964 965 966 VspKdTreeNode * 967 VspKdTree::SubdivideLeaf( 968 VspKdTreeLeaf *leaf, 969 const float sizeThreshold 970 ) 971 { 972 VspKdTreeNode *node = leaf; 973 974 AxisAlignedBox3 leafBBox = GetBBox(leaf); 975 976 static int pass = 0; 977 pass ++; 978 979 // check if we should perform a dynamic subdivision of the leaf 980 if ( 981 // leaf->rays.size() > (unsigned)termMinCost && 982 (leaf->GetPvsSize() >= termMinPvs) && 983 SqrMagnitude(leafBBox.Size()) > sizeThreshold) { 984 985 // memory check and realese... 986 if (GetMemUsage() > maxTotalMemory) { 987 ReleaseMemory( pass ); 988 } 989 990 AxisAlignedBox3 backBBox, frontBBox; 991 992 // subdivide the node 993 node = 994 SubdivideNode(leaf, 995 leafBBox, 996 backBBox, 997 frontBBox 998 ); 999 } 1000 return node; 1001 } 1002 1003 1004 1005 void 1006 VspKdTree::UpdateRays(VssRayContainer &remove, 1007 VssRayContainer &add 1008 ) 1009 { 1010 VspKdTreeLeaf::NewMail(); 1011 1012 // schedule rays for removal 1013 for(VssRayContainer::const_iterator ri = remove.begin(); 1014 ri != remove.end(); 1015 ri++) { 1016 (*ri)->ScheduleForRemoval(); 1017 } 1018 1019 int inactive=0; 1020 1021 for(VssRayContainer::const_iterator ri = remove.begin(); 1022 ri != remove.end(); 1023 ri++) { 1024 if ((*ri)->ScheduledForRemoval()) 1025 // RemoveRay(*ri, NULL, false); 1026 // !!! BUG - with true it does not work correctly - aggreated delete 1027 RemoveRay(*ri, NULL, true); 1028 else 1029 inactive++; 1030 } 1031 1032 1033 // cout<<"all/inactive"<<remove.size()<<"/"<<inactive<<endl; 1034 1035 for(VssRayContainer::const_iterator ri = add.begin(); 1036 ri != add.end(); 1037 ri++) { 1038 AddRay(*ri); 1039 } 1040 1041 1042 } 1043 1044 1045 void 1046 VspKdTree::RemoveRay(VssRay *ray, 1047 vector<VspKdTreeLeaf *> *affectedLeaves, 1048 const bool removeAllScheduledRays 1049 ) 1050 { 1051 1052 stack<RayTraversalData> tstack; 1053 1054 tstack.push(RayTraversalData(root, VspKdTreeNode::RayInfo(ray))); 1055 1056 RayTraversalData data; 1057 1058 // cout<<"Number of ray refs = "<<ray->RefCount()<<endl; 1059 1060 while (!tstack.empty()) { 1061 data = tstack.top(); 1062 tstack.pop(); 1063 1064 if (!data.node->IsLeaf()) { 1065 // split the set of rays in two groups intersecting the 1066 // two subtrees 1067 1068 TraverseInternalNode(data, tstack); 1069 1070 } else { 1071 // remove the ray from the leaf 1072 // find the ray in the leaf and swap it with the last ray... 1073 VspKdTreeLeaf *leaf = (VspKdTreeLeaf *)data.node; 1074 1075 if (!leaf->Mailed()) { 1076 leaf->Mail(); 1077 if (affectedLeaves) 1078 affectedLeaves->push_back(leaf); 1079 1080 if (removeAllScheduledRays) { 1081 int tail = leaf->rays.size()-1; 1082 1083 for (int i=0; i < (int)(leaf->rays.size()); i++) { 1084 if (leaf->rays[i].mRay->ScheduledForRemoval()) { 1085 // find a ray to replace it with 1086 while (tail >= i && leaf->rays[tail].mRay->ScheduledForRemoval()) { 1087 stat.removedRayRefs++; 1088 leaf->rays[tail].mRay->Unref(); 1089 leaf->rays.pop_back(); 1090 tail--; 1091 } 1092 1093 if (tail < i) 1094 break; 1095 1096 stat.removedRayRefs++; 1097 leaf->rays[i].mRay->Unref(); 1098 leaf->rays[i] = leaf->rays[tail]; 1099 leaf->rays.pop_back(); 1100 tail--; 1101 } 1102 } 1103 } 1104 } 1105 1106 if (!removeAllScheduledRays) 1107 for (int i=0; i < (int)leaf->rays.size(); i++) { 1108 if (leaf->rays[i].mRay == ray) { 1109 stat.removedRayRefs++; 1110 ray->Unref(); 1111 leaf->rays[i] = leaf->rays[leaf->rays.size()-1]; 1112 leaf->rays.pop_back(); 1113 // check this ray again 1114 break; 1115 } 1116 } 1117 1118 } 1119 } 1120 1121 if (ray->RefCount() != 0) { 1122 cerr<<"Error: Number of remaining refs = "<<ray->RefCount()<<endl; 1123 exit(1); 1124 } 1125 1126 } 1127 1128 1129 void 1130 VspKdTree::AddRay(VssRay *ray) 1131 { 1132 1133 stack<RayTraversalData> tstack; 1134 1135 tstack.push(RayTraversalData(root, VspKdTreeNode::RayInfo(ray))); 1136 1137 RayTraversalData data; 1138 1139 while (!tstack.empty()) { 1140 data = tstack.top(); 1141 tstack.pop(); 1142 1143 if (!data.node->IsLeaf()) { 1144 TraverseInternalNode(data, tstack); 1145 } else { 1146 // remove the ray from the leaf 1147 // find the ray in the leaf and swap it with the last ray... 1148 VspKdTreeLeaf *leaf = (VspKdTreeLeaf *)data.node; 1149 leaf->AddRay(data.rayData); 1150 stat.addedRayRefs++; 1151 } 1152 } 1153 } 1154 1155 void 1156 VspKdTree::TraverseInternalNode( 1157 RayTraversalData &data, 1158 stack<RayTraversalData> &tstack) 1159 { 1160 VspKdTreeInterior *in = (VspKdTreeInterior *) data.node; 1161 1162 if (in->axis <= VspKdTreeNode::SPLIT_Z) { 1163 1164 // determine the side of this ray with respect to the plane 1165 int side = in->ComputeRayIntersection(data.rayData, 1166 data.rayData.mRay->mT); 1167 1168 1169 if (side == 0) { 1170 if (data.rayData.mRay->HasPosDir(in->axis)) { 1171 tstack.push(RayTraversalData(in->back, 1172 VspKdTreeNode::RayInfo(data.rayData.mRay, 1173 data.rayData.mMinT, 1174 data.rayData.mRay->mT)) 1175 ); 1176 1177 tstack.push(RayTraversalData(in->front, 1178 VspKdTreeNode::RayInfo(data.rayData.mRay, 1179 data.rayData.mRay->mT, 1180 data.rayData.mMaxT 1181 )) 1182 ); 1183 1184 } else { 1185 tstack.push(RayTraversalData(in->back, 1186 VspKdTreeNode::RayInfo(data.rayData.mRay, 1187 data.rayData.mRay->mT, 1188 data.rayData.mMaxT 1189 )) 1190 ); 1191 1192 tstack.push(RayTraversalData(in->front, 1193 VspKdTreeNode::RayInfo(data.rayData.mRay, 1194 data.rayData.mMinT, 1195 data.rayData.mRay->mT)) 1196 ); 1197 1198 1199 } 1200 } else 1201 if (side == 1) 1202 tstack.push(RayTraversalData(in->front, data.rayData)); 1203 else 1204 tstack.push(RayTraversalData(in->back, data.rayData)); 1205 } 1206 else { 1207 // directional split 1208 if (data.rayData.mRay->GetDirParametrization(in->axis - 3) > in->position) 1209 tstack.push(RayTraversalData(in->front, data.rayData)); 1210 else 1211 tstack.push(RayTraversalData(in->back, data.rayData)); 1212 } 1213 } 1214 1215 1216 int 1217 VspKdTree::CollapseSubtree(VspKdTreeNode *sroot, const int time) 1218 { 1219 // first count all rays in the subtree 1220 // use mail 1 for this purpose 1221 stack<VspKdTreeNode *> tstack; 1222 int rayCount = 0; 1223 int totalRayCount = 0; 1224 int collapsedNodes = 0; 1225 1226 #if DEBUG_COLLAPSE 1227 cout<<"Collapsing subtree"<<endl; 1228 cout<<"acessTime="<<sroot->GetAccessTime()<<endl; 1229 cout<<"depth="<<(int)sroot->depth<<endl; 503 1230 #endif 504 return ratio; 505 } 506 507 int 508 ViewCellKd::CastRay( 509 Ray &ray 510 ) 511 { 512 int hits = 0; 513 514 stack<RayTraversalData> tStack; 515 516 float maxt = 1e6; 517 float mint = 0; 518 519 Intersectable::NewMail(); 520 521 if (!mBox.GetMinMaxT(ray, &mint, &maxt)) 522 return 0; 523 524 if (mint < 0) 525 mint = 0; 526 527 maxt += Limits::Threshold; 528 529 Vector3 entp = ray.Extrap(mint); 530 Vector3 extp = ray.Extrap(maxt); 531 532 ViewCellKdNode *node = mRoot; 533 ViewCellKdNode *farChild; 534 float position; 535 int axis; 536 537 while (1) { 538 if (!node->IsLeaf()) { 539 ViewCellKdInterior *in = (ViewCellKdInterior *) node; 540 position = in->mPosition; 541 axis = in->mAxis; 542 543 if (entp[axis] <= position) { 544 if (extp[axis] <= position) { 545 node = in->mBack; 546 // cases N1,N2,N3,P5,Z2,Z3 547 continue; 548 } else { 549 // case N4 550 node = in->mBack; 551 farChild = in->mFront; 552 } 553 } 554 else { 555 if (position <= extp[axis]) { 556 node = in->mFront; 557 // cases P1,P2,P3,N5,Z1 558 continue; 559 } else { 560 node = in->mFront; 561 farChild = in->mBack; 562 // case P4 563 } 564 } 565 // $$ modification 3.5.2004 - hints from Kamil Ghais 566 // case N4 or P4 567 float tdist = (position - ray.GetLoc(axis)) / ray.GetDir(axis); 568 tStack.push(RayTraversalData(farChild, extp, maxt)); 569 extp = ray.GetLoc() + ray.GetDir()*tdist; 570 maxt = tdist; 571 } else { 572 // compute intersection with all objects in this leaf 573 ViewCellKdLeaf *leaf = (ViewCellKdLeaf *) node; 574 // if (ray.mFlags & Ray::STORE_KDLEAVES) 575 // ray.kdLeaves.push_back(leaf); 576 577 ObjectContainer::const_iterator mi; 578 for ( mi = leaf->mObjects.begin(); 579 mi != leaf->mObjects.end(); 580 mi++) { 581 Intersectable *object = *mi; 582 if (!object->Mailed() ) { 583 object->Mail(); 584 if (ray.mFlags & Ray::STORE_TESTED_OBJECTS) 585 ray.testedObjects.push_back(object); 586 hits += object->CastRay(ray); 587 } 588 } 589 590 if (hits && ray.GetType() == Ray::LOCAL_RAY) 591 if (ray.intersections[0].mT <= maxt) 592 break; 593 594 // get the next node from the stack 595 if (tStack.empty()) 596 break; 597 598 entp = extp; 599 mint = maxt; 600 if (ray.GetType() == Ray::LINE_SEGMENT && mint > 1.0f) 601 break; 602 603 RayTraversalData &s = tStack.top(); 604 node = s.mNode; 605 extp = s.mExitPoint; 606 maxt = s.mMaxT; 607 tStack.pop(); 608 } 609 } 610 return hits; 611 } 612 613 void 614 ViewCellKd::CollectObjects(ViewCellKdNode *n, ObjectContainer &objects) 615 { 616 stack<ViewCellKdNode *> nodeStack; 617 618 nodeStack.push(n); 619 620 while (!nodeStack.empty()) { 621 ViewCellKdNode *node = nodeStack.top(); 622 nodeStack.pop(); 1231 1232 // tstat.collapsedSubtrees++; 1233 // tstat.collapseDepths += (int)sroot->depth; 1234 // tstat.collapseAccessTimes += time - sroot->GetAccessTime(); 1235 1236 tstack.push(sroot); 1237 VssRay::NewMail(); 1238 1239 while (!tstack.empty()) { 1240 collapsedNodes++; 1241 VspKdTreeNode *node = tstack.top(); 1242 tstack.pop(); 1243 623 1244 if (node->IsLeaf()) { 624 ViewCellKdLeaf *leaf = (ViewCellKdLeaf *)node; 625 for (int j=0; j < leaf->mObjects.size(); j++) { 626 Intersectable *object = leaf->mObjects[j]; 627 if (!object->Mailed()) { 628 object->Mail(); 629 objects.push_back(object); 1245 VspKdTreeLeaf *leaf = (VspKdTreeLeaf *) node; 1246 for(VspKdTreeNode::RayInfoContainer::iterator ri = leaf->rays.begin(); 1247 ri != leaf->rays.end(); 1248 ri++) { 1249 1250 totalRayCount++; 1251 if ((*ri).mRay->IsActive() && !(*ri).mRay->Mailed()) { 1252 (*ri).mRay->Mail(); 1253 rayCount++; 630 1254 } 631 1255 } 632 1256 } else { 633 ViewCellKdInterior *interior = (ViewCellKdInterior *)node; 634 nodeStack.push(interior->mFront); 635 nodeStack.push(interior->mBack); 1257 tstack.push(((VspKdTreeInterior *)node)->back); 1258 tstack.push(((VspKdTreeInterior *)node)->front); 636 1259 } 637 1260 } 638 } 639 640 // Find random neighbor which was not mailed 641 ViewCellKdNode * 642 ViewCellKd::FindRandomNeighbor(ViewCellKdNode *n, 643 bool onlyUnmailed 644 ) 645 { 646 stack<ViewCellKdNode *> nodeStack; 647 648 nodeStack.push(mRoot); 649 650 AxisAlignedBox3 box = GetBox(n); 651 int mask = rand(); 652 653 while (!nodeStack.empty()) { 654 ViewCellKdNode *node = nodeStack.top(); 655 nodeStack.pop(); 1261 1262 VssRay::NewMail(); 1263 1264 // create a new node that will hold the rays 1265 VspKdTreeLeaf *newLeaf = new VspKdTreeLeaf( sroot->parent, rayCount ); 1266 if ( newLeaf->parent ) 1267 newLeaf->parent->ReplaceChildLink(sroot, newLeaf); 1268 1269 1270 tstack.push( sroot ); 1271 1272 while (!tstack.empty()) { 1273 1274 VspKdTreeNode *node = tstack.top(); 1275 tstack.pop(); 1276 656 1277 if (node->IsLeaf()) { 657 if ( node != n && (!onlyUnmailed || !node->Mailed()) ) 658 return node; 659 } else { 660 ViewCellKdInterior *interior = (ViewCellKdInterior *)node; 661 if (interior->mPosition > box.Max(interior->mAxis)) 662 nodeStack.push(interior->mBack); 663 else 664 if (interior->mPosition < box.Min(interior->mAxis)) 665 nodeStack.push(interior->mFront); 666 else { 667 // random decision 668 if (mask&1) 669 nodeStack.push(interior->mBack); 670 else 671 nodeStack.push(interior->mFront); 672 mask = mask>>1; 673 } 674 } 675 } 676 677 return NULL; 678 } 679 680 int 681 ViewCellKd::FindNeighbors(ViewCellKdNode *n, 682 vector<ViewCellKdNode *> &neighbors, 683 bool onlyUnmailed 684 ) 685 { 686 stack<ViewCellKdNode *> nodeStack; 687 688 nodeStack.push(mRoot); 689 690 AxisAlignedBox3 box = GetBox(n); 691 692 while (!nodeStack.empty()) { 693 ViewCellKdNode *node = nodeStack.top(); 694 nodeStack.pop(); 695 if (node->IsLeaf()) { 696 if ( node != n && (!onlyUnmailed || !node->Mailed()) ) 697 neighbors.push_back(node); 698 } else { 699 ViewCellKdInterior *interior = (ViewCellKdInterior *)node; 700 if (interior->mPosition > box.Max(interior->mAxis)) 701 nodeStack.push(interior->mBack); 702 else 703 if (interior->mPosition < box.Min(interior->mAxis)) 704 nodeStack.push(interior->mFront); 705 else { 706 // random decision 707 nodeStack.push(interior->mBack); 708 nodeStack.push(interior->mFront); 709 } 710 } 711 } 712 713 return (int)neighbors.size(); 714 } 715 716 // Find random neighbor which was not mailed 717 ViewCellKdNode * 718 ViewCellKd::GetRandomLeaf(const Plane3 &plane) 719 { 720 stack<ViewCellKdNode *> nodeStack; 721 722 nodeStack.push(mRoot); 723 724 int mask = rand(); 725 726 while (!nodeStack.empty()) { 727 ViewCellKdNode *node = nodeStack.top(); 728 nodeStack.pop(); 729 if (node->IsLeaf()) { 730 return node; 731 } else { 732 ViewCellKdInterior *interior = (ViewCellKdInterior *)node; 733 ViewCellKdNode *next; 734 if (GetBox(interior->mBack).Side(plane) < 0) 735 next = interior->mFront; 736 else 737 if (GetBox(interior->mFront).Side(plane) < 0) 738 next = interior->mBack; 739 else { 740 // random decision 741 if (mask&1) 742 next = interior->mBack; 743 else 744 next = interior->mFront; 745 mask = mask>>1; 746 } 747 nodeStack.push(next); 748 } 749 } 750 751 752 return NULL; 753 } 754 755 void 756 ViewCellKd::CollectLeaves(vector<ViewCellKdLeaf *> &leaves) 757 { 758 stack<ViewCellKdNode *> nodeStack; 759 nodeStack.push(mRoot); 760 761 while (!nodeStack.empty()) { 762 ViewCellKdNode *node = nodeStack.top(); 763 nodeStack.pop(); 764 if (node->IsLeaf()) { 765 ViewCellKdLeaf *leaf = (ViewCellKdLeaf *)node; 766 leaves.push_back(leaf); 767 } else { 768 ViewCellKdInterior *interior = (ViewCellKdInterior *)node; 769 nodeStack.push(interior->mBack); 770 nodeStack.push(interior->mFront); 771 } 772 } 773 } 774 775 776 int 777 ViewCellKd::CollectLeafPvs() 778 { 779 int totalPvsSize = 0; 780 stack<ViewCellKdNode *> nodeStack; 781 782 nodeStack.push(mRoot); 783 784 while (!nodeStack.empty()) { 785 ViewCellKdNode *node = nodeStack.top(); 786 nodeStack.pop(); 787 if (node->IsLeaf()) { 788 ViewCellKdLeaf *leaf = (ViewCellKdLeaf *)node; 789 for (int j=0; j < leaf->mObjects.size(); j++) { 790 Intersectable *object = leaf->mObjects[j]; 791 if (!object->Mailed()) { 792 object->Mail(); 793 // add this node to pvs of all nodes it can see 794 /* ViewCellKdPvsMap::iterator ni = object->mKdPvs.mEntries.begin(); 795 for (; ni != object->mKdPvs.mEntries.end(); ni++) { 796 ViewCellKdNode *node = (*ni).first; 797 // $$ JB TEMPORARY solution -> should add object PVS or explictly computed 798 // kd tree PVS 799 if (leaf->mKdPvs.AddSample(node)) 800 totalPvsSize++; 801 }*/ 802 } 1278 VspKdTreeLeaf *leaf = (VspKdTreeLeaf *) node; 1279 1280 for(VspKdTreeNode::RayInfoContainer::iterator ri = leaf->rays.begin(); 1281 ri != leaf->rays.end(); 1282 ri++) { 1283 1284 // unref this ray from the old node 1285 1286 if ((*ri).mRay->IsActive()) { 1287 (*ri).mRay->Unref(); 1288 if (!(*ri).mRay->Mailed()) { 1289 (*ri).mRay->Mail(); 1290 newLeaf->AddRay(*ri); 1291 } 1292 } else 1293 (*ri).mRay->Unref(); 1294 803 1295 } 804 1296 } else { 805 ViewCellKdInterior *interior = (ViewCellKdInterior *)node; 806 nodeStack.push(interior->mFront); 807 nodeStack.push(interior->mBack); 1297 tstack.push(((VspKdTreeInterior *)node)->back); 1298 tstack.push(((VspKdTreeInterior *)node)->front); 808 1299 } 809 1300 } 810 811 return totalPvsSize; 812 } 813 814 815 ViewCellKdNode * 816 ViewCellKd::GetRandomLeaf(const bool onlyUnmailed) 817 { 818 stack<ViewCellKdNode *> nodeStack; 819 nodeStack.push(mRoot); 820 821 int mask = rand(); 822 823 while (!nodeStack.empty()) { 824 ViewCellKdNode *node = nodeStack.top(); 825 nodeStack.pop(); 1301 1302 // delete the node and all its children 1303 delete sroot; 1304 1305 // for(VspKdTreeNode::SRayContainer::iterator ri = newLeaf->rays.begin(); 1306 // ri != newLeaf->rays.end(); 1307 // ri++) 1308 // (*ri).ray->UnMail(2); 1309 1310 1311 #if DEBUG_COLLAPSE 1312 cout<<"Total memory before="<<GetMemUsage()<<endl; 1313 #endif 1314 1315 stat.nodes -= collapsedNodes - 1; 1316 stat.rayRefs -= totalRayCount - rayCount; 1317 1318 #if DEBUG_COLLAPSE 1319 cout<<"collapsed nodes"<<collapsedNodes<<endl; 1320 cout<<"collapsed rays"<<totalRayCount - rayCount<<endl; 1321 cout<<"Total memory after="<<GetMemUsage()<<endl; 1322 cout<<"================================"<<endl; 1323 #endif 1324 1325 // tstat.collapsedNodes += collapsedNodes; 1326 // tstat.collapsedRays += totalRayCount - rayCount; 1327 1328 return totalRayCount - rayCount; 1329 } 1330 1331 1332 int 1333 VspKdTree::GetPvsSize(VspKdTreeNode *node, const AxisAlignedBox3 &box) const 1334 { 1335 stack<VspKdTreeNode *> tstack; 1336 tstack.push(root); 1337 1338 Intersectable::NewMail(); 1339 int pvsSize = 0; 1340 1341 while (!tstack.empty()) { 1342 VspKdTreeNode *node = tstack.top(); 1343 tstack.pop(); 1344 1345 826 1346 if (node->IsLeaf()) { 827 if ( (!onlyUnmailed || !node->Mailed()) ) 828 return node; 829 } else { 830 ViewCellKdInterior *interior = (ViewCellKdInterior *)node; 831 // random decision 832 if (mask&1) 833 nodeStack.push(interior->mBack); 834 else 835 nodeStack.push(interior->mFront); 836 mask = mask>>1; 1347 VspKdTreeLeaf *leaf = (VspKdTreeLeaf *)node; 1348 for(VspKdTreeNode::RayInfoContainer::iterator ri = leaf->rays.begin(); 1349 ri != leaf->rays.end(); 1350 ri++) 1351 if ((*ri).mRay->IsActive()) { 1352 Intersectable *object; 1353 #if BIDIRECTIONAL_RAY 1354 object = (*ri).mRay->mOriginObject; 1355 if (object && !object->Mailed()) { 1356 pvsSize++; 1357 object->Mail(); 1358 } 1359 #endif 1360 object = (*ri).mRay->mTerminationObject; 1361 if (object && !object->Mailed()) { 1362 pvsSize++; 1363 object->Mail(); 1364 } 1365 } 1366 } else { 1367 VspKdTreeInterior *in = (VspKdTreeInterior *)node; 1368 if (in->axis < 3) { 1369 if (box.Max(in->axis) >= in->position ) 1370 tstack.push(in->front); 1371 1372 if (box.Min(in->axis) <= in->position ) 1373 tstack.push(in->back); 1374 } else { 1375 // both nodes for directional splits 1376 tstack.push(in->front); 1377 tstack.push(in->back); 1378 } 837 1379 } 838 1380 } 839 return NULL; 840 } 1381 return pvsSize; 1382 } 1383 1384 void 1385 VspKdTree::GetRayContributionStatistics( 1386 float &minRayContribution, 1387 float &maxRayContribution, 1388 float &avgRayContribution 1389 ) 1390 { 1391 stack<VspKdTreeNode *> tstack; 1392 tstack.push(root); 1393 1394 minRayContribution = 1.0f; 1395 maxRayContribution = 0.0f; 1396 float sumRayContribution = 0.0f; 1397 int leaves = 0; 1398 1399 while (!tstack.empty()) { 1400 VspKdTreeNode *node = tstack.top(); 1401 tstack.pop(); 1402 1403 if (node->IsLeaf()) { 1404 leaves++; 1405 VspKdTreeLeaf *leaf = (VspKdTreeLeaf *)node; 1406 float c = leaf->GetAvgRayContribution(); 1407 if (c > maxRayContribution) 1408 maxRayContribution = c; 1409 if (c < minRayContribution) 1410 minRayContribution = c; 1411 sumRayContribution += c; 1412 1413 } else { 1414 VspKdTreeInterior *in = (VspKdTreeInterior *)node; 1415 // both nodes for directional splits 1416 tstack.push(in->front); 1417 tstack.push(in->back); 1418 } 1419 } 1420 1421 cout<<"sum="<<sumRayContribution<<endl; 1422 cout<<"leaves="<<leaves<<endl; 1423 avgRayContribution = sumRayContribution/(float)leaves; 1424 } 1425 1426 1427 int 1428 VspKdTree::GenerateRays(const float ratioPerLeaf, 1429 SimpleRayContainer &rays) 1430 { 1431 stack<VspKdTreeNode *> tstack; 1432 tstack.push(root); 1433 1434 while (!tstack.empty()) { 1435 VspKdTreeNode *node = tstack.top(); 1436 tstack.pop(); 1437 1438 if (node->IsLeaf()) { 1439 VspKdTreeLeaf *leaf = (VspKdTreeLeaf *)node; 1440 float c = leaf->GetAvgRayContribution(); 1441 int num = (c*ratioPerLeaf + 0.5); 1442 // cout<<num<<" "; 1443 1444 for (int i=0; i < num; i++) { 1445 Vector3 origin = GetBBox(leaf).GetRandomPoint(); 1446 Vector3 dirVector = GetDirBBox(leaf).GetRandomPoint(); 1447 Vector3 direction = Vector3(sin(dirVector.x), sin(dirVector.y), cos(dirVector.x)); 1448 //cout<<"dir vector.x="<<dirVector.x<<"direction'.x="<<atan2(direction.x, direction.y)<<endl; 1449 rays.push_back(SimpleRay(origin, direction)); 1450 } 1451 1452 } else { 1453 VspKdTreeInterior *in = (VspKdTreeInterior *)node; 1454 // both nodes for directional splits 1455 tstack.push(in->front); 1456 tstack.push(in->back); 1457 } 1458 } 1459 1460 return rays.size(); 1461 } 1462 1463 1464 float 1465 VspKdTree::GetAvgPvsSize() 1466 { 1467 stack<VspKdTreeNode *> tstack; 1468 tstack.push(root); 1469 1470 int sumPvs = 0; 1471 int leaves = 0; 1472 while (!tstack.empty()) { 1473 VspKdTreeNode *node = tstack.top(); 1474 tstack.pop(); 1475 1476 if (node->IsLeaf()) { 1477 VspKdTreeLeaf *leaf = (VspKdTreeLeaf *)node; 1478 // update pvs size 1479 leaf->UpdatePvsSize(); 1480 sumPvs += leaf->GetPvsSize(); 1481 leaves++; 1482 } else { 1483 VspKdTreeInterior *in = (VspKdTreeInterior *)node; 1484 // both nodes for directional splits 1485 tstack.push(in->front); 1486 tstack.push(in->back); 1487 } 1488 } 1489 1490 1491 return sumPvs/(float)leaves; 1492 } -
trunk/VUT/GtpVisibilityPreprocessor/src/VspKdTree.h
r406 r408 1 #ifndef _ViewCellKdTree_H__ 2 #define _ViewCellKdTree_H__ 3 1 // ================================================================ 2 // $Id$ 3 // **************************************************************** 4 // 5 // Initial coding by 6 /** 7 @author Jiri Bittner 8 */ 9 10 #ifndef __VSPKDTREE_H__ 11 #define __VSPKDTREE_H__ 12 13 // Standard headers 14 #include <iomanip> 15 #include <vector> 4 16 #include <functional> 5 using namespace std; 6 7 #include "Containers.h" 17 #include <stack> 18 19 20 // User headers 21 #include "VssRay.h" 8 22 #include "AxisAlignedBox3.h" 23 24 25 #define USE_KDNODE_VECTORS 1 26 #define _RSS_STATISTICS 27 #define _RSS_TRAVERSAL_STATISTICS 28 29 30 #include "Statistics.h" 9 31 #include "Ray.h" 10 #include "Pvs.h"11 12 13 class ViewCellKdNode;14 class ViewCellKdLeaf;15 class ViewCellKdInterior;16 class Intersectable;17 18 32 19 33 // -------------------------------------------------------------- 20 34 // Static statistics for kd-tree search 21 35 // -------------------------------------------------------------- 22 class V iewCellKdTreeStatistics36 class VspKdStatistics: public StatisticsBase 23 37 { 24 38 public: … … 29 43 // totals number of rays 30 44 int rays; 31 // total number of query domains 45 // initial size of the pvs 46 int initialPvsSize; 47 // total number of query domains 32 48 int queryDomains; 33 49 // total number of ray references 34 50 int rayRefs; 35 // refs in non empty leafs 36 int rayRefsNonZeroQuery; 37 // total number of query references 38 int objectRefs; 39 // nodes with zero queries 40 int zeroQueryNodes; 41 // max depth nodes 51 52 // max depth nodes 42 53 int maxDepthNodes; 43 54 // max depth nodes 44 int minCostNodes; 55 int minPvsNodes; 56 int minRaysNodes; 57 // max ray contribution nodes 58 int maxRayContribNodes; 59 // max depth nodes 60 int minSizeNodes; 61 45 62 // max number of rays per node 46 int max ObjectRefs;63 int maxRayRefs; 47 64 // number of dynamically added ray refs 48 65 int addedRayRefs; … … 51 68 52 69 // Constructor 53 V iewCellKdTreeStatistics() {70 VspKdStatistics() { 54 71 Reset(); 55 72 } … … 64 81 splits[i] = 0; 65 82 rays = queryDomains = 0; 66 rayRefs = rayRefsNonZeroQuery = objectRefs = 0; 67 zeroQueryNodes = 0; 83 rayRefs = 0; 68 84 maxDepthNodes = 0; 69 minCostNodes = 0; 70 maxObjectRefs = 0; 85 minPvsNodes = 0; 86 minRaysNodes = 0; 87 maxRayRefs = 0; 71 88 addedRayRefs = removedRayRefs = 0; 72 } 73 89 initialPvsSize = 0; 90 maxRayContribNodes = 0; 91 minSizeNodes = 0; 92 } 93 94 74 95 void 75 96 Print(ostream &app) const; 76 97 77 friend ostream &operator<<(ostream &s, const V iewCellKdTreeStatistics &stat) {98 friend ostream &operator<<(ostream &s, const VspKdStatistics &stat) { 78 99 stat.Print(s); 79 100 return s; … … 82 103 }; 83 104 84 85 class ViewCellKdInterior; 86 /** Abstract class for kd-tree node */ 87 class ViewCellKdNode { 105 106 // -------------------------------------------------------------- 107 // For sorting rays 108 // -------------------------------------------------------------- 109 struct SortableEntry 110 { 111 enum EType { 112 ERayMin, 113 ERayMax 114 }; 115 116 int type; 117 float value; 118 void *data; 119 120 SortableEntry() {} 121 SortableEntry(const int t, const float v, void *d):type(t), 122 value(v), 123 data(d) {} 124 125 friend bool operator<(const SortableEntry &a, const SortableEntry &b) { 126 return a.value < b.value; 127 } 128 }; 129 130 131 class VspKdTreeInterior; 132 133 134 // -------------------------------------------------------------- 135 // KD-tree node - abstract class 136 // -------------------------------------------------------------- 137 class VspKdTreeNode 138 { 139 public: 140 141 #define USE_FIXEDPOINT_T 1 142 143 struct RayInfo 144 { 145 // pointer to the actual ray 146 VssRay *mRay; 147 148 // endpoints - do we need them? 149 #if USE_FIXEDPOINT_T 150 short mMinT, mMaxT; 151 #else 152 float mMinT, mMaxT; 153 #endif 154 155 RayInfo():mRay(NULL) {} 156 157 RayInfo(VssRay *r):mRay(r), mMinT(0), 158 #if USE_FIXEDPOINT_T 159 #define FIXEDPOINT_ONE 0x7FFE 160 // mMaxT(0xFFFF) 161 mMaxT(FIXEDPOINT_ONE) 162 #else 163 mMaxT(1.0f) 164 #endif 165 {} 166 167 RayInfo(VssRay *r, 168 const float _min, 169 const float _max 170 ):mRay(r) { 171 SetMinT(_min); 172 SetMaxT(_max); 173 } 174 175 RayInfo(VssRay *r, 176 const short _min, 177 const float _max 178 ):mRay(r), mMinT(_min) { 179 SetMaxT(_max); 180 } 181 182 RayInfo(VssRay *r, 183 const float _min, 184 const short _max 185 ):mRay(r), mMaxT(_max) { 186 SetMinT(_min); 187 } 188 189 friend bool operator<(const RayInfo &a, const RayInfo &b) { 190 return a.mRay < b.mRay; 191 } 192 193 194 float ExtrapOrigin(const int axis) const { 195 return mRay->GetOrigin(axis) + GetMinT()*mRay->GetDir(axis); 196 } 197 198 float ExtrapTermination(const int axis) const { 199 return mRay->GetOrigin(axis) + GetMaxT()*mRay->GetDir(axis); 200 } 201 202 #if USE_FIXEDPOINT_T 203 float GetMinT () const { return mMinT/(float)(FIXEDPOINT_ONE); } 204 float GetMaxT () const { return mMaxT/(float)(FIXEDPOINT_ONE); } 205 206 void SetMinT (const float t) { 207 mMinT = (short) (t*(float)(FIXEDPOINT_ONE)); 208 } 209 210 void SetMaxT (const float t) { 211 mMaxT = (short) (t*(float)(FIXEDPOINT_ONE)); 212 mMaxT++; 213 // if (mMaxT!=0xFFFF) 214 // mMaxT++; 215 } 216 #else 217 float GetMinT () const { return mMinT; } 218 float GetMaxT () const { return mMaxT; } 219 220 void SetMinT (const float t) { mMinT = t; } 221 void SetMaxT (const float t) { mMaxT = t; } 222 #endif 223 224 225 int ComputeRayIntersection(const float axis, 226 const float position, 227 float &t 228 ) const { 229 230 // intersect the ray with the plane 231 float denom = mRay->GetDir(axis); 232 233 if (fabs(denom) < 1e-20) 234 //if (denom == 0.0f) 235 return (mRay->GetOrigin(axis) > position) ? 1 : -1; 236 237 t = (position - mRay->GetOrigin(axis))/denom; 238 239 if (t < GetMinT()) 240 return (denom > 0) ? 1 : -1; 241 242 if (t > GetMaxT()) 243 return (denom > 0) ? -1 : 1; 244 245 return 0; 246 } 247 248 249 }; 250 251 252 typedef vector<RayInfo> RayInfoContainer; 253 254 enum { EInterior, ELeaf }; 255 256 ///////////////////////////////// 257 // The actual data goes here 258 259 // link to the parent 260 VspKdTreeInterior *parent; 261 262 enum {SPLIT_X=0, SPLIT_Y, SPLIT_Z, SPLIT_DIRX, SPLIT_DIRY, SPLIT_DIRZ}; 263 264 // splitting axis 265 char axis; 266 267 // depth 268 unsigned char depth; 269 270 // short depth; 271 // 272 ///////////////////////////////// 273 274 inline VspKdTreeNode(VspKdTreeInterior *p); 275 276 277 virtual ~VspKdTreeNode() {}; 278 virtual int Type() const = 0; 279 280 281 bool IsLeaf() const { return axis == -1; } 282 283 virtual void Print(ostream &s) const = 0; 284 285 virtual int GetAccessTime() { 286 return 0x7FFFFFF; 287 } 288 289 290 291 }; 292 293 // -------------------------------------------------------------- 294 // KD-tree node - interior node 295 // -------------------------------------------------------------- 296 class VspKdTreeInterior : 297 public VspKdTreeNode 298 { 299 public: 300 // plane in local modelling coordinates 301 float position; 302 303 // pointers to children 304 VspKdTreeNode *back, *front; 305 306 // the bbox of the node 307 AxisAlignedBox3 bbox; 308 309 // the bbox of the node 310 AxisAlignedBox3 dirBBox; 311 312 // data for caching 313 long accesses; 314 long lastAccessTime; 315 316 VspKdTreeInterior(VspKdTreeInterior *p):VspKdTreeNode(p), 317 back(NULL), 318 front(NULL), 319 accesses(0), 320 lastAccessTime(-1) 321 { } 322 323 virtual int GetAccessTime() { 324 return lastAccessTime; 325 } 326 327 void SetupChildLinks(VspKdTreeNode *b, VspKdTreeNode *f) { 328 back = b; 329 front = f; 330 b->parent = f->parent = this; 331 } 332 333 void ReplaceChildLink(VspKdTreeNode *oldChild, VspKdTreeNode *newChild) { 334 if (back == oldChild) 335 back = newChild; 336 else 337 front = newChild; 338 } 339 340 virtual int Type() const { return EInterior; } 341 342 virtual ~VspKdTreeInterior() { 343 if (back) 344 delete back; 345 if (front) 346 delete front; 347 } 348 349 virtual void Print(ostream &s) const { 350 if (axis == 0) 351 s<<"x "; 352 else 353 if (axis == 1) 354 s<<"y "; 355 else 356 s<<"z "; 357 s<<position<<" "; 358 back->Print(s); 359 front->Print(s); 360 } 361 362 363 364 int ComputeRayIntersection(const RayInfo &rayData, 365 float &t 366 ) { 367 return rayData.ComputeRayIntersection(axis, position, t); 368 } 369 370 }; 371 372 373 // -------------------------------------------------------------- 374 // KD-tree node - leaf node 375 // -------------------------------------------------------------- 376 class VspKdTreeLeaf : 377 public VspKdTreeNode 378 { 379 private: 380 int mPvsSize; 88 381 public: 89 382 static int mailID; 90 383 int mailbox; 91 384 385 RayInfoContainer rays; 386 bool mValidPvs; 387 388 VspKdTreeLeaf(VspKdTreeInterior *p, 389 const int nRays 390 ):VspKdTreeNode(p), rays(), mPvsSize(0), mValidPvs(false) { 391 rays.reserve(nRays); 392 } 393 394 virtual ~VspKdTreeLeaf() { } 395 396 virtual int Type() const { return ELeaf; } 397 398 virtual void Print(ostream &s) const { 399 s<<endl<<"L: r="<<rays.size()<<endl; 400 }; 401 402 void AddRay(const RayInfo &data) { 403 mValidPvs = false; 404 rays.push_back(data); 405 data.mRay->Ref(); 406 } 407 408 int GetPvsSize() const { 409 return mPvsSize; 410 } 411 void SetPvsSize(const int s) { 412 mPvsSize = s; 413 } 414 415 void 416 UpdatePvsSize(); 417 92 418 void Mail() { mailbox = mailID; } 93 419 static void NewMail() { mailID++; } 94 420 bool Mailed() const { return mailbox == mailID; } 95 96 97 ViewCellKdNode(ViewCellKdInterior *parent); 98 99 /** Determines whether this node is a leaf or interior node 100 @return true if leaf 101 */ 102 virtual bool IsLeaf() const = 0; 103 104 /** Determines whether this node is the root of the tree 105 @return true if root 106 */ 107 virtual bool IsRoot() const { 108 return mParent == NULL; 109 } 110 111 /** Parent of the node - the parent is a little overhead for maintanance of the tree, 112 but allows various optimizations of tree traversal algorithms */ 113 ViewCellKdInterior *mParent; 114 int mDepth; 421 422 bool Mailed(const int mail) { 423 return mailbox >= mailID + mail; 424 } 425 426 float GetAvgRayContribution() const { 427 return GetPvsSize()/((float)rays.size() + Limits::Small); 428 } 429 430 float GetSqrRayContribution() const { 431 return sqr(GetPvsSize()/((float)rays.size() + Limits::Small)); 432 } 433 115 434 }; 116 435 117 /** Implementation of the kd-tree interior node */ 118 class ViewCellKdInterior : public ViewCellKdNode { 119 120 public: 121 122 ViewCellKdInterior(ViewCellKdInterior *parent):ViewCellKdNode(parent), mBack(NULL), mFront(NULL) {} 123 124 /** \sa ViewCellKdNode::IsLeaf() */ 125 virtual bool IsLeaf() const { return false; } 126 127 /** splitting axis */ 128 int mAxis; 129 /** splitting position, absolute position within the bounding box of this node */ 130 float mPosition; 131 /** bounding box of interior node */ 132 AxisAlignedBox3 mBox; 133 134 /** back node */ 135 ViewCellKdNode *mBack; 136 /** front node */ 137 ViewCellKdNode *mFront; 138 139 void SetupChildLinks(ViewCellKdNode *b, ViewCellKdNode *f) { 140 mBack = b; 141 mFront = f; 142 b->mParent = f->mParent = this; 143 } 144 145 void ReplaceChildLink(ViewCellKdNode *oldChild, ViewCellKdNode *newChild) { 146 if (mBack == oldChild) 147 mBack = newChild; 148 else 149 mFront = newChild; 150 } 151 152 153 }; 154 155 156 /** Implementation of the kd-tree leaf node */ 157 class ViewCellKdLeaf : public ViewCellKdNode { 158 public: 159 ViewCellKdLeaf(ViewCellKdInterior *parent, const int objects):ViewCellKdNode(parent) { 160 mObjects.reserve(objects); 161 } 162 163 void AddPassingRay(const Ray &ray, 164 const int contributions) { 165 mPassingRays.AddRay(ray, contributions); 166 // Debug << "adding passing ray" << endl; 167 } 168 169 170 void AddPassingRay2(const Ray &ray, 171 const int objects, 172 const int viewcells 173 ) { 174 mPassingRays.AddRay2(ray, objects, viewcells); 175 // Debug << "adding passing ray" << endl; 176 } 177 178 /** \sa ViewCellKdNode::IsLeaf() */ 179 virtual bool IsLeaf() const { return true; } 180 181 182 183 184 /** pointers to occluders contained in this node */ 185 ObjectContainer mObjects; 186 187 /** pointers to viewcells contained in this node */ 188 // ViewCellContainer mViewCells; 189 190 /** Ray set description of the rays passing through this node */ 191 PassingRaySet mPassingRays; 192 193 /** PVS consisting of visible ViewCellKd nodes */ 194 ViewCellKdPvs mKdPvs; 195 196 /** PVS consisting of visible objects */ 197 ViewCellPvs mPvs; 198 }; 199 200 201 202 /** ViewCellKd for indexing scene entities - occluders/occludees/viewcells */ 203 class ViewCellKd { 204 205 protected: 436 // Inline functions 437 inline 438 VspKdTreeNode::VspKdTreeNode(VspKdTreeInterior *p): 439 parent(p), axis(-1), depth(p ? p->depth + 1 : 0) {} 440 441 442 443 // --------------------------------------------------------------- 444 // Main LSDS search class 445 // --------------------------------------------------------------- 446 class VspKdTree 447 { 206 448 struct TraversalData 207 449 { 208 V iewCellKdNode *mNode;209 AxisAlignedBox3 mBox;210 int mDepth;211 float mPriority;450 VspKdTreeNode *node; 451 AxisAlignedBox3 bbox; 452 int depth; 453 float priority; 212 454 213 455 TraversalData() {} 214 456 215 TraversalData(V iewCellKdNode *n, const float p):216 mNode(n), mPriority(p)457 TraversalData(VspKdTreeNode *n, const float p): 458 node(n), priority(p) 217 459 {} 218 219 TraversalData(V iewCellKdNode *n,460 461 TraversalData(VspKdTreeNode *n, 220 462 const AxisAlignedBox3 &b, 221 463 const int d): 222 mNode(n), mBox(b), mDepth(d) {}464 node(n), bbox(b), depth(d) {} 223 465 224 225 bool operator<( 226 const TraversalData &b) const { 227 ViewCellKdLeaf *leafa = (ViewCellKdLeaf *) mNode; 228 ViewCellKdLeaf *leafb = (ViewCellKdLeaf *) b.mNode; 229 return 230 leafa->mObjects.size()*mBox.SurfaceArea() 231 < 232 leafb->mObjects.size()*b.mBox.SurfaceArea(); 233 } 234 235 466 236 467 // comparator for the 237 468 struct less_priority : public 238 469 binary_function<const TraversalData, const TraversalData, bool> { 239 470 240 471 bool operator()(const TraversalData a, const TraversalData b) { 241 return a. mPriority < b.mPriority;472 return a.priority < b.priority; 242 473 } 243 474 244 475 }; 245 476 477 // ~TraversalData() {} 478 // TraversalData(const TraversalData &s):node(s.node), bbox(s.bbox), depth(s.depth) {} 479 480 friend bool operator<(const TraversalData &a, 481 const TraversalData &b) { 482 // return a.node->queries.size() < b.node->queries.size(); 483 VspKdTreeLeaf *leafa = (VspKdTreeLeaf *) a.node; 484 VspKdTreeLeaf *leafb = (VspKdTreeLeaf *) b.node; 485 #if 0 486 return 487 leafa->rays.size()*a.bbox.GetVolume() 488 < 489 leafb->rays.size()*b.bbox.GetVolume(); 490 #endif 491 #if 1 492 return 493 leafa->GetPvsSize()*a.bbox.GetVolume() 494 < 495 leafb->GetPvsSize()*b.bbox.GetVolume(); 496 #endif 497 #if 0 498 return 499 leafa->GetPvsSize() 500 < 501 leafb->GetPvsSize(); 502 #endif 503 #if 0 504 return 505 leafa->GetPvsSize()/(leafa->rays.size()+1) 506 > 507 leafb->GetPvsSize()/(leafb->rays.size()+1); 508 #endif 509 #if 0 510 return 511 leafa->GetPvsSize()*leafa->rays.size() 512 < 513 leafb->GetPvsSize()*leafb->rays.size(); 514 #endif 515 } 246 516 }; 247 248 249 250 public: 251 252 enum {SPLIT_OBJECT_MEDIAN, 253 SPLIT_SPATIAL_MEDIAN, 254 SPLIT_SAH}; 255 256 ViewCellKd(); 257 517 518 // simplified data for ray traversal only... 519 520 struct RayTraversalData { 258 521 259 /** Insert view cell into the tree */ 260 virtual void InsertViewCell(ViewCell *viewCell) { 261 // mRoot->mViewcells.push_back(viewCell); 262 } 263 264 virtual bool Construct(); 265 266 /** Check whether subdivision criteria are met for the given subtree. 267 If not subdivide the leafs of the subtree. The criteria are specified in 268 the environment as well as the subdivision method. By default surface area 269 heuristics is used. 270 271 @param subtree root of the subtree 272 273 @return true if subdivision was performed, false if subdivision criteria 274 were already met 275 */ 276 virtual ViewCellKdNode *Subdivide(const TraversalData &tdata); 277 278 /** Get the root of the tree */ 279 ViewCellKdNode *GetRoot() const { 280 return mRoot; 281 } 282 283 284 AxisAlignedBox3 GetBox() const { return mBox; } 285 286 int 287 CastRay( 288 Ray &ray 289 ); 290 291 const ViewCellKdTreeStatistics &GetStatistics() const { 292 return mStat; 293 } 294 295 void 296 CollectObjects(ViewCellKdNode *n, ObjectContainer &objects); 297 298 void 299 CollectLeaves(vector<ViewCellKdLeaf *> &leaves); 300 301 AxisAlignedBox3 GetBox(const ViewCellKdNode *node) const { 302 ViewCellKdInterior *parent = node->mParent; 303 if (parent == NULL) 304 return mBox; 305 306 if (!node->IsLeaf()) 307 return ((ViewCellKdInterior *)node)->mBox; 308 309 AxisAlignedBox3 box(parent->mBox); 310 if (parent->mFront == node) 311 box.SetMin(parent->mAxis, parent->mPosition); 312 else 313 box.SetMax(parent->mAxis, parent->mPosition); 314 return box; 315 } 316 317 ViewCellKdNode * 318 FindRandomNeighbor(ViewCellKdNode *n, 319 bool onlyUnmailed 320 ); 321 322 ViewCellKdNode * 323 ViewCellKd::GetRandomLeaf(const Plane3 &halfspace); 324 325 ViewCellKdNode * 326 GetRandomLeaf(const bool onlyUnmailed = false); 327 328 int 329 FindNeighbors(ViewCellKdNode *n, 330 vector<ViewCellKdNode *> &neighbors, 331 bool onlyUnmailed 332 ); 333 334 int 335 CollectLeafPvs(); 336 337 protected: 338 339 struct RayData { 340 // pointer to the actual ray 341 Ray *ray; 342 343 // endpoints - do we need them? 344 #if USE_FIXEDPOINT_T 345 short tmin, tmax; 346 #else 347 float tmin, tmax; 348 #endif 349 350 RayData():ray(NULL) {} 351 RayData(Ray *r):ray(r), tmin(0), 352 353 #if USE_FIXEDPOINT_T 354 #define FIXEDPOINT_ONE 0x7FFE 355 // tmax(0xFFFF) 356 tmax(FIXEDPOINT_ONE) 357 #else 358 tmax(1.0f) 359 #endif 360 {} 361 362 RayData(Ray *r, 363 const float _min, 364 const float _max 365 ):ray(r) { 366 SetTMin(_min); 367 SetTMax(_max); 368 } 369 370 RayData(Ray *r, 371 const short _min, 372 const float _max 373 ):ray(r), tmin(_min) { 374 SetTMax(_max); 375 } 376 377 RayData(Ray *r, 378 const float _min, 379 const short _max 380 ):ray(r), tmax(_max) { 381 SetTMin(_min); 382 } 383 384 friend bool operator<(const RayData &a, const RayData &b) { 385 return a.ray < b.ray; 386 } 387 388 389 float ExtrapOrigin(const int axis) const { 390 return ray->GetLoc(axis) + GetTMin()*ray->GetDir(axis); 391 } 392 393 float ExtrapTermination(const int axis) const { 394 return ray->GetLoc(axis) + GetTMax()*ray->GetDir(axis); 395 } 396 397 #if USE_FIXEDPOINT_T 398 float GetTMin () const { return tmin/(float)(FIXEDPOINT_ONE); } 399 float GetTMax () const { return tmax/(float)(FIXEDPOINT_ONE); } 400 401 void SetTMin (const float t) { 402 tmin = (short) (t*(float)(FIXEDPOINT_ONE)); 403 } 404 405 void SetTMax (const float t) { 406 tmax = (short) (t*(float)(FIXEDPOINT_ONE)); 407 tmax++; 408 // if (tmax!=0xFFFF) 409 // tmax++; 410 } 411 #else 412 float GetTMin () const { return tmin; } 413 float GetTMax () const { return tmax; } 414 415 void SetTMin (const float t) { tmin = t; } 416 void SetTMax (const float t) { tmax = t; } 417 #endif 418 }; 419 420 struct RayTraversalData { 421 ViewCellKdNode *mNode; 422 Vector3 mExitPoint; 423 float mMaxT; 522 VspKdTreeNode::RayInfo rayData; 523 VspKdTreeNode *node; 424 524 425 525 RayTraversalData() {} 426 RayTraversalData(ViewCellKdNode *n, 427 const Vector3 &p, 428 const float maxt): 429 mNode(n), mExitPoint(p), mMaxT(maxt) {} 526 RayTraversalData(VspKdTreeNode *n, 527 const VspKdTreeNode::RayInfo &data): 528 rayData(data), node(n) {} 430 529 }; 431 432 // -------------------------------------------------------------- 433 // For sorting objects 434 // -------------------------------------------------------------- 435 struct SortableEntry 436 { 437 enum { 438 BOX_MIN, 439 BOX_MAX 440 }; 441 442 int type; 443 float value; 444 Intersectable *intersectable; 445 446 SortableEntry() {} 447 SortableEntry(const int t, const float v, Intersectable *i):type(t), 448 value(v), 449 intersectable(i) {} 450 451 bool operator<(const SortableEntry &b) const { 452 return value < b.value; 453 } 454 455 }; 530 531 public: 532 ///////////////////////////// 533 // The core pointer 534 VspKdTreeNode *root; 535 536 ///////////////////////////// 537 // Basic properties 538 539 // total number of nodes of the tree 540 int nodes; 541 // axis aligned bounding box of the scene 542 AxisAlignedBox3 bbox; 543 544 // axis aligned bounding box of directions 545 AxisAlignedBox3 dirBBox; 546 547 ///////////////////////////// 548 // Construction parameters 549 550 // epsilon used for the construction 551 float epsilon; 552 553 // ratio between traversal and intersection costs 554 float ct_div_ci; 555 // max depth of the tree 556 int termMaxDepth; 557 // minimal ratio of the volume of the cell and the query volume 558 float termMinSize; 559 560 // minimal pvs per node to still get subdivided 561 int termMinPvs; 562 563 // minimal ray number per node to still get subdivided 564 int termMinRays; 565 566 // maximal cost ration to subdivide a node 567 float termMaxCostRatio; 568 569 // maximal contribution per ray to subdivide the node 570 float termMaxRayContribution; 571 572 573 // randomized construction 574 bool randomize; 575 576 // type of the splitting to use fo rthe tree construction 577 enum {ESplitRegular, ESplitHeuristic }; 578 int splitType; 579 580 // maximal size of the box on which the refdir splitting can be performed 581 // (relative to the scene bbox 582 float refDirBoxMaxSize; 583 584 // maximum alovable memory in MB 585 float maxTotalMemory; 586 587 // maximum alovable memory for static kd tree in MB 588 float maxStaticMemory; 589 590 // this is used during the construction depending 591 // on the type of the tree and queries... 592 float maxMemory; 593 594 595 // minimal acess time for collapse 596 int accessTimeThreshold; 597 598 // minimal depth at which to perform collapse 599 int minCollapseDepth; 600 456 601 457 602 // reusable array of split candidates 458 603 vector<SortableEntry> *splitCandidates; 459 460 float 461 BestCostRatio( 462 ViewCellKdLeaf *node, 463 const AxisAlignedBox3 &box, 464 const int axis, 465 float &position, 466 int &objectsBack, 467 int &objectsFront 468 ); 604 ///////////////////////////// 605 606 VspKdStatistics stat; 607 608 609 VspKdTree(); 610 virtual ~VspKdTree(); 611 612 virtual void 613 Construct( 614 VssRayContainer &rays, 615 AxisAlignedBox3 *forcedBoundingBox = NULL 616 ); 617 618 // incemental construction 619 virtual void UpdateRays(VssRayContainer &remove, 620 VssRayContainer &add 621 ); 622 623 virtual void AddRays( 624 VssRayContainer &add 625 ) 626 { 627 VssRayContainer remove; 628 UpdateRays(remove, add); 629 } 630 631 632 633 VspKdTreeNode * 634 Locate(const Vector3 &v); 635 636 VspKdTreeNode * 637 SubdivideNode(VspKdTreeLeaf *leaf, 638 const AxisAlignedBox3 &box, 639 AxisAlignedBox3 &backBox, 640 AxisAlignedBox3 &frontBox 641 ); 642 643 VspKdTreeNode * 644 Subdivide(const TraversalData &tdata); 645 646 int 647 SelectPlane(VspKdTreeLeaf *leaf, 648 const AxisAlignedBox3 &box, 649 float &position, 650 int &raysBack, 651 int &raysFront, 652 int &pvsBack, 653 int &pvsFront 654 ); 469 655 470 656 void 471 657 SortSplitCandidates( 472 ViewCellKdLeaf *node, 473 const int axis 474 ); 658 VspKdTreeLeaf *node, 659 const int axis 660 ); 661 662 663 // return memory usage in MB 664 float GetMemUsage() const { 665 return 666 (sizeof(VspKdTree) + 667 stat.Leaves()*sizeof(VspKdTreeLeaf) + 668 stat.Interior()*sizeof(VspKdTreeInterior) + 669 stat.rayRefs*sizeof(VspKdTreeNode::RayInfo))/(1024.0f*1024.0f); 670 } 671 672 float GetRayMemUsage() const { 673 return 674 stat.rays*(sizeof(VssRay))/(1024.0f*1024.0f); 675 } 676 677 float 678 BestCostRatioHeuristic( 679 VspKdTreeLeaf *node, 680 int &axis, 681 float &position, 682 int &raysBack, 683 int &raysFront, 684 int &pvsBack, 685 int &pvsFront 686 ); 687 688 float 689 BestCostRatioRegular( 690 VspKdTreeLeaf *node, 691 int &axis, 692 float &position, 693 int &raysBack, 694 int &raysFront, 695 int &pvsBack, 696 int &pvsFront 697 698 ); 699 700 float 701 EvalCostRatio( 702 VspKdTreeLeaf *node, 703 const int axis, 704 const float position, 705 int &raysBack, 706 int &raysFront, 707 int &pvsBack, 708 int &pvsFront 709 ); 710 711 AxisAlignedBox3 GetBBox(const VspKdTreeNode *node) { 712 if (node->parent == NULL) 713 return bbox; 714 715 if (!node->IsLeaf()) 716 return ((VspKdTreeInterior *)node)->bbox; 717 718 if (node->parent->axis >= 3) 719 return node->parent->bbox; 720 721 AxisAlignedBox3 box(node->parent->bbox); 722 if (node->parent->front == node) 723 box.SetMin(node->parent->axis, node->parent->position); 724 else 725 box.SetMax(node->parent->axis, node->parent->position); 726 return box; 727 } 728 729 AxisAlignedBox3 GetDirBBox(const VspKdTreeNode *node) { 730 731 if (node->parent == NULL) 732 return dirBBox; 733 734 if (!node->IsLeaf() ) 735 return ((VspKdTreeInterior *)node)->dirBBox; 736 737 if (node->parent->axis < 3) 738 return node->parent->dirBBox; 739 740 AxisAlignedBox3 dBBox(node->parent->dirBBox); 741 742 if (node->parent->front == node) 743 dBBox.SetMin(node->parent->axis - 3, node->parent->position); 744 else 745 dBBox.SetMax(node->parent->axis - 3, node->parent->position); 746 return dBBox; 747 } 748 749 int 750 ReleaseMemory(const int time); 751 752 int 753 CollapseSubtree(VspKdTreeNode *node, const int time); 475 754 476 755 void 756 CountAccess(VspKdTreeInterior *node, const long time) { 757 node->accesses++; 758 node->lastAccessTime = time; 759 } 760 761 VspKdTreeNode * 762 SubdivideLeaf( 763 VspKdTreeLeaf *leaf, 764 const float SAThreshold 765 ); 766 767 void 768 RemoveRay(VssRay *ray, 769 vector<VspKdTreeLeaf *> *affectedLeaves, 770 const bool removeAllScheduledRays 771 ); 772 773 void 774 AddRay(VssRay *ray); 775 776 void 777 TraverseInternalNode( 778 RayTraversalData &data, 779 stack<RayTraversalData> &tstack); 780 781 void 477 782 EvaluateLeafStats(const TraversalData &data); 478 783 479 ViewCellKdNode * 480 SubdivideNode( 481 ViewCellKdLeaf *leaf, 482 const AxisAlignedBox3 &box, 483 AxisAlignedBox3 &backBBox, 484 AxisAlignedBox3 &frontBBox 485 ); 486 487 bool 488 TerminationCriteriaMet(const ViewCellKdLeaf *leaf); 489 490 int 491 SelectPlane(ViewCellKdLeaf *leaf, 492 const AxisAlignedBox3 &box, 493 float &position 494 ); 495 496 497 498 float mSplitBorder; 499 int mTermMaxDepth; 500 int mTermMinCost; 501 float mMaxCostRatio; 502 float mCt_div_ci; 503 int mSplitMethod; 504 bool mSahUseFaces; 505 /// root of the tree 506 ViewCellKdNode *mRoot; 507 /// bounding box of the tree root 508 AxisAlignedBox3 mBox; 509 ViewCellKdTreeStatistics mStat; 510 784 785 int 786 GetRootPvsSize() const { 787 return GetPvsSize(root, bbox); 788 } 789 790 int 791 GetPvsSize(VspKdTreeNode *node, const AxisAlignedBox3 &box) const; 792 793 void 794 GetRayContributionStatistics( 795 float &minRayContribution, 796 float &maxRayContribution, 797 float &avgRayContribution 798 ); 799 800 int 801 GenerateRays(const float ratioPerLeaf, 802 SimpleRayContainer &rays); 803 804 float 805 GetAvgPvsSize(); 806 511 807 }; 512 808 513 #endif 809 810 #endif // __LSDS_KDTREE_H__ 811
Note: See TracChangeset
for help on using the changeset viewer.