Browse Source

Fix bug in Ray::HitDistance functions for geometry. (#2863)

* Fix bug in Ray::HitDistance functions which may return incorrect normal and UV when encountering multiple geometry triangle hits.

* Avoids using underscores at end of local variable names, to avoid confusion with class member variables.

* Update Ray.cpp

Co-authored-by: Chris Denham <[email protected]>
Co-authored-by: 1vanK <[email protected]>
ChrisDenham 3 years ago
parent
commit
90abed55a8
1 changed files with 33 additions and 5 deletions
  1. 33 5
      Source/Urho3D/Math/Ray.cpp

+ 33 - 5
Source/Urho3D/Math/Ray.cpp

@@ -249,19 +249,30 @@ float Ray::HitDistance(const void* vertexData, unsigned vertexStride, unsigned v
     float nearest = M_INFINITY;
     float nearest = M_INFINITY;
     const unsigned char* vertices = ((const unsigned char*)vertexData) + vertexStart * vertexStride;
     const unsigned char* vertices = ((const unsigned char*)vertexData) + vertexStart * vertexStride;
     unsigned index = 0, nearestIdx = M_MAX_UNSIGNED;
     unsigned index = 0, nearestIdx = M_MAX_UNSIGNED;
+
+    Vector3 tempNormal;
+    Vector3* tempNormalPtr = outNormal ? &tempNormal : nullptr;
+
     Vector3 barycentric;
     Vector3 barycentric;
-    Vector3* outBary = outUV ? &barycentric : nullptr;
+    Vector3 tempBarycentric;
+    Vector3* tempBarycentricPtr = outUV ? &tempBarycentric : nullptr;
 
 
     while (index + 2 < vertexCount)
     while (index + 2 < vertexCount)
     {
     {
         const Vector3& v0 = *((const Vector3*)(&vertices[index * vertexStride]));
         const Vector3& v0 = *((const Vector3*)(&vertices[index * vertexStride]));
         const Vector3& v1 = *((const Vector3*)(&vertices[(index + 1) * vertexStride]));
         const Vector3& v1 = *((const Vector3*)(&vertices[(index + 1) * vertexStride]));
         const Vector3& v2 = *((const Vector3*)(&vertices[(index + 2) * vertexStride]));
         const Vector3& v2 = *((const Vector3*)(&vertices[(index + 2) * vertexStride]));
-        float distance = HitDistance(v0, v1, v2, outNormal, outBary);
+        float distance = HitDistance(v0, v1, v2, tempNormalPtr, tempBarycentricPtr);
         if (distance < nearest)
         if (distance < nearest)
         {
         {
             nearestIdx = index;
             nearestIdx = index;
             nearest = distance;
             nearest = distance;
+
+            if (outNormal)
+                *outNormal = tempNormal;
+
+            if (outUV)
+                barycentric = tempBarycentric;
         }
         }
         index += 3;
         index += 3;
     }
     }
@@ -289,8 +300,13 @@ float Ray::HitDistance(const void* vertexData, unsigned vertexStride, const void
 {
 {
     float nearest = M_INFINITY;
     float nearest = M_INFINITY;
     const auto* vertices = (const unsigned char*)vertexData;
     const auto* vertices = (const unsigned char*)vertexData;
+    
+    Vector3 tempNormal;
+    Vector3* tempNormalPtr = outNormal ? &tempNormal : nullptr;
+    
     Vector3 barycentric;
     Vector3 barycentric;
-    Vector3* outBary = outUV ? &barycentric : nullptr;
+    Vector3 tempBarycentric;
+    Vector3* tempBarycentricPtr = outUV ? &tempBarycentric : nullptr;
 
 
     // 16-bit indices
     // 16-bit indices
     if (indexSize == sizeof(unsigned short))
     if (indexSize == sizeof(unsigned short))
@@ -304,11 +320,17 @@ float Ray::HitDistance(const void* vertexData, unsigned vertexStride, const void
             const Vector3& v0 = *((const Vector3*)(&vertices[indices[0] * vertexStride]));
             const Vector3& v0 = *((const Vector3*)(&vertices[indices[0] * vertexStride]));
             const Vector3& v1 = *((const Vector3*)(&vertices[indices[1] * vertexStride]));
             const Vector3& v1 = *((const Vector3*)(&vertices[indices[1] * vertexStride]));
             const Vector3& v2 = *((const Vector3*)(&vertices[indices[2] * vertexStride]));
             const Vector3& v2 = *((const Vector3*)(&vertices[indices[2] * vertexStride]));
-            float distance = HitDistance(v0, v1, v2, outNormal, outBary);
+            float distance = HitDistance(v0, v1, v2, tempNormalPtr, tempBarycentricPtr);
             if (distance < nearest)
             if (distance < nearest)
             {
             {
                 nearestIndices = indices;
                 nearestIndices = indices;
                 nearest = distance;
                 nearest = distance;
+
+                if (outNormal)
+                    *outNormal = tempNormal;
+
+                if (outUV)
+                    barycentric = tempBarycentric;
             }
             }
             indices += 3;
             indices += 3;
         }
         }
@@ -340,11 +362,17 @@ float Ray::HitDistance(const void* vertexData, unsigned vertexStride, const void
             const Vector3& v0 = *((const Vector3*)(&vertices[indices[0] * vertexStride]));
             const Vector3& v0 = *((const Vector3*)(&vertices[indices[0] * vertexStride]));
             const Vector3& v1 = *((const Vector3*)(&vertices[indices[1] * vertexStride]));
             const Vector3& v1 = *((const Vector3*)(&vertices[indices[1] * vertexStride]));
             const Vector3& v2 = *((const Vector3*)(&vertices[indices[2] * vertexStride]));
             const Vector3& v2 = *((const Vector3*)(&vertices[indices[2] * vertexStride]));
-            float distance = HitDistance(v0, v1, v2, outNormal, outBary);
+            float distance = HitDistance(v0, v1, v2, tempNormalPtr, tempBarycentricPtr);
             if (distance < nearest)
             if (distance < nearest)
             {
             {
                 nearestIndices = indices;
                 nearestIndices = indices;
                 nearest = distance;
                 nearest = distance;
+
+                if (outNormal)
+                    *outNormal = tempNormal;
+
+                if (outUV)
+                    barycentric = tempBarycentric;
             }
             }
             indices += 3;
             indices += 3;
         }
         }