#White #Dark #txt #download

        
#!coding: utf-8
from __future__ import print_function, division

from OpenGL.GL import *
from OpenGL.GL import shaders
import ctypes
import pygame
from math import sin, cos, degrees, radians, tan

import numpy
from numpy import array, linalg

from vecutils import * # téléchargez vecutils ici

vertex_shader = """
#version 330
in vec3 position;
in vec3 color;

uniform mat4 pvmMatrix;

out vec3 fcolor;

void main()
{
    gl_Position = pvmMatrix * vec4(position, 1);
    fcolor = color;
}
"""

fragment_shader = """
#version 330

in vec3 fcolor;
out vec4 pixel;

void main()
{
    pixel = vec4(fcolor, 1);
}
"""

vertices = farray([
     0, 0, 0.60,
     1, 0, 0,
     0, 1, 0,
     
     1, 0, 0,
     0, 1, 0,
     1, 1, 1,
     
     0, 0, 0.60,
     -1, 0, 0,
     0, 1, 0,
     
     -1, 0, 0,
     0, 1, 0,
     -1, 1, 1,
])

colors = farray([
     1, 0, 0,
     0, 1, 0,
     0, 0, 1,
     
     1, 0, 0,
     0, 1, 0,
     0, 0, 1,
     
     1, 0, 0,
     0, 1, 0,
     0, 0, 1,
     
     1, 0, 0,
     0, 1, 0,
     0, 0, 1,
])

def create_object(shader):
    # Create a new VAO (Vertex Array Object) and bind it
    vertex_array_object = glGenVertexArrays(1)
    glBindVertexArray( vertex_array_object )
    
    # Get the position of the 'position' in parameter of our shader and bind it.
    position = glGetAttribLocation(shader, 'position')
    if position != -1: # maybe the attribute is useless and was discarded by the compiler
        glEnableVertexAttribArray(position)
    
        # Generate buffers to hold our vertices
        vertex_buffer = glGenBuffers(1)
        glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer)
        
        # Describe the position data layout in the buffer
        glVertexAttribPointer(position, 3, GL_FLOAT, False, 0, ctypes.c_void_p(0))
    
        # Send the data over to the buffer
        glBufferData(GL_ARRAY_BUFFER, ArrayDatatype.arrayByteCount(vertices), vertices, GL_STATIC_DRAW)
    else:
        print('Inactive attribute "{}"'.format('position'))
    
    # Get the position of the 'position' in parameter of our shader and bind it.
    color = glGetAttribLocation(shader, 'color')
    
    if color != -1: # maybe the attribute is useless and was discarded by the compiler
        glEnableVertexAttribArray(color)
        
        # Generate buffers to hold our colors
        vertex_buffer_color = glGenBuffers(1)
        glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_color)
    
        # Describe the color data layout in the buffer
        glVertexAttribPointer(color, 3, GL_FLOAT, False, 0, ctypes.c_void_p(0))
        
        # Send the data over to the buffer
        glBufferData(GL_ARRAY_BUFFER, ArrayDatatype.arrayByteCount(colors), colors, GL_STATIC_DRAW)
    else:
        print('Inactive attribute "{}"'.format('color'))
    
    # Unbind the VAO first
    glBindVertexArray(0)
    
    # Unbind the VBO
    glBindBuffer(GL_ARRAY_BUFFER, 0)
    
    return vertex_array_object
    
def display(shader, vertex_array_object, t):
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    glUseProgram(shader)
    
    # build projection matrix
    P = PerspectiveMatrix(45, 1.0 * 512/512, 0.1, 100)
    
    # build view matrix (lookAt)
    V = LookAtMatrix(vec3(7 * polar(0.5 * t), 5), (0, 0, 0), (0, 0, 1))
    PV = P @ V
    
    # build model matrix of triangles (bouncy animation)
    M = TranslationMatrix(0, 0, abs(sin(3*t)))
    PVM = PV @ M
    
    # use our only vao
    glBindVertexArray(vertex_array_object)
    
    # set matrix
    loc_matrix = glGetUniformLocation(shader, 'pvmMatrix')
    glUniformMatrix4fv(loc_matrix, 1, True, PVM)
    
    # draw
    glDrawArrays(GL_TRIANGLES, 0, 18)
    
    # draw other models !
    m2 = TranslationMatrix(3, 2, 1)
    glUniformMatrix4fv(loc_matrix, 1, True, pv @ m2)
    glDrawArrays(GL_TRIANGLES, 0, 18)
    
    m3 = ScaleMatrix(1/2) @ TranslationMatrix(-2, 3, 0) @ RotationMatrix(150, (0,0,1))
    glUniformMatrix4fv(loc_matrix, 1, True, pv @ m3)
    glDrawArrays(GL_TRIANGLES, 0, 18)
    
    # unbind
    glBindVertexArray(0)
    glUseProgram(0)

def main():
    pygame.init()
    screen = pygame.display.set_mode((512, 512), pygame.OPENGL | pygame.DOUBLEBUF)
    pygame.display.set_caption('Colorful birds')
    
    glClearColor(135/255, 206/255, 235/255, 1)
    # glViewport(0, 0, 512, 512) # we don't have to do that because it's the size of the window
    glEnable(GL_DEPTH_TEST)

    shader = shaders.compileProgram(
        shaders.compileShader(vertex_shader, GL_VERTEX_SHADER),
        shaders.compileShader(fragment_shader, GL_FRAGMENT_SHADER))
    
    vertex_array_object = create_object(shader)
    
    clock = pygame.time.Clock()
    
    tick = 0
    done = False
    while not done:     
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                done = True
        
        tick += 1
        display(shader, vertex_array_object, tick/60)
        pygame.display.flip()
        clock.tick(60)

if __name__ == '__main__':
    try:
        main()
    finally:
        pygame.quit()