glTranslate, como exatamente isso funciona?

7

Tenho alguns problemas para entender como o glTranslate funciona. No começo, pensei que seria simplesmente adicionar valores ao eixo para fazer a transformação.

No entanto, criei dois objetos que carregariam bitmaps, um tem matriz definida como GL_TEXTURE:

public class Background
{
    float[] vertices = new float[]
        { 0f, -1f, 0.0f, 
          4f, -1f, 0.0f, 
          0f, 1f, 0.0f, 
          4f, 1f, 0.0f };

    ....
    private float backgroundScrolled = 0;
    public void scrollBackground(GL10 gl)
    {
        gl.glLoadIdentity();
        gl.glMatrixMode(GL10.GL_MODELVIEW);
        gl.glTranslatef(0f, 0f, 0f);
        gl.glPushMatrix();

        gl.glLoadIdentity();
        gl.glMatrixMode(GL10.GL_TEXTURE);
        gl.glTranslatef(backgroundScrolled, 0.0f, 0.0f);
        gl.glPushMatrix();

        this.draw(gl);
        gl.glPopMatrix();

        backgroundScrolled += 0.01f;
        gl.glLoadIdentity();
    }
}

e outra para GL_MODELVIEW:

public class Box
{
    float[] vertices = new float[]
        { 0.5f, 0f, 0.0f, 
          1f, 0f, 0.0f, 
          0.5f, 0.5f, 0.0f, 
          1f, 0.5f, 0.0f };

    ....

    private float boxScrolled = 0;
    public void scrollBackground(GL10 gl)
    {
        gl.glMatrixMode(GL10.GL_MODELVIEW);
        gl.glLoadIdentity();
        gl.glTranslatef(0f, 0f, 0f);
        gl.glPushMatrix();

        gl.glMatrixMode(GL10.GL_MODELVIEW);
        gl.glLoadIdentity();
        gl.glTranslatef(boxScrolled, 0.0f, 0.0f);
        gl.glPushMatrix();

        this.draw(gl);
        gl.glPopMatrix();

        boxScrolled+= 0.01f;
        gl.glLoadIdentity();
    }
}

Agora eles são desenhados no Renderer.OnDraw. No entanto, o plano de fundo se move exatamente 5 vezes mais rápido. Se eu multiplicar boxScrolled por 5, eles serão sinc e moverão juntos. Se eu modificar os vértices de segundo plano para

    float[] vertices = new float[]
        { 1f, -1f, 0.0f, 
          0f, -1f, 0.0f, 
          1f, 1f, 0.0f, 
          0f, 1f, 0.0f };

Também estará em sintonia com a caixa. Então, o que está acontecendo com o glTranslate?

mykk
fonte
talvez o problema seja com o número de chamadas glpush / glpop que você faz. note que em todas as funções você está chamando glpush duas vezes e glpop apenas uma vez.
Ali1S232
Talvez não, com certeza, o OpenGL tenha uma pilha com apenas 32 unidades por tipo de matriz, se não estiver enganado. Isso permite alguma profundidade de renderização em sua árvore de cenas, mas não muito. Mas assim, o programa deve falhar dentro de um segundo :)
Grimshaw
bem, eu acho que não, como eu disse, se eu modificar os vértices dos fundos, de 0 a 1 no eixo x, funcionará perfeitamente.
mykk
2
Eu acho que o segundo glPushMatrix deve ser excluído. O glPushMatrix é algo como backup da sua matriz atual. Então, se você está empurrando e não poping, pilha é transbordou ...
zacharmarz
E a segunda coisa: glTranslate não está adicionando algo às coordenadas. Está mudando a matriz atual (modelview ou textura no seu caso). A matriz Modelview é usada para multiplicar coordenadas de vértice, matriz de textura para multiplicar coordenadas de textura.
Zacharmarz

Respostas:

5

Aqui está a minha resposta completa:

Sua contagem de glPushMatrix e glPopMatrix deve ser igual. É o primeiro problema.

Mas o principal problema está no modo matriz. No primeiro caso (plano de fundo), você está usando a matriz de textura, que é modificada pelo glTranslate. Isso significa que em cada etapa as coordenadas da textura serão multiplicadas por essa tradução.

Como as coordenadas da textura estão no intervalo <0,1> e o retângulo do plano de fundo tem 4 unidades, ele não será traduzido por 0,01 a cada quadro, mas será traduzido por 0,04 unidades no mundo.

No segundo caso (caixa), você está alterando a matriz modelview. O que fará com que sua caixa seja traduzida em 0,01 unidades a cada quadro no mundo.

Quando você altera o retângulo de segundo plano para novas coordenadas (as coordenadas x são 0 e 1), todas as coordenadas da textura do quadro são realmente convertidas por 0,01 unidades.

zacharmarz
fonte
Obrigado! Eu tenho kinda figurado após seus comentários e agora é muito mais clara
mykk
(eu só quero acrescentar que fundo é de 5 unidades de largura)
mykk
6

glTranslatef

glTranslatefconverte (um caso especial de "transformação") a matriz correspondente ao modo de matriz atualmente selecionado. Então, chamá-lo depois glMatrixMode(GL_MODELVIEW)significa que você transforma a matriz de visualização de modelo e depois de glMatrixMode(GL_TEXTURE)transformar a matriz de textura. Consulte o artigo da Wikipedia sobre matrizes de tradução para saber mais sobre isso.

A matriz de visualização de modelo é aplicada às coordenadas do objeto para obter as coordenadas oculares, o que significa que as coordenadas absolutas do mundo são transformadas em coordenadas relativas à "câmera". (Antes que o objeto seja renderizado, suas coordenadas são transformadas várias vezes extras, os detalhes estão nas perguntas frequentes do OpenGL sobre transformações , mas não são importantes no momento.)

A matriz de textura faz algo completamente diferente; é aplicada às coordenadas da textura antes de serem mapeadas. Utilizá-lo permitirá obter um efeito de textura de rolagem, rotação, redimensionamento ou distorção de perspectiva.

Espero que você veja agora que essas duas matrizes não são intercambiáveis da maneira que você pensa que são. Eles são aplicados em diferentes estágios do processo de renderização. Quando os resultados da transformação de ambas as matrizes se alinham na tela, é pura coincidência que também depende das posições e coordenadas de textura dos objetos, entre outros.

Algumas pequenas observações extras

Além disso, os comentaristas estão certos ao dizer que você deve equilibrar suas ligações para glPush/PopMatrix. Sem ver o resto do seu código e sem saber o que outros objetos estão sendo renderizados, é difícil dizer, mas é possível que parte do efeito que você está enfrentando (a conversão da escala por um fator de 5) seja devido à visualização do modelo matriz de um objeto que está sendo aplicada incorretamente a outro objeto porque ainda está na pilha da matriz.

Além disso:

  • Chamar glMatrixModeem sucessão com os mesmos argumentos não mudará nada, pois o estado OpenGL permanece o mesmo.
  • glLoadIdentitycarrega a matriz de identidade: uma matriz que retorna exatamente as mesmas coordenadas às quais foi aplicada. Pode ser visto como um "reset" da matriz atual. Chamar várias vezes não terá efeito (a menos que você faça algo com a matriz atual).
  • glTranslatef(0f, 0f, 0f) não terá nenhum efeito.
Eric
fonte
1

O que exatamente o glTranslate faz? Antes de tudo, ele calcula uma matriz de conversão - essa é apenas uma matriz de identidade com os valores de conversão nos slots 3 (para x), 7 (para y) e 11 (para z) (assumindo a coluna maior). Em seguida, multiplica a matriz atual por essa matriz de conversão para obter uma nova matriz, na qual substitui a matriz atual. É basicamente isso.

Maximus Minimus
fonte