[编辑09/23/12]想象一下,从上到下的角度来看FPS控制(strafe,转弯)。现在想象一下,当播放器转动整个屏幕时,它们总是面向显示器的顶部。现在想象一下投影的“相机”总是相对于他们的方向在玩家上方和后方10英尺处。这意味着相机以45度角向下俯视景观,随着玩家的转动而旋转。我正在试图掌握为此所需的代码而失去理智,这就是我迄今为止所得到的结果好坏参与:
Public Sub Mode_Perspective()
' Set OpenGL matrices to perspective mode.
' Set projection mode.
Gl.MatrixMode(Gl.PROJECTION)
Gl.LoadIdentity()
Glu.Perspective(45, sWidth / sHeight, Camera.Near, Camera.Far)
Gl.MatrixMode(Gl.MODELVIEW)
Gl.LoadIdentity()
Gl.Scalef(1, -1, 1 * ElevationScale)
End
Public Sub Update_Camera()
' Calculate translated camera position.
CameraXY = Calculate.TranslateInDirection(Camera.WorldX, Camera.WorldY, 10, Camera.Orientation + 90)
' Calculate up vector.
CameraTarget[0] = Client.PlayerData[Client.Number].WorldX_Current
CameraTarget[1] = Client.PlayerData[Client.Number].WorldY_Current
CameraTarget[2] = Client.PlayerData[Client.Number].WorldZ_Current
CameraLeft[0] = Calculate.RotateX(CameraXY[0], CameraXY[1], Camera.WorldX, Camera.WorldY, 1)
CameraLeft[1] = Calculate.RotateY(CameraXY[0], CameraXY[1], Camera.WorldX, Camera.WorldY, 1)
CameraLeft[2] = Camera.WorldZ
CameraRight[0] = Calculate.RotateX(CameraXY[0], CameraXY[1], Camera.WorldX, Camera.WorldY, -1)
CameraRight[1] = Calculate.RotateY(CameraXY[0], CameraXY[1], Camera.WorldX, Camera.WorldY, -1)
CameraRight[2] = Camera.WorldZ
UpVector = Calculate.Normal(CameraTarget, CameraLeft, CameraRight)
' Update OpenGL matrix.
Glu.LookAt(CameraXY[0], CameraXY[1], Camera.WorldZ, Client.PlayerData[Client.Number].WorldX_Current, Client.PlayerData[Client.Number].WorldY_Current, Client.PlayerData[Client.Number].WorldZ_Current, UpVector[0], UpVector[1], UpVector[2])
End
Public Function TranslateInDirection(StartX As Single, StartY As Single, Distance As Single, Direction As Single) As Single[]
' Translate specified coordinates by specified units at specified direction.
' General declarations.
Dim NewXY As New Single[2]
NewXY[0] = StartX + Distance * Cos(Rad(Direction))
NewXY[1] = StartY + Distance * Sin(Rad(Direction))
' Return new coordinates.
Return NewXY
End
Public Function RotateX(PWOX As Single, PWOY As Single, OriginX As Single, OriginY As Single, Orientation As Single) As Single
' Rotate specified point about specified point and return new X coordinate.
Return (OriginX + (Cos(Rad(Orientation)) * (PWOX - OriginX) - Sin(Rad(Orientation)) * (PWOY - OriginY)))
End
Public Function RotateY(PWOX As Single, PWOY As Single, OriginX As Single, OriginY As Single, Orientation As Single) As Single
' Rotate specified point about specified point and return new Y coordinate.
Return (OriginY + (Sin(Rad(Orientation)) * (PWOX - OriginX) + Cos(Rad(Orientation)) * (PWOY - OriginY)))
End
Public Function Normal(p1 As Single[], p2 As Single[], p3 As Single[]) As Single[]
' Calculate and return surface normal of specified triangle.
' General declarations.
Dim N As New Single[3]
Dim Magnitude As Single
' Calculate normal.
N[0] = (p2[1] - p1[1]) * (p3[2] - p1[2]) - (p2[2] - p1[2]) * (p3[1] - p1[1])
N[1] = (p2[2] - p1[2]) * (p3[0] - p1[0]) - (p2[0] - p1[0]) * (p3[2] - p1[2])
N[2] = ((p2[0] - p1[0]) * (p3[1] - p1[1]) - (p2[1] - p1[1]) * (p3[0] - p1[0])) * -1
' Normalize normal.
Magnitude = Sqr(N[0] ^ 2 + N[1] ^ 2 + N[2] ^ 2)
N[0] = N[0] / Magnitude
N[1] = N[1] / Magnitude
N[2] = N[2] / Magnitude
Return N
End
以下是我正在使用Update_Camera程序进行的总结:
1)暂时将相机移到自身后方10英尺处(它松散地跟随播放器)。
2)计算三个点。一个是玩家的位置或相机目标。第二个和第三个是移动的摄像机位置,一个绕着播放器顺时针旋转,另一个稍微逆时针旋转。
3)使用步骤2中的三个点计算“向上”向量。
4)使用glu.LookAt正确定位和定位“相机”。
这一开始似乎运作良好,但是当我降低相机或增加它与播放器的距离时,事情开始变形。相机似乎放大,并且景观的垂直比例似乎增加。与景观平行渲染的精灵四边形仍然呈现为好像相机正好在它们上方,当它们应该在降低相机时以增加的角度渲染。我能错过什么?