ShadowedRenderPass

I have a trouble casting shadows.



I have this portion of code:


RenderPass rootPass = new RenderPass();
      rootPass.add(rootNode);
      pManager.add(rootPass);
      
      pass = new ShadowedRenderPass();
      
      pass.add(rootNode);
      pass.addOccluder(c.getNodo());
      pass.setRenderShadows(true);
      //pass.setRenderVolume(true);
      pass.setLightingMethod(ShadowedRenderPass.ADDITIVE);
      pManager.add(pass);



When c is a .jme spaceship with a cube rotating around it. When I activate the RenderVolume (comment line) I can see volumes in green but my objects don't cast any shadows.

I don't understand it. Maybe I have to create my objects whith in a especial order/way. I don't know. My objects have no boundaries but I don'y expect that it causes my problem
Can you help me, please?

render volumes is a debug feature that shows where the volumes would leaves shadows (assuming they also have been added to the shadow render pass)

simple shadow example, hope this helps


import java.util.logging.Level;

import com.jme.app.BaseGame;
import com.jme.bounding.BoundingBox;
import com.jme.bounding.BoundingSphere;
import com.jme.input.KeyBindingManager;
import com.jme.input.KeyInput;
import com.jme.light.DirectionalLight;
import com.jme.math.Vector3f;
import com.jme.renderer.Camera;
import com.jme.renderer.ColorRGBA;
import com.jme.renderer.Renderer;
import com.jme.renderer.pass.BasicPassManager;
import com.jme.renderer.pass.ShadowedRenderPass;
import com.jme.scene.Node;
import com.jme.scene.shape.Box;
import com.jme.scene.shape.Sphere;
import com.jme.scene.state.LightState;
import com.jme.scene.state.ZBufferState;
import com.jme.system.DisplaySystem;
import com.jme.system.JmeException;
import com.jme.util.LoggingSystem;
import com.jme.util.Timer;

public class TestShadowPass extends BaseGame {
   protected Timer timer;
   private int width, height, depth, freq;
   protected float tpf;
   protected Camera cam;
   private boolean fullscreen;
   protected BasicPassManager pManager;
   protected LightState lightState;
    protected int stencilBits = 0;
   protected Node rootNode;
   Sphere guy;
  
    private static ShadowedRenderPass sPass = new ShadowedRenderPass();
 

    public static void main(String[] args) {
        LoggingSystem.getLogger().setLevel(java.util.logging.Level.WARNING);
        TestShadowPass app = new TestShadowPass();
        app.setDialogBehaviour(NEVER_SHOW_PROPS_DIALOG);
        app.start();
    }
   
    TestShadowPass() {
        stencilBits = 4; // we need a minimum stencil buffer at least.
    }
   
    private void setupCharacter() {
    
        guy=new Sphere("ball",16,16,1.55f);
        guy.setModelBound(new BoundingSphere());
        guy.updateModelBound();
       
        guy.setLocalTranslation(new Vector3f(0,3,0));
 
       guy.setRenderQueueMode(Renderer.QUEUE_OPAQUE);
   
       guy.updateRenderState();
      
        rootNode.attachChild(guy);
        rootNode.updateGeometricState(0,true);
       
    }
   
    private void setupFloor() {

        Box floor = new Box("box", new Vector3f(), 25, 1, 25);
        floor.setModelBound(new BoundingBox());
        floor.updateModelBound();
        floor.setLocalTranslation(new Vector3f(0,-2,0));
        rootNode.attachChild(floor);
       
        floor.updateGeometricState(0,false);
        floor.updateRenderState();
      
    }

   protected void update(float interpolation) {
      
      timer.update();
    
        tpf = timer.getTimePerFrame();
      
      pManager.updatePasses(tpf);
      
      rootNode.updateGeometricState(tpf, true);

        if (KeyBindingManager.getKeyBindingManager().isValidCommand("exit",
                false)) {
            finish();
        }

   }

   protected void render(float interpolation) {
      Renderer r = display.getRenderer();
       
        r.clearStatistics();
      
        r.clearBuffers();
       
      pManager.renderPasses(r);
      
   }
   
   protected void initSystem() {
      
      try {
            display = DisplaySystem.getDisplaySystem(properties.getRenderer());
           
            display.setMinStencilBits(stencilBits);
          
            width = properties.getWidth();
          height = properties.getHeight();
          depth = properties.getDepth();
          freq = properties.getFreq();
          fullscreen = properties.getFullscreen();
           
            display.createWindow(properties.getWidth(), properties.getHeight(),
                    properties.getDepth(), properties.getFreq(), properties
                            .getFullscreen());
          
            cam = display.getRenderer().createCamera(display.getWidth(),
                    display.getHeight());

        } catch (JmeException e) {
          
            e.printStackTrace();
            System.exit(1);
        }

        display.getRenderer().setBackgroundColor(ColorRGBA.black);

        cameraPerspective();
        Vector3f loc = new Vector3f(0.0f, 4.0f, 25.0f);
        Vector3f left = new Vector3f(-1.0f, 0.0f, 0.0f);
        Vector3f up = new Vector3f(0.0f, 1.0f, 0.0f);
        Vector3f dir = new Vector3f(0.0f, 0f, -1.0f);
      
        cam.setFrame(loc, left, up, dir);
      
        cam.update();
      
        display.getRenderer().setCamera(cam);

        timer = Timer.getTimer(properties.getRenderer());

        KeyBindingManager.getKeyBindingManager().set("exit",
                KeyInput.KEY_ESCAPE);
       
   }

   protected void initGame() {
      pManager = new BasicPassManager();
      
        rootNode = new Node("rootNode");

        ZBufferState buf = display.getRenderer().createZBufferState();
        buf.setEnabled(true);
        buf.setFunction(ZBufferState.CF_LEQUAL);
        rootNode.setRenderState(buf);
        rootNode.updateRenderState();
       
        DirectionalLight light = new DirectionalLight();
        light.setDiffuse(new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f));
        light.setAmbient(new ColorRGBA(0.5f, 0.5f, 0.5f, .5f));
        light.setDirection(new Vector3f(1,-1,0));
        light.setShadowCaster(true);
        light.setEnabled(true);

        LightState lightState = display.getRenderer().createLightState();
        lightState.setEnabled(true);
        lightState.setGlobalAmbient(new ColorRGBA(.2f, .2f, .2f, 1f));
        lightState.attach(light);
        rootNode.setRenderState(lightState);

        setupCharacter();
        setupFloor();
       
        rootNode.setRenderQueueMode(Renderer.QUEUE_OPAQUE);
        rootNode.updateRenderState();
       
        sPass.add(rootNode);
        sPass.addOccluder(guy);
        sPass.setRenderShadows(true);
        sPass.setLightingMethod(ShadowedRenderPass.MODULATIVE);
        pManager.add(sPass);
      
   }
   protected void cameraPerspective() {
        cam.setFrustumPerspective(35.0f, (float) display.getWidth()
                / (float) display.getHeight(), 1, 1000);
        cam.setParallelProjection(false);
        cam.update();
    }
   protected void reinit() {
      display.recreateWindow(width, height, depth, freq, fullscreen);
      
   }

   protected void cleanup() {
      LoggingSystem.getLogger().log(Level.INFO, "Cleaning up resources.");
      
   }
}

But does not SimplePassGame implement all procedement to do it?



Ok. Another question, how can I to cast shadows froma a .jme loaded object?



My program throw an exception that said:


java.lang.NullPointerException
   at com.jme.scene.shadow.MeshShadows.createGeometry(Unknown Source)
   at com.jme.renderer.pass.ShadowedRenderPass.generateVolumes(Unknown Source)
   at com.jme.renderer.pass.ShadowedRenderPass.doRender(Unknown Source)
   at com.jme.renderer.pass.Pass.renderPass(Unknown Source)
   at com.jme.renderer.pass.BasicPassManager.renderPasses(Unknown Source)
   at com.jme.app.SimplePassGame.render(Unknown Source)
   at com.jme.app.BaseGame.start(Unknown Source)
   at sombras.Sombras.main(Sombras.java:114)



And I dont understan what it mean.

My loader is:

public static Node loadJMEModel(String modelPath, String texturePath){
      // URL of the model
      URL model=JMELoader.class.getResource(modelPath);
      
      // URL of the texture
      URL tex=JMELoader.class.getResource(texturePath);

      JmeBinaryReader jbr=new JmeBinaryReader();
            
      try{
            // Tell the binary reader to use bounding boxes instead of bounding spheres
            jbr.setProperty("bound","box");
             
            // Load the binary .jme format into a scene graph
            Node modelNode=jbr.loadBinaryFormat(model.openStream());
                
            TextureState ts=DisplaySystem.getDisplaySystem().getRenderer().createTextureState();
            ts.setTexture(TextureManager.loadTexture(tex,Texture.MM_LINEAR,Texture.FM_LINEAR));
            ts.setEnabled(true);
            modelNode.setRenderState(ts);
                            
            return modelNode;          
        }
        catch (IOException e) {   // Just in case anything happens
            System.out.println("Damn exceptions!" + e);
            e.printStackTrace();
          
            return null;
        }
    }



I dont know what happen.