Additional Camera / MiniMap Crisis

Hey guys, i've tried using TestCameraMan as the base to build a camera zoomed out above my terrain - as a 'minimap' - i can't even get the camera node to show up over the 'game' state though (it's part of a third person adventure game)



Can anyone please help by shedding light on the situation???



I'm of course adding it to gamestatemanager and setting to active after the main level state has been loaded



Thanks,



HC



import com.jme.light.DirectionalLight;
import com.jme.light.LightNode;
import com.jme.light.SpotLight;
import com.jme.math.Vector3f;
import com.jme.renderer.ColorRGBA;
import com.jme.renderer.TextureRenderer;
import com.jme.scene.CameraNode;
import com.jme.scene.Node;
import com.jme.scene.Spatial;
import com.jme.scene.state.AlphaState;
import com.jme.scene.state.CullState;
import com.jme.scene.state.LightState;
import com.jme.system.DisplaySystem;
import com.jmex.game.state.BasicGameState;

public class MiniMap extends BasicGameState
{
// Camera Node (Minimap Stuff)
CameraNode camNode;
TextureRenderer tRenderer;

public MiniMap(String name)
{
super(name);
this.init();
}

public void init()
{
ColorRGBA color = new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f);

AlphaState alphaState = DisplaySystem.getDisplaySystem().getRenderer().createAlphaState();
alphaState.setBlendEnabled(true);
alphaState.setSrcFunction(AlphaState.SB_SRC_ALPHA);
alphaState.setDstFunction(AlphaState.DB_ONE_MINUS_SRC_ALPHA);
alphaState.setTestEnabled(true);
alphaState.setTestFunction(AlphaState.TF_GREATER);
alphaState.setEnabled(true);

rootNode = this.getRootNode();
rootNode.setCullMode(Spatial.CULL_NEVER);
rootNode.setLightCombineMode(LightState.OFF);

/* Add the minimap camera */
   
    tRenderer = DisplaySystem.getDisplaySystem().createTextureRenderer(256, 256, TextureRenderer.RENDER_TEXTURE_2D);
    camNode = new CameraNode("Camera Node", tRenderer.getCamera());
    camNode.setLocalTranslation(new Vector3f(0.0f, 50.0f, -50.0f));
    camNode.updateGeometricState(0, true);
   
    DirectionalLight am = new DirectionalLight();
    am.setDiffuse(new ColorRGBA(0.0f, 1.0f, 0.0f, 1.0f));
    am.setAmbient(new ColorRGBA(0.5f, 0.5f, 0.5f, 1.0f));
    am.setDirection(new Vector3f(1.0f, 0.0f, 0.0f));
       
    LightState state = DisplaySystem.getDisplaySystem().getRenderer().createLightState();
    state.setEnabled(true);
   
    LightNode cameraLight = new LightNode("Camera Light", state);
   
    camNode.attachChild(cameraLight);
     
    CullState cs = DisplaySystem.getDisplaySystem().getRenderer().createCullState();
    cs.setCullMode(CullState.CS_BACK);
    cs.setEnabled(true);
    rootNode.setRenderState(cs);
   
    rootNode.attachChild(camNode);
}

public void update(float f)
{
super.update(f);
this.getRootNode().updateGeometricState(f, true);
}

public void render(float f)
{
super.render(f);
DisplaySystem.getDisplaySystem().getRenderer().draw(this.getRootNode());
}

}

Are you using StandardGame or a similar Multithreaded environment by chance?

Then you need to call the MiniMap constructor with the help of GameTaskQueueManager.

Because createTextureRenderer() needs to be called inside the OpenGL thread.

Thanks core-dump! I am using Standardgame, i'm told that's the way cool kids use JME these days,



My new code is below - have I done it right? I still can't see any hint of a camera node on the screen



HC




import java.util.concurrent.Callable;

import com.jme.light.DirectionalLight;
import com.jme.light.LightNode;
import com.jme.light.SpotLight;
import com.jme.math.Vector3f;
import com.jme.renderer.ColorRGBA;
import com.jme.renderer.TextureRenderer;
import com.jme.scene.CameraNode;
import com.jme.scene.Node;
import com.jme.scene.Spatial;
import com.jme.scene.state.AlphaState;
import com.jme.scene.state.CullState;
import com.jme.scene.state.LightState;
import com.jme.system.DisplaySystem;
import com.jme.util.GameTaskQueue;
import com.jme.util.GameTaskQueueManager;
import com.jmex.game.state.BasicGameState;

public class MiniMap extends BasicGameState
{
// Camera Node (Minimap Stuff)
CameraNode camNode;
TextureRenderer tRenderer;

public MiniMap(String name)
{
super(name);
GameTaskQueueManager.getManager().getQueue(GameTaskQueue.RENDER).enqueue(new Callable<Object>() {

public Object call()
{
init();
return null;
}

});

this.init();
}

public void init()
{
ColorRGBA color = new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f);

AlphaState alphaState = DisplaySystem.getDisplaySystem().getRenderer().createAlphaState();
alphaState.setBlendEnabled(true);
alphaState.setSrcFunction(AlphaState.SB_SRC_ALPHA);
alphaState.setDstFunction(AlphaState.DB_ONE_MINUS_SRC_ALPHA);
alphaState.setTestEnabled(true);
alphaState.setTestFunction(AlphaState.TF_GREATER);
alphaState.setEnabled(true);

rootNode = this.getRootNode();
rootNode.setCullMode(Spatial.CULL_NEVER);
rootNode.setLightCombineMode(LightState.OFF);

/* Add the minimap camera */
   
    tRenderer = DisplaySystem.getDisplaySystem().createTextureRenderer(256, 256, TextureRenderer.RENDER_TEXTURE_2D);
    camNode = new CameraNode("Camera Node", tRenderer.getCamera());
    camNode.setLocalTranslation(new Vector3f(0.0f, 50.0f, -50.0f));
    camNode.updateGeometricState(0, true);
   
    DirectionalLight am = new DirectionalLight();
    am.setDiffuse(new ColorRGBA(0.0f, 1.0f, 0.0f, 1.0f));
    am.setAmbient(new ColorRGBA(0.5f, 0.5f, 0.5f, 1.0f));
    am.setDirection(new Vector3f(1.0f, 0.0f, 0.0f));
       
    LightState state = DisplaySystem.getDisplaySystem().getRenderer().createLightState();
    state.setEnabled(true);
   
    LightNode cameraLight = new LightNode("Camera Light", state);
   
    camNode.attachChild(cameraLight);
     
    CullState cs = DisplaySystem.getDisplaySystem().getRenderer().createCullState();
    cs.setCullMode(CullState.CS_BACK);
    cs.setEnabled(true);
    rootNode.setRenderState(cs);
   
    rootNode.attachChild(camNode);
}

public void update(float f)
{
super.update(f);
this.getRootNode().updateGeometricState(f, true);
GameTaskQueueManager.getManager().getQueue(GameTaskQueue.UPDATE).execute();
}

public void render(float f)
{
super.render(f);
GameTaskQueueManager.getManager().getQueue(GameTaskQueue.RENDER).execute();
}

}

The constructor could be something like:

   public MiniMap(String name) {
      super(name);
      GameTaskQueueManager.getManager().render(new Callable<Object>() {
      Callable<Object>() {
         public Object call() {
            init();
            return null;
         }
      }).get();
   }



And you don't need to overwrite the update and render methods. BasicGamestate already takes care of updating and rendering the root Node.

But i think you are missing a few things to get a working MiniMap.
Now you have set up a Camera and the TextureRenderer,  but do you apply the generated Texture to a quad and display it?

Amazing, again i've used the test but I can't make out I understand all the code - par for the course with JME documentation however! Learn by doing/asking for help!



This currently gets stuck at 'Starting mmap render…' - it freezes the program and I have to kill the process manually to get back to my IDE



import java.util.concurrent.Callable;

import com.jme.image.Texture;
import com.jme.light.DirectionalLight;
import com.jme.light.LightNode;
import com.jme.light.SpotLight;
import com.jme.math.Vector3f;
import com.jme.renderer.ColorRGBA;
import com.jme.renderer.TextureRenderer;
import com.jme.scene.CameraNode;
import com.jme.scene.Node;
import com.jme.scene.Spatial;
import com.jme.scene.shape.Quad;
import com.jme.scene.state.AlphaState;
import com.jme.scene.state.CullState;
import com.jme.scene.state.LightState;
import com.jme.scene.state.TextureState;
import com.jme.scene.state.ZBufferState;
import com.jme.system.DisplaySystem;
import com.jme.util.GameTaskQueue;
import com.jme.util.GameTaskQueueManager;
import com.jmex.game.state.BasicGameState;

public class MiniMap extends BasicGameState
{
// Camera Node (Minimap Stuff)
CameraNode camNode;
TextureRenderer tRenderer;

public MiniMap(String name)
{
super(name);
System.out.println("Starting mmap render..");
try
{
GameTaskQueueManager.getManager().render(new Callable<Object>()
{

public Object call()
{
System.out.println("Rendering minimap");
init();
return null;
}

}).get();
}
catch (Exception e)
{
System.out.println("Exception while generating minimap!");
}

}

public void init()
{
System.out.println("In init!");
ColorRGBA color = new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f);

AlphaState alphaState = DisplaySystem.getDisplaySystem().getRenderer().createAlphaState();
alphaState.setBlendEnabled(true);
alphaState.setSrcFunction(AlphaState.SB_SRC_ALPHA);
alphaState.setDstFunction(AlphaState.DB_ONE_MINUS_SRC_ALPHA);
alphaState.setTestEnabled(true);
alphaState.setTestFunction(AlphaState.TF_GREATER);
alphaState.setEnabled(true);

rootNode = this.getRootNode();
rootNode.setCullMode(Spatial.CULL_NEVER);
rootNode.setLightCombineMode(LightState.OFF);

/* Add the minimap camera */
   
    tRenderer = DisplaySystem.getDisplaySystem().createTextureRenderer(256, 256, TextureRenderer.RENDER_TEXTURE_2D);
    camNode = new CameraNode("Camera Node", tRenderer.getCamera());
    camNode.setLocalTranslation(new Vector3f(0.0f, 50.0f, -50.0f));
    camNode.updateGeometricState(0, true);
   
    DirectionalLight am = new DirectionalLight();
    am.setDiffuse(new ColorRGBA(0.0f, 1.0f, 0.0f, 1.0f));
    am.setAmbient(new ColorRGBA(0.5f, 0.5f, 0.5f, 1.0f));
    am.setDirection(new Vector3f(1.0f, 0.0f, 0.0f));
       
    LightState state = DisplaySystem.getDisplaySystem().getRenderer().createLightState();
    state.setEnabled(true);
   
    LightNode cameraLight = new LightNode("Camera Light", state);
   
    camNode.attachChild(cameraLight);
     
    CullState cs = DisplaySystem.getDisplaySystem().getRenderer().createCullState();
    cs.setCullMode(CullState.CS_BACK);
    cs.setEnabled(true);
    rootNode.setRenderState(cs);
   
    rootNode.attachChild(camNode);
   
    // Create quads for display
    Node monitorNode = new Node("Monitor Node");
    Quad quad = new Quad("Monitor");
    quad.initialize(3, 3);
    quad.setLocalTranslation(new Vector3f(3.75f, 52.5f, 90));
    monitorNode.attachChild(quad);

    Quad quad2 = new Quad("Monitor");
    quad2.initialize(3.4f, 3.4f);
    quad2.setLocalTranslation(new Vector3f(3.95f, 52.6f, 89.5f));
    monitorNode.attachChild(quad2);

    // Setup our params for the depth buffer
    ZBufferState buf = DisplaySystem.getDisplaySystem().getRenderer().createZBufferState();
    buf.setEnabled(true);
    buf.setFunction(ZBufferState.CF_LEQUAL);

    monitorNode.setRenderState(buf);

    // Create a texture for the quads
    // Ok, now lets create the Texture object that our scene will be rendered to.
    tRenderer.setBackgroundColor(new ColorRGBA(0f, 0f, 0f, 1f));
    Texture fakeTex = new Texture();
    fakeTex.setRTTSource(Texture.RTT_SOURCE_RGBA);
    tRenderer.setupTexture(fakeTex);
    TextureState screen = DisplaySystem.getDisplaySystem().getRenderer().createTextureState();
    screen.setTexture(fakeTex);
    screen.setEnabled(true);
    quad.setRenderState(screen);

    monitorNode.updateGeometricState(0.0f, true);
    monitorNode.updateRenderState();
    monitorNode.setLightCombineMode(LightState.OFF);
    rootNode.attachChild(monitorNode);
   
    System.out.println("Done MM");
}
}

Is the StandardGame already running ( standardGame.start()) when the MiniMap constructor is called?



the .get() Method waits for the thread to return, but that works only if the Opengl thread is already running of course.