Просмотр исходного кода

fix issue where rays pass through Quads in certain cases: corresponds to SVN rev 10785 in trunk

[email protected] 11 лет назад
Родитель
Сommit
0c4bfed950
1 измененных файлов с 42 добавлено и 6 удалено
  1. 42 6
      engine/src/core/com/jme3/bounding/BoundingBox.java

+ 42 - 6
engine/src/core/com/jme3/bounding/BoundingBox.java

@@ -865,19 +865,55 @@ public class BoundingBox extends BoundingVolume {
         // plane. Otherwise 'false' is returned in which case the line segment
         // is entirely clipped.
         if (denom > 0.0f) {
-            if (numer > denom * t[1]) {
+            // This is the old if statement...
+            // if (numer > denom * t[1]) {
+            //
+            // The problem is that what is actually stored is
+            // numer/denom.  In non-floating point, this math should
+            // work out the same but in floating point there can
+            // be subtle math errors.  The multiply will exaggerate
+            // errors that may have been introduced when the value
+            // was originally divided.
+            //
+            // This is especially true when the bounding box has zero
+            // extents in some plane because the error rate is critical.
+            // comparing a to b * c is not the same as comparing a/b to c
+            // in this case.  In fact, I tried converting this method to
+            // double and the and the error was in the last decimal place.
+            //
+            // So, instead, we now compare the divided version to the divided
+            // version.  We lose some slight performance here as divide
+            // will be more expensive than the divide.  Some microbenchmarks
+            // show divide to be 3x slower than multiple on Java 1.6.
+            // BUT... we also saved a multiply in the non-clipped case because
+            // we can reuse the divided version in both if checks.
+            // I think it's better to be right in this case.
+            //
+            // Bug that I'm fixing: rays going right through quads at certain
+            // angles and distances because they fail the bounding box test.
+            // Many Bothans died bring you this fix.
+            //    -pspeed
+            float newT = numer / denom;
+            if (newT > t[1]) {
                 return false;
             }
-            if (numer > denom * t[0]) {
-                t[0] = numer / denom;
+            if (newT > t[0]) {
+                t[0] = newT;
             }
             return true;
         } else if (denom < 0.0f) {
-            if (numer > denom * t[0]) {
+            // Old if statement... see above
+            // if (numer > denom * t[0]) {
+            //
+            // Note though that denom is always negative in this block.
+            // When we move it over to the other side we have to flip
+            // the comparison.  Algebra for the win.
+            float newT = numer / denom;
+            if (newT < t[0]) {
                 return false;
             }
-            if (numer > denom * t[1]) {
-                t[1] = numer / denom;
+            if (newT < t[1]) {
+                t[1] = newT;
             }
             return true;
         } else {