Merge pull request #364 from Dokthar/light
Lights : added light v. sphere intersection
This commit is contained in:
commit
edaf49c00c
@ -32,6 +32,7 @@
|
|||||||
package com.jme3.light;
|
package com.jme3.light;
|
||||||
|
|
||||||
import com.jme3.bounding.BoundingBox;
|
import com.jme3.bounding.BoundingBox;
|
||||||
|
import com.jme3.bounding.BoundingSphere;
|
||||||
import com.jme3.math.ColorRGBA;
|
import com.jme3.math.ColorRGBA;
|
||||||
import com.jme3.math.Vector3f;
|
import com.jme3.math.Vector3f;
|
||||||
import com.jme3.renderer.Camera;
|
import com.jme3.renderer.Camera;
|
||||||
@ -62,6 +63,11 @@ public class AmbientLight extends Light {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean intersectsSphere(BoundingSphere sphere, TempVars vars) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean intersectsFrustum(Camera camera, TempVars vars) {
|
public boolean intersectsFrustum(Camera camera, TempVars vars) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2014 jMonkeyEngine
|
* Copyright (c) 2009-2015 jMonkeyEngine
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* 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) {
|
} else if (bv instanceof BoundingSphere) {
|
||||||
if (!Float.isInfinite( ((BoundingSphere)bv).getRadius() )) {
|
if (!Float.isInfinite( ((BoundingSphere)bv).getRadius() )) {
|
||||||
// Non-infinite bounding sphere... Not supported yet.
|
if (!light.intersectsSphere((BoundingSphere)bv, vars)) {
|
||||||
throw new UnsupportedOperationException("Only AABB supported for now");
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
package com.jme3.light;
|
package com.jme3.light;
|
||||||
|
|
||||||
import com.jme3.bounding.BoundingBox;
|
import com.jme3.bounding.BoundingBox;
|
||||||
|
import com.jme3.bounding.BoundingSphere;
|
||||||
import com.jme3.export.InputCapsule;
|
import com.jme3.export.InputCapsule;
|
||||||
import com.jme3.export.JmeExporter;
|
import com.jme3.export.JmeExporter;
|
||||||
import com.jme3.export.JmeImporter;
|
import com.jme3.export.JmeImporter;
|
||||||
@ -116,6 +117,11 @@ public class DirectionalLight extends Light {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean intersectsSphere(BoundingSphere sphere, TempVars vars) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean intersectsFrustum(Camera camera, TempVars vars) {
|
public boolean intersectsFrustum(Camera camera, TempVars vars) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
package com.jme3.light;
|
package com.jme3.light;
|
||||||
|
|
||||||
import com.jme3.bounding.BoundingBox;
|
import com.jme3.bounding.BoundingBox;
|
||||||
|
import com.jme3.bounding.BoundingSphere;
|
||||||
import com.jme3.export.*;
|
import com.jme3.export.*;
|
||||||
import com.jme3.math.ColorRGBA;
|
import com.jme3.math.ColorRGBA;
|
||||||
import com.jme3.renderer.Camera;
|
import com.jme3.renderer.Camera;
|
||||||
@ -196,6 +197,20 @@ public abstract class Light implements Savable, Cloneable {
|
|||||||
*/
|
*/
|
||||||
public abstract boolean intersectsBox(BoundingBox box, TempVars vars);
|
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.
|
* Determines if the light intersects with the given camera frustum.
|
||||||
*
|
*
|
||||||
|
@ -32,12 +32,14 @@
|
|||||||
package com.jme3.light;
|
package com.jme3.light;
|
||||||
|
|
||||||
import com.jme3.bounding.BoundingBox;
|
import com.jme3.bounding.BoundingBox;
|
||||||
|
import com.jme3.bounding.BoundingSphere;
|
||||||
import com.jme3.bounding.BoundingVolume;
|
import com.jme3.bounding.BoundingVolume;
|
||||||
import com.jme3.bounding.Intersection;
|
import com.jme3.bounding.Intersection;
|
||||||
import com.jme3.export.InputCapsule;
|
import com.jme3.export.InputCapsule;
|
||||||
import com.jme3.export.JmeExporter;
|
import com.jme3.export.JmeExporter;
|
||||||
import com.jme3.export.JmeImporter;
|
import com.jme3.export.JmeImporter;
|
||||||
import com.jme3.export.OutputCapsule;
|
import com.jme3.export.OutputCapsule;
|
||||||
|
import com.jme3.math.FastMath;
|
||||||
import com.jme3.math.ColorRGBA;
|
import com.jme3.math.ColorRGBA;
|
||||||
import com.jme3.math.Vector3f;
|
import com.jme3.math.Vector3f;
|
||||||
import com.jme3.renderer.Camera;
|
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 Intersection.intersect(sphere, position, radius);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean intersectsFrustum(Camera camera, TempVars vars) {
|
public boolean intersectsFrustum(Camera camera, TempVars vars) {
|
||||||
if (this.radius == 0) {
|
if (this.radius == 0) {
|
||||||
|
@ -32,7 +32,9 @@
|
|||||||
package com.jme3.light;
|
package com.jme3.light;
|
||||||
|
|
||||||
import com.jme3.bounding.BoundingBox;
|
import com.jme3.bounding.BoundingBox;
|
||||||
|
import com.jme3.bounding.BoundingSphere;
|
||||||
import com.jme3.bounding.BoundingVolume;
|
import com.jme3.bounding.BoundingVolume;
|
||||||
|
import com.jme3.bounding.Intersection;
|
||||||
import com.jme3.export.*;
|
import com.jme3.export.*;
|
||||||
import com.jme3.math.ColorRGBA;
|
import com.jme3.math.ColorRGBA;
|
||||||
import com.jme3.math.FastMath;
|
import com.jme3.math.FastMath;
|
||||||
@ -188,9 +190,7 @@ public class SpotLight extends Light {
|
|||||||
if (this.spotRange > 0f) {
|
if (this.spotRange > 0f) {
|
||||||
// Check spot range first.
|
// Check spot range first.
|
||||||
// Sphere v. box collision
|
// Sphere v. box collision
|
||||||
if (FastMath.abs(box.getCenter().x - position.x) >= spotRange + box.getXExtent()
|
if (!Intersection.intersect(box, position, spotRange)) {
|
||||||
|| FastMath.abs(box.getCenter().y - position.y) >= spotRange + box.getYExtent()
|
|
||||||
|| FastMath.abs(box.getCenter().z - position.z) >= spotRange + box.getZExtent()) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -225,6 +225,43 @@ public class SpotLight extends Light {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean intersectsSphere(BoundingSphere sphere, TempVars vars) {
|
||||||
|
if (this.spotRange > 0f) {
|
||||||
|
// Check spot range first.
|
||||||
|
// Sphere v. sphere collision
|
||||||
|
if (!Intersection.intersect(sphere, position, spotRange)) {
|
||||||
|
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
|
@Override
|
||||||
public boolean intersectsFrustum(Camera cam, TempVars vars) {
|
public boolean intersectsFrustum(Camera cam, TempVars vars) {
|
||||||
if (spotRange == 0) {
|
if (spotRange == 0) {
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.jme3.light;
|
package com.jme3.light;
|
||||||
|
|
||||||
|
import com.jme3.bounding.BoundingSphere;
|
||||||
import com.jme3.math.FastMath;
|
import com.jme3.math.FastMath;
|
||||||
import com.jme3.math.Vector3f;
|
import com.jme3.math.Vector3f;
|
||||||
import com.jme3.renderer.Camera;
|
import com.jme3.renderer.Camera;
|
||||||
@ -81,12 +82,20 @@ public class LightFilterTest {
|
|||||||
public void testAmbientFiltering() {
|
public void testAmbientFiltering() {
|
||||||
geom.addLight(new AmbientLight());
|
geom.addLight(new AmbientLight());
|
||||||
checkFilteredLights(1); // Ambient lights must never be filtered
|
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
|
@Test
|
||||||
public void testDirectionalFiltering() {
|
public void testDirectionalFiltering() {
|
||||||
geom.addLight(new DirectionalLight(Vector3f.UNIT_Y));
|
geom.addLight(new DirectionalLight(Vector3f.UNIT_Y));
|
||||||
checkFilteredLights(1); // Directional lights must never be filtered
|
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
|
@Test
|
||||||
@ -127,6 +136,45 @@ public class LightFilterTest {
|
|||||||
// Rotate the camera so it is up, light is outside frustum.
|
// Rotate the camera so it is up, light is outside frustum.
|
||||||
cam.lookAtDirection(Vector3f.UNIT_Y, Vector3f.UNIT_Y);
|
cam.lookAtDirection(Vector3f.UNIT_Y, Vector3f.UNIT_Y);
|
||||||
checkFilteredLights(0);
|
checkFilteredLights(0);
|
||||||
|
|
||||||
|
// ==================================
|
||||||
|
// Tests for bounding Sphere
|
||||||
|
geom.setModelBound(new BoundingSphere(1f, Vector3f.ZERO));
|
||||||
|
geom.setLocalTranslation(0, 0, 2);
|
||||||
|
pl.setPosition(new Vector3f(0, 0, 2f));
|
||||||
|
|
||||||
|
// Infinite point lights must never be filtered
|
||||||
|
pl.setRadius(0);
|
||||||
|
checkFilteredLights(1);
|
||||||
|
|
||||||
|
pl.setRadius(1f);
|
||||||
|
// 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, 0));
|
||||||
|
checkFilteredLights(0);
|
||||||
|
|
||||||
|
// And more close - now its an intersection.
|
||||||
|
pl.setPosition(new Vector3f(0, 0, 0f + FastMath.ZERO_TOLERANCE));
|
||||||
|
checkFilteredLights(1);
|
||||||
|
|
||||||
|
geom.setLocalTranslation(0, 0, 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
|
@Test
|
||||||
@ -175,5 +223,49 @@ public class LightFilterTest {
|
|||||||
// now, the spot will touch the box.
|
// now, the spot will touch the box.
|
||||||
geom.setMesh(new Box(5, 1, 1));
|
geom.setMesh(new Box(5, 1, 1));
|
||||||
checkFilteredLights(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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user