Para
maior facilidade de implementação do segundo e do possível
terceiro trabalho, fiz algumas melhoras. São elas:
-
Implementei uma biblioteca que gerenciasse toda interface com o
usuário e implementação do pipeline gráfico ( Até agora apenas
só os dois últimos passos do pipeline);
-
Orientação a Objeto em C++;
-
Criação dos módulos de Matrizes e Vetores para facilitar e
abstrair algumas operações.
Segue
os cabeçalhos de todos os módulos utilizados.
1: #include "definitions.h"
2: #include "lib/Color.h"
3: #include "lib/Vertex.h"
4: #include "lib/Matrix.h"
5: #include "lib/Vector.h"
Implementação
A
implementação foi feita toda na função private void
myglCanonicalToScreen(void) encontrada
na classe MyGL.
Seguindo a sequencia de passos:
- Inverter a coordenada Y ( Transformação de Escala );
- Escalar as coordenadas X e Y pela metade do tamanho da tela;
- Transladar pela metade do tamanho da tela nas coordenadas X e Y;
- Enfim, arrendondar e truncar os valores para que possa ser feita a rasterização corretamente.
Obs.:
O desenhos nesse momento estarão invertidos, porem a tela tem o eixo
Y direcionado para baixo fazendo assim com que o desenho seja
desenhado na sua forma original.
Podemos
perceber que toda sequencia consiste em duas matrizes a de translação
e a de escala, são elas:
![]() |
| Escala |
1: /********************************************************
2: * Transformações
3: ********************************************************/
4: void MyGL::myglTranslate(MYGLmatrix &matrix, float dx = 0, float dy = 0, float dz = 0, float dw = 1 )
5: {
6: MYGLmatrix temp{{1,0,0,0},
7: {0,1,0,0},
8: {0,0,1,0},
9: {dx,dy,dz,dw}};
10: matrix = temp;
11: }
12: void MyGL::myglScale(MYGLmatrix &matrix, float sx = 1, float sy = 1, float sz = 1, float sw = 1 )
13: {
14: MYGLmatrix temp{{sx,0,0,0},
15: {0,sy,0,0},
16: {0,0,sz,0},
17: {0,0,0,sw}};
18: matrix = temp;
19: }
1.
Inverter a coordenada Y
Invertemos
as coordenadas Y de todos os vertices usando a matriz de escala
seguinte:
Ilustração depois de invertemos as coordenadas Y dos vertices.
2. Escalamos as coordenadas X e Y com o valor da metade do tamanho da largura e altura da janela. Sendo IMAGE_WIDTH e IMAGE_HEIGHT constantes de largura e altura. Usando a seguinte matriz:
myglScale(scale,(IMAGE_WIDTH
– 1) / 2,(IMAGE_HEIGHT – 1) / 2);
Na imagem estou supondo que o tamanho da tela é 511, ou seja, de 0 até 510.
myglTranslate(trans,(IMAGE_WIDTH
– 1) / 2,(IMAGE_HEIGHT – 1) / 2, 0);
Exemplo após a translação:
1: // **************************************************************************
2: MYGLvector &MyGL::myglRound(MYGLvector &res)
3: {
4: for(int j = 0; j < res.getSize(); j++)
5: res[j] = (int)(res[j] + 0.5);
6: return res;
7: }
Podemos
também executar tudo de uma vez usando apenas uma matriz então
basta multiplicarmos na ordem que o mais a direita seja a primeira
transformação e o mais a esquerda a ultima transformação, porem estou implementando o vetor linha então temos que inverter essa ordem, ficando assim a primeira transformação mais a esquerda. Para
isso sobrecarreguei o operador de multiplicação para tipo
Matrix<float> que foi definido como MYGLmatrix. Com isso temos
o exemplo após todas as transformações e o eixo de coordenada Y
virado para baixo como é utilizado pela tela.
Matriz após as multiplicações:
Matriz após as multiplicações:
Segue
abaixo a implementação de toda a função
myglCanonicalToScreen(void):
1: // ********************************************************************
2: void MyGL::myglCanonicalToScreen(void)
3: {
4: MYGLmatrix trans(4,4); // translação
5: MYGLmatrix scale(4,4); // escala
6: MYGLmatrix invertY(4,4); // escala invertida
7:
8: MYGLmatrix MatrixScreen(4,4); // Matriz resultado
9:
10: // Aplica as transformações
11: myglTranslate(trans,(IMAGE_WIDTH - 1)/2.0f,(IMAGE_HEIGHT - 1)/2.0f);
12: myglScale(invertY,1.0f,-1.0f);
13: myglScale(scale,(IMAGE_WIDTH - 1)/2.0f,(IMAGE_HEIGHT - 1)/2.0f);
14:
15: /* Estou usando a respresentação vetor coluna então usamos as
16: transpostas das matrizes e invertemos a ordem de multiplicação*/
17: MatrixScreen = invertY * scale * trans;
18:
19: // Pegamos toda malha de vertices e multiplicamos pela matriz retornando
20: // os vertices já transformados e armazena atualiza os valores de todos eles
21: for(auto p = vectorVertex.begin(); p != vectorVertex.end(); p++ )
22: {
23: MYGLvector result(4);
24: result = p->getVector() * MatrixScreen;
25: p->setVector( myglRound(result) );
26: }
27: }
Observação:
O processo de Rasterização se encontra na função
myglRasterization(void) as
duas funções são executadas na função Flush(void).
E a classe MyGL
possui um vector de Vertex que é usada tanto na hora da mudança de
espaço e na de desenhar.
Agora alguns printscreens para comparação dos
resultados com o do OpenGL, vale lembrar que estou usando uma
interface parecida com a do OpenGL:
1: //-----------------------------------------------------------------------------
2: void MyGlDraw(void)
3: {
4: //*************************************************************************
5: // Chame aqui as funções do mygl.h
6: //*************************************************************************
7: MyGL::ClearColor(0,0,0);
8: MyGL::Clear();
9:
10: MyGL::setColor(255,255,255);
11:
12: MyGL::Begin(MYGL_LINES);
13: MyGL::setVertex(-0.5f,-0.5f);
14: MyGL::setVertex( 0.5f,-0.5f);
15: MyGL::setVertex(0.5f,-0.5f);
16: MyGL::setVertex(0.0f,0.5f);
17: MyGL::setVertex(0.0f,0.5f);
18: MyGL::setVertex(-0.5f,-0.5f);
19: MyGL::End();
20:
21: MyGL::Flush();
22: }
1: void display(void)
2: {
3: glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
4: glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
5: glViewport(0, 0, 512, 512);
6:
7: glOrtho(-1.0f,1.0f,-1.0f,1.0f,-1.0f,1.0f);
8: glColor3f(1.0f,1.0f,1.0f);
9: // Alterar o trecho abaixo para desenhar os pontos, linhas e triãngulos
10: // a serem utilizados nas comparações.
11: glBegin(GL_LINES);
12: glVertex3f(-0.5f,-0.5f,0.0f);
13: glVertex3f( 0.5f,-0.5f,0.0f);
14: glVertex3f(0.5f,-0.5f,0.0f);
15: glVertex3f(0.0f,0.5f,0.0f);
16: glVertex3f(0.0f,0.5f,0.0f);
17: glVertex3f(-0.5f,-0.5f,0.0f);
18: glEnd();
19: glFlush();
20: glutSwapBuffers();
21: glutPostRedisplay();
22: }
1: //-----------------------------------------------------------------------------
2: void MyGlDraw(void)
3: {
4: //*************************************************************************
5: // Chame aqui as funções do mygl.h
6: //*************************************************************************
7: MyGL::ClearColor(0,0,0);
8: MyGL::Clear();
9:
10: MyGL::Begin(MYGL_TRIANGLES);
11: MyGL::setColor(255,0,0);
12: MyGL::setVertex(-0.5f,-0.5f);
13: MyGL::setColor(0,255,0);
14: MyGL::setVertex(0.5f,-0.5f);
15: MyGL::setColor(0,0,255);
16: MyGL::setVertex(0.0f,0.5f);
17: MyGL::End();
18:
19: MyGL::Flush();
20: }
1: //
2: void display(void)
3: {
4: glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
5: glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
6: glViewport(0, 0, 512, 512);
7:
8: glOrtho(-1.0f,1.0f,-1.0f,1.0f,-1.0f,1.0f);
9: // Alterar o trecho abaixo para desenhar os pontos, linhas e triãngulos
10: // a serem utilizados nas comparações.
11: glBegin(GL_TRIANGLES);
12: glColor3f(1.0f,0.0f,0.0f);
13: glVertex3f(-0.5f,-0.5f,0.0f);
14: glColor3f(0.0f,1.0f,0.0f);
15: glVertex3f(0.5f,-0.5f,0.0f);
16: glColor3f(0.0f,0.0f,1.0f);
17: glVertex3f(0.0f,0.5f,0.0f);
18: glEnd();
19: glFlush();
20: glutSwapBuffers();
21: glutPostRedisplay();
22: }
Possíveis melhoras
Não vejo uma possível melhora com a implementação do
que foi proposto, porem tem muita coisa a ser feita e melhorada em
relação a Classe MyGL que ainda não está completa e não possui
um tratamento de exceção adequado.
Dificuldades encontradas
Também não tive problemas com a implementação do
trabalho em si. A principal dificuldade encontrada foi com minha
adaptação e aprendizado com o C++ que me fez perder muito tempo
preparando minha classe MyGL pra que ficasse apta a implementar a
mudança de espaços e a implementação da sobrecarga do operador *
pois devido algumas dificuldade com a linguagem em si.
Referência bibliográfica
s
- Foley,
Capítulo 5: "Geometrical Transformations"














