parent
c41058a5a0
commit
81b5c48fb0
@ -0,0 +1,166 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2009-2015 jMonkeyEngine |
||||||
|
* All rights reserved. |
||||||
|
* |
||||||
|
* Redistribution and use in source and binary forms, with or without |
||||||
|
* modification, are permitted provided that the following conditions are |
||||||
|
* met: |
||||||
|
* |
||||||
|
* * Redistributions of source code must retain the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer. |
||||||
|
* |
||||||
|
* * Redistributions in binary form must reproduce the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer in the |
||||||
|
* documentation and/or other materials provided with the distribution. |
||||||
|
* |
||||||
|
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors |
||||||
|
* may be used to endorse or promote products derived from this software |
||||||
|
* without specific prior written permission. |
||||||
|
* |
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
*/ |
||||||
|
package com.jme3.collision; |
||||||
|
|
||||||
|
import static com.jme3.collision.CollisionUtil.*; |
||||||
|
|
||||||
|
import com.jme3.bounding.BoundingBox; |
||||||
|
import com.jme3.bounding.BoundingSphere; |
||||||
|
import com.jme3.math.FastMath; |
||||||
|
import com.jme3.math.Ray; |
||||||
|
import com.jme3.math.Vector3f; |
||||||
|
import com.jme3.scene.Geometry; |
||||||
|
import com.jme3.scene.shape.Quad; |
||||||
|
import org.junit.Test; |
||||||
|
|
||||||
|
/** |
||||||
|
* Tests collision detection between bounding volumes. |
||||||
|
* |
||||||
|
* @author Kirill Vainer |
||||||
|
*/ |
||||||
|
public class BoundingCollisionTest { |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testBoxBoxCollision() { |
||||||
|
BoundingBox box1 = new BoundingBox(Vector3f.ZERO, 1, 1, 1); |
||||||
|
BoundingBox box2 = new BoundingBox(Vector3f.ZERO, 1, 1, 1); |
||||||
|
checkCollision(box1, box2, 1); |
||||||
|
|
||||||
|
// Put it at the very edge - should still intersect.
|
||||||
|
box2.setCenter(new Vector3f(2f, 0f, 0f)); |
||||||
|
checkCollision(box1, box2, 1); |
||||||
|
|
||||||
|
// Put it a wee bit farther - no intersection expected
|
||||||
|
box2.setCenter(new Vector3f(2f + FastMath.ZERO_TOLERANCE, 0, 0)); |
||||||
|
checkCollision(box1, box2, 0); |
||||||
|
|
||||||
|
// Check the corners.
|
||||||
|
box2.setCenter(new Vector3f(2f, 2f, 2f)); |
||||||
|
checkCollision(box1, box2, 1); |
||||||
|
|
||||||
|
box2.setCenter(new Vector3f(2f, 2f, 2f + FastMath.ZERO_TOLERANCE)); |
||||||
|
checkCollision(box1, box2, 0); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testSphereSphereCollision() { |
||||||
|
BoundingSphere sphere1 = new BoundingSphere(1, Vector3f.ZERO); |
||||||
|
BoundingSphere sphere2 = new BoundingSphere(1, Vector3f.ZERO); |
||||||
|
checkCollision(sphere1, sphere2, 1); |
||||||
|
|
||||||
|
// Put it at the very edge - should still intersect.
|
||||||
|
sphere2.setCenter(new Vector3f(2f, 0f, 0f)); |
||||||
|
checkCollision(sphere1, sphere2, 1); |
||||||
|
|
||||||
|
// Put it a wee bit farther - no intersection expected
|
||||||
|
sphere2.setCenter(new Vector3f(2f + FastMath.ZERO_TOLERANCE, 0, 0)); |
||||||
|
checkCollision(sphere1, sphere2, 0); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testBoxSphereCollision() { |
||||||
|
BoundingBox box1 = new BoundingBox(Vector3f.ZERO, 1, 1, 1); |
||||||
|
BoundingSphere sphere2 = new BoundingSphere(1, Vector3f.ZERO); |
||||||
|
checkCollision(box1, sphere2, 1); |
||||||
|
|
||||||
|
// Put it at the very edge - for sphere vs. box, it will not intersect
|
||||||
|
sphere2.setCenter(new Vector3f(2f, 0f, 0f)); |
||||||
|
checkCollision(box1, sphere2, 0); |
||||||
|
|
||||||
|
// Put it a wee bit closer - should intersect.
|
||||||
|
sphere2.setCenter(new Vector3f(2f - FastMath.ZERO_TOLERANCE, 0, 0)); |
||||||
|
checkCollision(box1, sphere2, 1); |
||||||
|
|
||||||
|
// Test if the algorithm converts the sphere
|
||||||
|
// to a box before testing the collision (incorrect)
|
||||||
|
float sqrt3 = FastMath.sqrt(3); |
||||||
|
|
||||||
|
sphere2.setCenter(Vector3f.UNIT_XYZ.mult(2)); |
||||||
|
sphere2.setRadius(sqrt3); |
||||||
|
checkCollision(box1, sphere2, 0); |
||||||
|
|
||||||
|
// Make it a wee bit larger.
|
||||||
|
sphere2.setRadius(sqrt3 + FastMath.ZERO_TOLERANCE); |
||||||
|
checkCollision(box1, sphere2, 1); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testBoxRayCollision() { |
||||||
|
BoundingBox box = new BoundingBox(Vector3f.ZERO, 1, 1, 1); |
||||||
|
Ray ray = new Ray(Vector3f.ZERO, Vector3f.UNIT_Z); |
||||||
|
|
||||||
|
// XXX: seems incorrect, ray inside box should only generate
|
||||||
|
// one result...
|
||||||
|
checkCollision(box, ray, 2); |
||||||
|
|
||||||
|
ray.setOrigin(new Vector3f(0, 0, -5)); |
||||||
|
checkCollision(box, ray, 2); |
||||||
|
|
||||||
|
// XXX: is this right? the ray origin is on the box's side..
|
||||||
|
ray.setOrigin(new Vector3f(0, 0, 2f)); |
||||||
|
checkCollision(box, ray, 0); |
||||||
|
|
||||||
|
ray.setOrigin(new Vector3f(0, 0, -2f)); |
||||||
|
checkCollision(box, ray, 2); |
||||||
|
|
||||||
|
// parallel to the edge, touching the side
|
||||||
|
ray.setOrigin(new Vector3f(0, 1f, -2f)); |
||||||
|
checkCollision(box, ray, 2); |
||||||
|
|
||||||
|
// still parallel, but not touching the side
|
||||||
|
ray.setOrigin(new Vector3f(0, 1f + FastMath.ZERO_TOLERANCE, -2f)); |
||||||
|
checkCollision(box, ray, 0); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testBoxTriangleCollision() { |
||||||
|
BoundingBox box = new BoundingBox(Vector3f.ZERO, 1, 1, 1); |
||||||
|
Geometry geom = new Geometry("geom", new Quad(1, 1)); |
||||||
|
checkCollision(box, geom, 2); // Both triangles intersect
|
||||||
|
|
||||||
|
// The box touches the edges of the triangles.
|
||||||
|
box.setCenter(new Vector3f(-1f, 0, 0)); |
||||||
|
checkCollision(box, geom, 2); |
||||||
|
|
||||||
|
// Move it slightly farther..
|
||||||
|
box.setCenter(new Vector3f(-1f - FastMath.ZERO_TOLERANCE, 0, 0)); |
||||||
|
checkCollision(box, geom, 0); |
||||||
|
|
||||||
|
// Parallel triangle / box side, touching
|
||||||
|
box.setCenter(new Vector3f(0, 0, -1f)); |
||||||
|
checkCollision(box, geom, 2); |
||||||
|
|
||||||
|
// Not touching
|
||||||
|
box.setCenter(new Vector3f(0, 0, -1f - FastMath.ZERO_TOLERANCE)); |
||||||
|
checkCollision(box, geom, 0); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,80 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2009-2015 jMonkeyEngine |
||||||
|
* All rights reserved. |
||||||
|
* |
||||||
|
* Redistribution and use in source and binary forms, with or without |
||||||
|
* modification, are permitted provided that the following conditions are |
||||||
|
* met: |
||||||
|
* |
||||||
|
* * Redistributions of source code must retain the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer. |
||||||
|
* |
||||||
|
* * Redistributions in binary form must reproduce the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer in the |
||||||
|
* documentation and/or other materials provided with the distribution. |
||||||
|
* |
||||||
|
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors |
||||||
|
* may be used to endorse or promote products derived from this software |
||||||
|
* without specific prior written permission. |
||||||
|
* |
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
*/ |
||||||
|
package com.jme3.collision; |
||||||
|
|
||||||
|
import com.jme3.bounding.BoundingVolume; |
||||||
|
|
||||||
|
/** |
||||||
|
* Utilities for testing collision. |
||||||
|
* |
||||||
|
* @author Kirill Vainer |
||||||
|
*/ |
||||||
|
final class CollisionUtil { |
||||||
|
|
||||||
|
private static void checkCollisionBase(Collidable a, Collidable b, int expected) { |
||||||
|
// Test bounding volume methods
|
||||||
|
if (a instanceof BoundingVolume && b instanceof BoundingVolume) { |
||||||
|
BoundingVolume bv1 = (BoundingVolume) a; |
||||||
|
BoundingVolume bv2 = (BoundingVolume) b; |
||||||
|
assert bv1.intersects(bv2) == (expected != 0); |
||||||
|
} |
||||||
|
|
||||||
|
// Test standard collideWith method
|
||||||
|
CollisionResults results = new CollisionResults(); |
||||||
|
int numCollisions = a.collideWith(b, results); |
||||||
|
assert results.size() == numCollisions; |
||||||
|
assert numCollisions == expected; |
||||||
|
|
||||||
|
// force the results to be sorted here..
|
||||||
|
results.getClosestCollision(); |
||||||
|
|
||||||
|
if (results.size() > 0) { |
||||||
|
assert results.getCollision(0) == results.getClosestCollision(); |
||||||
|
} |
||||||
|
if (results.size() == 1) { |
||||||
|
assert results.getClosestCollision() == results.getFarthestCollision(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Tests various collisions between the two collidables and |
||||||
|
* the transitive property. |
||||||
|
* |
||||||
|
* @param a First collidable |
||||||
|
* @param b Second collidable |
||||||
|
* @param expect Number of expected results |
||||||
|
*/ |
||||||
|
public static void checkCollision(Collidable a, Collidable b, int expected) { |
||||||
|
checkCollisionBase(a, b, expected); |
||||||
|
checkCollisionBase(b, a, expected); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,179 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2009-2015 jMonkeyEngine |
||||||
|
* All rights reserved. |
||||||
|
* |
||||||
|
* Redistribution and use in source and binary forms, with or without |
||||||
|
* modification, are permitted provided that the following conditions are |
||||||
|
* met: |
||||||
|
* |
||||||
|
* * Redistributions of source code must retain the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer. |
||||||
|
* |
||||||
|
* * Redistributions in binary form must reproduce the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer in the |
||||||
|
* documentation and/or other materials provided with the distribution. |
||||||
|
* |
||||||
|
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors |
||||||
|
* may be used to endorse or promote products derived from this software |
||||||
|
* without specific prior written permission. |
||||||
|
* |
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
*/ |
||||||
|
package com.jme3.light; |
||||||
|
|
||||||
|
import com.jme3.math.FastMath; |
||||||
|
import com.jme3.math.Vector3f; |
||||||
|
import com.jme3.renderer.Camera; |
||||||
|
import com.jme3.scene.Geometry; |
||||||
|
import com.jme3.scene.shape.Box; |
||||||
|
import com.jme3.util.TempVars; |
||||||
|
import org.junit.Before; |
||||||
|
import org.junit.Test; |
||||||
|
|
||||||
|
/** |
||||||
|
* Test light filtering for various light types. |
||||||
|
* |
||||||
|
* @author Kirill Vainer |
||||||
|
*/ |
||||||
|
public class LightFilterTest { |
||||||
|
|
||||||
|
private DefaultLightFilter filter; |
||||||
|
private Camera cam; |
||||||
|
private Geometry geom; |
||||||
|
private LightList list; |
||||||
|
|
||||||
|
private void checkFilteredLights(int expected) { |
||||||
|
geom.updateGeometricState(); |
||||||
|
filter.setCamera(cam); // setCamera resets the intersection cache
|
||||||
|
list.clear(); |
||||||
|
filter.filterLights(geom, list); |
||||||
|
assert list.size() == expected; |
||||||
|
} |
||||||
|
|
||||||
|
@Before |
||||||
|
public void setUp() { |
||||||
|
filter = new DefaultLightFilter(); |
||||||
|
|
||||||
|
cam = new Camera(512, 512); |
||||||
|
cam.setFrustumPerspective(45, 1, 1, 1000); |
||||||
|
cam.setLocation(Vector3f.ZERO); |
||||||
|
cam.lookAtDirection(Vector3f.UNIT_Z, Vector3f.UNIT_Y); |
||||||
|
filter.setCamera(cam); |
||||||
|
|
||||||
|
Box box = new Box(1, 1, 1); |
||||||
|
geom = new Geometry("geom", box); |
||||||
|
geom.setLocalTranslation(0, 0, 10); |
||||||
|
geom.updateGeometricState(); |
||||||
|
list = new LightList(geom); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testAmbientFiltering() { |
||||||
|
geom.addLight(new AmbientLight()); |
||||||
|
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 |
||||||
|
public void testPointFiltering() { |
||||||
|
PointLight pl = new PointLight(Vector3f.ZERO); |
||||||
|
geom.addLight(pl); |
||||||
|
checkFilteredLights(1); // Infinite point lights must never be filtered
|
||||||
|
|
||||||
|
// Light at origin does not intersect geom which is at Z=10
|
||||||
|
pl.setRadius(1); |
||||||
|
checkFilteredLights(0); |
||||||
|
|
||||||
|
// Put it closer to geom, the very edge of the sphere touches the box.
|
||||||
|
// Still not considered an intersection though.
|
||||||
|
pl.setPosition(new Vector3f(0, 0, 8f)); |
||||||
|
checkFilteredLights(0); |
||||||
|
|
||||||
|
// And more close - now its an intersection.
|
||||||
|
pl.setPosition(new Vector3f(0, 0, 8f + FastMath.ZERO_TOLERANCE)); |
||||||
|
checkFilteredLights(1); |
||||||
|
|
||||||
|
// Move the geometry away
|
||||||
|
geom.move(0, 0, FastMath.ZERO_TOLERANCE); |
||||||
|
checkFilteredLights(0); |
||||||
|
|
||||||
|
// Test if the algorithm converts the sphere
|
||||||
|
// to a box before testing the collision (incorrect)
|
||||||
|
float sqrt3 = FastMath.sqrt(3); |
||||||
|
|
||||||
|
pl.setPosition(new Vector3f(2, 2, 8)); |
||||||
|
pl.setRadius(sqrt3); |
||||||
|
checkFilteredLights(0); |
||||||
|
|
||||||
|
// Make it a wee bit larger.
|
||||||
|
pl.setRadius(sqrt3 + FastMath.ZERO_TOLERANCE); |
||||||
|
checkFilteredLights(1); |
||||||
|
|
||||||
|
// Rotate the camera so it is up, light is outside frustum.
|
||||||
|
cam.lookAtDirection(Vector3f.UNIT_Y, Vector3f.UNIT_Y); |
||||||
|
checkFilteredLights(0); |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testSpotFiltering() { |
||||||
|
SpotLight sl = new SpotLight(Vector3f.ZERO, Vector3f.UNIT_Z); |
||||||
|
sl.setSpotRange(0); |
||||||
|
geom.addLight(sl); |
||||||
|
checkFilteredLights(1); // Infinite spot lights are only filtered
|
||||||
|
// if the geometry is outside the infinite cone.
|
||||||
|
|
||||||
|
TempVars vars = TempVars.get(); |
||||||
|
try { |
||||||
|
// The spot is not touching the near plane of the camera yet,
|
||||||
|
// should still be culled.
|
||||||
|
sl.setSpotRange(1f - FastMath.ZERO_TOLERANCE); |
||||||
|
assert !sl.intersectsFrustum(cam, vars); |
||||||
|
// should be culled from the geometry's PoV
|
||||||
|
checkFilteredLights(0); |
||||||
|
|
||||||
|
// Now it touches the near plane.
|
||||||
|
sl.setSpotRange(1f); |
||||||
|
// still culled from the geometry's PoV
|
||||||
|
checkFilteredLights(0); |
||||||
|
assert sl.intersectsFrustum(cam, vars); |
||||||
|
} finally { |
||||||
|
vars.release(); |
||||||
|
} |
||||||
|
|
||||||
|
// make it barely reach the geometry
|
||||||
|
sl.setSpotRange(9f); |
||||||
|
checkFilteredLights(0); |
||||||
|
|
||||||
|
// make it reach the geometry (touching its bound)
|
||||||
|
sl.setSpotRange(9f + FastMath.ZERO_TOLERANCE); |
||||||
|
checkFilteredLights(1); |
||||||
|
|
||||||
|
// rotate the cone a bit so it no longer faces the geom
|
||||||
|
sl.setDirection(new Vector3f(0.316f, 0, 0.948f).normalizeLocal()); |
||||||
|
checkFilteredLights(0); |
||||||
|
|
||||||
|
// extent the range much farther
|
||||||
|
sl.setSpotRange(20); |
||||||
|
checkFilteredLights(0); |
||||||
|
|
||||||
|
// Create box of size X=10 (double the extent)
|
||||||
|
// now, the spot will touch the box.
|
||||||
|
geom.setMesh(new Box(5, 1, 1)); |
||||||
|
checkFilteredLights(1); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,115 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2009-2015 jMonkeyEngine |
||||||
|
* All rights reserved. |
||||||
|
* |
||||||
|
* Redistribution and use in source and binary forms, with or without |
||||||
|
* modification, are permitted provided that the following conditions are |
||||||
|
* met: |
||||||
|
* |
||||||
|
* * Redistributions of source code must retain the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer. |
||||||
|
* |
||||||
|
* * Redistributions in binary form must reproduce the above copyright |
||||||
|
* notice, this list of conditions and the following disclaimer in the |
||||||
|
* documentation and/or other materials provided with the distribution. |
||||||
|
* |
||||||
|
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors |
||||||
|
* may be used to endorse or promote products derived from this software |
||||||
|
* without specific prior written permission. |
||||||
|
* |
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
||||||
|
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
||||||
|
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
||||||
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
||||||
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
||||||
|
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
||||||
|
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||||
|
*/ |
||||||
|
package com.jme3.light; |
||||||
|
|
||||||
|
import com.jme3.math.Vector3f; |
||||||
|
import com.jme3.scene.Geometry; |
||||||
|
import com.jme3.scene.Mesh; |
||||||
|
import com.jme3.scene.Node; |
||||||
|
import org.junit.Test; |
||||||
|
|
||||||
|
/** |
||||||
|
* Test light sorting (in the scene graph) for various light types. |
||||||
|
* |
||||||
|
* @author Kirill Vainer |
||||||
|
*/ |
||||||
|
public class LightSortTest { |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testSimpleSort() { |
||||||
|
Geometry g = new Geometry("test", new Mesh()); |
||||||
|
LightList list = new LightList(g); |
||||||
|
|
||||||
|
list.add(new SpotLight(Vector3f.ZERO, Vector3f.UNIT_X)); |
||||||
|
list.add(new PointLight(Vector3f.UNIT_X)); |
||||||
|
list.add(new DirectionalLight(Vector3f.UNIT_X)); |
||||||
|
list.add(new AmbientLight()); |
||||||
|
|
||||||
|
list.sort(true); |
||||||
|
|
||||||
|
assert list.get(0) instanceof AmbientLight; // Ambients always first
|
||||||
|
assert list.get(1) instanceof DirectionalLight; // .. then directionals
|
||||||
|
assert list.get(2) instanceof SpotLight; // Spot is 0 units away from geom
|
||||||
|
assert list.get(3) instanceof PointLight; // .. and point is 1 unit away.
|
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
public void testSceneGraphSort() { |
||||||
|
Node n = new Node("node"); |
||||||
|
Geometry g = new Geometry("geom", new Mesh()); |
||||||
|
SpotLight spot = new SpotLight(Vector3f.ZERO, Vector3f.UNIT_X); |
||||||
|
PointLight point = new PointLight(Vector3f.UNIT_X); |
||||||
|
DirectionalLight directional = new DirectionalLight(Vector3f.UNIT_X); |
||||||
|
AmbientLight ambient = new AmbientLight(); |
||||||
|
|
||||||
|
// Some lights are on the node
|
||||||
|
n.addLight(spot); |
||||||
|
n.addLight(point); |
||||||
|
|
||||||
|
// .. and some on the geometry.
|
||||||
|
g.addLight(directional); |
||||||
|
g.addLight(ambient); |
||||||
|
|
||||||
|
n.attachChild(g); |
||||||
|
n.updateGeometricState(); |
||||||
|
|
||||||
|
LightList list = g.getWorldLightList(); |
||||||
|
|
||||||
|
// check the sorting (when geom is at 0,0,0)
|
||||||
|
assert list.get(0) instanceof AmbientLight; |
||||||
|
assert list.get(1) instanceof DirectionalLight; |
||||||
|
assert list.get(2) instanceof SpotLight; |
||||||
|
assert list.get(3) instanceof PointLight; |
||||||
|
|
||||||
|
// move the geometry closer to the point light
|
||||||
|
g.setLocalTranslation(Vector3f.UNIT_X); |
||||||
|
n.updateGeometricState(); |
||||||
|
|
||||||
|
assert list.get(0) instanceof AmbientLight; |
||||||
|
assert list.get(1) instanceof DirectionalLight; |
||||||
|
assert list.get(2) instanceof PointLight; |
||||||
|
assert list.get(3) instanceof SpotLight; |
||||||
|
|
||||||
|
// now move the point light away from the geometry
|
||||||
|
// and the spot light closer
|
||||||
|
|
||||||
|
// XXX: doesn't work! jME can't detect that the light moved!
|
||||||
|
// point.setPosition(Vector3f.ZERO);
|
||||||
|
// spot.setPosition(Vector3f.UNIT_X);
|
||||||
|
// n.updateGeometricState();
|
||||||
|
//
|
||||||
|
// assert list.get(0) instanceof AmbientLight;
|
||||||
|
// assert list.get(1) instanceof DirectionalLight;
|
||||||
|
// assert list.get(2) instanceof SpotLight;
|
||||||
|
// assert list.get(3) instanceof PointLight;
|
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue