fix shadow disappearing when frustum in front of caster
This commit is contained in:
parent
0fae3839d3
commit
4b4bf24127
@ -32,7 +32,9 @@
|
|||||||
package com.jme3.shadow;
|
package com.jme3.shadow;
|
||||||
|
|
||||||
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.collision.UnsupportedCollisionException;
|
||||||
import com.jme3.math.FastMath;
|
import com.jme3.math.FastMath;
|
||||||
import com.jme3.math.Matrix4f;
|
import com.jme3.math.Matrix4f;
|
||||||
import com.jme3.math.Transform;
|
import com.jme3.math.Transform;
|
||||||
@ -42,6 +44,7 @@ import com.jme3.renderer.Camera;
|
|||||||
import com.jme3.renderer.ViewPort;
|
import com.jme3.renderer.ViewPort;
|
||||||
import com.jme3.renderer.queue.GeometryList;
|
import com.jme3.renderer.queue.GeometryList;
|
||||||
import com.jme3.renderer.queue.RenderQueue;
|
import com.jme3.renderer.queue.RenderQueue;
|
||||||
|
import com.jme3.renderer.queue.RenderQueue.ShadowMode;
|
||||||
import com.jme3.scene.Geometry;
|
import com.jme3.scene.Geometry;
|
||||||
import com.jme3.scene.Node;
|
import com.jme3.scene.Node;
|
||||||
import com.jme3.scene.Spatial;
|
import com.jme3.scene.Spatial;
|
||||||
@ -295,46 +298,64 @@ public class ShadowUtil {
|
|||||||
return casterCount;
|
return casterCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean intersectsIgnoreNearZ(BoundingBox splitBB, BoundingSphere occSphere) {
|
||||||
|
float distSqr = occSphere.getRadius() * occSphere.getRadius();
|
||||||
|
|
||||||
|
float minX = splitBB.getCenter().x - splitBB.getXExtent();
|
||||||
|
float maxX = splitBB.getCenter().x + splitBB.getXExtent();
|
||||||
|
|
||||||
|
float minY = splitBB.getCenter().y - splitBB.getYExtent();
|
||||||
|
float maxY = splitBB.getCenter().y + splitBB.getYExtent();
|
||||||
|
|
||||||
|
float maxZ = splitBB.getCenter().z + splitBB.getZExtent();
|
||||||
|
|
||||||
|
if (occSphere.getCenter().x < minX) distSqr -= FastMath.sqr(occSphere.getCenter().x - minX);
|
||||||
|
else if (occSphere.getCenter().x > maxX) distSqr -= FastMath.sqr(occSphere.getCenter().x - maxX);
|
||||||
|
|
||||||
|
if (occSphere.getCenter().y < minY) distSqr -= FastMath.sqr(occSphere.getCenter().y - minY);
|
||||||
|
else if (occSphere.getCenter().y > maxY) distSqr -= FastMath.sqr(occSphere.getCenter().y - maxY);
|
||||||
|
|
||||||
|
if (occSphere.getCenter().z > maxZ) distSqr -= FastMath.sqr(occSphere.getCenter().z - maxZ);
|
||||||
|
|
||||||
|
return distSqr > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean intersectsIgnoreNearZ(BoundingBox splitBB, BoundingBox occBB) {
|
||||||
|
if (splitBB.getCenter().x + splitBB.getXExtent() < occBB.getCenter().x - occBB.getXExtent()
|
||||||
|
|| splitBB.getCenter().x - splitBB.getXExtent() > occBB.getCenter().x + occBB.getXExtent()) {
|
||||||
|
return false;
|
||||||
|
} else if (splitBB.getCenter().y + splitBB.getYExtent() < occBB.getCenter().y - occBB.getYExtent()
|
||||||
|
|| splitBB.getCenter().y - splitBB.getYExtent() > occBB.getCenter().y + occBB.getYExtent()) {
|
||||||
|
return false;
|
||||||
|
} else if (splitBB.getCenter().z + splitBB.getZExtent() < occBB.getCenter().z - occBB.getZExtent()) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean intersectsIgnoreNearZ(BoundingBox splitBB, BoundingVolume occBV) {
|
||||||
|
if (occBV instanceof BoundingBox) {
|
||||||
|
return intersectsIgnoreNearZ(splitBB, (BoundingBox) occBV);
|
||||||
|
} else if (occBV instanceof BoundingSphere) {
|
||||||
|
return intersectsIgnoreNearZ(splitBB, (BoundingSphere) occBV);
|
||||||
|
} else {
|
||||||
|
throw new UnsupportedCollisionException("With: " + occBV.getClass().getSimpleName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void process(Spatial scene) {
|
private void process(Spatial scene) {
|
||||||
if (scene.getCullHint() == Spatial.CullHint.Always) return;
|
if (scene.getCullHint() == Spatial.CullHint.Always) return;
|
||||||
|
|
||||||
RenderQueue.ShadowMode shadowMode = scene.getShadowMode();
|
if (scene instanceof Geometry) {
|
||||||
if ( scene instanceof Geometry )
|
|
||||||
{
|
|
||||||
// convert bounding box to light's viewproj space
|
// convert bounding box to light's viewproj space
|
||||||
Geometry occluder = (Geometry)scene;
|
Geometry occluder = (Geometry) scene;
|
||||||
if (shadowMode != RenderQueue.ShadowMode.Off && shadowMode != RenderQueue.ShadowMode.Receive
|
ShadowMode shadowMode = scene.getShadowMode();
|
||||||
&& !occluder.isGrouped() && occluder.getWorldBound()!=null) {
|
if (shadowMode != ShadowMode.Off && shadowMode != ShadowMode.Receive
|
||||||
|
&& !occluder.isGrouped()) {
|
||||||
BoundingVolume bv = occluder.getWorldBound();
|
BoundingVolume bv = occluder.getWorldBound();
|
||||||
BoundingVolume occBox = bv.transform(viewProjMatrix, vars.bbox);
|
BoundingVolume occBox = bv.transform(viewProjMatrix, vars.bbox);
|
||||||
|
if (intersectsIgnoreNearZ(splitBB, occBox)) {
|
||||||
boolean intersects = splitBB.intersects(occBox);
|
|
||||||
if (!intersects && occBox instanceof BoundingBox) {
|
|
||||||
BoundingBox occBB = (BoundingBox) occBox;
|
|
||||||
//Kirill 01/10/2011
|
|
||||||
// Extend the occluder further into the frustum
|
|
||||||
// This fixes shadow dissapearing issues when
|
|
||||||
// the caster itself is not in the view camera
|
|
||||||
// but its shadow is in the camera
|
|
||||||
// The number is in world units
|
|
||||||
occBB.setZExtent(occBB.getZExtent() + 50);
|
|
||||||
occBB.setCenter(occBB.getCenter().addLocal(0, 0, 25));
|
|
||||||
if (splitBB.intersects(occBB)) {
|
|
||||||
//Nehon : prevent NaN and infinity values to screw the final bounding box
|
|
||||||
if (!Float.isNaN(occBox.getCenter().x) && !Float.isInfinite(occBox.getCenter().x)) {
|
|
||||||
// To prevent extending the depth range too much
|
|
||||||
// We return the bound to its former shape
|
|
||||||
// Before adding it
|
|
||||||
occBB.setZExtent(occBB.getZExtent() - 50);
|
|
||||||
occBB.setCenter(occBB.getCenter().subtractLocal(0, 0, 25));
|
|
||||||
casterBB.mergeLocal(occBox);
|
|
||||||
casterCount++;
|
|
||||||
}
|
|
||||||
if (splitOccluders != null) {
|
|
||||||
splitOccluders.add(occluder);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (intersects) {
|
|
||||||
casterBB.mergeLocal(occBox);
|
casterBB.mergeLocal(occBox);
|
||||||
casterCount++;
|
casterCount++;
|
||||||
if (splitOccluders != null) {
|
if (splitOccluders != null) {
|
||||||
@ -342,30 +363,10 @@ public class ShadowUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else if (scene instanceof Node) {
|
||||||
else if ( scene instanceof Node && ((Node)scene).getWorldBound()!=null )
|
BoundingVolume bv = scene.getWorldBound();
|
||||||
{
|
|
||||||
Node nodeOcc = (Node)scene;
|
|
||||||
boolean intersects = false;
|
|
||||||
// some
|
|
||||||
BoundingVolume bv = nodeOcc.getWorldBound();
|
|
||||||
BoundingVolume occBox = bv.transform(viewProjMatrix, vars.bbox);
|
BoundingVolume occBox = bv.transform(viewProjMatrix, vars.bbox);
|
||||||
|
if (intersectsIgnoreNearZ(splitBB, occBox)) {
|
||||||
intersects = splitBB.intersects(occBox);
|
|
||||||
if (!intersects && occBox instanceof BoundingBox) {
|
|
||||||
BoundingBox occBB = (BoundingBox) occBox;
|
|
||||||
//Kirill 01/10/2011
|
|
||||||
// Extend the occluder further into the frustum
|
|
||||||
// This fixes shadow dissapearing issues when
|
|
||||||
// the caster itself is not in the view camera
|
|
||||||
// but its shadow is in the camera
|
|
||||||
// The number is in world units
|
|
||||||
occBB.setZExtent(occBB.getZExtent() + 50);
|
|
||||||
occBB.setCenter(occBB.getCenter().addLocal(0, 0, 25));
|
|
||||||
intersects = splitBB.intersects(occBB);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( intersects ) {
|
|
||||||
for (Spatial child : ((Node)scene).getChildren()) {
|
for (Spatial child : ((Node)scene).getChildren()) {
|
||||||
process(child);
|
process(child);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user