소스 검색

Lights (see #362) : added light v. sphere intersection, and implementations of intersectsSphere(), second attempt

Dokthar 10 년 전
부모
커밋
cfdb9a8759

+ 6 - 0
jme3-core/src/main/java/com/jme3/light/AmbientLight.java

@@ -32,6 +32,7 @@
 package com.jme3.light;
 
 import com.jme3.bounding.BoundingBox;
+import com.jme3.bounding.BoundingSphere;
 import com.jme3.math.ColorRGBA;
 import com.jme3.math.Vector3f;
 import com.jme3.renderer.Camera;
@@ -62,6 +63,11 @@ public class AmbientLight extends Light {
         return true;
     }
     
+    @Override
+    public boolean intersectsSphere(BoundingSphere sphere, TempVars vars) {
+        return true;
+    }
+
     @Override
     public boolean intersectsFrustum(Camera camera, TempVars vars) {
         return true;

+ 4 - 3
jme3-core/src/main/java/com/jme3/light/DefaultLightFilter.java

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009-2014 jMonkeyEngine
+ * Copyright (c) 2009-2015 jMonkeyEngine
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -78,8 +78,9 @@ public final class DefaultLightFilter implements LightFilter {
                     }
                 } else if (bv instanceof BoundingSphere) {
                     if (!Float.isInfinite( ((BoundingSphere)bv).getRadius() )) {
-                        // Non-infinite bounding sphere... Not supported yet.
-                        throw new UnsupportedOperationException("Only AABB supported for now");
+                        if (!light.intersectsSphere((BoundingSphere)bv, vars)) {
+                            continue;
+                        }
                     }
                 }
 

+ 6 - 0
jme3-core/src/main/java/com/jme3/light/DirectionalLight.java

@@ -32,6 +32,7 @@
 package com.jme3.light;
 
 import com.jme3.bounding.BoundingBox;
+import com.jme3.bounding.BoundingSphere;
 import com.jme3.export.InputCapsule;
 import com.jme3.export.JmeExporter;
 import com.jme3.export.JmeImporter;
@@ -116,6 +117,11 @@ public class DirectionalLight extends Light {
         return true;
     }
     
+    @Override
+    public boolean intersectsSphere(BoundingSphere sphere, TempVars vars) {
+        return true;
+    }
+
     @Override
     public boolean intersectsFrustum(Camera camera, TempVars vars) {
         return true;

+ 15 - 0
jme3-core/src/main/java/com/jme3/light/Light.java

@@ -32,6 +32,7 @@
 package com.jme3.light;
 
 import com.jme3.bounding.BoundingBox;
+import com.jme3.bounding.BoundingSphere;
 import com.jme3.export.*;
 import com.jme3.math.ColorRGBA;
 import com.jme3.renderer.Camera;
@@ -196,6 +197,20 @@ public abstract class Light implements Savable, Cloneable {
      */
     public abstract boolean intersectsBox(BoundingBox box, TempVars vars);
     
+    /**
+     * Determines if the light intersects with the given bounding sphere.
+     * <p>
+     * For non-local lights, such as {@link DirectionalLight directional lights},
+     * {@link AmbientLight ambient lights}, or {@link PointLight point lights}
+     * without influence radius, this method should always return true.
+     * 
+     * @param sphere The sphere to check intersection against.
+     * @param vars TempVars in case it is needed.
+     * 
+     * @return True if the light intersects the sphere, false otherwise.
+     */
+    public abstract boolean intersectsSphere(BoundingSphere sphere, TempVars vars);
+
     /**
      * Determines if the light intersects with the given camera frustum.
      * 

+ 12 - 0
jme3-core/src/main/java/com/jme3/light/PointLight.java

@@ -32,12 +32,14 @@
 package com.jme3.light;
 
 import com.jme3.bounding.BoundingBox;
+import com.jme3.bounding.BoundingSphere;
 import com.jme3.bounding.BoundingVolume;
 import com.jme3.bounding.Intersection;
 import com.jme3.export.InputCapsule;
 import com.jme3.export.JmeExporter;
 import com.jme3.export.JmeImporter;
 import com.jme3.export.OutputCapsule;
+import com.jme3.math.FastMath;
 import com.jme3.math.ColorRGBA;
 import com.jme3.math.Vector3f;
 import com.jme3.renderer.Camera;
@@ -195,6 +197,16 @@ public class PointLight extends Light {
         }
     }
     
+    @Override
+    public boolean intersectsSphere(BoundingSphere sphere, TempVars vars) {
+        if (this.radius == 0) {
+            return true;
+        } else {
+            // Sphere v. sphere collision
+            return sphere.getCenter().subtract(position).lengthSquared() < FastMath.sqr(radius + sphere.getRadius());
+        }
+    }
+    
     @Override
     public boolean intersectsFrustum(Camera camera, TempVars vars) {
         if (this.radius == 0) {

+ 40 - 2
jme3-core/src/main/java/com/jme3/light/SpotLight.java

@@ -32,6 +32,7 @@
 package com.jme3.light;
 
 import com.jme3.bounding.BoundingBox;
+import com.jme3.bounding.BoundingSphere;
 import com.jme3.bounding.BoundingVolume;
 import com.jme3.export.*;
 import com.jme3.math.ColorRGBA;
@@ -225,12 +226,49 @@ public class SpotLight extends Light {
         return false;
     }
     
+    @Override
+    public boolean intersectsSphere(BoundingSphere sphere, TempVars vars) {
+        if (this.spotRange > 0f) {
+            // Check spot range first.
+            // Sphere v. sphere collision
+            if (sphere.getCenter().subtract(position).lengthSquared() >= FastMath.sqr(spotRange + sphere.getRadius())) {
+                return false;
+            }
+        }
+
+        float otherRadiusSquared = FastMath.sqr(sphere.getRadius());
+        float otherRadius = sphere.getRadius();
+
+        // Check if sphere is within spot angle.
+        // Cone v. sphere collision.
+        Vector3f E = direction.mult(otherRadius * outerAngleSinRcp, vars.vect1);
+        Vector3f U = position.subtract(E, vars.vect2);
+        Vector3f D = sphere.getCenter().subtract(U, vars.vect3);
+
+        float dsqr = D.dot(D);
+        float e = direction.dot(D);
+
+        if (e > 0f && e * e >= dsqr * outerAngleCosSqr) {
+            D = sphere.getCenter().subtract(position, vars.vect3);
+            dsqr = D.dot(D);
+            e = -direction.dot(D);
+
+            if (e > 0f && e * e >= dsqr * outerAngleSinSqr) {
+                return dsqr <= otherRadiusSquared;
+            } else {
+                return true;
+            }
+        }
+        
+        return false;
+    }
+    
     @Override
     public boolean intersectsFrustum(Camera cam, TempVars vars) {
         if (spotRange == 0) {
             // The algorithm below does not support infinite spot range.
-            return true;
-        }
+                return true;
+            }
         Vector3f farPoint = vars.vect1.set(position).addLocal(vars.vect2.set(direction).multLocal(spotRange));
         for (int i = 5; i >= 0; i--) {
             //check origin against the plane