Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

  1. #1
    Membre régulier Avatar de BioKore
    Homme Profil pro
    Ingénieur généraliste
    Inscrit en
    septembre 2016
    Messages
    101
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Ingénieur généraliste
    Secteur : Conseil

    Informations forums :
    Inscription : septembre 2016
    Messages : 101
    Points : 108
    Points
    108

    Par défaut transformations GLM et SFML

    Bonjour à tous,

    Je prends un peu le temps d'avancer un projet laissé de côté il y a quelques mois, lié à l'intelligence artificielle, mais dans lequel je nécessite une représentation graphique.
    Pour se faire, mon choix s'est porté sur SFML et l'utilisation de GLM pour tout ce qui est déplacements, le but étant de permettre une éventuelle évolution vers un rendu plus complexe et sous openGL. initialement, les déplacements étaient "hard codés" avec les fonctions trigo de base, et fonctionnaient correctement, mais ça avait ses limites.

    Le projet est simple, dans un premier temps sans utilisation de mon "moteur IA", et consiste simplement à déplacer des pastilles de couleur dans un espace continu (en 2D), chacune étant indépendante des autres.

    J'ai de solides bases en méca générale de part ma formation initiale, mais concernant la compréhension du fonctionnement des transformations GLM, j'ai un peu plus de mal (question d'organisation du code je pense).

    En effet, j'ai bien compris le fait de donner une matrice de transformation globale à mon objet, je comprends, bien entendu, l'ordre de ces transformations (rotation puis translation). Mais peu importe la manière dont je traite le sujet, les rotations se font toujours par rapport au repère de base et non par rapport à la position précédente de mon objet.

    Étant en période de test, le code est assez simpliste et pas forcément propre. Dans un premier temps, je veux comprendre l'implémentation des transformations avec glm.

    Ici, le code de mon objet :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
     
    // m_pos : position du centre de la pastille
    // m_trans : tenseur des transformations (souvent appelé modelView dans les tutos)
     
     
    agent::agent(const float radius): m_pos(.0f, .0f, .0f, 1.0f), m_trans(1.0f), m_radius(radius)
    {
    	this->m_model.setRadius(radius);		// rayon de la pastille
    	this->m_model.setFillColor(sf::Color(50.0f, .0f, .0f));		// couleur de la pastille
    	this->m_model.setPosition(this->m_pos.x - this->m_radius, this->m_pos.y - this->m_radius);	// position de la pastille (moins le rayon afin de centrer les coordonnées par rapport à la pastille)
    }
     
    agent::agent(const agent &src): m_pos(src.m_pos), m_trans(src.m_trans), m_model(src.m_model), m_radius(src.m_radius)
    {
    	this->m_model.setFillColor(sf::Color(50.0f, .0f, .0f));
    	this->m_model.setPosition(this->m_pos.x - this->m_radius, this->m_pos.y - this->m_radius);
    }
     
    agent::~agent()
    {
     
    }
     
     
    void agent::setPosition(const float &px, const float &py, const float &pz)
    {
    	this->m_trans = glm::translate(this->m_trans, glm::vec3(px, py, pz));    // la position initiale est intégrée dans le tenseur de l'agent
    }
     
    void agent::rotate(const float &angle)
    {
    	this->m_trans = glm::rotate(this->m_trans, glm::radians(angle), glm::vec3(.0f, .0f, 1.0f));   // la rotation est applique au tenseur de l'agent
    }
     
    void agent::translate(const float &tx, const float &ty, const float &tz)
    {
    	this->m_trans = glm::translate(this->m_trans, glm::vec3(tx, ty, tz));    // la translation est appliquée au tenseur de l'agent
    }
     
    void agent::update()
    {
    	this->m_pos = this->m_trans * this->m_pos;
    	this->m_model.setPosition(this->m_pos.x - this->m_radius, this->m_pos.y - this->m_radius);
    	this->m_trans = glm::mat4(1.0f);    // flush du tenseur afin d'éviter de repositionner infiniment l'agent
    }
     
    void agent::display(sf::RenderWindow &win)
    {
    	this->update();
    	win.draw(this->m_model);   // simple affichage de la pastille par sfml... 
    }
     
     
    // END
    Et là, le code du thread d'affichage (en gros, la boucle principale quoi) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
     
    void renderingThread(sf::RenderWindow *win)
    {
    	win->setActive(true);
    	glViewport(0,0, 800, 600);
     
    	agent circle(30);                             // création d'un agent = une pastille de rayon 30
    	circle.setPosition(400, 300, 0);          // on positionne l'agent au centre de la fenêtre
    	circle.display(*win);     // affichage de l'agent
     
    	while(win->isOpen())
    	{
    		// flush buffers (so the screen)
    		glClearColor(.0f, .0f, .2f, .0f);
    		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     
    		// draw scene here.....
    		//circle.rotate(.2f);
    		//circle.translate(.5f, .0f, .0f);
    		circle.display(*win);
     
    		win->display();		// --> rendering buffers exchange
    	}
    }
    Je vous fait grâce de l'implémentation du reste du code, selon moi, inutile à la compréhension du problème.

    Le code tel que présenté ci dessus fonctionne bien. Une pastille de couleur rouge est bien affichée au centre de la fenêtre. Mais si je lui demande une rotation, cette dernière se fait depuis le point 0,0,0 et non sur l'objet lui-même.
    J'ai bien tenté de conserver le "m_trans" plutôt que de le rendre identité dans la fonction "agent::update()", mais dans ce cas la translation 400, 300, 0 se répète 144 fois par secondes (c'est mon framerate) à partir du moment où m_pos = m_trans * m_pos;


    Bref, j'ai l'impression d'être proche de la réponse mais je n'arrive pas à voir comment tourner mon code pour que ça fonctionne... Tous les exemples que je trouve sur le net concernant glm ne traitent quasiment que de son application en 3D sur de l'openGL pur. En ce qui me concerne, openGL viendra plus tard, et en 2D seulement dans un premier temps.


    Pour info, il me faut impérativement
    - une fonction pour tourner l'objet sur lui-même
    - une fonction pour translater (que je déclinerais peut être plus tard en 4 fonctions : avant, gauche, arrière, droite selon l'intégration de mon IA à l'application)


    Voilà. Si certains se sont déjà cassés les dents (ou pas d'ailleurs) sur ce sujet, je serais heureux de connaître votre recette ! Merci d'avance.

  2. #2
    Membre régulier Avatar de BioKore
    Homme Profil pro
    Ingénieur généraliste
    Inscrit en
    septembre 2016
    Messages
    101
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Ingénieur généraliste
    Secteur : Conseil

    Informations forums :
    Inscription : septembre 2016
    Messages : 101
    Points : 108
    Points
    108

    Par défaut

    Ouf!!

    Après une analyse plus poussée, tout en conservant l'organisation de mon code tel-quel, j'ai enfin réussi (d'apparence en tout cas) à obtenir ce que je voulais.

    Dans le code de mon post précédent, j'ai modifié la fonction agent::update() de manière à obtenir le code ci-dessous :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
     
    void agent::update()
    {
    	this->m_pos = this->m_trans * glm::vec4(.0f, .0f, .0f, 1.0f);
    	this->m_model.setPosition(this->m_pos.x - this->m_radius, this->m_pos.y - this->m_radius);
    	//this->m_trans = glm::mat4(1.0f);
    }
    Alors, bien que cela réponde à mes questions initiales, et que ce code ma parait effectivement plus logique, je me demande néanmoins s'il n'existe pas une écriture plus optimale de tout ça.
    Qu'en pensez-vous ? Suis-je sur la bonne voie ou existe-t-il une manière plus propre de faire ces simples transformations ?


    Merci !

  3. #3
    Expert éminent
    Avatar de Kannagi
    Homme Profil pro
    cyber-paléontologue
    Inscrit en
    mai 2010
    Messages
    2 427
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : cyber-paléontologue

    Informations forums :
    Inscription : mai 2010
    Messages : 2 427
    Points : 7 315
    Points
    7 315

    Par défaut

    Le code me semble correct (mais jamais fait de la SFML +GLM) , plus optimal dans quel sens ?
    A part au pire gérer sois même les matrices avec OpenGL , et encore je ne suis pas sur que la différence serait grande.
    C'est pas forcément le code qui est un goulot d'étranglement dans le rendu 2D/3D.

  4. #4
    Membre régulier Avatar de BioKore
    Homme Profil pro
    Ingénieur généraliste
    Inscrit en
    septembre 2016
    Messages
    101
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Ingénieur généraliste
    Secteur : Conseil

    Informations forums :
    Inscription : septembre 2016
    Messages : 101
    Points : 108
    Points
    108

    Par défaut

    Ayant encore besoin de pas mal de pratique en développement et algorithmique, quand je parle "optimisation", j'entends par là quelque chose de plus propre / facile à utiliser et/ou plus performant.
    Après, je l'accorde, vu le code abordé ici, il n'y a pas non plus de grandes révolutions à faire, mais je me disais que peut-être certains utilisaient d'autres méthodes (toujours avec glm) pour traiter les transformations.

    Néanmoins, ta réponse me rassure donc, le peu de code pondu ici ne semble pas trop mauvais. Je m'en contenterais donc jusqu'à la prochaine problématique... Il me reste tout de même la gestion des collisions à programmer.

    Je passe le sujet en résolu. Merci à vous.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Projet terminé] [Android] I Can Transform (C++/SFML)
    Par Is_Daouda dans le forum Projets
    Réponses: 2
    Dernier message: 05/12/2018, 18h53
  2. [PERL] transformation de fichier
    Par bob20000 dans le forum Langage
    Réponses: 6
    Dernier message: 27/07/2006, 12h13
  3. transformer un jour en JJ/MM/AA
    Par gemini_010 dans le forum Algorithmes et structures de données
    Réponses: 8
    Dernier message: 08/11/2002, 23h55
  4. Transformer un caractère en type énuméré
    Par HT dans le forum Langage
    Réponses: 3
    Dernier message: 22/10/2002, 21h46
  5. FFT(Fast Fourier Transform)
    Par IngBen dans le forum Traitement du signal
    Réponses: 6
    Dernier message: 23/05/2002, 17h35

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo