Need help with glOrtho

Started by squishy, November 15, 2005, 19:41:43

Previous topic - Next topic

squishy

Hello,
all i want to do is draw a bunch of 2D rectangles in a 100x100 grid. It is for an adaption of Conway's Game of Life if anyone wants to know.
I simply took the code from the wiki's basic open gl tut and inserted into the render() method my own drawing code. I tested that rectangle-drawing code with the default settings and it works fine, but it is in the middle of the window and each grid-cell is only 1 pixel big.
To make it 100x100 and starting in the top left corner i put
       GL11.glOrtho(0, 100, 100, 0, 1, -1);

into the render() method.
but now nothing's drawn i just get a  black window :/
I also tried translating the origin a little into the picture, it doesnt help either :O

My code is exactly the same as in the tutorial except for
       GL11.glOrtho(0, 100, 100, 0, 1, -1);

and if i remove it, it still draws something but not how i want it...

How do i make it draw again? :O

Fool Running

You need to set the Matrix mode like this:
GL11.glMatrixMode(GL11.GL_PROJECTION_MATRIX);
GL11.glOrtho(0, 100, 100, 0, 1, -1);
GL11.glMatrixMode(GL11.GL_MODELVIEW_MATRIX);

I think that should help.
Programmers will, one day, rule the world... and the world won't notice until its too late.Just testing the marquee option ;D

napier

Usually I've seen ortho mode mapped to the entire screen, ie. glOrtho(0,1024,0,768,-1,1), then you can glTranslate and glScale to place your rendering in that coord system at any size you want.  

If your original rendering was at the middle of the screen (in ortho mode), and you set glOrtho to 100x100 then I would guess that your drawing is now way off to the right somewhere (just a guess).  

FYI I use this function to set ortho mode:

   public static void setOrtho()
    {
        // select projection matrix (controls view on screen)
        GL11.glMatrixMode(GL11.GL_PROJECTION);
        GL11.glLoadIdentity();
        // set ortho to same size as viewport, positioned at 0,0
        GL11.glOrtho(0,viewportW,0,viewportH,-1,1);
    }


where the viewportW and H are usually the same as the display resolution (800x600 or 1024x768).  Use glTranslate to move to a pixel position, and glScale to make things larger.
penGL/Java/LWJGL demos and code: http://potatoland.org/code/gl

squishy

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


That did the trick thanks alots!
Still have to learn a lot about this whole opengl thing X.o

Whackjack

I've got exactly what napier put in his code, but whenever I try to translate a polygon on the Z-axis, it doesn't show up.  I've seen other code use the gluPerspective() function, but I was hoping to avoid the GLU functions if possible.
Could anyone explain to me what difference it makes?

CaseyB

Ortho gives you an orthoscopic projection.  This is good for doing things in 2D.  If you try to do anything 3D in an orthoscopic projection it will not look 3D because as things move further away from the camera they will stay the same size instead of diminishing, as they would in a "real" 3D environment.  The gluPerspective() method creates a viewing frustum.  This shape allows things to diminish in size as they move away from the camera which is critical in achieving the illusion of a third dimension.

That being said, the reason that your object dissappeared is because the orthographic viewing volume that you set up is only 2 units deep in the Z direction (again this is becuase it is usually used for 2D work!) so your object went outside of what the camera can "see."

Whackjack

Thanks for your reply CaseyB.  I actually did try to alter the parameters and give the "far" parameter a much higher value (i.e. 100), but still had no luck.  However, based on your description of an orthogonal view, this isn't what I would want anyway to get a 3D effect.

JoC

I got another question on the same subject(almost).
I am playing around with 2D using opeenGL and there for uses glOrtho set to the screen size. But what is the best approch if i want to add some 3D objects, like txured cubes and such?
Like if you see a city from above and roads and such are drawn in 2D mode and now wanting to add simple 3D buildings.

CaseyB

If you want them to look 3D (i.e. diminish as they get farther away) then you need to use GL11.glPerspective() to create the viewing volume.  Then you can define some (more or less) arbitrary plane on the Z-Axis to be the "ground."  From the camera's point of view it will look like it is looking straight down on some buildings.

-=EDIT=-
Here is a little program that shows what I am talking about!  Use the arrow keys to move the cylinder around.
import org.lwjgl.LWJGLException;
import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.glu.Cylinder;
import org.lwjgl.opengl.glu.GLU;

public class CityView
{
	private DisplayMode mode;
	private boolean done;
	private Cylinder tube = new Cylinder();
	private float x, y;

	public static void main(String[] args)
	{
		new CityView();
	}

	public CityView()
	{
		createDisplay();
		initGL();
		run();
	}
	
	private void createDisplay()
	{
		try
        {
            //find displaymode
            DisplayMode[] modes = Display.getAvailableDisplayModes();
            for (int i = 0; i < modes.length; i++)
            {
                if (modes[i].getWidth() == 640 &&
                        modes[i].getHeight() == 480 &&
                        modes[i].getBitsPerPixel() >= 32 &&
                        modes[i].getFrequency() == 60)
                {
                    mode = modes[i];
                    break;
                }
            }
            Display.setDisplayMode(mode);
            Display.setTitle("CityView");
            Display.create();
            return;
        }
        catch (LWJGLException e)
        {
            e.printStackTrace();
        }
	}
	
	private void initGL()
	{
		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(45f, (float)mode.getWidth()/(float)mode.getHeight(), 0.1f, 100f);
		
		GL11.glMatrixMode(GL11.GL_MODELVIEW);
		GL11.glLoadIdentity();
		GL11.glViewport(0, 0, mode.getWidth(), mode.getHeight());
	}
	
	private void run()
	{
		while(!done)
		{
			mainloop();
			render();
			try
			{
				Thread.sleep(1);
			}
			catch(InterruptedException ie)
			{
				ie.printStackTrace();
			}
		}
		Display.destroy();
		System.exit(0);
	}
	
	private void mainloop()
	{
		if(Keyboard.isKeyDown(Keyboard.KEY_ESCAPE) || Display.isCloseRequested())
		{
			done = true;
		}
		if(Keyboard.isKeyDown(Keyboard.KEY_UP)) y += 0.05f;
		if(Keyboard.isKeyDown(Keyboard.KEY_DOWN)) y -= 0.05f;
		if(Keyboard.isKeyDown(Keyboard.KEY_RIGHT)) x += 0.05f;
		if(Keyboard.isKeyDown(Keyboard.KEY_LEFT)) x -= 0.05f;
	}
	
	private void render()
	{
		GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
		GL11.glLoadIdentity();
		GL11.glTranslatef(x, y, -50.0f);		
		GL11.glColor3f(1.0f, 1.0f, 1.0f);
		tube.draw(5f, 5f, 15f, 20, 1);
		Display.update();
	}
}

JoC

Wow, thanks alot for the quick answer and the nice code.
Yes your effect was what I had in mind, so I guess I need to drop glOrtho and read up on glPerspective(only done 2D before :) ). Just one follow up question here. Can I have exact control of the 2D "bottom" grid regarding size in pixels and also position with glPerspective?

CaseyB

The short answer, no.
The Long answer, sort of, it depends on how much work you want to do!  I actually spent the better part of today working on this!  Everything is definded in Cartesian coordinates in the standard (x, y, z) format BUT the whole thing is bounded by a viewing frustum (Picture the frustum as a pyramid with the point missing) which you define with the call to GLU.gluPerspective().  The parameters are the angle of the viewing volume, the ratio of width/height, the distance to the near clipping plane and the distance to the far clipping plane.  For example the call in the program that I posted earlier was:
GLU.gluPerspective(45f, (float)mode.getWidth()/(float)mode.getHeight(), 0.1f, 100f);

where 45f is the angle of the viewing volume at the tip of the pyramid, the next is the ratio of width/height, then from the camera to the near clipping plane in 0.1 units, so it would lie at -0.1 on the Z-Axis, and the distance to the far clipping plane is 100f.  That means that it is 100 units from the camera, or at -100 on the Z-Axis.

Armed with all of that information you can use some trig to calculate how many units are visible at any given depth and, knowing the screen resolution, the number of units per pixel.

-=EDIT=-
Here is a link to a paper I just put together talking about how to do this conversion.  It's in Microsoft Word format, sorry, but that's all we have here at work!

tomb

In this case glFrustum might be easier to use than gluPerspective. Still have to do a tine amount of math. Getting the right factor between the front clipping plane and your 1x1 screen/coordinate plane.

JoC

Thanks alot CaseyB for that great explenation of how it works, was really helpful for me. I will experiment with that stuff when i get home.
tomb, thanks for the suggestion I will check out glFrustum too.


The word document link was misspelled, should be http://www.angelfire.com/co2/tarot/units_per_pixel.doc :)

JoC

I am back with a few more question.
If I drop and glOrtho go with the glPerspective solution how do I detect wich "bottom grid 2d objects(quads), or any object for that matter, that is out side the view and  therefor shouldnt be drawn?

CaseyB

What you need to do is called Frustum Culling.  I haven't done this yet so I don't have any ideas on impleentation but the basic idea is as follows.  Create 6 planes that represent the 6 sides of your viewing volume and then perform rough tests against these to decide what geometry should be passses to the graphics card.