diff --git a/jme3-core/src/main/java/com/jme3/light/SpotLight.java b/jme3-core/src/main/java/com/jme3/light/SpotLight.java index 444d58b3a..bd1c03c6e 100644 --- a/jme3-core/src/main/java/com/jme3/light/SpotLight.java +++ b/jme3-core/src/main/java/com/jme3/light/SpotLight.java @@ -267,8 +267,8 @@ public class SpotLight extends Light { 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 diff --git a/jme3-core/src/test/java/com/jme3/light/LightFilterTest.java b/jme3-core/src/test/java/com/jme3/light/LightFilterTest.java index 0d1e71988..d4fc18db9 100644 --- a/jme3-core/src/test/java/com/jme3/light/LightFilterTest.java +++ b/jme3-core/src/test/java/com/jme3/light/LightFilterTest.java @@ -31,6 +31,7 @@ */ package com.jme3.light; +import com.jme3.bounding.BoundingSphere; import com.jme3.math.FastMath; import com.jme3.math.Vector3f; import com.jme3.renderer.Camera; @@ -81,12 +82,20 @@ public class LightFilterTest { public void testAmbientFiltering() { geom.addLight(new AmbientLight()); checkFilteredLights(1); // Ambient lights must never be filtered + + // Test for bounding Sphere + geom.setModelBound(new BoundingSphere(0.5f, Vector3f.ZERO)); + checkFilteredLights(1); // Ambient lights must never be filtered } @Test public void testDirectionalFiltering() { geom.addLight(new DirectionalLight(Vector3f.UNIT_Y)); checkFilteredLights(1); // Directional lights must never be filtered + + // Test for bounding Sphere + geom.setModelBound(new BoundingSphere(0.5f, Vector3f.ZERO)); + checkFilteredLights(1); // Directional lights must never be filtered } @Test @@ -127,6 +136,44 @@ public class LightFilterTest { // Rotate the camera so it is up, light is outside frustum. cam.lookAtDirection(Vector3f.UNIT_Y, Vector3f.UNIT_Y); checkFilteredLights(0); + + // ================================== + // Tests for bounding Sphere + geom.setLocalTranslation(0, 0, 0); + + // Infinite point lights must never be filtered + pl.setRadius(0); + checkFilteredLights(1); + + pl.setRadius(1f); + geom.setModelBound(new BoundingSphere(1f, Vector3f.ZERO)); + + // Put the light at the very close to the geom, + // the very edge of the sphere touches the other bounding sphere + // Still not considered an intersection though. + pl.setPosition(new Vector3f(0, 0, -2f)); + checkFilteredLights(0); + + // And more close - now its an intersection. + pl.setPosition(new Vector3f(0, 0, 0f)); + checkFilteredLights(0); + + // In this case its an intersection for pointLight v. box + // But not for pointLight v. sphere + // Vector3f(0, 0.5f, 0.5f).normalize().mult(2) ~ >= (0.0, 1.4142135, 1.4142135) + //pl.setPosition(new Vector3f(0, 0.5f, 0.5f).normalizeLocal().multLocal(2 + FastMath.ZERO_TOLERANCE)); + pl.setPosition(new Vector3f(0f, 1.4142135f, 1.4142135f).multLocal(1+FastMath.ZERO_TOLERANCE)); + checkFilteredLights(0); + + // Make the distance a wee bit closer, now its an intersection + //pl.setPosition(new Vector3f(0, 0.5f, 0.5f).normalizeLocal().multLocal(2 - FastMath.ZERO_TOLERANCE)); + pl.setPosition(new Vector3f(0f, 1.4142135f, 1.4142135f).multLocal(1-FastMath.ZERO_TOLERANCE)); + checkFilteredLights(1); + + // it's a point light, also test for the other corner + pl.setPosition(new Vector3f(0f, -1.4142135f, -1.4142135f).multLocal(1-FastMath.ZERO_TOLERANCE)); + checkFilteredLights(0); + } @Test @@ -175,5 +222,49 @@ public class LightFilterTest { // now, the spot will touch the box. geom.setMesh(new Box(5, 1, 1)); checkFilteredLights(1); + + // ================================== + // Tests for bounding sphere, with a radius of 1f (in the box geom) + sl.setPosition(Vector3f.ZERO); + sl.setDirection(Vector3f.UNIT_Z); + geom.setLocalTranslation(Vector3f.ZERO); + geom.setModelBound(new BoundingSphere(1f, Vector3f.ZERO)); + + // Infinit spot lights are only filtered + // if the geometry is outside the infinite cone. + sl.setSpotRange(0); + checkFilteredLights(1); + + //the geommetry is outside the infinit cone (cone direction going away from the geom) + sl.setPosition(Vector3f.UNIT_Z.mult(1+FastMath.ZERO_TOLERANCE)); + checkFilteredLights(0); + + //place the spote ligth in the corner of the box geom, (in order to test bounding sphere) + sl.setDirection(new Vector3f(1, 1, 0).normalizeLocal()); + geom.setLocalTranslation(0, 0, 10); + sl.setPosition(sl.getDirection().mult(-2f).add(geom.getLocalTranslation())); + + // make it barely reach the sphere, incorect with a box + sl.setSpotRange(1f - FastMath.ZERO_TOLERANCE); + checkFilteredLights(0); + + // make it reach the sphere + sl.setSpotRange(1f + FastMath.ZERO_TOLERANCE); + checkFilteredLights(1); + + // extent the range + sl.setPosition(Vector3f.ZERO); + sl.setDirection(Vector3f.UNIT_Z); + sl.setSpotRange(20); + checkFilteredLights(1); + + // rotate the cone a bit so it no longer faces the geom + sl.setDirection(new Vector3f(0, 0.3f, 0.7f).normalizeLocal()); + checkFilteredLights(0); + + // Create sphere of size X=10 (double the radius) + // now, the spot will touch the sphere. + geom.setModelBound(new BoundingSphere(5f, Vector3f.ZERO)); + checkFilteredLights(1); } }