[Solved, btw] Is it possible to create multiple windows?

I was hoping to create some sort of console for my project, and I wondered if I could create multiple instances/windows of the SimpleApplication.

I have tested both using Swing and creating a second SimpleApplication, and both don’t work.
Is LWJGL still limiting this?

Do you mean ONE big application/window with several instances of SimpleApplication or do you mean somehing like start an application 3 times, so that you have 3 windows / instances ???

No, like you have your standard game, you press a key, ano another, new window pops up next to the original.

Not starting the same app multiple times.

I wonder how Blender does this. They allow multiple windows (press SHIFT on the title of a window and use Drag+Drop to create a clone of that window which you can move around on your virtual desktop).
Do they start multiple processes or do they create multiple render windows from the same process.
Actually an interesting question this is… :alien: (there was no Yoda-smiley available) :chimpanzee_wink:

Try this link to this site.

1 Like

Holy sh*t it works! I did not expect that!
Thank you for your answer.

You copy-pasted that magic code from 2006 and it worked?

Would be nice to have an example code snippet in the wiki (one for LWJGL and one for JOGL).
Also a simple swing app in the Test projects would be cool.

Can you post some code here so that others can add this?

I just added the line
settings.setRenderer("JOGL"); and it worked.

3 Likes

So many answers…
Glad I could help. I haven’t implemented that yet, cause i’m working on other things. But, I might do that today just so I have some progress.
Yes, the link from 2006. I couldn’t imagine it being broken.
It would be nice to have that added to the tutorials.
Are you working on 3D navigation next? I can do that too.

Wow! You got that done in a day! I’m finally getting around to implementing multiple windows…
Where did you find JMECanvasImplementor, DisplaySystem, Anchor and com.jme.uti.Timer, etc…?
I added jogamp-all-platforms as well as jogl-java-src.zip to my project and I stil can’t find them.

Ah, yes.

I still haven’t created a good application that runs multiple windows. I do have 2 basics, whichor might end well. I was trying to do this as an experiment, and have not fully finished the apps.

  1. Use Jogl or so as your renderer. This way, you get no exception. However, the original flycam completely spaces out, so you should write your own. Keyboard might also space out, but probably not.
  2. Create 2 apps (why didn’t I think of this before). After some personal prototyping I accidentally found another solution: Create a second jar and run it from another jar. This way you have control over System.in, System.out and System.err. You can send messages like any other stream and read them every update/tick. Again, I have not fully tested this, so you could encounter loads of problems (especially in communication).

There is also the approach where you render to texture and then copy this texture to BufferedImage. Then you can draw as many windows as you want.

Hummm, Leo. You may have something there. In the LwjglRenderer.java file, there is talk about the RenderBuffer. But, can you explain how to draw something to it and get it before it gets copied to the wrong spot? That said… asked…

I had another approach. Java3D used a View object to coordinate cameras and Canvases. I was wondering if we could do something similar.

public class JMEView {
    private Camera camera;
    private Canvas  canvas;
    
    JMEView(Camera camera, Canvas canvas){
        this.camera = camera;
        this.canvas = canvas;
    }
    
    
    public Camera getCamera(){
        return(camera);
    }
    
    
    public Canvas getCanvas(){
        return(canvas);
    }
    
    
    //if you can't resize the canvas, change it
    public void changeCanvas(Canvas canvas){
        this.canvas = canvas;
    }
}
public class JMEViewManager {
    private ArrayList<JMEView> list = new ArrayList();
    
    JMEViewManager(){
    }
    
    
    //add default camera and default canvas (if already created)
    JMEViewManager(Camera camera, Canvas canvas){
        JMEView view = new JMEView(camera, canvas);
        list.add(view);
    }
    
/*
    public void addJMEView(JMEView view){
        list.add(view);
    }
*/
    
    public JMEView getNewJMEView(){
        JMEView view = new JMEView(new Camera(), new Canvas());
        list.add(view);
        
        return(view);
    }
    
    
    public Iterator getIterator(){
        return (list.iterator());
    }
    
    
    @Override
    public void finalize(){
        list.clear();
    }
    
    
}

and then…

    public void renderTest(Spatial scene, RenderManager rm){//scene is rootNode, 
        Renderer renderer = rm.getRenderer();
        Iterator<JMEView> it = viewManager.getIterator();
        
        while (it.hasNext()){
            JMEView view = it.next();
            Camera camera = view.getCamera();
            Canvas canvas = view.getCanvas();
            ViewPort viewport = new ViewPort("dummy", camera);
            Graphics g = canvas.getGraphics();

            //then
            //1) can we force JME to render to g?
            //Graphics offscr = offscreenImage.getGraphics();
            
            //2) Image offscreenImage = canvas.createImage(canvas.getWidth(), canvas.getHeight());
            //FrameBuffer fb = new FrameBuffer(canvas.getWidth(), canvas.getHeight(), 1);
            //renderer.setFrameBuffer(fb);
            
            renderer.clearBuffers(true, true, true);
            //some kind of pre-render
            //renderer.draw(rootNode);//what the other guy had - there is no lwjgl renderer.draw();
            rm.renderScene(scene, viewPort);//viewPort has the camera
            //some kind of post-render
            //1) g.drawImage(offscreenImage, 0, 0, null);
            //2) how would you copy a FrameBuffer to a canvas?
            
        }
    }

So, we have access to our Graphics object, How can we hack JME to use the one we want?
I’m still looking into how to copy the FrameBuffer to the canvas.

Oh, you need to add the ViewPort to the JMEView. Then you can adjust its settings (add SceneProcesors) and change to background color, etc. And it holds the camera.

Yes, you can have multiple viewports, but these are in the same window. There is an example in jme how to do render to texture.

Also, if you decide to render to texture and then copy this texture to BufferredImage, you might find yourself not needing any jme window(since you will be eg. using swing). In this case, you can start your application with JmeContext.Type.OffscreenSurface.

Thanks The_Leo.

Um… So… Well…

Also, if you decide to render to texture and then copy this texture to BufferredImage, you might find yourself not needing any jme window(since you will be eg. using swing). In this case, you can start your application with JmeContext.Type.OffscreenSurface.

  1. So, is JME meant to be used in one full screened window? I play an MMORPG (Lord of the Rings Online) so I’m familiar with the concept.
  2. Am I loosing speed by not only using JME?

I have 12 JME/LWJGL classes open and keep running in circles going from one to the other. I’m familiar Applets and and Applet animation cycle (Init, Start, Stop, Run, Update, Paint) and am looking for a place to hook into (run() and paint(g), for example). I implemented the SceneProcessor interface as you suggested, but, I can’t find where to do a render – unless its:
renderManager.renderScene(scene, viewPort);
In which case, I’m close. I call my renderTest() from simpleRender() so it’s ugly and my canvas flickers from red (its background color) and black (not what I have the background color in the ViewPort set to) but, doesn’t draw anything 3D.
3) Can you show me/tell me where the main loop is? I haven’t found it unless it’s in

I had hopes that this might be useful to someone and be incorporated into JME so that someone could use it in one window or many windows. If so, noobs like MisterCavespider and myself, wouldn’t know the difference. We would just go along with all our windows.

@Mipada

  1. Depends on what you are making. You can make single window app or a multiwindowed one.
  2. That depends on your application. Yes it might be slower to render to texture->copy texture to BufferedImage and paint it with Swing. But, does it matter if your app still goes with 60 FPS? Thus, use this approach only when you need it eg. multiple windows.

In the TestRenderToMemory.java updates are handled in simpleUpdate, and rendered texture is copied to memory in postFrame method. If you want to do additional rendering you can extend SimpleApplication’s simpleRender() or SceneProcessor’s postQueue. :chimpanzee_amused:

…or use an app state and hook the appropriate methods there.

Well, I’m getting close.
(MisterCavespider may have been right. You may need to run as many SimpleApplications as you want canvases.)
Again, in my virtual solar system, I’m trying to add cameras/monitors to the ships/cameras I fly around. It would be cool if I can have multiple monitors. So…
My goal is to make (below) work.

public void multiRender(RenderManager defaultRenderManager){
    float tpf = timer.getTimePerFrame() * speed;
    ArrayList list = viewManager.getList();
    for (int i = 0;i < list.size();i++){
        View view = (View)list.get(i);
        view.getRenderManager().render(tpf, false);//has camera and canvas
        view.getViewCanvas().repaint();//maybe not needed
    }
}

To do that, each View needs it’s own RenderManager – which needs it’s own context which has it’s own canvas. I hacked my way through all the Lwjgl stuff and copied/edited them to make my own context and setup the canvas to use the SceneProcessor interface and work offscreen. (It may not have been useful ‘cause with multiple RenderManagers, I don’t need to do anything offscreen.) I went back to JmeSystem.newContext(…). Now, when I add my canvases, I get:

Oct 03, 2016 6:00:16 PM com.jme3.app.Application handleError
SEVERE: Uncaught exception thrown in Thread[LWJGL Renderer Thread,6,main]
java.lang.RuntimeException: No OpenGL context found in the current thread.
    at org.lwjgl.opengl.GLContext.getCapabilities(GLContext.java:124)
    at org.lwjgl.opengl.GL11.glGetError(GL11.java:1289)
    at org.lwjgl.opengl.Util.checkGLError(Util.java:57)
    at org.lwjgl.opengl.WindowsContextImplementation.setSwapInterval(WindowsContextImplementation.java:113)
    at org.lwjgl.opengl.ContextGL.setSwapInterval(ContextGL.java:232)
    at org.lwjgl.opengl.DrawableGL.setSwapInterval(DrawableGL.java:86)
    at org.lwjgl.opengl.Display.setSwapInterval(Display.java:1120)
    at org.lwjgl.opengl.Display.setVSyncEnabled(Display.java:1133)
    at com.jme3.system.lwjgl.LwjglCanvas.createContext(LwjglCanvas.java:462)
    at com.jme3.system.lwjgl.LwjglCanvas.restoreCanvas(LwjglCanvas.java:267)
    at com.jme3.system.lwjgl.LwjglCanvas.runLoop(LwjglCanvas.java:196)
    at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:228)
    at java.lang.Thread.run(Thread.java:745)

I’ll look through Application.java and LegacyApplication.java to see if I can find the answer – but, if you have an idea, I’d appreciate the help.

I have an idea, but not an answer:

See if it is possible with lwjgl only.
if it is possible, then see how you can implement that into jME.

If not, you will have to do considerably more work.
Maybe you try to make multiple jars (completely different programs), for the monitor and for the game.
You can connect them with a server (e.g. make the game a server and let monitors be the client).

Good luck anyway