Add to rootNode from outside SimpleGame class

I would like to dynamically add/remove spatials to the scene from an outside class. Something like…



My SimpleGame class…


//GraphicsLayer.java
public class GraphicsLayer extends SimpleGame {
   private static final Logger logger = Logger.getLogger(GraphicsLayer.class
         .getName());
   
   public GraphicsLayer() {
      this.setDialogBehaviour(2);
   }

   protected void simpleUpdate() {
   }

   protected void simpleInitGame() {
      // need a name for our project...
      display.setTitle("Name of our project...");
   }
   
   public Node getRootNode() {
      return rootNode;
   }
}



My controlling class...


//MainFile.java
public class Main {
   public static void main(String[] args){
      GraphicsLayer gl = new GraphicsLayer();
      gl.start();

      gl.getRootNode().attachChild(new Sphere("name of my sphere", 63, 50, 1));
   }
}



But nothing gets rendered to the scene when I run my main class -- can something like this be done or must I only add spatials in the extended SimpleGame class that I called GraphicsLayer?

SimpleGame is not MultiThreaded, so your call to attach the spehere, gets executed only after SimpleGame ends :).


gl.start();
gl.getRootNode().attachChild(new Sphere("name of my sphere", 63, 50, 1));



After calling start(), SimpleGame will remain in its Game Loop and calling only simpleGame.update() / render().
So any modification need to be initiated from the SimpleGame.update() Method.

Might be of interest: StandardGame and GameStates

Ah, I forgot about this – thanks a lot!

OK, I figured out how to accomplish this (in case anyone cares). You just have to start the class which extends simpleGame as a separate thread…



// Main.java
public class Main {
   
   public static GraphicsLayer gl;
   
   public static void main(String[] args) throws InterruptedException{
      gl = new GraphicsLayer();
      
      Thread t = new Thread() {
         public void run() {
            
            gl.start();
         }
      };
      t.start();

      Thread.sleep(10000);
      gl.getRootNode().attachChild(new Sphere("Name of My Sphere", 63, 50, 1));
   }
}



You have to put some sort of delay before you start adding/removing from the rootNode because SimpleGame hasn't fully started yet. I remembered trying this without the Thread.sleep() and I could not figure out why this was not working. Also, don't forget to update the renderState after you attach a child since otherwise you will just get a sphere or an object with the default text texture wrapped around it.

Actually, you might want to set a boolean to see if simpleGame is running.  Then put your node creation into a loop which sleeps for a couple of milliseconds and exits the loop once finished creating the node.

I am not sure if attaching, removing scene elements in a separate thread is a good idea.

Because just at the moment, you add or remove a element, the scene graph might be traversed, and then you'll get an index out of bounds exception or worse.



Additionally the MultiThreading thing will lead to problems sooner or later, because all OpenGL relevant calls (calls to the GL11 and similar Classes need to be done from the OpenGL thread. That means you need to be careful what you do outside of the main thread. (but this problem can be solved with GameTasks / GameTaskQueueManager)



Maybe you want to take a look at GameStates. GameStates will help you organize your GameLogic in seperate 'modules' which can be aded removed or enabled/disabled independently.

Because just at the moment, you add or remove a element, the scene graph might be traversed, and then you'll get an index out of bounds exception or worse.

Yeah I was thinking the same thing, also using locks to safeguard the information would probably not be a good idea.  Could lead to horrible frame rates....

You might want to consider using StandardGame instead of rewriting all the multi-threaded and synchronization logic of a game.



The migration is fairly simple, and painless assuming you have read a couple of Wiki articles.

Thanks for all of the help – I am impressed with all of the expertise here. I am now using StandardGame and creating GameStates instead of doing things the old way. I certainly did start to run into problems with GL11, especially when I tried to create new JMEDesktops. I found that there is a JMEDesktopState in the repos and will use that instead of trying to attach a JMEDesktop to the rootNode.



Any other advice in terms of threading and using GameStates? I read both of DarkFrog's articles…

http://jmonkeyengine.com/wiki/doku.php?id=simplegame_to_standardgame&s=standardgame

http://www.jmonkeyengine.com/wiki/doku.php?id=standardgame_gamestates_and_multithreading_a_new_way_of_thinking



but am still confused about the difference between StandardGame and BaseGame. How are these different in terms of using GameStates and also what is with DebugGameState? By the name I gather that we are only supposed to use DebugGameState temporarily and sub it with something more specific – much like migrating from SimpleGame to StandardGame?



Thanks for all of the help!

Also, whenever you might want to alter the scene outside of a gamestate be sure to read "GameTasks and GameTaskQueue" in the first link you provided.



Using this technique will make sure your changes get added at a safe point in the openGL thread.





An example when you would want to change the scene outside of a gamestate is when you have a thread that listenens for network connections and creates a character when a connection is being made.


DebugGameState is there to provide (most) functionality from SimpleGame… In other words, it has simple key/mouse navigation, 'n', 't', 'l' for normals, wire-frame and lights resp. It is to provide an almost seamless change from SimpleGame to StandardGame.



StandardGame uses GamseStates as you might have already noticed… The idea is that StandardGames manages the GL-Thread itself, and creates and also maintains the GameQueue and GameStatesManager… There are also solutions for using different render passes with it.



Al in all, a nice piece of software.  :wink:

duenez said:

Al in all, a nice piece of software.  ;)


Agreed. Very impressed.