OpenGL:帮助进行相机变换

发布于 2024-07-29 04:27:55 字数 2794 浏览 6 评论 0原文

我正在尝试按照 OpenGL SuperBible 中给出的描述在 Delphi/OpenGL 中实现相机模型。 相机有一个位置、一个向前向量和一个向上向量。 平移相机似乎工作正常,但是当我尝试根据前向矢量旋转相机时,我看不到物体了。

function TCamera.GetCameraOrientation: TMatrix4f;
var
  x, z: T3DVector;
begin
  z := T3DVector.Create(-FForward.X, -FForward.y, -FForward.z);
  x := T3DVector.Cross(z, FUp);

  result[0, 0] := x.X;
  result[1, 0] := x.Y;
  result[2, 0] := x.Z;
  result[3, 0] := 0;

  result[0, 1] := FUp.X;
  result[1, 1] := FUp.Y;
  result[2, 1] := FUp.Z;
  result[3, 1] := 0;

  result[0, 2] := z.x;
  result[1, 2] := z.y;
  result[2, 2] := z.z;
  result[3, 2] := 0;

  result[0, 3] := 0;
  result[1, 3] := 0;
  result[2, 3] := 0;
  result[3, 3] := 1;
end;

procedure TCamera.ApplyTransformation;
var
  cameraOrient: TMatrix4f;
  a, b, c: TMatrix4f;
begin
  cameraOrient := getcameraOrientation;
  glMultMatrixf(@cameraOrient);
  glTranslatef(-FPosition.x, -FPosition.y, -FPosition.z);
end;

给定位置 (0, 0, -15)、前向向量 (0 0 1) 和向上向量 (0 1 0),我期望从 getCameraOrientation 方法中获得单位矩阵,但相反,

(1, 0,  0, 0)
(0, 1,  0, 0)
(0, 0, -1, 0)
(0, 0,  0, 1)

如果我更改将向量转发到 (0 0 -1) 我得到以下矩阵:

(-1, 0, 0, 0)
( 0, 1, 0, 0)
( 0, 0, 1, 0)
( 0, 0, 0, 1)

在调用 glMultMatrix( ) 和 glTranslate( ) 后,glGet( ) 给出以下 GL_MODELVIEW_MATRIX:

( 1, 0,  0, 0)
( 0, 1,  0, 0)
( 0, 0, -1, 0)
( 0, 0, 15, 1)

我预计 15 位于第 4 列第 3 行,不是第 3 列第 4 行。

有人能看出我哪里出错了吗?

编辑:OpenGL SuperBible 的原始代码:

    inline void GetCameraOrientation(M3DMatrix44f m)
        {
        M3DVector3f x, z;

        // Make rotation matrix
        // Z vector is reversed
        z[0] = -vForward[0];
        z[1] = -vForward[1];
        z[2] = -vForward[2];

        // X vector = Y cross Z 
        m3dCrossProduct(x, vUp, z);

        // Matrix has no translation information and is
        // transposed.... (rows instead of columns)
        #define M(row,col)  m[col*4+row]
           M(0, 0) = x[0];
           M(0, 1) = x[1];
           M(0, 2) = x[2];
           M(0, 3) = 0.0;
           M(1, 0) = vUp[0];
           M(1, 1) = vUp[1];
           M(1, 2) = vUp[2];
           M(1, 3) = 0.0;
           M(2, 0) = z[0];
           M(2, 1) = z[1];
           M(2, 2) = z[2];
           M(2, 3) = 0.0;
           M(3, 0) = 0.0;
           M(3, 1) = 0.0;
           M(3, 2) = 0.0;
           M(3, 3) = 1.0;
        #undef M 
        }

    inline void ApplyCameraTransform(bool bRotOnly = false)    
        {
        M3DMatrix44f m;

        GetCameraOrientation(m);

        // Camera Transform   
        glMultMatrixf(m);

        // If Rotation only, then do not do the translation
        if(!bRotOnly)
            glTranslatef(-vOrigin[0], -vOrigin[1], -vOrigin[2]);
        }

I'm trying to implement a camera-model in Delphi/OpenGL after the description given in OpenGL SuperBible. The camera has a position, a forward vector and a up vector. Translating the camera seems to work OK, but when I try to rotate the camera according to the forward vector, I loose sight of my object.

function TCamera.GetCameraOrientation: TMatrix4f;
var
  x, z: T3DVector;
begin
  z := T3DVector.Create(-FForward.X, -FForward.y, -FForward.z);
  x := T3DVector.Cross(z, FUp);

  result[0, 0] := x.X;
  result[1, 0] := x.Y;
  result[2, 0] := x.Z;
  result[3, 0] := 0;

  result[0, 1] := FUp.X;
  result[1, 1] := FUp.Y;
  result[2, 1] := FUp.Z;
  result[3, 1] := 0;

  result[0, 2] := z.x;
  result[1, 2] := z.y;
  result[2, 2] := z.z;
  result[3, 2] := 0;

  result[0, 3] := 0;
  result[1, 3] := 0;
  result[2, 3] := 0;
  result[3, 3] := 1;
end;

procedure TCamera.ApplyTransformation;
var
  cameraOrient: TMatrix4f;
  a, b, c: TMatrix4f;
begin
  cameraOrient := getcameraOrientation;
  glMultMatrixf(@cameraOrient);
  glTranslatef(-FPosition.x, -FPosition.y, -FPosition.z);
end;

Given the position (0, 0, -15), forward vector (0 0 1) and up vector (0 1 0), I expected to get a identity-matrix from the getCameraOrientation-method, but instead I get

(1, 0,  0, 0)
(0, 1,  0, 0)
(0, 0, -1, 0)
(0, 0,  0, 1)

If I change the forward vector to (0 0 -1) I get the following matrix:

(-1, 0, 0, 0)
( 0, 1, 0, 0)
( 0, 0, 1, 0)
( 0, 0, 0, 1)

After the call to glMultMatrix( ) and glTranslate( ), glGet( ) gives me the following GL_MODELVIEW_MATRIX:

( 1, 0,  0, 0)
( 0, 1,  0, 0)
( 0, 0, -1, 0)
( 0, 0, 15, 1)

I would have expected the 15 to be in column 4, row 3, not column 3, row 4.

Can anyone see where I get this wrong?

EDIT: The original code from OpenGL SuperBible:

    inline void GetCameraOrientation(M3DMatrix44f m)
        {
        M3DVector3f x, z;

        // Make rotation matrix
        // Z vector is reversed
        z[0] = -vForward[0];
        z[1] = -vForward[1];
        z[2] = -vForward[2];

        // X vector = Y cross Z 
        m3dCrossProduct(x, vUp, z);

        // Matrix has no translation information and is
        // transposed.... (rows instead of columns)
        #define M(row,col)  m[col*4+row]
           M(0, 0) = x[0];
           M(0, 1) = x[1];
           M(0, 2) = x[2];
           M(0, 3) = 0.0;
           M(1, 0) = vUp[0];
           M(1, 1) = vUp[1];
           M(1, 2) = vUp[2];
           M(1, 3) = 0.0;
           M(2, 0) = z[0];
           M(2, 1) = z[1];
           M(2, 2) = z[2];
           M(2, 3) = 0.0;
           M(3, 0) = 0.0;
           M(3, 1) = 0.0;
           M(3, 2) = 0.0;
           M(3, 3) = 1.0;
        #undef M 
        }

    inline void ApplyCameraTransform(bool bRotOnly = false)    
        {
        M3DMatrix44f m;

        GetCameraOrientation(m);

        // Camera Transform   
        glMultMatrixf(m);

        // If Rotation only, then do not do the translation
        if(!bRotOnly)
            glTranslatef(-vOrigin[0], -vOrigin[1], -vOrigin[2]);
        }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

触ぅ动初心 2024-08-05 04:27:55

鉴于您的 getcameraOrientation 代码,生成的矩阵非常明显:forward = (0, 0, 1) 产生 z = (0, 0, -1),它对应于矩阵的第三行。 z = (0, 0, -1) 和 FUp = (0, 1, 0) 的叉积得到 x = (1, 0, 0),它对应于矩阵的第一行。 第二行只是 FUp 的副本,第四行只是固定的。

我实际上不明白你想要实现什么,但是当你旋转相机时,你显然会看不到你的物体。 在现实世界中,如果你看着一个点并转动你的头 - 这是同样的事情。 您是否尝试过颠倒平移和旋转的顺序?

Given your code of getcameraOrientation the resulting matrix is quite obvious: forward = (0, 0, 1) yields z = (0, 0, -1), which corresponds to the 3rd line of the matrix. The cross product of z = (0, 0, -1) and FUp = (0, 1, 0) results in x = (1, 0, 0), which corresponds to the first line of the matrix. The second line is just a copy of FUp and the 4th line is just fixed.

I actually don't understand what you want to achieve, but when you rotate the camera you clearly loose sight of your object. In the real world if you look at a point and turn your head - it's the same thing. Have you tried to reverse the order of translation and rotation?

二智少女猫性小仙女 2024-08-05 04:27:55

单位矩阵

我不确定为什么 SuperBible 建议使用 (-FForward.X, -FForward.y, -FForward.z) 来创建 Z 向量。 如果去掉负号,那么当你的前向向量为 (0, 0, 1) 时,你将得到你期望的单位矩阵。

如果您想保留减号,并且想要 (0, 0, -1) 的前向向量生成单位矩阵,那么您需要将叉积从 Cross(z, FUp) 更改为 Cross(FUp, z),因为OpenGL使用右手坐标系。 请参阅交叉产品

15 在错误的位置

我同意你的观点,我希望平移矩阵看起来像这样:

(1, 0, 0, x)
(0, 1, 0, y)
(0, 0, 1, z)
(0, 0, 0, 1)

请注意,OpenGL按顺序存储其矩阵,而不是 顺序,因此当您 glGet 模型视图矩阵时,它将按以下顺序显示:

(m[0],  m[4],  m[8], m[12])
(m[1],  m[5],  m[9], m[13])
(m[2],  m[6], m[10], m[14])
(m[3],  m[7], m[11], m[15])

如果您认为它是按行顺序,那么这可能是导致混乱的原因。

Identity matrix

I'm not sure why the SuperBible suggests using (-FForward.X, -FForward.y, -FForward.z) to create your Z vector. If you take out the minus signs then you will get the identity matrix that you expect when your forward vector is (0, 0, 1).

If you want to keep the minus signs, and you want a forward vector of (0, 0, -1) to produce an identity matrix, then you need to change your cross product from Cross(z, FUp) to Cross(FUp, z), because OpenGL uses a right-handed coordinate system. See Cross product.

15 in the wrong spot

I agree with you that I would expect a translation matrix to look like this:

(1, 0, 0, x)
(0, 1, 0, y)
(0, 0, 1, z)
(0, 0, 0, 1)

Note though that OpenGL stores its matrix in column order not row order, so when you glGet the modelview matrix it will come out in this order:

(m[0],  m[4],  m[8], m[12])
(m[1],  m[5],  m[9], m[13])
(m[2],  m[6], m[10], m[14])
(m[3],  m[7], m[11], m[15])

If you thought that it was in row order then that may be what is causing the confusion.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文