- Timestamp:
- 01/12/09 00:17:58 (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
GTP/trunk/App/Demos/Vis/FriendlyCulling/src/BvhConstructor.cpp
r3268 r3269 8 8 #include <stack> 9 9 #include <fstream> 10 11 #define MAX_FLOAT 1e20f 12 10 13 11 14 #ifdef _CRT_SET … … 32 35 mFirst(first), 33 36 mLast(last), 34 mMaxDepth( 10),37 mMaxDepth(20), 35 38 mMaxObjects(1), 36 mNumNodes(0) 37 { 39 mMaxTriangles(1), 40 mNumNodes(0), 41 mSplitType(SAH) 42 { 43 } 44 45 46 float BvhConstructor::EvaluateSahCost(BvhLeaf *leaf, int axis, float position) 47 { 48 // count triangles on the left / right 49 int left = 0; 50 int right = 0; 51 AxisAlignedBox3 leftBox, rightBox; 52 53 leftBox.Initialize(); 54 rightBox.Initialize(); 55 56 const int candidates = std::max(50, (int)(leaf->CountPrimitives() / 20)); 57 const float finc = leaf->CountPrimitives() / (float)candidates; 58 59 int i = leaf->mFirst; 60 float fi = leaf->mFirst + 0.5f; 61 62 AxisAlignedBox3 box; 63 64 for (; i <= leaf->mLast;) 65 { 66 box = mEntities[i]->GetWorldBoundingBox(); 67 68 if (box.Center(axis) < position) 69 { 70 ++ left; 71 // update the box 72 leftBox.Include(box); 73 } 74 else 75 { 76 ++ right; 77 rightBox.Include(box); 78 } 79 80 fi += finc; 81 i = (int)fi; 82 } 83 84 float bW = 1.0f; 85 float leftRatio = left / (float)leaf->CountPrimitives(); 86 float rightRatio = right / (float)leaf->CountPrimitives(); 87 88 float saLeft = 0.0f; 89 float saRight = 0.0f; 90 91 // not a valid split 92 if (!left || !right) 93 return 1e25f; 94 95 saLeft = leftBox.SurfaceArea(); 96 saRight = rightBox.SurfaceArea(); 97 98 99 return 100 saLeft * ((1.0f - bW) + bW * leftRatio) + 101 saRight * ((1.0f - bW) + bW * rightRatio); 102 } 103 104 105 float BvhConstructor::SelectPlaneSah(BvhLeaf *leaf, int &axis, float &minCost) 106 { 107 minCost = MAX_FLOAT; 108 float bestPos = minCost; 109 int bestAxis = 0; 110 111 // cout<<"Evaluating axis..."<<endl<<flush; 112 113 const int initialPlanes = 3; 114 115 // initiate the costs 116 for (axis = 0; axis < 3; ++ axis) 117 { 118 const float size = leaf->mBox.Size(axis); 119 120 for (int i = 0; i < initialPlanes; ++ i) 121 { 122 const float pos = leaf->mBox.Min(axis) + (i + 1) * size / (initialPlanes + 1); 123 const float cost = EvaluateSahCost(leaf, axis, pos); 124 125 if (cost < minCost) 126 { 127 minCost = cost; 128 bestPos = pos; 129 bestAxis = axis; 130 } 131 } 132 } 133 134 axis = bestAxis; 135 136 // cout<<axis<<endl<<flush; 137 const float shrink = 0.5f; 138 139 // now hierarchically refine the initial interval 140 float size = shrink * 141 (leaf->mBox.Max(axis) - leaf->mBox.Min(axis)) / (initialPlanes + 1); 142 143 const int steps = 4; 144 float cost; 145 146 for (int i = 0; i < steps; ++ i) 147 { 148 const float left = bestPos - size; 149 const float right = bestPos + size; 150 151 cost = EvaluateSahCost(leaf, axis, left); 152 153 if (cost < minCost) 154 { 155 minCost = cost; 156 bestPos = left; 157 } 158 159 cost = EvaluateSahCost(leaf, axis, right); 160 161 if (cost < minCost) 162 { 163 minCost = cost; 164 bestPos = right; 165 } 166 167 size = shrink * size; 168 } 169 170 //OUT1("best axis: " << axis << " " << bestPos << " " << minCost); 171 172 return bestPos; 38 173 } 39 174 … … 102 237 103 238 239 int BvhConstructor::SortTrianglesObjectMedian(BvhLeaf *leaf, int axis, float &pos) 240 { 241 // Now distribute the objects into the subnodes 242 // Use QuickMedian sort 243 int l = leaf->mFirst; 244 int r = leaf->mLast; 245 int k = (l + r) / 2; 246 247 while (l < r) 248 { 249 int i = l; 250 int j = r; 251 252 // get some estimation of the pivot 253 pos = mEntities[(l + r) / 2]->GetBoundingBox().Center(axis); 254 255 while (1) 256 { 257 while ((i <= leaf->mLast) && (mEntities[i]->GetWorldBoundingBox().Center(axis) < pos)) 258 ++ i; 259 260 while((j >= leaf->mFirst) && (pos < mEntities[j]->GetWorldBoundingBox().Center(axis))) 261 -- j; 262 263 if (i <= j) 264 { 265 std::swap(mEntities[i], mEntities[j]); 266 ++ i; 267 -- j; 268 } 269 else 270 { 271 break; 272 } 273 } 274 275 // now check the extents 276 if (i >= k) 277 r = j; 278 else 279 l = i; 280 } 281 282 return k; 283 } 284 285 104 286 BvhNode *BvhConstructor::SubdivideLeaf(BvhLeaf *leaf, 105 287 int parentAxis … … 114 296 115 297 //const int axis = (parentAxis + 1) % 3; 116 constint axis = leaf->mBox.MajorAxis();298 int axis = leaf->mBox.MajorAxis(); 117 299 const int scale = 20; 118 300 … … 121 303 int split = -1; 122 304 float pos = -1.0f; 123 305 124 306 // Spatial median subdivision 125 split = SortTrianglesSpatialMedian(leaf, axis); 126 pos = leaf->mBox.Center()[axis]; 307 switch (mSplitType) 308 { 309 case SPATIAL_MEDIAN: 310 split = SortTrianglesSpatialMedian(leaf, axis); 311 pos = leaf->mBox.Center()[axis]; 312 break; 313 case OBJECT_MEDIAN: 314 // Object median subdivision: approximately the same number 315 // of objects on the left of the the splitting point. 316 split = SortTrianglesObjectMedian(leaf, axis, pos); 317 break; 318 case SAH: 319 { 320 float cost; 321 pos = SelectPlaneSah(leaf, axis, cost); 322 323 if (pos != MAX_FLOAT) 324 { 325 split = SortTriangles(leaf, axis, pos); 326 } 327 328 if ((pos == MAX_FLOAT) || (split == leaf->mLast)) 329 { 330 split = -1; 331 split = SortTrianglesObjectMedian(leaf, axis, pos); 332 } 333 } 334 break; 335 default: 336 cerr << "should not come here" << endl; 337 break; 338 } 127 339 128 340 if (split == leaf->mLast) … … 168 380 169 381 382 int BvhConstructor::CountTriangles(BvhNode *node) const 383 { 384 int numTriangles = 0; 385 386 for (int i = node->mFirst; i <= node->mLast; ++ i) 387 { 388 numTriangles += mEntities[i]->CountNumTriangles(0); 389 } 390 391 return numTriangles; 392 } 393 394 170 395 bool BvhConstructor::TerminationCriteriaMet(BvhLeaf *leaf) const 171 396 { 172 397 const bool criteriaMet = 173 398 (leaf->mDepth > mMaxDepth) || 174 (leaf->CountPrimitives() <= mMaxObjects); 399 (leaf->CountPrimitives() <= mMaxObjects) || 400 (CountTriangles(leaf) <= mMaxTriangles); 175 401 176 402 return criteriaMet; … … 188 414 l->mLast = mLast; 189 415 190 cout << "constructing bvh from " << l->mFirst << " to " << l->mLast << endl; 416 cout << "\n================================" << endl; 417 cout << "constructing bvh for " << l->mLast - l->mFirst + 1 << " entities" << endl; 191 418 192 419 l->mBox = SceneEntity::ComputeBoundingBox(mEntities + mFirst, mLast - mFirst + 1);
Note: See TracChangeset
for help on using the changeset viewer.