使用PyOpenGL以适当的方式让相机进行偏航,俯仰和翻转?

时间:2016-01-30 03:58:51

标签: python opengl matrix camera

我现在已经挣扎了一段时间,试图实现一个可以在任何一个轴上自由旋转的摄像机(即增加偏航,俯仰和滚动时)。我设法设置相机根据当前的向前,向右和向上矢量正确地改变它的位置,这通常不会搞砸(通常我的意思是当我省略滚动时)。简单地说,相机向前移动,但问题是当我尝试旋转相机时,我不知道如何正确设置。

我产生了一个用于这个类的相机:

import math
import numpy


class Camera:
    def __init__(self, position=(0, 0, 0), pitch=0, yaw=0, roll=0):
        self.position = list(position)
        self.yaw = yaw
        self.pitch = pitch
        self.roll = roll
        self.direction = [0.0, 0.0, -1.0]
        self.right = [1.0, 0.0, 0.0]
        self.up = [0.0, 1.0, 0.0]

    # Calculates where each camera vector (front, right, up) is facing given the current pitch, yaw, roll.
    # The derived vectors are the camera's own coordinate system, while the pitch, yaw and roll are world-based so far.
    def cameraVectors(self):
        x = math.sin(math.radians(self.yaw))*math.cos(math.radians(self.pitch))
        y = math.sin(math.radians(self.pitch))
        z = math.cos(math.radians(self.yaw))*math.cos(math.radians(self.pitch))
        self.direction = [x, y, z]

        x = math.sin(math.radians(self.yaw + 90))*math.cos(math.radians(self.roll))
        y = math.sin(math.radians(self.roll))
        z = math.cos(math.radians(self.yaw + 90))*math.cos(math.radians(self.roll))
        self.right = [x, y, z]

        self.up = numpy.cross(self.direction, self.right)

    # Simply increases the rotation when told to. Stuff below function is irrelevant (maybe) as it works alright.
    def cameraRotate(self, rotX, rotY, rotZ):
        self.yaw += rotX
        self.pitch += rotY
        self.roll += rotZ
        self.cameraVectors()

    def cameraMoveF(self, value):
        self.position[0] += value * self.direction[0]
        self.position[1] += value * self.direction[1]
        self.position[2] += value * self.direction[2]
        self.cameraVectors()

    def cameraMoveB(self, value):
        self.position[0] -= value * self.direction[0]
        self.position[1] -= value * self.direction[1]
        self.position[2] -= value * self.direction[2]
        self.cameraVectors()

    def cameraMoveL(self, value):
        self.position[0] += value * self.right[0]
        self.position[1] += value * self.right[1]
        self.position[2] += value * self.right[2]
        self.cameraVectors()

    def cameraMoveR(self, value):
        self.position[0] -= value * self.right[0]
        self.position[1] -= value * self.right[1]
        self.position[2] -= value * self.right[2]
        self.cameraVectors()

    def cameraMoveU(self, value):
        self.position[0] += value * self.up[0]
        self.position[1] += value * self.up[1]
        self.position[2] += value * self.up[2]
        self.cameraVectors()

    def cameraMoveD(self, value):
        self.position[0] -= value * self.up[0]
        self.position[1] -= value * self.up[1]
        self.position[2] -= value * self.up[2]
        self.cameraVectors()

    def getPosition(self):
        return self.position

    def getDirection(self):
        return self.direction

    def getRight(self):
        return self.right

    def getUp(self):
        return self.up

    def getPitch(self):
        return self.pitch

    def getYaw(self):
        return self.yaw

    def getRoll(self):
        return self.roll

我使用这个我创建每一帧的ViewMatrix:

def createViewMatrix(eyePos, eyeForward, eyeUp):
    E = numpy.array(eyePos)
    F = numpy.array(eyeForward)
    U = numpy.array(eyeUp)

    F = F/numpy.linalg.norm(F)

    S = numpy.cross(F, U)
    S = S/numpy.linalg.norm(S)

    Uprim = numpy.cross(S, F)

    mat = numpy.zeros(shape=(4, 4))

    mat[0][0] = S[0]
    mat[1][0] = S[1]
    mat[2][0] = S[2]

    mat[0][1] = Uprim[0]
    mat[1][1] = Uprim[1]
    mat[2][1] = Uprim[2]

    mat[0][2] = -F[0]
    mat[1][2] = -F[1]
    mat[2][2] = -F[2]

    mat[3][0] = -numpy.dot(S, E)
    mat[3][1] = -numpy.dot(Uprim, E)
    mat[3][2] = numpy.dot(F, E)

    mat[0][3] = 0.0
    mat[1][3] = 0.0
    mat[2][3] = 0.0
    mat[3][3] = 1.0

    return mat

转换矩阵,投影和视图矩阵在渲染视图时完美无缺 - 所有对象都能正常渲染,但问题是我正在努力设置相机自己的坐标系并使其成为可能根据自己的坐标系统进行滚转,俯仰和偏航。我在代码中的某处显然是错的,但我真的不知道问题出在哪里。我已经放了一个简短的视频,展示了相机如何在不同的相机旋转中渲染物体(例如,当向下看时我向右转,相机及其目标都根据世界Y轴旋转,而不是相机'我想要的,当我滚动更多奇怪的事情发生)。轴被表示为旋转以面向相机的正方形。

https://www.youtube.com/watch?v=aBaLkE1cUSo

首先,我展示了偏航和俯仰的正常旋转。您可以注意到我的俯仰和偏航越多,旋转变得越滚动(因为偏航与世界坐标系相关。当摄像机翻转时,显然也会反转)。然后我在0:48左右显示滚动。在凌晨1点,我向你展示了滚动是如何混乱的,整个场景都是奇怪的。

如果有人能找到我失踪的地方和地点,请相信我能分享你的想法,我真的很开心!我把头发拉出来,我找不到我所缺少的东西。有人提到改造相机或其他东西,但我真的不明白怎么做这一切,我确实参考了很多资源...

提前谢谢!

1 个答案:

答案 0 :(得分:0)

在一天结束时,无法使用我正在使用的简单欧拉旋转进行此类旋转。即使尝试以多种方式旋转向上,向右和向前矢量,最终我还是使用Quaternions来实现我的目标。现在旋转就像一个魅力!