OpenGL:帮助进行相机转换

时间:2009-07-24 10:08:19

标签: delphi opengl camera transformation

我正在尝试在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方法获得一个单位矩阵,但我得到< / p>

(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]);
        }

2 个答案:

答案 0 :(得分:2)

鉴于你的getcameraOrientation代码,得到的矩阵非常明显:forward =(0,0,1)产生z =(0,0,-1),它对应于矩阵的第3行。 z =(0,0,-1)和FUp =(0,1,0)的叉积导致x =(1,0,0),其对应于矩阵的第一行。第二行只是FUp的副本,第四行刚刚修复。

我实际上并不明白你想要达到的目标,但是当你旋转相机时,你会清楚地看到你的物体。在现实世界中,如果你看一点并转过头 - 这是同样的事情。您是否试图颠倒翻译和轮换的顺序?

答案 1 :(得分:1)

身份矩阵

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

如果你想保留减号,并且你想要一个(0,0,-1)的前向矢量来产生一个单位矩阵,那么你需要将十字产品从Cross(z,FUp)改为Cross (FUp,z),因为OpenGL使用右手坐标系。请参阅Cross product

15在错误的地方

我同意你的意见,我希望翻译矩阵看起来像这样:

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

请注意,OpenGL将其矩阵存储在顺序而非顺序中,因此当您获取模型视图矩阵时,它将按以下顺序出现:

(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])

如果您认为它按行顺序排列,则可能是导致混淆的原因。