void Octant::GetDrawablesOnlyInternal(RayOctreeQuery& query, PODVector<Drawable*>& drawables) const { float octantDist = query.ray_.HitDistance(cullingBox_); if (octantDist >= query.maxDistance_) return; if (drawables_.Size()) { Drawable** start = const_cast<Drawable**>(&drawables_[0]); Drawable** end = start + drawables_.Size(); while (start != end) { Drawable* drawable = *start++; if ((drawable->GetDrawableFlags() & query.drawableFlags_) && (drawable->GetViewMask() & query.viewMask_)) drawables.Push(drawable); } } for (unsigned i = 0; i < NUM_OCTANTS; ++i) { if (children_[i]) children_[i]->GetDrawablesOnlyInternal(query, drawables); } }
void Zone::ClearDrawablesZone() { if (octant_ && lastWorldBoundingBox_.defined_) { PODVector<Drawable*> result; BoxOctreeQuery query(result, lastWorldBoundingBox_, DRAWABLE_GEOMETRY | DRAWABLE_ZONE); octant_->GetRoot()->GetDrawables(query); for (PODVector<Drawable*>::Iterator i = result.Begin(); i != result.End(); ++i) { Drawable* drawable = *i; unsigned drawableFlags = drawable->GetDrawableFlags(); if (drawableFlags & DRAWABLE_GEOMETRY) drawable->SetZone(0); else if (drawableFlags & DRAWABLE_ZONE) { Zone* zone = static_cast<Zone*>(drawable); zone->lastAmbientStartZone_.Reset(); zone->lastAmbientEndZone_.Reset(); } } } lastWorldBoundingBox_ = GetWorldBoundingBox(); lastAmbientStartZone_.Reset(); lastAmbientEndZone_.Reset(); }
void Octant::GetDrawablesInternal(RayOctreeQuery& query) const { float octantDist = query.ray_.HitDistance(cullingBox_); if (octantDist >= query.maxDistance_) return; if (drawables_.Size()) { auto** start = const_cast<Drawable**>(&drawables_[0]); Drawable** end = start + drawables_.Size(); while (start != end) { Drawable* drawable = *start++; if ((drawable->GetDrawableFlags() & query.drawableFlags_) && (drawable->GetViewMask() & query.viewMask_)) drawable->ProcessRayQuery(query, query.result_); } } for (auto child : children_) { if (child) child->GetDrawablesInternal(query); } }
void BoxOctreeQuery::TestDrawables(Drawable** start, Drawable** end, bool inside) { while (start != end) { Drawable* drawable = *start++; if ((drawable->GetDrawableFlags() & drawableFlags_) && (drawable->GetViewMask() & viewMask_)) { if (inside || box_.IsInsideFast(drawable->GetWorldBoundingBox())) result_.Push(drawable); } } }
void Zone::OnMarkedDirty(Node* node) { // Due to the octree query and weak pointer manipulation, is not safe from worker threads Scene* scene = GetScene(); if (scene && scene->IsThreadedUpdate()) { scene->DelayedMarkedDirty(this); return; } Drawable::OnMarkedDirty(node); // When marked dirty, clear the cached zone from all drawables inside the zone bounding box, // and mark gradient dirty in all neighbor zones if (octant_ && lastWorldBoundingBox_.defined_) { PODVector<Drawable*> result; BoxOctreeQuery query(result, lastWorldBoundingBox_, DRAWABLE_GEOMETRY | DRAWABLE_ZONE); octant_->GetRoot()->GetDrawables(query); for (PODVector<Drawable*>::Iterator i = result.Begin(); i != result.End(); ++i) { Drawable* drawable = *i; unsigned drawableFlags = drawable->GetDrawableFlags(); if (drawableFlags & DRAWABLE_GEOMETRY) { if (drawable->GetZone() == this) drawable->SetZone(0); } else if (drawableFlags & DRAWABLE_ZONE) { Zone* zone = static_cast<Zone*>(drawable); zone->lastAmbientStartZone_.Reset(); zone->lastAmbientEndZone_.Reset(); } } } lastWorldBoundingBox_ = GetWorldBoundingBox(); lastAmbientStartZone_.Reset(); lastAmbientEndZone_.Reset(); inverseWorldDirty_ = true; }