<jupyter_start><jupyter_text>27 Quadrado com transformaçõesNeste exemplo, a biblioteca glm é utilizada para criar e combinar matrizes a fim de transformar um único quadrado de diferentes formas.<jupyter_code>import glm
import numpy as np
import OpenGL.GL as gl
from PyQt5 import QtOpenGL
from PyQt5.QtCore import QCoreApplication
from PyQt5.QtWidgets import QApplication

from cg.shader_programs.SimpleShaderProgram_v2 import SimpleShaderProgram
from cg.renderers.ModelRenderer_v2 import ModelRenderer
from cg.models.SquareMesh_v1 import SquareMesh

class MyWidget(QtOpenGL.QGLWidget):
    def initializeGL(self):
        
        # cria uma malha quadrada
        square_mesh = SquareMesh(0.5, 0.5, 5, 5)
        
        # cria o objeto responsável por carregar os dados para a GPU e renderizá-los
        self.squareRenderer = ModelRenderer(square_mesh.getVertexPositions(), vertex_indices=square_mesh.getVertexIndices())
        
        # cria um shader program simples
        self.shaderProgram = SimpleShaderProgram()
        
        # ativa o shader programa para configurar uma cor única para todos os vértices
        self.shaderProgram.bind()
        self.shaderProgram.useUniformColor(True)
        self.shaderProgram.release()

        # recupera o endereço da variável de entrada do shader program
        position_loc = self.shaderProgram.getVertexPositionLoc()
        
        # configura os dados do modelo para serem os dados de entrada do shader program
        self.squareRenderer.setVertexPositionLoc(position_loc)

        # inicializa a variável que contém o ângulo de rotação
        self.angle = 0
        
    def paintGL(self):
        
        # configura a cor de background
        gl.glClearColor(0, 0, 0, 1)
        
        # limpa o background com a cor especificada
        gl.glClear(gl.GL_COLOR_BUFFER_BIT)
        
        # ativa o recurso de culling
        gl.glEnable(gl.GL_CULL_FACE)
        
        # incrementa a variável que contém o ângulo de rotação
        self.angle += 0.05
        
        # ativa o shader program que será executado pela GPU
        self.shaderProgram.bind()
        
        # renderiza um quadrado com wireframe no centro
        self.renderCentralTriangleWithWireframe()
        
        # renderiza um quadrado no canto superior direito
        self.renderUpperRightTriangle()
        
        # renderiza um quadrado no canto inferior esquerdo
        self.renderBottomLeftTriangle()
        
        # renderiza um quadrado no canto superior esquerdo
        self.renderUpperLeftWireframe()
        
        # renderiza um quadrado no canto inferior direito
        self.renderBottomRightWireframe()
        
        # desativa o shader program
        self.shaderProgram.release()
        
        # solicita que o método paintGL seja chamado novamente
        self.update()
    
    def renderCentralTriangleWithWireframe(self):
        
        # calcula as matrizes de rotação do quadrado
        model_matrix = glm.rotate(glm.mat4(), glm.radians(self.angle), glm.vec3(0.0, 1.0, 0.0))
        self.shaderProgram.setUniformMVPMatrix(model_matrix)
        
        # mudar a cor no shader e renderiza o quadrado
        self.shaderProgram.setUniformColor(np.array([0.0, 0.0, 0.5, 1.0], dtype=np.float32))
        self.squareRenderer.render()
        
        # mudar a cor no shader e renderiza o wireframe do quadrado
        self.shaderProgram.setUniformColor(np.array([1.0, 1.0, 1.0, 1.0], dtype=np.float32))
        self.squareRenderer.renderWireframe()
    
    def renderUpperRightTriangle(self):
        
        # calcula as matrizes de transformação do quadrado e atualiza a matriz do shader
        # nesse caso, a composição das matrizes é feita manualmente
        transl = glm.translate(glm.mat4(), glm.vec3(0.5, 0.5, 0.0))
        rot = glm.rotate(glm.mat4(), glm.radians(self.angle), glm.vec3(0.0, 0.0, 1.0))
        model_matrix = transl * rot
        self.shaderProgram.setUniformMVPMatrix(model_matrix)
        
        # mudar a cor no shader e renderiza o quadrado
        self.shaderProgram.setUniformColor(np.array([0.0, 0.0, 0.5, 1.0], dtype=np.float32))
        self.squareRenderer.render()
    
    def renderBottomLeftTriangle(self):
        
        # calcula as matrizes de transformação do quadrado e atualiza a matriz do shader
        # nesse caso, a composição das matrizes é feita manualmente
        transl = glm.translate(glm.mat4(), glm.vec3(-0.5, -0.5, 0.0))
        rot = glm.rotate(glm.mat4(), glm.radians(self.angle), glm.vec3(0.0, 0.0, 1.0))
        scale = glm.scale(glm.mat4(), glm.vec3(0.5, 0.5, 0.0))
        model_matrix = transl * rot * scale
        self.shaderProgram.setUniformMVPMatrix(model_matrix)
        
        # mudar a cor no shader e renderiza o quadrado
        self.shaderProgram.setUniformColor(np.array([0.0, 0.0, 0.5, 1.0], dtype=np.float32))
        self.squareRenderer.render()
    
    def renderUpperLeftWireframe(self):
        
        # calcula a matriz de transformação do wireframe e atualiza a matriz do shader
        # perceba que a matriz criada na linha anterior é passada como parâmetro para a função que gera a próxima matriz
        # nesse caso, a composição das matrizes é feita pelo próprio glm
        transl = glm.translate(glm.mat4(), glm.vec3(-0.5, 0.5, 0.0))
        rot = glm.rotate(transl, glm.radians(-self.angle), glm.vec3(0.0, 0.0, 1.0))
        model_matrix = glm.scale(rot, glm.vec3(1.0, 0.3, 0.0))
        self.shaderProgram.setUniformMVPMatrix(model_matrix)
        
        # mudar a cor no shader e renderiza o wireframe do quadrado
        self.shaderProgram.setUniformColor(np.array([1.0, 1.0, 1.0, 1.0], dtype=np.float32))
        self.squareRenderer.renderWireframe()
    
    def renderBottomRightWireframe(self):
        
        # calcula a matriz de transformação do wireframe e atualiza a matriz do shader
        # perceba que a matriz criada na linha anterior é passada como parâmetro para a função que gera a próxima matriz
        # nesse caso, a composição das matrizes é feita pelo próprio glm
        transl = glm.translate(glm.mat4(), glm.vec3(0.5, -0.5, 0.0))
        model_matrix = glm.rotate(transl, glm.radians(-self.angle), glm.vec3(0.0, 0.0, 1.0))
        self.shaderProgram.setUniformMVPMatrix(model_matrix)
        
        # mudar a cor no shader e renderiza o wireframe do quadrado
        self.shaderProgram.setUniformColor(np.array([1.0, 1.0, 1.0, 1.0], dtype=np.float32))
        self.squareRenderer.renderWireframe()

    def resizeGL(self, width, height):
        gl.glViewport(0, 0, width, height)

def main():
    import sys

    #Criação de um aplicativo Qt
    app = QCoreApplication.instance()
    if app is None:
        app = QApplication(sys.argv)

    #Especificação do contexto OpenGL
    glformat = QtOpenGL.QGLFormat()
    glformat.setVersion(3, 3)
    glformat.setDoubleBuffer(True)
    glformat.setProfile(QtOpenGL.QGLFormat.CoreProfile)
    
    #Criação da janela de renderização
    w = MyWidget(glformat)
    w.resize(640, 480)
    w.setWindowTitle('OpenGL example')
    w.show()
    
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()
! jupyter nbconvert --to python 27_Quadrado_com_transformacoes.ipynb
%run -i 27_Quadrado_com_transformacoes.py<jupyter_output>[NbConvertApp] Converting notebook 27_Varios_quadrados.ipynb to python
[NbConvertApp] Writing 4298 bytes to 27_Varios_quadrados.py
{'fraction_non_alphanumeric': 0.08334453555585428, 'fraction_numerical': 0.025406640677510417, 'mean_word_length': 2.6668309512074915, 'pattern_counts': {'":': 0, '<': 4, '<?xml version=': 0, '>': 4, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '1', 'dir': 'jupyter-structured-clean-dedup', 'id': '285909', 'license': 'MIT', 'n_tokens_mistral': 2492, 'n_tokens_neox': 2400, 'n_words': 636, 'path': '1S2020/27_Quadrado_com_transformacoes.ipynb', 'repo_name': 'lrittner/ia979', 'size': '7439'}