Partage
  • Partager sur Facebook
  • Partager sur Twitter

[SFML] polygones aux contours déformés

un bug exceptionnel ! !

    5 août 2008 à 1:01:20

    Bonsoir, j'aurais besoin de vos lumières sur la SFML. Tout d'abord merci aux âmes sensibles de ne pas lire ce qui va suivre. Non je plaisante bien sûr ! (quoique... :lol: ). Je m'explique : j'ai voulu afficher un cube avec la SFML, autrement dit j'ai voulu faire de la 3D avec une librairie 2D ! Oui c'est totalement inutile et stupide, mais bon ça m'entraîne avec la SFML et ça me fait bosser mes cours ^^

    Le programme en lui même est simple (mais le problème lui est vraiment tordu) : un cube transparent sur fond blanc qu'on peut faire tourner en utilisant les touches du clavier numérique selon trois axes : x, y et... z ! !.

    J'ai dans un premier temps utilisé des sf::Shape::Line, méthode qui a porté ses fruits puisque j'ai réussit ! Mais je me suis heurté à un problème : colorier les faces du cube. C'est pourquoi j'ai décidé de changer de méthode et j'ai refait ce programme en utilisant cette fois des sf::Shape simples. Et j'ai encore réussit, enfin à un détail près, celui-ci :

    Image utilisateur


    A gauche du trait rouge il s'agit d'un screenshot réalisé lorsque deux des trois angles de rotations étaient différents de zéro. A droite le screenshot a été pris quand un seul des angles de rotation était non nul, mais cet effet n'apparaît que lors des rotations autour des axes x et y ! ! Autrement dit si on note (angle_rotation_axe_x, angle_rotation_axe_y, angle_rotation_axe_z), toutes les configurations sont bonnes exceptées celles de la forme (x,0,0) et (0,y,0)...

    C'est déjà bizarre que ça ne marche qu'avec deux des trois rotations alors qu'elles sont toutes implémentées de la même façon, mais il y a encore plus fort ! ! :D En effet dans l'exemple ci-dessus j'affichais les contours de la forme et je ne la remplissais pas, mais si je fais l'inverse (remplissage et pas de bordures) l'affichage fonctionne normalement ! !

    Après divers tests j'ai pu établir que :
    - tous mes points sont situés dans la fenêtre définie
    - ce bug n'est lié ni à l'épaisseur du contour, ni à sa couleur, ni à celle du remplissage, ni au remplissage lui même
    - ce sont toujours les rotations autour des mêmes axes qui entraînent le bug

    J'ai passé déjà quelques heures sur ce problème sans parvenir à lui trouver une solution, j'espère que vous le pourrez. Je n'ai pas posté mon code car il est bourré de lignes de tests, mal commenté, mal organisé, ... et surtout long, 300 lignes au total (normal j'y suis allé comme un bourrin, que des algos récursifs :p ), et après un post aussi long que celui-ci j'aurais fini d'achever tout le monde, mais si besoin est je lui ferai une beauté et je le posterai. Merci d'avance et bravo à ceux qui ont eu le courage de me suivre jusqu'ici ! !


    PS : j'ai utilisé le mot bug, à vous de l'entendre comme vous le voulez (bug de mon code, de mon pc, de la lib...) ;)
    • Partager sur Facebook
    • Partager sur Twitter
      5 août 2008 à 2:50:59

      J'ai tout lu, et une question me vient, pourquoi ne pas utiliser opengl pour faire ça ? Le cube te prend 24 lignes de code avec les couleurs ( moins meme si tu mets les coordonnées dans un fichier à part ), puis il suffit d'ajouter les rotations. Et ça fonctionne !
      • Partager sur Facebook
      • Partager sur Twitter
        5 août 2008 à 2:57:25

        Les points de sf::Shape doivent vérifier deux conditions :
        - définir une surface convexe
        - être donnés dans l'ordre

        Si l'une de ces deux conditions n'est pas vérifiée, cela donne typiquement ce que tu vois à l'écran ;)
        • Partager sur Facebook
        • Partager sur Twitter
          5 août 2008 à 10:10:46

          Citation : askerat

          pourquoi ne pas utiliser opengl pour faire ça ?


          Parce que mon but réel n'est pas de faire de la 3D, mais de m'entraîner au C++ et à la SFML ^^


          Par contre, j'ai un soucis avec ta réponse Laurent. Normalement je suis censé savoir ce qu'est une surface convexe, mais je ne vois pas à quoi ça correspond pour un polygone. J'ai pu trouver cette définition sur le net : "Un polygone convexe est un polygone plan dont les sommets sont dans un même demi-plan par rapport à n'importe quel côté du polygone.". Je n'utilise que des parallélogrammes, donc si cette définition est correcte le problème ne devrait pas venir de là.

          Ensuite pour l'ordre des points, j'ai vérifié et initialement il est bon. Par la suite je n'applique que des rotations, donc je suis censé conserver l'ordre non ? Mais quand j'ai deux rotations le problème disparaît, donc est-ce que pour un polygone plat il faut aller d'une extrémité à l'autre ?
          • Partager sur Facebook
          • Partager sur Twitter
          Anonyme
            5 août 2008 à 10:44:44

            Si t'as que des #grammes alors c'est sur qu'ils seront convexes.
            J'avais appris une définition bien plus simple de "convexe" : on doit être capable de tirer un segment entre n'importe quel point du polygone sans en sortir.
            • Partager sur Facebook
            • Partager sur Twitter
              6 août 2008 à 8:52:44

              Quelqu'un sait-il ce que je peut faire pour contourner le problème ?
              • Partager sur Facebook
              • Partager sur Twitter
              Anonyme
                6 août 2008 à 9:50:20

                Gérer face par face?
                • Partager sur Facebook
                • Partager sur Twitter
                  6 août 2008 à 9:57:06

                  Je pense que face par face est la bonne chose a faire.
                  Sinon, peux tu nous refaire un screenshot avec les sommets numérotés (ou alors tu le détailles avec du texte), et nous dire dans quel ordre tu donnes ces points dans la liste de polygones.

                  Ton probleme de "rotation" me met la puce a l'oreille
                  En fait, si je comprends bien, tu fais un cube en 3D, tu le projettes a l'écran (tu as donc des points 2D x,y), et a partir de la projection tu essaies de faire un polygone (2D) ?
                  Si c'set le cas, la projection ne conservera pas l'ordre des points projetés.
                  • Partager sur Facebook
                  • Partager sur Twitter

                  Recueil de code C et C++  http://fvirtman.free.fr/recueil/index.html

                    6 août 2008 à 10:24:03

                    Si je comprends bien.

                    Ton programme bogue graphiquement quand tu as deux arrêtes qui sont parfaitement identiques d'un point de vue 2D.

                    Le problème principal peut facilement être contourné à mon avis. Il te suffit de structurer ton programme :p

                    En gros, tu as tes angles.

                    Tu vas mettre à jour les coordonnées de chaque points.

                    Mais si tu vois que l'angle est de la forme :

                    l'angle x et l'angle y sont tous deux égaux à 0 modulo 90 ou
                    l'angle x et l'angle z sont tous deux égaux à 0 modulo 90 ou
                    l'angle y et l'angle z sont tous deux égaux à 0 modulo 90.

                    Je dis ça car je suis sûr que ton programme plante également en (90,y,0), (180,y,0).

                    Donc je disais, si tu vois que ces angles ont cette forme, pour chaque exception tu ne traites pas deux arrêtes mais une seule.

                    ________________



                    .....p1.._____________.p2.......->.....______________
                    ........|\.................\.............p1.|...p5|.....|p2...| p6
                    ........|.\.................\................|......|.....|.....|
                    ........|..\____________\.p6.....->....|......|.....|.....|
                    ........|..p5


                    Le schéma est pas lisible, désolé :lol:

                    Dans le premier cas, tu relis p1 avec p2 et p5 avec p6.
                    Dans le second cas, tu relis p1 avec p6.

                    Tu ne devrais plus avoir aucun problème à partir de là je pense.
                    Après je n'ai jamais crée de cube sur pivot avec la SFML :p
                    • Partager sur Facebook
                    • Partager sur Twitter
                      6 août 2008 à 19:41:06

                      Je ne comprends pas bien ce que vous entendez par "face par face", donc je vais développer la structure de mon programme.

                      Tout d'abord, j'ai une classe point qui contient les coordonnées initiales (celles données lors de la création du point) qui ne changent pas, et les coordonnées actuelles qui elles sont variables. Je sais, c'est maladroit, je devrais plutôt n'avoir qu'une seule matrice de coordonnées. Ensuite j'ai une autre classe polygon, qui elle contient un tableau de pointeurs sur point. Enfin, il reste une classe solid qui contient un tableau de pointeurs sur polygon.

                      Le fonctionnement maintenant. Dans le main.cpp, je déclare mes point en donnant leurs coordonnées 3D :

                      point *A=new point(-1,1,-1) ;
                      point *B=new point(1,1,-1) ;
                      point *C=new point(1,1,1) ;
                      point *D=new point(-1,1,1) ;
                      point *E=new point(-1,-1,-1) ;
                      point *F=new point(1,-1,-1) ;
                      point *G=new point(1,-1,1) ;
                      point *H=new point(-1,-1,1) ;
                      

                      Puis viennent les polygon, je passe d'abord le nombre de point , puis les pointeurs sur point dans l'ordre.

                      polygon *face1=new polygon(4,A,B,C,D) ;
                      polygon *face2=new polygon(4,A,B,F,E) ;
                      polygon *face3=new polygon(4,E,H,D,A) ;
                      polygon *face4=new polygon(4,E,H,G,F) ;
                      polygon *face5=new polygon(4,C,G,H,D) ;
                      polygon *face6=new polygon(4,C,G,F,B) ;
                      

                      Finalement je construis mon solid comme suit (il faudra que j'utilise un contructeur du même type que celui de polygon, c'est quand même plus clair) :

                      solid *cube=new solid(&screen) ;
                      cube->addPolygon(face1) ;
                      cube->addPolygon(face2) ;
                      ...
                      

                      (screen est la fenêtre sur laquelle je dessine.)

                      Voici un cube sur lequel j'ai placé les points (désolé pour la qualité de l'image je suis pas très doué avec les logiciels de retouche photo :D ) :

                      Image utilisateur

                      Quand j'appuie sur une touche du clavier numérique, une méthode de solid récupère l'axe de rotation, modifie l'angle et la matrice de rotation concernés, parcourt tous les polygon, qui eux-mêmes parcourent tous les point qu'ils contiennent (donc certains points sont recalculés trois fois, c'est un autre défaut de mon code), et mettent à jour leurs coordonnées.

                      Lorsque je veux dessiner le solid, j'appelle la méthode draw() de chaque polygon qui récupère les coordonnées (x,y) de chaque point qu'il contient (toujours dans l'ordre) et dessine ainsi le projeté de la face à l'écran.

                      Citation : Xahell

                      Ton programme bogue graphiquement quand tu as deux arrêtes qui sont parfaitement identiques d'un point de vue 2D.


                      Pas exactement, au début je prends mon cube de face, on ne voit donc qu'un carré, mais il n'y a pas de bug. C'est lorsqu'il y a seulement une rotation et que l'axe de rotation est dans le plan de l'écran. Je vais quand même essayer de changer ce que tu m'as indiqué (le tout est de trouver un moyen intelligent de savoir quel points sont aux extrémités ^^ mais ça doit être dans mes cordes)
                      • Partager sur Facebook
                      • Partager sur Twitter
                      Anonyme
                        6 août 2008 à 21:12:16

                        Je me pose une question : OpenGL ne peut-il pas faire ça lui-même? Je sais que créer 6 face c'est possible, après pour l'aplatissement je sais pas, je connais pas.
                        Mais si c'est le cas, ne serait-ce pas plus simple?
                        • Partager sur Facebook
                        • Partager sur Twitter
                          6 août 2008 à 22:18:24

                          Citation : Moi

                          j'ai voulu faire de la 3D avec une librairie 2D ! Oui c'est totalement inutile et stupide, mais bon ça m'entraîne avec la SFML et ça me fait bosser mes cours ^^


                          Citation : Moi

                          Parce que mon but réel n'est pas de faire de la 3D, mais de m'entraîner au C++ et à la SFML ^^


                          Comme tu le vois j'ai déjà expliqué pourquoi, de plus OpenGL ne m'intéresse pas, et enfin si jamais j'utilisais une autre librairie, je ne résoudrais pas le problème mais j'en inventerais un autre, et puisque c'est moi qui me le suis suis posé j'aurais tout aussi bien pu ne pas poster ce message et changer moi-même l'énoncé ;)
                          • Partager sur Facebook
                          • Partager sur Twitter
                          Anonyme
                            6 août 2008 à 22:58:27

                            oups, excuse, j'ai sauté ce passage. :-°
                            Bonne continuation alors.
                            • Partager sur Facebook
                            • Partager sur Twitter
                              7 août 2008 à 0:02:57

                              Il n'y a pas de soucis ;) Par contre pour ce qui est de la continuation elle attendra demain ! ! :lol:
                              • Partager sur Facebook
                              • Partager sur Twitter
                                7 août 2008 à 8:20:57

                                Petit détail, si tu essais d'appliquer le fait de dessiner les arêtes intelligemment, pense aussi à modifier ton code cube->addPolygon(faceX) si ce n'est pas fait, sinon ça servira à rien du tout ;)

                                Vu que si tu dessines la face ABCD puis la face FBCG (par exemple), dans ce cas tu dessines deux fois l'arête BC.

                                Peut-être que tu dessines plusieurs arêtes deux fois et qu'avec la rotation t'arrives dans un cas particulier d'arêtes superposés ?

                                La piste du convexe me semble louche, comment une surface carré tracé avec des lignes peut-elle ne pas être convexe ?
                                • Partager sur Facebook
                                • Partager sur Twitter

                                [SFML] polygones aux contours déformés

                                × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                • Editeur
                                • Markdown