Search code examples
pythonopenglpygamelinear-algebrapyopengl

Can't zoom in with gluLookAt(), only zoom out?


I'm trying to implement an orbital camera in PyOpenGL Legacy and am trying to make it zoom in and out (so, go forward and back).

This is the relevant bit of code:

def update(self):
    self.pos = self.orbitalPos()
    print(f"self.pos length {self.magnitude(self.pos)}")
    self.look = self.pos * (-1.0)
    gluLookAt(*(self.pos), *(self.look), *(self.up))

def moveForward(self):
    print("in moveForward")
    direction = glm.normalize(self.look)
    speed = direction * 0.001
    self.pos = self.pos + speed
    self.radius = self.magnitude(self.pos)
    print(self.radius)

def moveBack(self):
    print("in moveBack")
    direction = glm.normalize(self.look)
    speed = direction * (-0.001)
    self.pos = self.pos + speed
    self.radius = self.magnitude(self.pos)
    print(self.radius)

def orbitalPos(self):
    return glm.vec3(
        self.radius * math.sin(math.radians(self.phi)) * math.sin(math.radians(self.theta)), 
        self.radius * math.cos(math.radians(self.phi)),
        self.radius * math.sin(math.radians(self.phi)) * math.cos(math.radians(self.theta)) 
    )

def magnitude(self, vec):
    return math.sqrt(vec.x ** 2 + vec.y ** 2 + vec.z ** 2)

Up is (0,1,0). In the main function, I call ether moveForward() or moveBack() and then call update().

This is just zooming in and out so phi and theta stay the same, and the only thing that changes is the radius, which is decreasing with moveForward() and increasing with moveBack(), as it should. But in the pygame window the object just keeps getting further away no matter what key I press.

I'm fairly sure I'm borking something in the algebra but I don't know what. Any ideas?


Solution

  • gluLookAt not only sets a matrix, but defines a matrix and multiplies the current matrix (which can be the matrix of the last frame) with the new look at matrix. Therefore you have to load the identity matrix with glLoadIdentity before calling gluLookAt:

    def update(self):
        self.pos = self.orbitalPos()
        print(f"self.pos length {self.magnitude(self.pos)}")
        self.look = self.pos * (-1.0)
    
        glLoadIdentity()
        gluLookAt(*(self.pos), *(self.look), *(self.up))