{"id":2485,"date":"2020-01-03T23:02:16","date_gmt":"2020-01-03T20:02:16","guid":{"rendered":"http:\/\/demensdeum.com\/blog\/?p=2485"},"modified":"2024-12-16T22:32:30","modified_gmt":"2024-12-16T19:32:30","slug":"flipped-world","status":"publish","type":"post","link":"https:\/\/demensdeum.com\/blog\/fr\/2020\/01\/03\/flipped-world\/","title":{"rendered":"Monde \u00e0 l\u2019envers"},"content":{"rendered":"<p>Pour d\u00e9velopper un nouveau projet, Cube Art Project a adopt\u00e9 la m\u00e9thodologie Test Driven Development. Dans cette approche, un test pour une fonctionnalit\u00e9 sp\u00e9cifique de l&#8217;application est d&#8217;abord impl\u00e9ment\u00e9, puis la fonctionnalit\u00e9 sp\u00e9cifique est impl\u00e9ment\u00e9e. Je consid\u00e8re que le gros avantage de cette approche r\u00e9side dans la mise en \u0153uvre des interfaces finales, qui sont aussi peu impliqu\u00e9es que possible dans les d\u00e9tails de mise en \u0153uvre, avant le d\u00e9but du d\u00e9veloppement des fonctionnalit\u00e9s. Avec cette approche, le test dicte la poursuite de l&#8217;impl\u00e9mentation, ajoutant tous les avantages de la programmation contractuelle, lorsque les interfaces sont des contrats pour une impl\u00e9mentation sp\u00e9cifique.<br \/>Projet d&#8217;art cubique &#8211; Un \u00e9diteur 3D dans lequel l&#8217;utilisateur construit des figures \u00e0 partir de cubes ; il n&#8217;y a pas si longtemps, ce genre \u00e9tait tr\u00e8s populaire. Puisqu&#8217;il s&#8217;agit d&#8217;une application graphique, j&#8217;ai d\u00e9cid\u00e9 d&#8217;ajouter des tests avec validation de capture d&#8217;\u00e9cran.<br \/>Pour valider les captures d&#8217;\u00e9cran, vous devez les r\u00e9cup\u00e9rer depuis le contexte OpenGL, cela se fait \u00e0 l&#8217;aide de la fonction glReadPixels. La description des arguments de la fonction est simple\u00a0: position de d\u00e9part, largeur, hauteur, format (RGB\/RGBA\/etc.), pointeur vers le tampon de sortie\u00a0; toute personne ayant travaill\u00e9 avec SDL ou ayant de l&#8217;exp\u00e9rience avec les tampons de donn\u00e9es en C remplacera simplement les arguments n\u00e9cessaires. Cependant, je pense qu&#8217;il est n\u00e9cessaire de d\u00e9crire une fonctionnalit\u00e9 int\u00e9ressante du tampon de sortie glReadPixels\u00a0: les pixels y sont stock\u00e9s de bas en haut, tandis que dans SDL_Surface, toutes les op\u00e9rations de base se d\u00e9roulent de haut en bas.<br \/>Autrement dit, apr\u00e8s avoir charg\u00e9 une capture d&#8217;\u00e9cran de r\u00e9f\u00e9rence \u00e0 partir d&#8217;un fichier png, je n&#8217;ai pas pu comparer directement les deux tampons, car l&#8217;un d&#8217;eux \u00e9tait \u00e0 l&#8217;envers.<br \/>Pour retourner le tampon de sortie d&#8217;OpenGL, vous devez le remplir en soustrayant la hauteur de la capture d&#8217;\u00e9cran pour la coordonn\u00e9e Y. Cependant, il convient de consid\u00e9rer qu&#8217;il y a une chance d&#8217;aller au-del\u00e0 des limites du tampon si vous n&#8217;en soustrayez pas une lors du remplissage, ce qui le fera. conduire \u00e0 une corruption de la m\u00e9moire.<br \/>Comme j&#8217;essaie toujours d&#8217;utiliser le paradigme POO de \u00ab programmation par interfaces \u00bb, au lieu d&#8217;un acc\u00e8s direct \u00e0 la m\u00e9moire de type C par pointeur, lorsque j&#8217;ai essay\u00e9 d&#8217;\u00e9crire des donn\u00e9es en dehors du tampon, l&#8217;objet m&#8217;en a inform\u00e9 gr\u00e2ce \u00e0 la validation des limites dans la m\u00e9thode. .<br \/>Le code final pour la m\u00e9thode permettant d&#8217;obtenir une capture d&#8217;\u00e9cran de haut en bas\u00a0:<\/p>\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-unknown\" data-lang=\"unknown\"><code>    auto width = params->width;\n    auto height = params->height;\n\n    auto colorComponentsCount = 3;\n    GLubyte *bytes = (GLubyte *)malloc(colorComponentsCount * width * height);\n    glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, bytes);\n\n    auto screenshot = make_shared<Screenshot>(width, height);\n\n    for (auto y = 0; y < height; y++) {\n        for (auto x = 0; x < width; x++) {\n            auto byteX = x * colorComponentsCount;\n            auto byteIndex = byteX + (y * (width * colorComponentsCount));\n            auto redColorByte = bytes[byteIndex];\n            auto greenColorByte = bytes[byteIndex + 1];\n            auto blueColorByte = bytes[byteIndex + 2];\n            auto color = make_shared<Color>(redColorByte, greenColorByte, blueColorByte, 255);\n            screenshot->setColorAtXY(color, x, height - y - 1);\n        }\n    }\n\n    free(bytes);\n\n<\/code><\/pre>\n<\/div>\n<h3>Sources<\/h3>\n<p><a href=\"https:\/\/community.khronos.org\/t\/glreadpixels-fliped-image\/26561\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/community.khronos.org\/ t\/glreadpixels-fliped-image\/26561<\/a><br \/><a href=\"https:\/\/stackoverflow.com\/questions\/8346115\/why-are-bmps-stored-upside-down\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/stackoverflow.com\/questions\/8346115\/why-are-bmps-stored-upside-down<\/a><\/p>\n<h3>Code source<\/h3>\n<p><a href=\"https:\/\/gitlab.com\/demensdeum\/cube-art-project-bootstrap\" target=\"_blank\" rel=\"noopener noreferrer\">https:\/\/gitlab.com\/demensdeum\/cube- art-project-bootstrap<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Pour d\u00e9velopper un nouveau projet, Cube Art Project a adopt\u00e9 la m\u00e9thodologie Test Driven Development. Dans cette approche, un test pour une fonctionnalit\u00e9 sp\u00e9cifique de l&#8217;application est d&#8217;abord impl\u00e9ment\u00e9, puis la fonctionnalit\u00e9 sp\u00e9cifique est impl\u00e9ment\u00e9e. Je consid\u00e8re que le gros avantage de cette approche r\u00e9side dans la mise en \u0153uvre des interfaces finales, qui sont<a class=\"more-link\" href=\"https:\/\/demensdeum.com\/blog\/fr\/2020\/01\/03\/flipped-world\/\">Continue reading <span class=\"screen-reader-text\">&#8220;Monde \u00e0 l\u2019envers&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[61,52],"tags":[143,142,76],"class_list":["post-2485","post","type-post","status-publish","format-standard","hentry","category-techie","category-tutorials","tag-cube-art-project","tag-glreadpixels","tag-opengl","entry"],"translation":{"provider":"WPGlobus","version":"3.0.2","language":"fr","enabled_languages":["en","ru","zh","de","fr","ja","pt","hi"],"languages":{"en":{"title":true,"content":true,"excerpt":false},"ru":{"title":true,"content":true,"excerpt":false},"zh":{"title":true,"content":true,"excerpt":false},"de":{"title":true,"content":true,"excerpt":false},"fr":{"title":true,"content":true,"excerpt":false},"ja":{"title":true,"content":true,"excerpt":false},"pt":{"title":true,"content":true,"excerpt":false},"hi":{"title":false,"content":false,"excerpt":false}}},"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/demensdeum.com\/blog\/fr\/wp-json\/wp\/v2\/posts\/2485","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/demensdeum.com\/blog\/fr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/demensdeum.com\/blog\/fr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/demensdeum.com\/blog\/fr\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/demensdeum.com\/blog\/fr\/wp-json\/wp\/v2\/comments?post=2485"}],"version-history":[{"count":11,"href":"https:\/\/demensdeum.com\/blog\/fr\/wp-json\/wp\/v2\/posts\/2485\/revisions"}],"predecessor-version":[{"id":3925,"href":"https:\/\/demensdeum.com\/blog\/fr\/wp-json\/wp\/v2\/posts\/2485\/revisions\/3925"}],"wp:attachment":[{"href":"https:\/\/demensdeum.com\/blog\/fr\/wp-json\/wp\/v2\/media?parent=2485"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/demensdeum.com\/blog\/fr\/wp-json\/wp\/v2\/categories?post=2485"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/demensdeum.com\/blog\/fr\/wp-json\/wp\/v2\/tags?post=2485"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}