diff --git a/jme3-core/src/main/java/com/jme3/shadow/ShadowUtil.java b/jme3-core/src/main/java/com/jme3/shadow/ShadowUtil.java index 8c6b1ab91..89081670d 100644 --- a/jme3-core/src/main/java/com/jme3/shadow/ShadowUtil.java +++ b/jme3-core/src/main/java/com/jme3/shadow/ShadowUtil.java @@ -271,7 +271,6 @@ public class ShadowUtil { { // global variables set in order not to have recursive process method with too many parameters Matrix4f viewProjMatrix; - public Integer casterCount; BoundingBox splitBB, casterBB; GeometryList splitOccluders; TempVars vars; @@ -279,9 +278,8 @@ public class ShadowUtil { public OccludersExtractor() {} // initialize the global OccludersExtractor variables - public OccludersExtractor(Matrix4f vpm, int cc, BoundingBox sBB, BoundingBox cBB, GeometryList sOCC, TempVars v) { - viewProjMatrix = vpm; - casterCount = cc; + public OccludersExtractor(Matrix4f vpm, BoundingBox sBB, BoundingBox cBB, GeometryList sOCC, TempVars v) { + viewProjMatrix = vpm; splitBB = sBB; casterBB = cBB; splitOccluders = sOCC; @@ -293,9 +291,8 @@ public class ShadowUtil { * The global OccludersExtractor variables need to be initialized first. * Variables are updated and used in {@link ShadowUtil#updateShadowCamera} at last. */ - public int addOccluders(Spatial scene) { + public void addOccluders(Spatial scene) { if ( scene != null ) process(scene); - return casterCount; } private boolean intersectsIgnoreNearZ(BoundingBox splitBB, BoundingSphere occSphere) { @@ -357,7 +354,6 @@ public class ShadowUtil { BoundingVolume occBox = bv.transform(viewProjMatrix, vars.bbox); if (intersectsIgnoreNearZ(splitBB, occBox)) { casterBB.mergeLocal(occBox); - casterCount++; if (splitOccluders != null) { splitOccluders.add(occluder); } @@ -384,7 +380,7 @@ public class ShadowUtil { GeometryList receivers, Camera shadowCam, Vector3f[] points, - GeometryList splitOccluders, + GeometryList shadowCasters, float shadowMapSize) { boolean ortho = shadowCam.isParallelProjection(); @@ -392,7 +388,7 @@ public class ShadowUtil { shadowCam.setProjectionMatrix(null); if (ortho) { - shadowCam.setFrustum(-shadowCam.getFrustumFar(), shadowCam.getFrustumFar(), -1, 1, 1, -1); + shadowCam.setFrustum(-1, 1, -1, 1, 1, -1); } // create transform to rotate points to viewspace @@ -405,36 +401,31 @@ public class ShadowUtil { BoundingBox casterBB = new BoundingBox(); BoundingBox receiverBB = new BoundingBox(); - int casterCount = 0, receiverCount = 0; - - for (int i = 0; i < receivers.size(); i++) { - // convert bounding box to light's viewproj space - Geometry receiver = receivers.get(i); - BoundingVolume bv = receiver.getWorldBound(); - BoundingVolume recvBox = bv.transform(viewProjMatrix, vars.bbox); - - if (splitBB.intersects(recvBox)) { - //Nehon : prevent NaN and infinity values to screw the final bounding box - if (!Float.isNaN(recvBox.getCenter().x) && !Float.isInfinite(recvBox.getCenter().x)) { - receiverBB.mergeLocal(recvBox); - receiverCount++; + if (receivers != null && receivers.size() != 0) { + for (int i = 0; i < receivers.size(); i++) { + // convert bounding box to light's viewproj space + Geometry receiver = receivers.get(i); + BoundingVolume bv = receiver.getWorldBound(); + BoundingVolume recvBox = bv.transform(viewProjMatrix, vars.bbox); + + if (splitBB.intersects(recvBox)) { + //Nehon : prevent NaN and infinity values to screw the final bounding box + if (!Float.isNaN(recvBox.getCenter().x) && !Float.isInfinite(recvBox.getCenter().x)) { + receiverBB.mergeLocal(recvBox); + } } } + } else { + receiverBB.setXExtent(Float.POSITIVE_INFINITY); + receiverBB.setYExtent(Float.POSITIVE_INFINITY); + receiverBB.setZExtent(Float.POSITIVE_INFINITY); } // collect splitOccluders through scene recursive traverse - OccludersExtractor occExt = new OccludersExtractor(viewProjMatrix, casterCount, splitBB, casterBB, splitOccluders, vars); + OccludersExtractor occExt = new OccludersExtractor(viewProjMatrix, splitBB, casterBB, shadowCasters, vars); for (Spatial scene : viewPort.getScenes()) { occExt.addOccluders(scene); } - casterCount = occExt.casterCount; - - //Nehon 08/18/2010 this is to avoid shadow bleeding when the ground is set to only receive shadows - if (casterCount != receiverCount) { - casterBB.setXExtent(casterBB.getXExtent() + 2.0f); - casterBB.setYExtent(casterBB.getYExtent() + 2.0f); - casterBB.setZExtent(casterBB.getZExtent() + 2.0f); - } Vector3f casterMin = casterBB.getMin(vars.vect1); Vector3f casterMax = casterBB.getMax(vars.vect2); @@ -445,27 +436,26 @@ public class ShadowUtil { Vector3f splitMin = splitBB.getMin(vars.vect5); Vector3f splitMax = splitBB.getMax(vars.vect6); - splitMin.z = 0; - -// if (!ortho) { -// shadowCam.setFrustumPerspective(45, 1, 1, splitMax.z); -// } Matrix4f projMatrix = shadowCam.getProjectionMatrix(); Vector3f cropMin = vars.vect7; Vector3f cropMax = vars.vect8; - // IMPORTANT: Special handling for Z values - cropMin.x = max(max(casterMin.x, receiverMin.x), splitMin.x); - cropMax.x = min(min(casterMax.x, receiverMax.x), splitMax.x); - - cropMin.y = max(max(casterMin.y, receiverMin.y), splitMin.y); - cropMax.y = min(min(casterMax.y, receiverMax.y), splitMax.y); - - cropMin.z = min(casterMin.z, splitMin.z); - cropMax.z = min(receiverMax.z, splitMax.z); - + if (shadowCasters.size() > 0) { + // IMPORTANT: Special handling for Z values + cropMin.x = max(max(casterMin.x, receiverMin.x), splitMin.x); + cropMax.x = min(min(casterMax.x, receiverMax.x), splitMax.x); + cropMin.y = max(max(casterMin.y, receiverMin.y), splitMin.y); + cropMax.y = min(min(casterMax.y, receiverMax.y), splitMax.y); + cropMin.z = min(casterMin.z, splitMin.z); + cropMax.z = min(receiverMax.z, splitMax.z); + } else { + // Set crop = split so that everything in the scene has a depth < 1.0 in light space. + // This avoids shadowing everything when there are no casters. + cropMin.set(splitMin); + cropMax.set(splitMax); + } // Create the crop matrix. float scaleX, scaleY, scaleZ;