Hello OpenGL developers!
I’ve made a simple test case and I don’t know what to think about behaviour of my program. I will try to describe it in few words. My program makes the following instructions:
- Creates an orthographic projection for my scene.
- Places OpenGL points (using GL.GL_POINTS and glVertex3d() function) in each corner of my ortho “box” (using the same coordinates as the glOrtho (left, right, bottom, top) parameters).
- Shows result frame to the user.
I’ve used three samples of parameters (xmin, xmax, ymin, ymax) for projection and points generation (in the source code two samples are placed in commented block):
- first one with a small numbers,
- second one is the first one + 5000000 and
- third one is the first one + 10000000.
As I’ve understood from the OpenGL Red Book (Chapter 3: Viewing, Orthographic Projection), that three images generated with those three samples should look the same - as the image generated with first sample (four equal white squares in each corner). But it isn’t :-.
There is no model in my test case except 4 points to get the clearest and simplest code.
It looks like glOrtho function gives the wrong perspective matrix when it paramaters are big numbers and left-to-right and bottom-to-top distance are small. Maybe it’s coused by double precision error ???.
Please help me with this problem beacause I think I’ve just exploited all good ideas with this task :
This test case has been done because of a big problem with map display precision that I must manage in my bigger map application.
So here is the source code of my test case:
import java.awt.*;
import java.awt.event.*;
import javax.media.opengl.*;
import com.sun.opengl.util.*;
public class OrthoTest implements GLEventListener {
/* private double xmin = 0.75;
private double xmax = 30.25;
private double ymin = 0.75;
private double ymax = 30.25;
*/
/* private double xmin = 5000000.75;
private double xmax = 5000030.25;
private double ymin = 5000000.75;
private double ymax = 5000030.25;
*/
private double xmin = 10000000.75;
private double xmax = 10000030.25;
private double ymin = 10000000.75;
private double ymax = 10000030.25;
public static void main(String[] args) {
Frame frame = new Frame("Ortho test");
GLCanvas canvas = new GLCanvas();
canvas.addGLEventListener(new OrthoTest());
frame.add(canvas);
frame.setSize(700, 700);
final Animator animator = new Animator(canvas);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
// Run this on another thread than the AWT event queue to
// make sure the call to Animator.stop() completes before
// exiting
new Thread(new Runnable() {
public void run() {
animator.stop();
System.exit(0);
}
}).start();
}
});
frame.setVisible(true);
animator.start();
}
public void init(GLAutoDrawable drawable) {}
public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {}
public void display(GLAutoDrawable drawable) {
GL gl = drawable.getGL();
if ((drawable instanceof GLJPanel) &&
!((GLJPanel) drawable).isOpaque() &&
((GLJPanel) drawable).shouldPreserveColorBufferIfTranslucent()) {
gl.glClear(GL.GL_DEPTH_BUFFER_BIT);
} else {
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
}
gl.glMatrixMode(GL.GL_PROJECTION);
gl.glLoadIdentity();
gl.glOrtho(
xmin, // left
xmax, // right
ymin, // bottom
ymax, // top
-10.0f, 10.0f);
gl.glMatrixMode(GL.GL_MODELVIEW);
gl.glLoadIdentity();
gl.glPointSize( 20.0f);
gl.glBegin(GL.GL_POINTS);
gl.glColor3f(1.0f, 1.0f, 1.0f);
gl.glVertex3d(xmin, ymin, 0.0f); // left-bottom
gl.glVertex3d(xmin, ymax, 0.0f); // left-top
gl.glVertex3d(xmax, ymin, 0.0f); // right-bottom
gl.glVertex3d(xmax, ymax, 0.0f); // right-top
gl.glEnd();
}
public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {}
}