Shadows for objects that have been scaled and rotated

Hi guys,



I have a problem with schadows when the object has been scaled and rotated: the shadow doesn’t rotate with the object:



before rotation:



after rotation:





If I don’t scale the object everything works fine. However, it would make my life a little easier if I could use scaling  :smiley:

I tried playing with the settings but couldn’t get it.

I hope I am missing something simple.



here’s a simple test case:

package testshadows;

import java.util.HashMap;

import javax.swing.ImageIcon;

import com.jme.app.SimplePassGame;
import com.jme.bounding.BoundingBox;
import com.jme.image.Texture;
import com.jme.input.ChaseCamera;
import com.jme.input.KeyBindingManager;
import com.jme.input.KeyInput;
import com.jme.input.ThirdPersonHandler;
import com.jme.light.DirectionalLight;
import com.jme.light.PointLight;
import com.jme.math.FastMath;
import com.jme.math.Vector3f;
import com.jme.renderer.ColorRGBA;
import com.jme.renderer.Renderer;
import com.jme.renderer.pass.RenderPass;
import com.jme.renderer.pass.ShadowedRenderPass;
import com.jme.scene.Node;
import com.jme.scene.VBOInfo;
import com.jme.scene.shape.Box;
import com.jme.scene.shape.PQTorus;
import com.jme.scene.state.CullState;
import com.jme.scene.state.FogState;
import com.jme.scene.state.TextureState;
import com.jme.util.TextureManager;
import com.jmex.terrain.TerrainPage;
import com.jmex.terrain.util.FaultFractalHeightMap;
import com.jmex.terrain.util.ProceduralTextureGenerator;

//effects
import com.jme.image.Texture;
import com.jme.renderer.pass.BasicPassManager;
import com.jme.system.DisplaySystem;
import com.jme.math.Vector3f;
import com.jme.renderer.pass.BasicPassManager;
import com.jme.renderer.pass.RenderPass;
import com.jme.scene.Node;
import com.jme.scene.Spatial;
import com.jme.scene.state.LightState;
import com.jmex.game.StandardGame;

import com.jme.math.FastMath;
import com.jme.math.Quaternion;

public class Main extends SimplePassGame {
 
    private static ShadowedRenderPass sPass = new ShadowedRenderPass();
   
    private Quaternion rotQuat = new Quaternion();
    private Quaternion tempQuat = new Quaternion(); 
    private Vector3f zAxis = new Vector3f(0, 0, 1);
   
    public static void main(String[] args) {
        Main app = new Main();
        app.setDialogBehaviour(ALWAYS_SHOW_PROPS_DIALOG);
        app.start();
    }
   
    Main() {
        stencilBits = 4; // we need a minimum stencil buffer at least.
       
    }

    protected void simpleInitGame() {
     
        KeyBindingManager.getKeyBindingManager().set("rotate",KeyInput.KEY_HOME);
       
        DirectionalLight dr = new DirectionalLight();
        dr.setEnabled(true);
        dr.setDiffuse(new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f));
        dr.setAmbient(new ColorRGBA(.2f, .2f, .2f, .3f));
        dr.setDirection(new Vector3f(-0.2f, -0.3f, .2f).normalizeLocal());
        dr.setShadowCaster(true);
        lightState.attach(dr);
       
       
        Box box = new Box("box",new Vector3f(), 1, 1, 1);
   
       rootNode.setLocalScale(new Vector3f(3,2,1));       // <-- shadow doesn't rotate with the box if I use scaling
       //  box.setLocalScale(new Vector3f(3,2,1));       // <-- shadow doesn't rotate with the box if I use scaling

      //  Box box = new Box("box",new Vector3f(), 3, 2, 1); // <-- shadow rotates with the box when there's no scaling
       
        box.setLocalRotation(rotQuat);
        box.setModelBound(new BoundingBox());
        box.updateModelBound();
       
        rootNode.attachChild(box);
       
        rootNode.setRenderQueueMode(Renderer.QUEUE_OPAQUE);

        sPass.add(rootNode);
        sPass.addOccluder(box);
        sPass.setRenderVolume(true);
        sPass.setRenderShadows(true);
        sPass.setLightingMethod(ShadowedRenderPass.MODULATIVE);
        pManager.add(sPass);
       
        RenderPass rPass = new RenderPass();
        rPass.add(fpsNode);
        pManager.add(rPass);
    }
   
    protected void simpleUpdate() {
        if (KeyBindingManager.getKeyBindingManager().isValidCommand("rotate",true)){
        rotQuat.multLocal(tempQuat.fromAngleAxis( FastMath.HALF_PI,zAxis ));
        }
    }

}



I think you have to mark the vertices as dirty so the shadow pass recalculates the volume.

Hi theNoob,



I tried your case and I think that it's a problem with core shadow pass! Maybe it's a bug!

It looks like the problem lies in the non-uniform scale,  using a scale of 0.5f works fine

also box.getBatch(0).setHasDirtyVertices(true); has no effect when using a non-uniform scale



even when scaled the shadow does change position but the scale throws it completely off

the reason why you dont see the shadow change in the provided code is because the box is square  (atleast it is if you dont look at the scale )

thanks for the replys guys.


box.getBatch(0).setHasDirtyVertices(true); has no effect when using a non-uniform scale

so I should't try solving it this way. Thanks for letting me know.

even when scaled the shadow does change position but the scale throws it completely off
the reason why you dont see the shadow change in the provided code is because the box is square  (atleast it is if you dont look at the scale )

I'm not sure what you mean here. The shadow works perfectly even with the non uniformly scaled box as long as there are no rotations. If the box is simply translated the shadow is also translated with it.

I tried your case and I think that it's a problem with core shadow pass! Maybe it's a bug!

I was afraid this might be the case. I can work around it. No biggy.

thanks