JME and Spag

Nala-Naj



Need help as I am stuck on this. Tried to get Spag and JME working following your code. I made the following assumptions:





JME handles the rendering for both JME and Spag

Spags rendering happens inside the render method of the JME

We do all the rendering in the JME’s render method (the main rendering loop)



Then cretaed a dialog in created a dialog in the createWin(), which was initiated in the initGame() and the usual setting of the mouse and keyboard - see code below:



import org.lwjgl.Display;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.*;
import org.lwjgl.vector.Vector3f;



import java.io.FileInputStream;
import com.shavenpuppy.jglib.Resources;
import com.shavenpuppy.jglib.AbsMouse;
import com.shavenpuppy.jglib.sprites.SpriteImage;
import net.puppygames.gui.*;

import jme.controller.*;
import jme.system.*;
import jme.locale.*;
import jme.AbstractGame;
import jme.system.DisplaySystem;
import jme.geometry.hud.text.Font2D;
import jme.utility.*;
import jme.texture.*;
import jme.geometry.primitive.*;
import jme.entity.*;
import jme.entity.camera.*;
import jme.entity.effects.*;
import jme.world.World;
import jme.geometry.hud.*;
import jme.locale.external.data.*;
import jme.locale.external.*;
import jme.lighting.*;
import jme.locale.external.feature.*;
import jme.math.*;
import jme.geometry.*;
import jme.geometry.model.ms.MilkshapeModel;



public class SpagTest04 extends AbstractGame {


   private SimpleLocale myLocale = null;
   private Font2D font;
   private Timer timer = null;
   Entity e7 = null;
   private World world = null;
   private Camera camera;
   private TestController cc;



   /**
   * The width of the screen or window.
   */
   private static int width = 640;

   /**
   * The height of the screen or window.
   */
   private static int height = 480;

//SPG
//   private net.puppygames.gui.Window w = null;   
   private net.puppygames.gui.Dialog w = null;   
   private static boolean finished = false;

   public void createWin()
   {
      try
      {
         Resources.load(new FileInputStream("resources.data"));
         Resources.manage();
      } catch (Exception e)
      {}
//        w = new net.puppygames.gui.Window("map at a glance");
//        w.setLocation(0, 0);

        w = new net.puppygames.gui.Dialog("map at a glance");
       w.centre();       
        w.setSize(250, 250);

//        TextArea text = new TextArea("This is where a scaled down version of the map will go.  The mouse cursor will turn into a box and allow you to quickly jump to anywhere on the map.");
//        text.setSize(230, 200);
//        text.setLocation(15, 80);
//        w.addChild(text);
        w.open();
   }
      

   public static void main(String[] args)
   {
      SpagTest04 app = new SpagTest04();
      app.start();
   }


   public SpagTest04()
   {
      font = null;
      camera = null;
      cc = null;
   }

   protected void update()
   {
       if(!cc.update(timer.getFrameRate()))
            finish();
       
       world.update(10F / timer.getFrameRate());
       timer.update(); 
   }

   protected void render()
   {
      GL.glClear(16640);
      GL.glLoadIdentity();
     cc.render(); //render after each key/mouse movement
     world.render(); //render entities & then locale
//SPG   
      AbsMouse.poll();
      Keyboard.poll();
      Keyboard.read();
      mainLoop();
      Interface.tick();
      Interface.render();
      org.lwjgl.opengl.Window.update();
      org.lwjgl.opengl.Window.paint();
   }

   private void initCamera()
   {
      .............
      .............
   }

   protected void initDisplay()
   {
      //create the window
      DisplaySystem.createDisplaySystem(640,480,16,60,false,"GameTest");
   }

   protected void initGL()
   {
     GL.glShadeModel(7425);
      //Define the clear color
      GL.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
     GL.glClearDepth(1.0D);
     GL.glEnable(2929);
     GL.glDepthFunc(GL.GL_LEQUAL);
      GL.glMatrixMode(5889);
      GL.glLoadIdentity();
      // Calculate The Aspect Ratio Of The Window
      GLU.gluPerspective(
         45.0f,
         (float)Display.getWidth() / (float)Display.getHeight(),
         0.01f,
         750.0f);
      GL.glMatrixMode(5888);
      GL.glHint(3152, 4354);
     GL.glBlendFunc(770, 1);
     DisplaySystem.getDisplaySystem().cullMode(1029, true);

   }

   protected void reinit()
   {
      Keyboard.destroy();
      Mouse.destroy();

      try
        {
          Keyboard.create();
            Mouse.create();
            initGL();
         initTimer();
         font = new Font2D("font.png");
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
//SPG   
        try
        {
         Interface.init(width, height, width, height);
        } catch(Exception e)
        {}
   }

   protected void initSystem()
   {
        initDisplay();
        initGL();
      initCamera();
      initTimer();
//SPG      
        try
        {
         Interface.init(width, height, width, height);
        } catch(Exception e)
        {}

      try
      {
           Mouse.create();
             AbsMouse.setSensitivity(8);
             AbsMouse.setSize(width, height);
           AbsMouse.setPosition(width / 2, height / 2);

             Keyboard.create();
             Keyboard.enableBuffer();   
      } catch(Exception e)
      {}
   }

   protected void initGame()
   {
      .............
      .............
      createWin();
   }
   
   private void initTimer()
   {
        timer = Timer.getTimer();
   }

   protected void cleanup()
   {
      .............
      .............
   }


    private final static void mainLoop()
    {
        processMouse();
        processKeyboard();
        processWindow();
    }

    /**
     * Process keyboard events.
     */
    private final static void processKeyboard()
   {
      .............
      .............
    }

    /**
     * Process mouse events.
     */
    private final static void processMouse()
   {
      .............
      .............
    }

    /**
     * Process window events.
     */
    private final static void processWindow() {
        if (org.lwjgl.opengl.Window.isCloseRequested()) {
            finished = true;
        }
    }


}



and compiled the code. When I run it I get :


java.lang.ArithmeticException: / by zero
        at net.puppygames.gui.Component.render(Component.java:1259)
        at net.puppygames.gui.Interface.render(Interface.java:570)
        at SpagTest04.render(SpagTest04.java:126)
        at jme.AbstractGame.start(Unknown Source)
        at SpagTest04.main(SpagTest04.java:94)
java.lang.NullPointerException
        at net.puppygames.gui.Interface.render(Interface.java:576)
        at SpagTest04.render(SpagTest04.java:126)
        at jme.AbstractGame.start(Unknown Source)
        at SpagTest04.main(SpagTest04.java:94)



I am not sure what is going on and I am not even sure if I am doing the right thing.

Any idea what is going on :(

I’ve had the same sort of problems. I’m not quite sure how to manage the two different renderers. Can you call Inteface.tick() & render() in the JME render() method? I can’t think why you can’t render spag stuff in JME - both the world & the mouse/keyboard controllers are renderered separtely in JME so why not GUI stuff?



Conceptually is this correct & why?

Well, I have never used the Spaghetti code, nor have I looked closely at it. However, it was written to sit on top of LWJGL (written by the same person). So, there is no reason that it shouldn’t work.



I would suggest written a minimal jME class that creates the window but doesn’t render any objects. See if you can get the speghetti code working with that, then if you get it working, add other render objects.

I think I’ve solved the rendering problem - well spag renders in a blank JME window now. I was having a problem with the spag Interface class. Instead of using my build of the spag/spgl.jar I used nala-naj’s which has everything, including the tools. This leads me to believe that the build file I used or the source code I built from had some errors & nala-naj fixed them before posting his combined jar over at the puppygames forum.



Good stuff naj! :slight_smile:

Hmmmmmm, having problems rendering a JME world with spag now.



I’ve been thinking about the static Interface class in spag, presumably this could be used to render JME worlds if the world was placed in a separate class extending a Spag dialog/window. Then this dialog/window could be rendered in the render() method in a class extending AbstractGame using Interface.render().



The spag dialog class does have some render methods to add to.





Does this sound logical?

Sounds plausible, take the source and play around.



However, I should mention that the new jme does not directly access LWJGL and it uses a renderer to handle it’s rendering. No longer do invidual entities render themselves.



This possibly will throw in a wrench with how the speghetti code works. Like I said, I haven’t looked at it yet.

Not sure if its a good idea for Spa to do the rendering for JME. I think we should keep JME to do its own rendering and use Spag for dialog boxes. We have some working (sort of) code which has worked with JME and Spag (thanks to both Mojo and Nala-Naj) which shows the principle.



Based on my understanding 8) spag’s Interface class seems to do the rendering for the dialogs created in Spag. Of course each dialog can have childrens like buttons, lables etc, but it seems that Interface class knows how to render them and more importantly knows all dialogs which need to be renered (still a bit of a mystry to me). As Interface is a 2D rendering engine (using the spgl) and uses the LWJGL, then it may not a be good idea to render everything using it.



The only thing which remains is how to handle keyboard and mouse events. As both JME and Spag seem (as far as I can see) to use the same library and because they both run on the same JVM, then I guess there should not be a problem (hope I am not showing too much ignorance here). I guess Mojo knows more about this than I do.



We still need to do the test using buttons and navigating in the JME world. Any comments??

I really don’t know what input I can give on the subject. I can just say that the replacement core does not have any knowledge of rendering APIs, so if you use Speghetti with it (if you are able to work through these issues) you will be using two products with two completely different design paradigms.



A possibility of the future would be to make a generic jme GUI system that provides the abstraction that then uses Speghetti at the low level rendering. But I haven’t yet thought that far.

I have to agree with that. As you rightly said, we will be using two different products and the integration is a bit of a bummer as I dont really understand how Spag works. I am really looking at it as s hort term solution and if we get it to work thats all it’ll be.

It would be great if JME offered the sort of thing we are after at some stage later. :wink: .

For those of you who are interested this is the code we used:



import org.lwjgl.Display;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.*;
import org.lwjgl.vector.Vector3f;

import java.io.FileInputStream;
import com.shavenpuppy.jglib.Resources;
import com.shavenpuppy.jglib.AbsMouse;
import com.shavenpuppy.jglib.sprites.SpriteImage;
import net.puppygames.gui.*;

import jme.controller.*;
import jme.system.*;
import jme.locale.*;
import jme.AbstractGame;
import jme.system.DisplaySystem;
import jme.geometry.hud.text.Font2D;
import jme.utility.*;
import jme.texture.*;
import jme.geometry.primitive.*;
import jme.entity.*;
import jme.entity.camera.*;
import jme.entity.effects.*;
import jme.world.World;
import jme.geometry.hud.*;
import jme.locale.external.data.*;
import jme.locale.external.*;
import jme.lighting.*;
import jme.locale.external.feature.*;
import jme.math.*;
import jme.geometry.*;
import jme.geometry.model.ms.MilkshapeModel;



public class SpagTest04 extends AbstractGame {


   private SimpleLocale myLocale = null;
   private Font2D font;
   private Timer timer = null;
   Entity e7 = null;
   private World world = null;
   private Camera camera;
   private TestController cc;



   /**
   * The width of the screen or window.
   */
   private static int width = 640;

   /**
   * The height of the screen or window.
   */
   private static int height = 480;

//SPG
   private net.puppygames.gui.Window w = null;   
//   private net.puppygames.gui.Dialog w = null;   
   private static boolean finished = false;

   public void createWin() throws Exception
   {
        final net.puppygames.gui.Window w = new net.puppygames.gui.Window("map at a glance");
        w.setLocation(0, 0);
        w.setSize(250, 250);

        TextArea text = new TextArea("This is where a scaled down version of the map will go.  The mouse cursor will turn into a box and allow you to quickly jump to anywhere on the map.");
        text.setSize(230, 200);
        text.setLocation(15, 80);
        w.addChild(text);

        CommandButton helpButton = new CommandButton("Help");
        helpButton.setSize(100, 20);
        helpButton.setLocation(75, 30);
        helpButton.addCommandButtonListener(new CommandButtonListener() {
            public boolean selected(CommandButton cb) {
                try {
                    MessageBox message = new MessageBox("Lame Help", "Use the arrow keys or move the mouse to the edges of the screen to scroll the map.  Press <ESC> to quit this demo.", 0, MessageBox.OK_DIALOG, null);
                    message.setVisible(true);
                } catch (Exception e) {}
                return false;
            }

        });
        w.addChild(helpButton);

        w.setDraggable(true);
        w.open();
   }
      

   public static void main(String[] args)
   {
      SpagTest04 app = new SpagTest04();
      app.start();
   }


   public SpagTest04()
   {

   }

   protected void update()
   {
       timer.update(); 
   }

   protected void render()
   {
      GL.glClear(16640);
      GL.glLoadIdentity();
//SPG   
      AbsMouse.poll();
      Keyboard.poll();
      Keyboard.read();
      mainLoop();
      Interface.tick();
      Interface.render();
      try
      {
         Resources.manage();
      } catch (Exception e)
      {}
      
//      org.lwjgl.opengl.Window.update();
//      org.lwjgl.opengl.Window.paint();
   }

   private void initCamera()
   {
       //2nd, 3rd & 4th values in camera constructoe set its start position
        camera = new Camera(1, 0, 25F, -100F, 0.0F, 0.0F, 0.0F, 0.0F, 1.0F, 0.0F);
      camera.getFrustum().setBuffer(3F);
        cc = new TestController(camera, this);
   }

   protected void initDisplay()
   {
      //create the window
      DisplaySystem.createDisplaySystem(640,480,16,60,false,"GameTest");
   }

   protected void initGL()
   {
     GL.glShadeModel(7425);
      //Define the clear color
      GL.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
     GL.glClearDepth(1.0D);
     GL.glEnable(2929);
     GL.glDepthFunc(GL.GL_LEQUAL);
      GL.glMatrixMode(5889);
      GL.glLoadIdentity();
      // Calculate The Aspect Ratio Of The Window
      GLU.gluPerspective(
         45.0f,
         (float)Display.getWidth() / (float)Display.getHeight(),
         0.01f,
         750.0f);
      GL.glMatrixMode(5888);
      GL.glHint(3152, 4354);
     GL.glBlendFunc(770, 1);
     DisplaySystem.getDisplaySystem().cullMode(1029, true);

   }

   protected void reinit()
   {
      Keyboard.destroy();
      Mouse.destroy();

      try
        {
          Keyboard.create();
            Mouse.create();
            initGL();
         initTimer();
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
   }

   protected void initSystem()
   {
        initDisplay();
        initGL();
//SPG      
      try
      {
         Resources.load(new FileInputStream("resources.data"));
         Interface.init(640, 480, 640, 480);
        }
        catch(Exception e)
        {
           System.out.println("Interface problems " + e.toString() );
        }
      initCamera();
      initTimer();

      try
      {
           Mouse.create();
             AbsMouse.setSensitivity(8);
             AbsMouse.setSize(width, height);
           AbsMouse.setPosition(width / 2, height / 2);
             Keyboard.create();
             Keyboard.enableBuffer();   
      } catch(Exception e)
      {
           System.out.println("Interface problems " + e.toString() );
      }
   }

   protected void initGame()
   {
      //put a locale at the center with a length of 100.
      .....
      .....
//SPG
      try
      {
         createWin();
      } catch(Exception e)
      {}
   }
   
   private void initTimer()
   {
        timer = Timer.getTimer();
   }

   protected void cleanup()
   {
      Keyboard.destroy();
       Mouse.destroy();
       //clean up the OpenGL resources
       org.lwjgl.opengl.Window.destroy();
      TextureManager.reset();
   }


    private final static void mainLoop()
    {
        processMouse();
        processKeyboard();
        processWindow();
    }

    /**
     * Process keyboard events.
     */
    private final static void processKeyboard() {
      .....
      .....
    }

    /**
     * Process mouse events.
     */
    private final static void processMouse()
    {
      .....
      .....
    }

    /**
     * Process window events.
     */
    private final static void processWindow() {
        if (org.lwjgl.opengl.Window.isCloseRequested()) {
            finished = true;
        }
    }


}



The theory is very simple. JME controls the main rendering loop in the render() method. createWin creates the Spag windows and then it is called in initGame() and basically puts the windows on the screen. In here I am not puting any JME enteties. This code works as long as you are rendering a JME world.

Next stage is to put the JME world in the program and test it.
A seperate point, I have come across some classes in the geometry.hud component, button, frame, panel etc but they are empty. How easy (or difficult) is it to put the code in to create a 2D window which sits on top


I don't know, how long would it take you? :D

All that is the framework that was going to be started for the GUI system. However, I abandoned it, because I had a lot I wanted to get done, and that was a little lower on my priority list then other things (namely, rebuilding the core system).

As far as the world not rendering when the speghetti code... Only thing I can think of off hand (and something worth checking) is when Speghetti is rendered it's probably being put into Ortho mode (glOrtho), it would have to reset itself to go back to projection mode. It was written for Alien Flux, which is a 2D game and perhaps never uses projection mode. So maybe it's always in Ortho mode?

For example, if I wanted to display 2D GUI panels I'd do something like:



//Save 3D projection and go into 2D for GUI
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(width, 0, height, -1, 1);
glMatrixModel(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();


//DRAW GUI STUFF


//Restore 3D
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();



perhaps the saving/restore of the 3D world view is not being done?

Again just a guess.

mojo,



I think you could very well be right, the static Interface class in spag which does all the rendering of the GUI does set itself to orthographic mode. I’m fairly certain from memory that it doesn’t/won’t switch back.



Probably something for our code to do rather than messing around with princec’s spag classes?



Something to check in the morning - thanks for the suggestion. :slight_smile:

mojo,



Your a genius! I really ought to learn some OpenGL I think. I sort of knew the problem may of been this but my solution in retrospect was extremely stupid.



I’ve got them rendering (the world & spag) together now, now I going to work out some sort of ordering so I can decide when I want the GUI on top or invisible/gone.



Thanks again! :smiley:

Good, glad I could help. You should post a screen shot. I’m curious to see what it looks like.

I’m having probs with my webspace at the moment - I’ll email & you can post if you like.



Once we get some functionality working I’m sure we’ll be able to email you or post some more code here.

man, i have been out of touch for a long time! …and things are not looking any less hectic for the short term. it looks like you guys figured out the spaghetti stuff though as i saw the screen shot on the front page… looks familar :wink:



jme is really looking sweet… since i havent had a chance to work on my game at all in the past month or two (i i’ve forgotten just about everything i have done), i think i am going to start playing with jme when i get back into it… i’d like to be able to contribute back a little.



ps: if you want my input on something again in the future and i havent been here in awhile, feel free to send me a private message (i think those send real email to notify ya) and tell me to get my ass over here :slight_smile:

Welcome back Nala-naj. That’d be real nice if you wanted to join up and start contributing. I’m still taking care of all the boring under-the-covers stuff, so there will be plenty left for you to contribute.



I’m not sure if private messages send out e-mail. hmmm.

that was me… my cookies are gone since my last visit too :frowning: