Forum de la communauté SFML

Aide => Graphique => Discussion démarrée par: Neckara le Avril 14, 2012, 11:06:40 am

Titre: [SFML 2.0] Chargement de sf::Texture
Posté par: Neckara le Avril 14, 2012, 11:06:40 am
Bonjour,

J'ai un petit problème et je ne comprend toujours pas ce qui se passe.
  std::ifstream fichier(chemin.c_str());
    std::string ligne;
    if(fichier.fail())
    {
        std::cerr << "fichier de config non trouv�\n" << std::endl;
        exit(1);
    }
    fichier >> nb_fenetre;
        std::cout << nb_fenetre << std::endl;
        std::cout << chemin << std::endl;
    liste_images = new sf::Texture[nb_fenetre];
    std::getline(fichier, ligne);
    while(i != nb_fenetre)
    {
        std::getline(fichier, ligne);
        std::cout << ligne << std::endl;
        if (!liste_images[i].loadFromFile(ligne.c_str()))
        std::cerr  << ligne << " not found" <<  std::endl;
            //exit(1);
        }
        i++;
        std::cout << ligne << "-" << std::endl;
        std::cout << i << "/" << nb_fenetre << std::endl;
    }
    fond.setTexture(liste_images[2], true);

Citer
do_wait: drmWaitVBlank returned -1, IRQs don't seem to be working correctly.
Try adjusting the vblank_mode configuration parameter.
3
Config/intro.txt
icone1.png
". Reason : Unable to open fileg
 not found
-cone1.png
1/3
icone2.png
". Reason : Unable to open fileg
 not found
-cone2.png
2/3
icone3.png
icone3.png-
3/3
void NFenetre_intro::getImage(Nwindow &wind)//Nwindow hérite de sf::RenderWindow
{
    wind.draw(fond);
}
pour l'affichage, j'ai une fenetre totalement noir.
Quand le chargement de la 3ème sf::Texture marche, et que je met true pour redimensionner le sf::Sprite, lorsqu'ensuite je décide de changer la source du sf::Sprite par une image non chargée, j'ai un carré blanc.

Je pense donc qu'il a réussi à charger la taille mais qu'il y a un problème dans le chargement ou l'affichage de mon image png (avec transparence)

En modifiant le dernier chemin en chemin absolue :
Citer
3/3
neckara@NeckDebian:~/test$ ./exe
do_wait: drmWaitVBlank returned -1, IRQs don't seem to be working correctly.
Try adjusting the vblank_mode configuration parameter.
3
Config/intro.txt
icone1.png
". Reason : Unable to open fileg
 not found
-cone1.png
1/3
icone2.png
". Reason : Unable to open fileg
 not found
-cone2.png
2/3
~/Documents/Donnees/Gestion-fenetre/icone3.png
". Reason : Unable to open filets/Donnees/Gestion-fenetre/icone3.png
 not founds/Donnees/Gestion-fenetre/icone3.png
-/Documents/Donnees/Gestion-fenetre/icone3.png
3/3

Sinon, je ne comprend pas tout à fait pourquoi quand je fais un :
std::cout << ligne << "-" << std::endl;
le "-" remplace le premier caractère de ligne dans l'affichage et ce uniquement lorsque le chargement de l'image ne marche pas.

Pourtant, j'ai une sf::Image qui me sert pour le logo et elle est toujours correctement affichée dans la barre de titre.

EDIT : si je remplace
!liste_images[i].loadFromFile(ligne.c_str())
par
!liste_images[i].loadFromFile("icone3.png")

Je n'ai plus d'erreur au chargement mais cela m'affiche des pixel aléatoirement comme si l'image n'avait en fait pas du tout été chargée.
Titre: Re : [SFML 2.0] Chargement de sf::Texture
Posté par: Orwel le Avril 14, 2012, 01:27:31 pm
Par contre je ne suis pas sur que cela résolve ton problème. Fait plutôt des cout<<"Step 1 "<<ligne...

C'est plus facile de suivre le déroulement du programme de notre coté  ::)

Peut-on connaître l’arborescence de ton projet???
Peut-on voir le fichier intro.txt???

Sinon, ce genre de lecture de fichier est souvent soumise à erreur. Je te conseille de passer par une structure moins linéaire et plus modulable.
Voir utiliser du XML.
Titre: Re : [SFML 2.0] Chargement de sf::Texture
Posté par: Neckara le Avril 14, 2012, 01:43:44 pm
Voici l'archive du projet  https://imo.im/fd/E/NXS2FUhnmp/test.zip (le lien ne dure que 24h)

le fichier intro.txt est bel et bien lu et tout est bel est bien noté dans le std::string ligne comme en atteste les std::cout

Mais j'ai fait un test en faisant
ligne += "/";
std::cout << ligne << std::endl;
et il m'affiche
Citer
/cone.png

Et quand ça arrive, le loadFromFile() retourne false donc je pense que le problème doit venir là, mais je ne vois pas du tout ce qui le provoque.

Ensuite, pour les images etc... ce n'est pas un problème de chemin vu que lorsque je remplace le "ligne.c_str()" par "icone3.png" il n'y a pas d'erreur lors du chargement de l'image.

Par contre, lors de l'affichage, on a bel et bien la bonne taille du sprite mais pas l'image.

EDIT : et ce n'est pas non plus un problème d'affichage vu que lorsque je met une couleur au sprite, le sprite s'affiche correctement.

EDIT : je pense avoir compris pourquoi les loadFromFiles ne marchaient pas, apparemment dans mon fichier texte, il y a un caractère non imprimable à la fin de chaque ligne.
Par contre pour le dernier du fichier, il n'a pas ce caractère non imprimable, bizarre...

Donc maintenant j'ai des sprite qui s'affichent avec un contenu aléatoire, dois y avoir encore un problème sur la source de l'image du sprite.

EDIT : le caractère mis à la fin de mes lignes serait un carriege return. (code ascii 13) mais que vient-il faire ici???
Titre: Re : [SFML 2.0] Chargement de sf::Texture
Posté par: Neckara le Avril 14, 2012, 03:44:52 pm
J'ai trouver ce qui ne va pas :

mon tableau de sf::Texture perd son contenu pour une raison inconnue (pourtant j'ai fait une allocation dynamique...)
Titre: Re : [SFML 2.0] Chargement de sf::Texture
Posté par: Neckara le Avril 14, 2012, 04:47:58 pm
Est-il normal que la fonction draw d'une classe héritée de sf::RenderWindow à laquelle je donne en argument un sf::Sprite dont la source de l'image est un sf::Texture vide la sf::Texture de son contenu???
Titre: Re : [SFML 2.0] Chargement de sf::Texture
Posté par: Koryushin le Avril 14, 2012, 10:58:14 pm
Je suis pas sur mais le sprite est il passé par reference? Sinon ça peut expliquer le problême.
Titre: Re : [SFML 2.0] Chargement de sf::Texture
Posté par: Neckara le Avril 15, 2012, 12:27:09 pm
Le sprite est effectivement passé par référence constante.
void draw (const Drawable &drawable, const RenderStates &states=RenderStates::Default)

Mais comment faire pour éviter que ma texture ne soit modifiée?
Titre: Re : [SFML 2.0] Chargement de sf::Texture
Posté par: Neckara le Avril 15, 2012, 03:27:52 pm
Pour une raison obscure,lors d'un sf::RenderWindow::draw() si le sf::Sprite a pour source d'image un sf::Texture dont l'image a été chargée avant l'activation de la fenêtre et pas dans le même thread, ce sf::Texture verra alors son contenu modifié.
Titre: Re : [SFML 2.0] Chargement de sf::Texture
Posté par: Laurent le Avril 15, 2012, 03:33:03 pm
https://github.com/SFML/SFML/issues/160 ?
Titre: Re : [SFML 2.0] Chargement de sf::Texture
Posté par: Neckara le Avril 15, 2012, 03:48:09 pm
Je ne suis pas super doué en anglais, mais j'arrive à comprendre un peu.

Apparemment, j'ai le même problème :

Un sf::Texture doit "recevoir son image"  pendant que la fenêtre est active (peu importe si elle est désactivée ensuite) sinon lors de l'appel de la fonction draw, la sf::Texture sera effacée. (pour le thread, je me suis trompé, peut importe le thread, le tout est d'avoir la fenetre activée dans le thread)

La fonction sf::Texture::create() n'apporte rien de plus.

EDIT : après relecture, je vois qu'ils ont trouvé la même explication, il faut que la fenêtre soit active.
Mais c'est très contraignant, ceci veut dire qu'il faut interrompre l'affichage pour charger les images.
Titre: Re : [SFML 2.0] Chargement de sf::Texture
Posté par: Laurent le Avril 15, 2012, 06:27:49 pm
Alors déjà c'est pas normal hein, ça ne se produit que sous Linux et ce sera corrigé une fois que j'aurai compris pourquoi ça ne marche pas ;)

Ensuite tu peux nous montrer ton code, ou un pseudo-code qui nous aide à comprendre ce que tu fais ? Parce que "très contraignant" et "interrompre l'affichage"... non, à mon avis tu fais des trucs inutilement compliqués.
Titre: Re : [SFML 2.0] Chargement de sf::Texture
Posté par: Neckara le Avril 15, 2012, 06:51:19 pm
Je n'ai pas tout à fait fini de réécrire le code correctement.

Voici un pseudo-code :
.hpp
class Hevent
{
private:
bool Running;
sf::RenderWindow wind;
public:
void event();
void afficher();
Hevent();
~Hevent();
};
.cpp
void lance_afficher(void *data)
{

Hevent *hevent = static_cast<Hevent*>(data);
hevent->afficher();
}

Hevent::Hevent()
{
sf::Thread Thread(&lance_afficher, this);
Thread.launch();
event();
Thread.wait();
}


Hevent::~Hevent()
{
}

void Hevent::event()
{
Running = true;
while (Running)
{
sf::Event Event;
while (wind.waitEvent(Event))
{
                              //traitement de l'évènement
}
}
}

void Hevent::afficher()
{
wind.setFramerateLimit(IMGPROSEC);
while(Running)
{
//tous les wind.draw
wind.display();
}
}

Je suis obligé de mettre l'affichage et la réception d'évènement dans deux partie distinctes car il pourra arriver que le traitement de certains évènements soient assez long et ceci ne devra pas interrompre l'affichage.

Le problème, c'est que je serais obliger de télécharger tous les éléments graphique avant de commencer d'afficher (ou en arrêtant l'affichage pour un temps) afin de pouvoir faire wind.setActive(false) dans la boucle d'affichage puis de faire un wind.setActive(true) dans le processus qui gèrera le chargement des images.

Donc il va falloir que je gère une ou plusieurs classes de stockage d'images pour stocker un maximum d'image avant de continuer l'affichage.

Ensuite, certains évènement vont conduire à modifier certaines textures, donc non seulement il va falloir que je mette des verrous un peu partout dans la boucle d'affichage.

Sinon, il faut que dans la fonction qui se chargera de récupérer le sf::Sprite d'une classe particulière pour le dessiner sur le sf::RenderWindows, faire un test et effectuer les modifications, mais cela va demander plus de temps (pas seulement le if, mais toutes les modifications à effectuer).

Je ne suis pas sûr mais je pense que ça doit être la même chose pour les sf::RenderTexture (?)
Si j'ai bien compris, il faudra que je fasse un clear(), des draw() puis un display() à chaque modifications (?)

Sinon, comment savoir s'il y a des correction apportée à la 2.0 et surtout comment les inclure à notre version?
Titre: Re : [SFML 2.0] Chargement de sf::Texture
Posté par: Laurent le Avril 15, 2012, 07:07:27 pm
Désolé, mais pour ma part il y a trop de code, trop d'explications. En ce moment j'ai très peu de temps libre alors si tu veux une aide efficace essaye de faire dans le concis. Je sais que c'est pas ta faute, mais là je peux vraiment pas prendre le temps de décortiquer ton code et tes explications :-[
Titre: Re : [SFML 2.0] Chargement de sf::Texture
Posté par: Neckara le Avril 15, 2012, 07:16:51 pm
Pour faire très simple, je fais deux threads :
- un pour l'affichage
- un pour le traitement des évènements

Mais il faut alors que j'arrête la boucle d'affichage (via un mutex) à chaque fois que je souhaite mettre une image dans un sf::Texture.

EDIT : puisque si j'ai deux threads où la sf::RenderWindow activée, ça plante.

Je redoute aussi d'avoir des problèmes similaire avec les sf::RenderTexture quand j'aurais à les utiliser.
Titre: Re : [SFML 2.0] Chargement de sf::Texture
Posté par: Laurent le Avril 15, 2012, 07:53:17 pm
Tu n'as pas à faire de trucs compliqués, il y a juste deux choses à retenir :
- les évènements doivent être gérés dans le thread qui a créé la fenêtre
- tu dois désactiver le contexte de la fenêtre (setActive(false)) dans le thread où elle est active, avant de dessiner (clear, draw, display) dans un autre thread
Titre: Re : [SFML 2.0] Chargement de sf::Texture
Posté par: Neckara le Avril 15, 2012, 08:10:35 pm
Donc je dois mettre un mutex dans la boucle d'affichage précédé d'un setActive(false) pour bloquer quand je dessine dans un autre thread (ou met une image dans un sf::Texture).

Ce qui veut donc dire bloquer l'affichage pendant un temps non négligeable, j'ai peur qu'au fur et à mesure que les affichages deviendrons complexe, de perdre trop de fps.
Titre: Re : [SFML 2.0] Chargement de sf::Texture
Posté par: Laurent le Avril 15, 2012, 08:24:04 pm
Si tu dessines dans un thread autre que celui d'affichage, déjà il y a un problème. Parce que normalement, dessiner c'est de l'affichage :P

Ensuite pour charger une texture par exemple, tu n'as absolument pas besoin de la fenêtre sur laquelle tu es en train de dessiner dans un autre thread. Tu n'as en fait besoin de rien du tout, SFML gère en interne automatiquement la création / activation de contextes OpenGL quand il y en a besoin.

Quant au mutex, tu n'en as pas besoin non plus. Non pas que SFML soit thread-safe, loin de là, mais si tu ne fais pas de choses bizarres tu ne dois pas avoir besoin d'accéder à des ressources partagées.
Titre: Re : [SFML 2.0] Chargement de sf::Texture
Posté par: Neckara le Avril 15, 2012, 08:29:04 pm
Sous Débian avec une carte graphique intel, je suis obligé d'activer le RenderWindow dans le thread quand je met une image dans un Texture sinon la texture est modifiée lors du draw(ma_texture) de la boucle d'affichage.

Or, si j'active le renderWindow dans deux thread, le programme plante.

Sinon, pour l'activation du renderWindow pour les draw, clear, display c'est juste pour les renderWindow? Je n'ai pas besoin de l'activé si je dessine sur un renderTexture?
Titre: Re : [SFML 2.0] Chargement de sf::Texture
Posté par: Laurent le Avril 15, 2012, 08:35:16 pm
Citer
Sous Débian avec une carte graphique intel, je suis obligé d'activer le RenderWindow dans le thread quand je met une image dans un Texture sinon la texture est modifiée lors du draw(ma_texture) de la boucle d'affichage.
Je veux bien un code complet minimal de ça, histoire de pouvoir creuser un peu.

Citer
Sinon, pour l'activation du renderWindow pour les draw, clear, display c'est juste pour les renderWindow? Je n'ai pas besoin de l'activé si je dessine sur un renderTexture?
Tu ne dois rien faire, ça fait tout seul ce que ça doit faire quand ça doit le faire :P
Titre: Re : [SFML 2.0] Chargement de sf::Texture
Posté par: Neckara le Avril 15, 2012, 08:41:39 pm
.hpp
class Hevent
{
private:
bool Running;
sf::RenderWindow wind;
public:
void event();
void afficher();
Hevent();
~Hevent();
                Fenetre * mafenetre;
};
.cpp
void lance_afficher(void *data)
{

Hevent *hevent = static_cast<Hevent*>(data);
hevent->afficher();
}

Hevent::Hevent() : mafenetre(NULL), wind(500,500)
{
        wind.setActive(false);
sf::Thread Thread(&lance_afficher, this);
Thread.launch();
         Fenetre toto;//chargement de sf::Texture et autre
         mafenetre = &toto;
event();
Thread.wait();
}

Hevent::~Hevent()
{
}

void Hevent::event()
{
Running = true;
while (Running)
{
sf::Event Event;
while (wind.waitEvent(Event))
{
                              //traitement de l'évènement
}
}
}

void Hevent::afficher()
{
wind.setFramerateLimit(IMGPROSEC);
while(Running)
{
                 if(mafenetre != NULL)
                              wind.draw(mafenetre->getSprite());
//tous les wind.draw
wind.display();
}
}

Fenetre.hpp
class Fenetre
{
         sf::Texture text;
         public :
          Fenetre()
          {
                     text.loadFromFile("toto.png");
           }
           const sf::Sprite & getSprite(){ sf::Sprite toto(text); return toto;  };
}
Titre: Re : [SFML 2.0] Chargement de sf::Texture
Posté par: Laurent le Avril 15, 2012, 10:06:28 pm
J'insiste sur complet et minimal, c'est pas juste pour embêter les gens qu'on le demande ;)
Titre: Re : [SFML 2.0] Chargement de sf::Texture
Posté par: Neckara le Avril 16, 2012, 10:35:31 am
#include <iostream>
#include <cstdlib>
#include <SFML/Graphics.hpp>
#include <SFML/System.hpp>

//g++ toto.cpp -o exe -lsfml-graphics -lsfml-system

bool Running(true);
sf::Sprite * toto(NULL);
sf::RenderWindow app(sf::VideoMode(500, 500, 32), "titre", sf::Style::Titlebar | sf::Style::Close);

void lance_afficher(void *data)
{
       app.setActive(true);
        app.setFramerateLimit(60);

        while(Running)
        {
                app.clear();
                if(toto != NULL)
                            app.draw(*toto);
                app.display();
        }
}

int main()
{
    int i;
     /*
    app.setActive(true);
    sf::Texture img_toto;
    img_toto.loadFromFile("icone1.png");
    /**/

    app.setActive(false);
    void *data(NULL);
    sf::Thread Thread(&lance_afficher, data);
    Thread.launch();/**/
    sf::Texture img_toto;
    img_toto.loadFromFile("icone1.png");/**/
    sf::Sprite Stoto(img_toto);
    toto = &Stoto;
    std::cin >> i;
    Running = false;
    Thread.wait();
}
 

Voilà, je ne peux pas faire mieux
Titre: Re : [SFML 2.0] Chargement de sf::Texture
Posté par: Laurent le Avril 16, 2012, 11:25:08 am
C'est impeccable, merci :)

Chez moi ça tourne impec, mais bon je suis sous Windows.

J'ai un peu retouché le code, voici la version que j'ai testée au cas où ça fasse une différence :
#include <SFML/Graphics.hpp>
#include <iostream>

bool running = true;
sf::Sprite sprite;

void lance_afficher(sf::RenderWindow* window)
{
    while (running)
    {
        window->clear();
        window->draw(sprite);
        window->display();
    }
}

int main()
{
    sf::RenderWindow window(sf::VideoMode(500, 500, 32), "titre");
    window.setActive(false);

    sf::Thread Thread(&lance_afficher, &window);
    Thread.launch();

    sf::Image image;
    image.create(250, 250, sf::Color::Green);
    sf::Texture texture;
    texture.loadFromImage(image);
    sprite.setTexture(texture, true);

    while (running)
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
                running = false;
        }
    }

    return 0;
}
 
Titre: Re : [SFML 2.0] Chargement de sf::Texture
Posté par: Neckara le Avril 16, 2012, 11:32:37 am
Je ne sais pas si utiliser une sf::Image change vraiment quelque chose.

Mais il me semble avoir le même problème que sur le lien que vous m'aviez donné : https://github.com/SFML/SFML/issues/160

On rencontre ce problème sous Linux (ici Débian avec carte graphique intel)

Il y a une explication ici :
Citer
I tried to look for the problem a little bit further. Maybe you already know these things, but I'll post them in case you didn't.

The problem lies with the glBindTexture call in texture.Create.

This is only one part of the problem, something in window.Create makes this problem.
So I split up the Create function in two parts: one was executed before and one after the texture was loaded.

Window.Create contains this line: "myContext = priv::GlContext::New(settings, myImpl, mode.BitsPerPixel);".
If this line is executed after the texture has been created then it will not be drawn correctly.

Here the problem lies with the "context->Initialize();" function.
And the line were the problem lies is "SetActive(true);"

So window.myContext has to be active before the texture gets created.
This would mean that the problem lies with currentContext.
Je n'ai pas tout à fait tout compris, mais j'ai retenu qu'il faut charger l'image dans le sf::Texture quand le renderWindow est activé
Titre: Re : [SFML 2.0] Chargement de sf::Texture
Posté par: Laurent le Avril 16, 2012, 11:37:49 am
Citer
Je ne sais pas si utiliser une sf::Image change vraiment quelque chose.
Oui on s'en fiche, c'était juste pour rendre le code indépendant de ressources externes. Comme ça n'importe qui peut le copier-coller et le tester directement.

Citer
Mais il me semble avoir le même problème que sur le lien que vous m'aviez donné : https://github.com/SFML/SFML/issues/160
Oui c'est fort possible, quoique là on aurait une nouvelle variante.

Citer
Je n'ai pas tout à fait tout compris, mais j'ai retenu qu'il faut charger l'image dans le sf::Texture quand le renderWindow est activé
Oui, et c'est là qu'est le bug : normalement SFML fait en sorte qu'il n'y ait pas besoin de faire ça.
Titre: Re : [SFML 2.0] Chargement de sf::Texture
Posté par: Laurent le Avril 16, 2012, 11:39:13 am
Est-ce que le fait d'ajouter cette ligne juste avant de charger la texture
sf::Context context;
y change quelque chose ?
Titre: Re : [SFML 2.0] Chargement de sf::Texture
Posté par: Neckara le Avril 16, 2012, 11:52:30 am
en mettant
sf::Context context;


Juste avant la création du sf::Texture, environ 1 coup sur 5 j'aurais l'image qui s'affiche correctement à part une petite bande noir en haut.
Sinon 4 fois sur 5, ça fait pareil qui si je mettait ce code juste avant le chargement de l'image : je vois des petits bout de mon écran par exemple, j'ai des bouts de ma "barre du bas", la barre de titre de ma fenêtre qui apparaissent dans ma fenetre.

C'est plus joli qu'avant (pixel aléatoire affiché) mais le problème persiste.