I am trying to get different perspectives in 3D on a OpenGL window.
If you run the code (with anything to do with gluLookAt commented out) and left click the red line point at the place you clicked, right click and the green line aligns to where you clicked. All happens in the xy plane with z=0.0, also it wont let you pick any -ve y values (that's deliberate).
I am trying to pan around the scene using 'x', 'y' & 'z' keys. The first thing I tried was changing the values for where the 'eye' is situated. It has been nothing but a complete disaster!!
No matter how many times I read what gluLookAt is supposed to do, I can never make it do it!
In the code that follows I am trying to set the view at 10 units in the z direction away from the origin, look towards the origin along the z axis.
I just get a black screen (if I leave out anything to do with gluLookAt it looks like https://i.stack.imgur.com/ATsJO.png )
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
import numpy as np
import sys
global lp, lq, rp, rq, z, eyeX, eyeY, eyeZ
lp = 0.0
lq = 2.5
rp = 0.0
rq = 2.5
z = 0.0
# gluLookAt 'eye' coordinates
eyeX = 0.0
eyeY = 0.0
eyeZ = 10.0
def init():
global eyeX, eyeY, eyeZ
glClearColor(0.0, 0.0, 0.0, 1.0)
glOrtho(-10.0, 10.0, -10.0, 10.0, -10.0, 10.0)
glClear(GL_COLOR_BUFFER_BIT)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
gluLookAt(eyeX, eyeY, eyeZ, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0)
def plotdial():
global lp, lq, rp, rq, eyeX, eyeY, eyeZ
#lOrigin = np.array((0.0, 0.0, 0.0))
rOrigin = np.array((5.0, 0.0, 0.0))
radius = 2.5
glClear(GL_COLOR_BUFFER_BIT)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
gluLookAt(eyeX, eyeY, eyeZ, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0)
# Left arm unit vector calculation
lVec = np.array((lp, lq, z))
lMag = np.linalg.norm(lVec)
lVec = (lVec/lMag)*radius
glColor3f(1.0, 0.0, 0.0)
glLineWidth(3.0)
glBegin(GL_LINES)
glVertex3f(0.0, 0.0, z)
glVertex3f(lVec[0], lVec[1], z)
glEnd()
glLineWidth(1.0)
glColor3f(0.0, 0.0, 1.0)
glutWireSphere(2.5, 25, 25)
# Right
glPushMatrix()
glTranslatef(rOrigin[0], rOrigin[1], z)
glColor3f(0.0, 1.0, 0.0)
glLineWidth(3.0)
glBegin(GL_LINES)
glVertex3f(0.0, 0.0, z)
rVec = np.array((rp, rq, z))
rMag = np.linalg.norm(rVec)
rVec = (rVec/rMag)*radius
glVertex3f(rVec[0], rVec[1], z)
glEnd()
glLineWidth(1.0)
glColor3f(0.0, 0.0, 1.0)
glutWireSphere(2.5, 25, 25)
glPopMatrix()
glFlush()
def keyboard(key, x, y):
global glutshape, solid, eyeX, eyeY, eyeZ
step = 0.01
if key == chr(27) or key == "q":
sys.exit()
if key == "x":
eyeX -= step
if key == "X":
eyeX += step
if key == "y":
eyeY -= step
if key == "Y":
eyeY += step
if key == "z":
eyeZ -= step
if key == "Z":
eyeZ -= step
glutPostRedisplay()
def mouse(button, state, x, y):
global lp, lq, rp, rq
o_lp = lp
o_lq = lq
o_rp = rp
o_rq = rq
if button == GLUT_LEFT_BUTTON and state == GLUT_DOWN:
lp = -10.0 + x/500.0 * 20
lq = 10 - y/500.0 * 20
if lq < 0.0:
lp = o_lp
lq = o_lq
if button == GLUT_RIGHT_BUTTON and state == GLUT_DOWN:
rp = -10.0 + x/500.0 * 20 - 5 # -5 is 2*radius
rq = 10 - y/500.0 * 20
if rq < 0.0:
rp = o_rp
rq = o_rq
glutPostRedisplay()
def main():
glutInit(sys.argv)
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB)
glutInitWindowSize(500,500)
glutInitWindowPosition(50,50)
glutCreateWindow('Dial Trial')
glutDisplayFunc(plotdial)
glutKeyboardFunc(keyboard)
glutMouseFunc(mouse)
init()
glutMainLoop()
main()
So what's the story here? Is it that glLookAt doesn't use the axes set in glOrtho?
You are missing glMatrixMode(GL_PROJECTION) before the glOrtho. So after the init call you have an identity (no-op) projection matrix and a modelview matrix that happens to include the orthographic projection before the lookat. I would assume that the first frame you draw looks OK.
After that you set up the MODELVIEW matrix correctly, but the projection is wrong.
The usual pattern for OpenGL rendering is to break up the display code into two functions or methods. One sets up the projection and looks something like:
The second sets up the viewpoint and looks like: