Changeset 408 for trunk/VUT/GtpVisibilityPreprocessor/src/VspKdTree.h
- Timestamp:
- 11/14/05 11:12:38 (19 years ago)
- File:
-
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
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.