Cannot render outside of render() ?

Started by gdboling, February 04, 2004, 15:58:50

Previous topic - Next topic

gdboling

I modified one of the NeHe tutorials to see if I could do something that has prevented me from using ANY Java OpenGl wrapper at all.  I am trying to render some graphics outside of the typical render() method.  So I check for a keyboard event and if I press the A button, I want to add a quad onto the screen.  And it doesn't work.  So I am wondering if this is even possible.  Below is my code

import org.lwjgl.*;
import org.lwjgl.opengl.*;
import org.lwjgl.input.*;

public class TestMain
{
	static
	{
		try
		{
			Window.create("Test Window", 50, 50, 640, 480, 16, 0, 8, 0);
		}
		catch(Exception e)
		{
			System.exit(1);
		}
	}
	
	private static boolean finished;
	
	private TestMain()
	{
	}
	
	public static void main(String[] args)
	{
		try
		{
			init();
			while(!finished)
			{
				Keyboard.poll();
				mainLoop();
				render();
				Window.update();
				Window.paint();
			}
			
		}
		catch(Throwable t)
		{
			t.printStackTrace();
		}
		finally
		{
			cleanup();
		}
	}
	
	private static void init() throws Exception
	{
		Keyboard.create();
		GL.glShadeModel(GL.GL_SMOOTH);
	    GL.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
	    GL.glClearDepth(1.0);
	    GL.glEnable(GL.GL_DEPTH_TEST);
	    GL.glDepthFunc(GL.GL_LEQUAL);
	
	    GL.glMatrixMode(GL.GL_PROJECTION);
	    GL.glLoadIdentity();
	
	    GLU.gluPerspective(
	      45.0f,
	      (float) Display.getWidth() / (float) Display.getHeight(),
	      0.1f,
	      100.0f);
	    GL.glMatrixMode(GL.GL_MODELVIEW);
	
	    GL.glHint(GL.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_NICEST);
    
    }
	
	private static void mainLoop()
	{
		processKeyboard();
		processWindow();
	}
	
	private static void render()
	{
		GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
	    GL.glLoadIdentity();     
	    GL.glTranslatef(-1.5f, 0.0f, -6.0f);
	   
	
	    GL.glBegin(GL.GL_TRIANGLES);
	    GL.glVertex3f(0.0f, 1.0f, 0.0f);
	    GL.glVertex3f(-1.0f, -1.0f, 0.0f);
	    GL.glVertex3f(1.0f, -1.0f, 0.0f);
	    GL.glEnd();
	}
	
	private static void processKeyboard()
	{
		if (Keyboard.isKeyDown(Keyboard.KEY_ESCAPE))
		{
			finished = true;
		}
		
		if (Keyboard.isKeyDown(Keyboard.KEY_A))
		{
			System.out.println ("Hit the A");
			GL.glTranslatef(3.0f, 0.0f, 0.0f);	
		    GL.glBegin(GL.GL_QUADS);
		    GL.glVertex3f(-1.0f, 1.0f, 0.0f);
		    GL.glVertex3f(1.0f, 1.0f, 0.0f);
		    GL.glVertex3f(1.0f, -1.0f, 0.0f);
		    GL.glVertex3f(-1.0f, -1.0f, 0.0f);
		    GL.glEnd();
	    
		}
      
	}
	
	private static void processWindow() 
	{
    	if (Window.isCloseRequested()) 
    	{
      		finished = true;
    	}
  	}
  	
  	private static void cleanup() 
  	{
    	Keyboard.destroy();
    	Window.destroy();
  	}
	
	
}


Thanks.

Matzon

well, you can, but it's a somewhat bad habit.

Your problem is that you render your quad in the processKeyboard method, and THEN do a render(); which starts off with deleting everything:
GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);

gdboling

Why is this a bad habit?  I don't want to fill my render() method with method calls and update checks to see if I need to redraw something or not.  This is why I quit looking at gl4java and JOGL.

I realise my mistake in that I am clearing everything.  But I am still curious as to why it is a bad habit to render outside of render()?

Thanks.

gdboling

I guess part of the problem is that I am in a constant Animation loop.  Which is good for games and I know LWJGL is designed specifically for gaming.

I suppose if I turn off the loop and just call Window.update()/Window.paint() when I need to issue an update, it would solve my problem.

I will give that a shot.

vilm

Quote from: "gdboling"I guess part of the problem is that I am in a constant Animation loop.  Which is good for games and I know LWJGL is designed specifically for gaming.

being in an animation loop isn't anything to do with LWJGL, just the example you've posted.  :)   like you say, you could remove the loop and just update the screen when required...

gdboling

Ok, I have modified my code so that render() is not called from within the loop.  I realized that appearntly Window.update() and Window.paint() have to be called in some forever loop or you can't drag the Window around the screen.  Strange.  Anyone know why?

Also, when I move the window around, it looks like the GL context shifts slightly to the left and down a bit.  See an example here:



And when I minimize the window and restore it I get a gray screen that cannot be fixed.  See example here:



And here is my code.  Thanks for any help with this.

import org.lwjgl.*;
import org.lwjgl.opengl.*;
import org.lwjgl.input.*;

public class TestMain
{
	static
	{
		try
		{
			Window.create("Test Window", 50, 50, 640, 480, 16, 0, 8, 0);
		}
		catch(Exception e)
		{
			System.exit(1);
		}
	}
	
	private static boolean finished;
	
	private TestMain()
	{
	}
	
	public static void main(String[] args)
	{
		try
		{
			init();
			render();
			while(!finished)
			{
				Keyboard.poll();
				mainLoop();
				Window.update();
				Window.paint();
			}
		
			
		}
		catch(Throwable t)
		{
			t.printStackTrace();
		}
		finally
		{
			cleanup();
		}
	}
	
	private static void init() throws Exception
	{
		Keyboard.create();
		GL.glShadeModel(GL.GL_SMOOTH);
	    GL.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
	    GL.glClearDepth(1.0);
	    GL.glEnable(GL.GL_DEPTH_TEST);
	    GL.glDepthFunc(GL.GL_LEQUAL);
	
	    GL.glMatrixMode(GL.GL_PROJECTION);
	    GL.glLoadIdentity();
	
	    GLU.gluPerspective(
	      45.0f,
	      (float) Display.getWidth() / (float) Display.getHeight(),
	      0.1f,
	      100.0f);
	    GL.glMatrixMode(GL.GL_MODELVIEW);
	
	    GL.glHint(GL.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_NICEST);
	    
    
    }
	
	private static void mainLoop()
	{
		processKeyboard();
		processWindow();
	}
	
	private static void render()
	{
		GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
	    GL.glLoadIdentity();     
	    GL.glTranslatef(-1.5f, 0.0f, -6.0f);
	   
	
	    GL.glBegin(GL.GL_TRIANGLES);
	    GL.glVertex3f(0.0f, 1.0f, 0.0f);
	    GL.glVertex3f(-1.0f, -1.0f, 0.0f);
	    GL.glVertex3f(1.0f, -1.0f, 0.0f);
	    GL.glEnd();
	}
	
	private static void processKeyboard()
	{
		if (Keyboard.isKeyDown(Keyboard.KEY_ESCAPE))
		{
			finished = true;
		}
		
		if (Keyboard.isKeyDown(Keyboard.KEY_A))
		{
		
			GL.glTranslatef(3.0f, 0.0f, 0.0f);	
		    GL.glBegin(GL.GL_QUADS);
		    GL.glVertex3f(-1.0f, 1.0f, 0.0f);
		    GL.glVertex3f(1.0f, 1.0f, 0.0f);
		    GL.glVertex3f(1.0f, -1.0f, 0.0f);
		    GL.glVertex3f(-1.0f, -1.0f, 0.0f);
		    GL.glEnd();
		    Window.update();
		    
	    
		}
      
	}
	
	private static void processWindow() 
	{
    	if (Window.isCloseRequested()) 
    	{
      		finished = true;
    	}
  	}
  	
  	private static void cleanup() 
  	{
    	Keyboard.destroy();
    	Window.destroy();
  	}
	
	
}


Gregg

Matzon

The grey window is because the content has to be redrawn, when it comes back from a minimize. and the only way to check that, is to check with Window.isMinimized() (which you'll need an active thread for).

Regarding movment and such, someone has to check the native message queue (by calling Window.update) - since we don't spawn a thread for that, you have to.

FWIW, *all* applications have at least 1 thread doing either active rendering or input checking. Typical event based applications block when no input is occuring. LWJGL based ones, do not.

Therefore you need to have your main thread continually call Window.update(), Keyboard.poll(), Mouse.poll() (and whatever else you have going) and respond accordingly.

in your case you could do:

while(!finished) {
  Window.update();
  checkForInput();

  // do stuff if needed
  if(/* key pressed or mouse moved */) {
    render();
  }

  Window.paint();
}


or something like that... - not perfect example - just an inspirational post :) - gotta go eat f00d now :))

gdboling

I am doing that.

while(!finished)
    {
	Window.update();
	Keyboard.poll();
	mainLoop();				
	Window.paint();
    }


And then my mainLoop() method is

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


And then those methods do their stuff accordingly.  processKeyboard checks for keyboard commands.  processWindow() does the check to see if the Window is being closed.

Thanks for the info on the minimize issue. I will give that a shot.  Still getting the strange context shift behavior though.

gdboling

And I tried the isMinimized() method.  Doesn't do the trick.  Seems like I should need to update on a isRestored() or isMaximized() method, however there isn't one.  What I have is:

if (Window.isMinimized())
{
	Window.update();
	Window.paint();
}

Matzon

I was going to post something lengthy - then my computer crashed *hard* while pressing A and minimizing. Now my file just contain 2144 of these:
Quote0

wee

but basically it works fine - however your quad code seemed buggy, so I just called render() instead:
import org.lwjgl.*;
import org.lwjgl.opengl.*;
import org.lwjgl.input.*;

public class TestMain {
  static {
    try {
      Window.create("Test Window", 50, 50, 640, 480, 16, 0, 8, 0);
    } catch (Exception e) {
      System.exit(1);
    }
  }

  private static boolean finished;

  private TestMain() {
  }

  public static void main(String[] args) {
    try {
      init();
      while (!finished) {
        Keyboard.poll();
        mainLoop();
        Window.update();
        Window.paint();
      }

    } catch (Throwable t) {
      t.printStackTrace();
    } finally {
      cleanup();
    }
  }

  private static void init() throws Exception {
    Keyboard.create();
    GL11.glShadeModel(GL11.GL_SMOOTH);
    GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    GL11.glClearDepth(1.0);
    GL11.glEnable(GL11.GL_DEPTH_TEST);
    GL11.glDepthFunc(GL11.GL_LEQUAL);

    GL11.glMatrixMode(GL11.GL_PROJECTION);
    GL11.glLoadIdentity();

    GLU.gluPerspective(45.0f, (float) Display.getWidth() / (float) Display.getHeight(), 0.1f, 100.0f);
    GL11.glMatrixMode(GL11.GL_MODELVIEW);

    GL11.glHint(GL11.GL_PERSPECTIVE_CORRECTION_HINT, GL11.GL_NICEST);

  }

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

  private static void render() {
    GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
    GL11.glLoadIdentity();
    GL11.glTranslatef(-1.5f, 0.0f, -6.0f);

    GL11.glBegin(GL11.GL_TRIANGLES);
    GL11.glVertex3f(0.0f, 1.0f, 0.0f);
    GL11.glVertex3f(-1.0f, -1.0f, 0.0f);
    GL11.glVertex3f(1.0f, -1.0f, 0.0f);
    GL11.glEnd();
  }

  private static void processKeyboard() {
    if (Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)) {
      finished = true;
    }

    if (Keyboard.isKeyDown(Keyboard.KEY_A)) {
      render();
    }
  }

  private static void processWindow() {
    if (Window.isCloseRequested()) {
      finished = true;
    }
  }

  private static void cleanup() {
    Keyboard.destroy();
    Window.destroy();
  }

}


now you'll need to replace GL11. with GL. - since I am running from CVS.

I can minimize & move with no issues.

if you take a look in the org.lwjgl.test.* subpackages, you should have a loop similar to the one in HWCursorTest:

 /**
   * Runs the main loop of the "test"
   */
  private void mainLoop() {
    while (!Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)
      && !Window.isCloseRequested()) {
      // allow subsystem to get a chance to run too
      Window.update();

      if (!Window.isMinimized()) {
        // check keyboard input
        processKeyboard();

        render();

        // paint window
        Window.paint();
      } else {

        // no need to render/paint if nothing has changed (ie. window dragged over)
        if (Window.isDirty()) {
          render();
          Window.paint();
        }

        // don't waste cpu time, sleep more
        try {
          Thread.sleep(100);
        } catch (InterruptedException inte) {
        }
      }
    }
  }