Browse Source

Octree query micro-optimizations.

Lasse Öörni 13 years ago
parent
commit
0937a62115
3 changed files with 134 additions and 87 deletions
  1. 92 45
      Engine/Graphics/Octree.cpp
  2. 24 24
      Engine/Graphics/OctreeQuery.cpp
  3. 18 18
      Engine/Graphics/View.cpp

+ 92 - 45
Engine/Graphics/Octree.cpp

@@ -209,30 +209,47 @@ void Octant::GetDrawablesInternal(OctreeQuery& query, bool inside) const
     if (this != root_)
     {
         Intersection res = query.TestOctant(cullingBox_, inside);
-        if (res == OUTSIDE)
-            // Fully outside, so cull this octant, its children & drawables
-            return;
         if (res == INSIDE)
             inside = true;
+        else if (res == OUTSIDE)
+        {
+            // Fully outside, so cull this octant, its children & drawables
+            return;
+        }
     }
     
-    for (PODVector<Drawable*>::ConstIterator i = drawables_.Begin(); i != drawables_.End(); ++i)
+    if (drawables_.Size())
     {
-        Drawable* drawable = *i;
-        
-        if (!(drawable->GetDrawableFlags() & query.drawableFlags_) || !drawable->IsVisible() ||
-            !(drawable->GetViewMask() & query.viewMask_))
-            continue;
-        
-        if (query.TestDrawable(drawable, inside) != OUTSIDE)
-            query.result_.Push(drawable);
+        Drawable** ptr = const_cast<Drawable**>(&drawables_.Front());
+        Drawable** end = ptr + drawables_.Size();
+       
+        while (ptr != end)
+        {
+            Drawable* drawable = *ptr;
+            if ((drawable->GetDrawableFlags() & query.drawableFlags_) && drawable->IsVisible() && 
+                (drawable->GetViewMask() & query.viewMask_) && (query.TestDrawable(drawable, inside) != OUTSIDE))
+                query.result_.Push(drawable);
+            
+            ++ptr;
+        }
     }
     
-    for (unsigned i = 0; i < NUM_OCTANTS; ++i)
-    {
-        if (children_[i])
-            children_[i]->GetDrawablesInternal(query, inside);
-    }
+    if (children_[0])
+        children_[0]->GetDrawablesInternal(query, inside);
+    if (children_[1])
+        children_[1]->GetDrawablesInternal(query, inside);
+    if (children_[2])
+        children_[2]->GetDrawablesInternal(query, inside);
+    if (children_[3])
+        children_[3]->GetDrawablesInternal(query, inside);
+    if (children_[4])
+        children_[4]->GetDrawablesInternal(query, inside);
+    if (children_[5])
+        children_[5]->GetDrawablesInternal(query, inside);
+    if (children_[6])
+        children_[6]->GetDrawablesInternal(query, inside);
+    if (children_[7])
+        children_[7]->GetDrawablesInternal(query, inside);
 }
 
 void Octant::GetDrawablesInternal(RayOctreeQuery& query) const
@@ -244,23 +261,38 @@ void Octant::GetDrawablesInternal(RayOctreeQuery& query) const
     if (octantDist > query.maxDistance_)
         return;
     
-    for (PODVector<Drawable*>::ConstIterator i = drawables_.Begin(); i != drawables_.End(); ++i)
+    if (drawables_.Size())
     {
-        Drawable* drawable = *i;
-        unsigned drawableFlags = drawable->GetDrawableFlags();
-        
-        if (!(drawable->GetDrawableFlags() & query.drawableFlags_) || !drawable->IsVisible() ||
-            !(drawable->GetViewMask() & query.viewMask_))
-            continue;
-        
-        drawable->ProcessRayQuery(query, query.result_);
+        Drawable** ptr = const_cast<Drawable**>(&drawables_.Front());
+        Drawable** end = ptr + drawables_.Size();
+       
+        while (ptr != end)
+        {
+            Drawable* drawable = *ptr;
+            if ((drawable->GetDrawableFlags() & query.drawableFlags_) && drawable->IsVisible() &&
+                (drawable->GetViewMask() & query.viewMask_))
+                drawable->ProcessRayQuery(query, query.result_);
+            
+            ++ptr;
+        }
     }
     
-    for (unsigned i = 0; i < NUM_OCTANTS; ++i)
-    {
-        if (children_[i])
-            children_[i]->GetDrawablesInternal(query);
-    }
+    if (children_[0])
+        children_[0]->GetDrawablesInternal(query);
+    if (children_[1])
+        children_[1]->GetDrawablesInternal(query);
+    if (children_[2])
+        children_[2]->GetDrawablesInternal(query);
+    if (children_[3])
+        children_[3]->GetDrawablesInternal(query);
+    if (children_[4])
+        children_[4]->GetDrawablesInternal(query);
+    if (children_[5])
+        children_[5]->GetDrawablesInternal(query);
+    if (children_[6])
+        children_[6]->GetDrawablesInternal(query);
+    if (children_[7])
+        children_[7]->GetDrawablesInternal(query);
 }
 
 void Octant::GetDrawablesOnlyInternal(RayOctreeQuery& query, PODVector<Drawable*>& drawables) const
@@ -272,23 +304,38 @@ void Octant::GetDrawablesOnlyInternal(RayOctreeQuery& query, PODVector<Drawable*
     if (octantDist > query.maxDistance_)
         return;
     
-    for (PODVector<Drawable*>::ConstIterator i = drawables_.Begin(); i != drawables_.End(); ++i)
+    if (drawables_.Size())
     {
-        Drawable* drawable = *i;
-        unsigned drawableFlags = drawable->GetDrawableFlags();
-        
-        if (!(drawable->GetDrawableFlags() & query.drawableFlags_) || !drawable->IsVisible() ||
-            !(drawable->GetViewMask() & query.viewMask_))
-            continue;
-        
-        drawables.Push(drawable);
+        Drawable** ptr = const_cast<Drawable**>(&drawables_.Front());
+        Drawable** end = ptr + drawables_.Size();
+       
+        while (ptr != end)
+        {
+            Drawable* drawable = *ptr;
+            if ((drawable->GetDrawableFlags() & query.drawableFlags_) && drawable->IsVisible() &&
+                (drawable->GetViewMask() & query.viewMask_))
+                drawables.Push(drawable);
+            
+            ++ptr;
+        }
     }
     
-    for (unsigned i = 0; i < NUM_OCTANTS; ++i)
-    {
-        if (children_[i])
-            children_[i]->GetDrawablesOnlyInternal(query, drawables);
-    }
+    if (children_[0])
+        children_[0]->GetDrawablesOnlyInternal(query, drawables);
+    if (children_[1])
+        children_[1]->GetDrawablesOnlyInternal(query, drawables);
+    if (children_[2])
+        children_[2]->GetDrawablesOnlyInternal(query, drawables);
+    if (children_[3])
+        children_[3]->GetDrawablesOnlyInternal(query, drawables);
+    if (children_[4])
+        children_[4]->GetDrawablesOnlyInternal(query, drawables);
+    if (children_[5])
+        children_[5]->GetDrawablesOnlyInternal(query, drawables);
+    if (children_[6])
+        children_[6]->GetDrawablesOnlyInternal(query, drawables);
+    if (children_[7])
+        children_[7]->GetDrawablesOnlyInternal(query, drawables);
 }
 
 void Octant::Release()

+ 24 - 24
Engine/Graphics/OctreeQuery.cpp

@@ -28,64 +28,64 @@
 
 Intersection PointOctreeQuery::TestOctant(const BoundingBox& box, bool inside) const
 {
-    if (!inside)
-        return box.IsInside(point_);
-    else
+    if (inside)
         return INSIDE;
+    else
+        return box.IsInside(point_);
 }
 
 Intersection PointOctreeQuery::TestDrawable(Drawable* drawable, bool inside) const
 {
-    if (!inside)
-        return drawable->GetWorldBoundingBox().IsInside(point_);
-    else
+    if (inside)
         return INSIDE;
+    else
+        return drawable->GetWorldBoundingBox().IsInside(point_);
 }
 
 Intersection SphereOctreeQuery::TestOctant(const BoundingBox& box, bool inside) const
 {
-    if (!inside)
-        return sphere_.IsInside(box);
-    else
+    if (inside)
         return INSIDE;
+    else
+        return sphere_.IsInside(box);
 }
 
 Intersection SphereOctreeQuery::TestDrawable(Drawable* drawable, bool inside) const
 {
-    if (!inside)
-        return sphere_.IsInsideFast(drawable->GetWorldBoundingBox());
-    else
+    if (inside)
         return INSIDE;
+    else
+        return sphere_.IsInsideFast(drawable->GetWorldBoundingBox());
 }
 
 Intersection BoxOctreeQuery::TestOctant(const BoundingBox& box, bool inside) const
 {
-    if (!inside)
-        return box_.IsInside(box);
-    else
+    if (inside)
         return INSIDE;
+    else
+        return box_.IsInside(box);
 }
 
 Intersection BoxOctreeQuery::TestDrawable(Drawable* drawable, bool inside) const
 {
-    if (!inside)
-        return box_.IsInsideFast(drawable->GetWorldBoundingBox());
-    else
+    if (inside)
         return INSIDE;
+    else
+        return box_.IsInsideFast(drawable->GetWorldBoundingBox());
 }
 
 Intersection FrustumOctreeQuery::TestOctant(const BoundingBox& box, bool inside) const
 {
-    if (!inside)
-        return frustum_.IsInside(box);
-    else
+    if (inside)
         return INSIDE;
+    else
+        return frustum_.IsInside(box);
 }
 
 Intersection FrustumOctreeQuery::TestDrawable(Drawable* drawable, bool inside) const
 {
-    if (!inside)
-        return frustum_.IsInsideFast(drawable->GetWorldBoundingBox());
-    else
+    if (inside)
         return INSIDE;
+    else
+        return frustum_.IsInsideFast(drawable->GetWorldBoundingBox());
 }

+ 18 - 18
Engine/Graphics/View.cpp

@@ -77,10 +77,10 @@ public:
     /// Intersection test for an octant.
     virtual Intersection TestOctant(const BoundingBox& box, bool inside) const
     {
-        if (!inside)
-            return frustum_.IsInside(box);
-        else
+        if (inside)
             return INSIDE;
+        else
+            return frustum_.IsInside(box);
     }
     
     /// Intersection test for a drawable.
@@ -88,10 +88,10 @@ public:
     {
         if (drawable->GetCastShadows())
         {
-            if (!inside)
-                return frustum_.IsInsideFast(drawable->GetWorldBoundingBox());
-            else
+            if (inside)
                 return INSIDE;
+            else
+                return frustum_.IsInsideFast(drawable->GetWorldBoundingBox());
         }
         else
             return OUTSIDE;
@@ -116,10 +116,10 @@ public:
     /// Intersection test for an octant.
     virtual Intersection TestOctant(const BoundingBox& box, bool inside) const
     {
-        if (!inside)
-            return frustum_.IsInside(box);
-        else
+        if (inside)
             return INSIDE;
+        else
+            return frustum_.IsInside(box);
     }
     
     /// Intersection test for a drawable.
@@ -128,10 +128,10 @@ public:
         unsigned char flags = drawable->GetDrawableFlags();
         if (flags == DRAWABLE_ZONE || (flags == DRAWABLE_GEOMETRY && drawable->IsOccluder()))
         {
-            if (!inside)
-                return frustum_.IsInsideFast(drawable->GetWorldBoundingBox());
-            else
+            if (inside)
                 return INSIDE;
+            else
+                return frustum_.IsInsideFast(drawable->GetWorldBoundingBox());
         }
         else
             return OUTSIDE;
@@ -157,15 +157,15 @@ public:
     /// Intersection test for an octant.
     virtual Intersection TestOctant(const BoundingBox& box, bool inside) const
     {
-        if (!inside)
+        if (inside)
+            return buffer_->IsVisible(box) ? INSIDE : OUTSIDE;
+        else
         {
             Intersection result = frustum_.IsInside(box);
             if (result != OUTSIDE && !buffer_->IsVisible(box))
                 result = OUTSIDE;
             return result;
         }
-        else
-            return buffer_->IsVisible(box) ? INSIDE : OUTSIDE;
     }
     
     /// Intersection test for a drawable. Note: drawable occlusion is performed later in worker threads.
@@ -173,10 +173,10 @@ public:
     {
         const BoundingBox& box = drawable->GetWorldBoundingBox();
         
-        if (!inside)
-            return frustum_.IsInsideFast(box);
-        else
+        if (inside)
             return INSIDE;
+        else
+            return frustum_.IsInsideFast(box);
     }
     
     /// Frustum.