| 281 | void RTree::validateRecursive(PxU32 level, RTreeNodeQ parentBounds, RTreePage* page, CallbackRefit* cbLeaf) |
| 282 | #else |
| 283 | void RTree::validateRecursive(PxU32 level, RTreeNodeQ parentBounds, RTreePage* page) |
| 284 | #endif |
| 285 | { |
| 286 | PX_UNUSED(parentBounds); |
| 287 | |
| 288 | static PxU32 validateCounter = 0; // this is to suppress a warning that recursive call has no side effects |
| 289 | validateCounter++; |
| 290 | |
| 291 | RTreeNodeQ n; |
| 292 | PxU32 pageNodeCount = page->nodeCount(); |
| 293 | for (PxU32 j = 0; j < pageNodeCount; j++) |
| 294 | { |
| 295 | page->getNode(j, n); |
| 296 | if (page->isEmpty(j)) |
| 297 | continue; |
| 298 | PX_ASSERT(n.minx >= parentBounds.minx); PX_ASSERT(n.miny >= parentBounds.miny); PX_ASSERT(n.minz >= parentBounds.minz); |
| 299 | PX_ASSERT(n.maxx <= parentBounds.maxx); PX_ASSERT(n.maxy <= parentBounds.maxy); PX_ASSERT(n.maxz <= parentBounds.maxz); |
| 300 | if (!n.isLeaf()) |
| 301 | { |
| 302 | PX_ASSERT((n.ptr&1) == 0); |
| 303 | RTreePage* childPage = reinterpret_cast<RTreePage*>(size_t(mPages) + n.ptr); |
| 304 | #if PX_ENABLE_DYNAMIC_MESH_RTREE |
| 305 | validateRecursive(level+1, n, childPage, cbLeaf); |
| 306 | } else if (cbLeaf) |
| 307 | { |
| 308 | Vec3V mnv, mxv; |
| 309 | cbLeaf->recomputeBounds(page->ptrs[j] & ~1, mnv, mxv); |
| 310 | PxVec3 mn3, mx3; V3StoreU(mnv, mn3); V3StoreU(mxv, mx3); |
| 311 | const PxBounds3 lb(mn3, mx3); |
| 312 | const PxVec3& mn = lb.minimum; const PxVec3& mx = lb.maximum; PX_UNUSED(mn); PX_UNUSED(mx); |
| 313 | PX_ASSERT(mn.x >= n.minx); PX_ASSERT(mn.y >= n.miny); PX_ASSERT(mn.z >= n.minz); |
| 314 | PX_ASSERT(mx.x <= n.maxx); PX_ASSERT(mx.y <= n.maxy); PX_ASSERT(mx.z <= n.maxz); |
| 315 | } |
| 316 | #else |
| 317 | validateRecursive(level+1, n, childPage); |
| 318 | } |
| 319 | #endif |
| 320 | } |
| 321 | RTreeNodeQ recomputedBounds; |
| 322 | page->computeBounds(recomputedBounds); |
| 323 | PX_ASSERT((recomputedBounds.minx - parentBounds.minx)<=RTREE_INFLATION_EPSILON); |