Browse Source

Fixed raycast early-out logic.

Lasse Öörni 14 years ago
parent
commit
f53f75f6f3
1 changed files with 12 additions and 4 deletions
  1. 12 4
      Engine/Graphics/Octree.cpp

+ 12 - 4
Engine/Graphics/Octree.cpp

@@ -502,19 +502,27 @@ void Octree::RaycastSingle(RayOctreeQuery& query) const
     
     Sort(rayGetDrawables_.Begin(), rayGetDrawables_.End(), CompareDrawables);
     
-    // The do the actual test according to the query, and early-out on the first hit or if maximum distance exceeded
+    // The do the actual test according to the query, and early-out as possible
+    float closestHit = M_INFINITY;
     for (PODVector<Drawable*>::Iterator i = rayGetDrawables_.Begin(); i != rayGetDrawables_.End(); ++i)
     {
         Drawable* drawable = *i;
-        if (drawable->GetSortValue() <= query.maxDistance_)
+        if (drawable->GetSortValue() <= Min(closestHit, query.maxDistance_))
         {
+            unsigned oldSize = query.result_.Size();
             drawable->ProcessRayQuery(query, query.result_);
-            if (!query.result_.Empty())
-                break;
+            if (query.result_.Size() > oldSize)
+                closestHit = Min(closestHit, query.result_.Back().distance_);
         }
         else
             break;
     }
+    
+    if (query.result_.Size() > 1)
+    {
+        Sort(query.result_.Begin(), query.result_.End(), CompareRayQueryResults);
+        query.result_.Resize(1);
+    }
 }
 
 void Octree::QueueUpdate(Drawable* drawable)