Projeto de Arte Cubo

Projeto de Arte Cubo – editor 3D cúbico.
Você tem uma oportunidade incrível de se mover pelo palco, construir e deletar cubos usando os botões WSAD + E, girar a roda do mouse para mudar a cor do cubo. Atualmente, apenas 16 cores são suportadas, mas muitas melhorias estão planejadas para o futuro.

Versão Web
https://demensdeum.com/games/CubeArtProjectWEB/

Windows
https://demensdeum.com/games/CubeArtProjectReleases/CubeArtProjectWin32.zip

macOS
https://demensdeum.com/games/CubeArtProjectReleases/CubeArtProjectMacOS.zip

Linux (x86-64)
https://demensdeum.com/games/CubeArtProjectReleases/CubeArtProjectLinux86_64.zip

Android
(Conceito, requer mouse USB)
https://demensdeum.com/games/CubeArtProjectReleases/CubeArtProject.apk

Código fonte
https://gitlab.com/demensdeum/cube-art-project-bootstrap
https://gitlab.com/demensdeum/cube-art-project-server

Tecnologias: SDL, Emscript, MinGW, Glew, GLM, Cpp-JSON

Mundo de cabeça para baixo

Para desenvolver um novo projeto, o Cube Art Project adotou a metodologia Test Driven Development. Nesta abordagem, primeiro é implementado um teste para uma funcionalidade específica do aplicativo e, em seguida, a funcionalidade específica é implementada. Considero que a grande vantagem desta abordagem é a implementação das interfaces finais, que são o menos envolvidas possível nos detalhes de implementação, antes do início do desenvolvimento da funcionalidade. Com esta abordagem, o teste dita a implementação posterior, agregando todos os benefícios da programação contratual, quando as interfaces são contratos para uma implementação específica.
Projeto de Arte Cubo – Um editor 3D no qual o usuário constrói figuras a partir de cubos; não faz muito tempo que esse gênero era muito popular. Por se tratar de uma aplicação gráfica, resolvi adicionar testes com validação de screenshots.
Para validar as capturas de tela, você precisa obtê-las do contexto OpenGL, isso é feito usando a função glReadPixels. A descrição dos argumentos da função é simples – posição inicial, largura, altura, formato (RGB/RGBA/etc.), ponteiro para buffer de saída; qualquer pessoa que tenha trabalhado com SDL ou tenha experiência com buffers de dados em C simplesmente substituirá os argumentos necessários. Entretanto, acho necessário descrever um recurso interessante do buffer de saída glReadPixels; os pixels são armazenados nele de baixo para cima, enquanto em SDL_Surface todas as operações básicas ocorrem de cima para baixo.
Ou seja, tendo carregado uma captura de tela de referência de um arquivo png, não consegui comparar os dois buffers diretamente, pois um deles estava de cabeça para baixo.
Para inverter o buffer de saída do OpenGL, você precisa preenchê-lo subtraindo a altura da captura de tela para a coordenada Y. No entanto, vale a pena considerar que há uma chance de ultrapassar os limites do buffer se você não subtrair um durante o preenchimento, o que acontecerá. levar à corrupção da memória.
Como sempre tento usar o paradigma OOP de “programação por interfaces”, em vez do acesso direto à memória tipo C por ponteiro, quando tentei escrever dados fora do buffer, o objeto me informou sobre isso graças à validação de limites no método .
O código final para o método de obtenção de uma captura de tela no estilo de cima para baixo:

    auto width = params->width;
    auto height = params->height;

    auto colorComponentsCount = 3;
    GLubyte *bytes = (GLubyte *)malloc(colorComponentsCount * width * height);
    glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, bytes);

    auto screenshot = make_shared(width, height);

    for (auto y = 0; y < height; y++) {
        for (auto x = 0; x < width; x++) {
            auto byteX = x * colorComponentsCount;
            auto byteIndex = byteX + (y * (width * colorComponentsCount));
            auto redColorByte = bytes[byteIndex];
            auto greenColorByte = bytes[byteIndex + 1];
            auto blueColorByte = bytes[byteIndex + 2];
            auto color = make_shared(redColorByte, greenColorByte, blueColorByte, 255);
            screenshot->setColorAtXY(color, x, height - y - 1);
        }
    }

    free(bytes);

Fontes

https://community.khronos.org/ t/glreadpixels-fliped-image/26561
https://stackoverflow.com/questions/8346115/why-are-bmps-stored-upside-down

Código fonte

https://gitlab.com/demensdeum/cube- art-project-bootstrap