OpenGL: Ajuda com a transformação da câmera

votos
2

Eu estou tentando implementar um modelo de câmera em Delphi / OpenGL após a descrição dada em OpenGL SuperBible. A câmara tem uma posição, um vector para a frente e um vector acima. Traduzindo a câmera parece funcionar bem, mas quando eu tento girar a câmera de acordo com o vector para a frente, eu perder de vista o meu objeto.

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;

Dada a posição (0, 0, -15), vector para a frente (0 0 1) e acima do vetor (0 1 0), que esperado para obter uma identidade de matriz a partir do getCameraOrientation-método, mas em vez disso chegar

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

Se mudar o vector para a frente (0 0 -1) fico com a matriz seguinte:

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

Após a chamada para glMultMatrix () e glTranslate (), glGet () me dá o seguinte GL_MODELVIEW_MATRIX:

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

Eu teria esperado a 15 para a coluna 4, linha 3, não coluna 3, linha 4.

Alguém pode ver onde eu receber esta errado?

EDIT: O código original de 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]);
        }
Publicado 24/07/2009 em 11:08
fonte usuário
Em outras línguas...                            


2 respostas

votos
2

Dado o seu código de getcameraOrientation a matriz resultante é bastante evidente: a frente = (0, 0, 1) produz z = (0, 0, -1), que corresponde à terceira linha da matriz. O produto cruzado de z = (0, 0, -1) e FUP = (0, 1, 0) resulta em x = (1, 0, 0), que corresponde à primeira linha da matriz. A segunda linha é apenas uma cópia da FUP e da 4ª linha é apenas fixa.

Eu realmente não entendo o que você quer alcançar, mas quando você girar a câmera que você vista claramente solta do seu objeto. No mundo real, se você olhar para um ponto e virar a cabeça - é a mesma coisa. Você já tentou inverter a ordem de translação e rotação?

Respondeu 24/07/2009 em 17:00
fonte usuário

votos
1

Matriz de identidade

Eu não sei por que o SuperBible sugere o uso (-FForward.X, -FForward.y, -FForward.z) para criar o seu Z vetor. Se você tirar os sinais de menos então você vai ter a matriz de identidade que você espera quando o vector para a frente é (0, 0, 1).

Se você quiser manter os sinais de menos, e você quer um vector para a frente de (0, 0, -1) para produzir uma matriz de identidade, então você precisa mudar o seu produto cruzamento da Cruz (z, FUP) para Cross (FUP, z), porque OpenGL usa um sistema de coordenada destro. Veja produto Cruz .

15 no lugar errado

Concordo com você que eu esperaria uma matriz de tradução para ficar assim:

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

Note porém que OpenGL armazena sua matriz em coluna para não remar fim, então quando você glGet a matriz de modelagem que sairá nesta ordem:

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

Se você pensou que era na ordem de linha, em seguida, que pode ser o que está causando a confusão.

Respondeu 29/07/2009 em 06:37
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more