0

Trying to implement a 3D roaming camera in my python and pygame 3D OpenGL game is something I've been trying to do, but I hit a roadblock. Every time I try to use the gluLookAt function, the camera just freaks out and yanks around while the x and z coordinates increase rapidly and switching from negative to positive. The game I am trying to make is just a flat surface that you walk around and on. I have all controls implemented for moving around, but not the camera.

Here is some summarized code for those who don't want to read all my coding:

while True:
    matrix = glGetDoublev(GL_MODELVIEW_MATRIX)
    camera_x = matrix[3][0]
    camera_y = matrix[3][1]
    camera_z = matrix[3][2]

    # the 3-6 ones are what the camera is looking at
    gluLookAt(camera_x, camera_y, camera_z, 0, 0, 0, 0, 1, 0)
    print("({}, {}, {})".format(int(-camera_x), int(-camera_y), int(-camera_z)))

If the problem cannot be solved with the code above, here is my full(ish) code:

import pygame
from pygame.locals import *
from OpenGL.GL import *
from OpenGL.GLU import *
import os

speed = .5

def enviroment():
    glBegin(GL_QUADS)
    for surface in surfaces:
        for vertex in surface:
            glColor3fv((1, 0, 0))
            glVertex3fv(verticies[vertex])
    glEnd()

    glBegin(GL_LINES)
    for edge in edges:
        for vertex in edge:
            glColor3fv((0, 1, 1))
            glVertex3fv(verticies[vertex])
    glEnd()


def main():
    pygame.init()
    display = (800, 600)
    pygame.display.set_mode(display, DOUBLEBUF | OPENGL)

    gluPerspective(45, (display[0] / display[1]), 0.1, 400)

    glTranslatef(0.0, -3, -150)

    glRotatef(0, 0, 0, 0)

    while True:
        press = pygame.key.get_pressed()

        matrix = glGetDoublev(GL_MODELVIEW_MATRIX)
        camera_x = matrix[3][0]
        camera_y = matrix[3][1]
        camera_z = matrix[3][2]

        # the 3-6 ones are what the camera is looking at
        gluLookAt(camera_x, camera_y, camera_z, 0, 0, 0, 0, 1, 0)

        print("({}, {}, {})".format(int(-camera_x), int(-camera_y), int(-camera_z)))

        if press[pygame.K_UP]:
            glTranslatef(0, -speed, 0)
        elif press[pygame.K_DOWN]:
            glTranslatef(0, speed, 0)

        elif press[pygame.K_w]:
            glTranslatef(0, 0, speed)
        elif press[pygame.K_s]:
            glTranslatef(0, 0, -speed)
        elif press[pygame.K_a]:
            glTranslatef(speed, 0, 0)
        elif press[pygame.K_d]:
            glTranslatef(-speed, 0, 0)

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
            elif event.type == KEYDOWN:
                if event.key == K_UP:
                    glTranslatef(0, -speed, 0)
                elif event.key == K_DOWN:
                    glTranslatef(0, speed, 0)

                elif event.key == K_w:
                    glTranslatef(0, 0, speed)
                elif event.key == K_s:
                    glTranslatef(0, 0, -speed)

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        enviroment()
        pygame.display.flip()
        pygame.time.wait(10)

main()

Any help would be appreciated!

  • 1
    It is not clear what you intend for this code to do. For example, why are you getting a translation value from the modelview matrix and passing that as the look-at point for the camera? And why is it in a *`while` loop*? Also, are you aware that you're putting the perspective matrix in your modeview matrix? – Nicol Bolas Jan 22 '16 at 14:33
  • I was adding the translation value from the modelview matrix to the gluLookAt because I was aware that was the point of the player's eye or perspective. It is in the while loop because I am not sure exactly where to put it, and if it was outside the loop, nothing really happened or worked. And finally, what is the difference between the perspective and the modelview matrix? Sorry for the abundance of questions because I cannot find many if any useful sources about OpenGL in Python, and I do not understand any other language really whatsoever other than Python. – Cullin Wright Jan 22 '16 at 22:18

1 Answers1

0

First of all, I don't see for what reasons you use pygame. OpenGL and GLUT (OpenGL Utility Toolkit) combined have almost everything you might need for 3D graphics in them (especially at the beginner's level). So if you want to start in 3D graphics - GLUT is pretty much everything you need.

About gluLookAt function: The function itself takes 9 parameters and if you want to control the camera's position - you need to operate with the first three:

gluLookAt(eyeX, eyeY, eyeZ, ...)

To rotate the camera around the object (stationed at 0, 0, 0) you need to change the eyeX, eyeY, and eyeZ so that the sum of their squares would be 1 (or some other value, depending on how far from the object the camera should be):

eyeX^2 + eyeY^2 + eyeZ^2 = 1

This is needed to be satisfied because this is an equation of a sphere in 3D.

To start, you can set eyeY variable to 0, so that the camera would rotate in a plane around the object only. Then we need to satisfy this statement:

eyeX^2 + eyeZ^2 = 1

This is an equation of a projection of a sphere to 2D - a circle

Let us introduce an angle α, which will represent our camera's position. To control how the camera revolves around the object, we will change this angle.

Angle image (the image is viewed from above)

So now, we need to convert this angle to coordinates, to use in OpenGL's function.

This can be done using trigonometric functions. Sin(α) will represent our Z-axis value, Cos(α) - our X-axis value. This code would convert our angle to coordinates:

eyeZ = math.sin(alpha)
eyeX = math.cos(alpha)

So now we just need to use gluLookAt function:

gluLookAt(eyeX, 0, eyeZ, 0, 0, 0, 0, 1, 0)

To move the camera you need to change the α angle in any way you prefer.

To do more complex camera management you will need to solve not the circle equality, but the sphere equality and use two angles instead of one.

This is a hard task, but I can recommend you to see the TRON project (https://github.com/leviathan117/TRON/). This is a 3D graphics Python library for beginners, and it has lots of these tasks already written, so you can either use the library itself or open the library's code to see how everything works from the inside.

Andrew Regan
  • 5,087
  • 6
  • 37
  • 73
codereptile
  • 93
  • 1
  • 11