Bienvenue, Invité. Merci de vous connecter ou de vous inscrire.
Avez-vous perdu votre e-mail d'activation ?

Auteur Sujet: Ecran blanc & loadFromMemory  (Lu 4042 fois)

0 Membres et 1 Invité sur ce sujet

nicooomg

  • Jr. Member
  • **
  • Messages: 66
    • Voir le profil
Ecran blanc & loadFromMemory
« le: Octobre 18, 2012, 02:35:34 am »
Bonjour,

j'essaye de precharger des textures en memoire, pour un chargement plus dynamique.
Voici ma classe qui va garder tout en memoire...
class Memory
{
        public:
                Memory() {};
                ~Memory()
                {
                    std::cout << "Call ~Memory() " << std::endl;
                }

        /// Pas important.
                void preload(const std::string& pack)
                {
                    Reader* own_reader = new Reader();
                    Node* child = own_reader->Read(pack);

                    m_nodes.insert(std::make_pair(Filesystem::extractFilename(pack),
                                    std::make_pair(own_reader, child)));
                }

        /// Ceci, marche a merveille ! Aucune exception levée
                void loadGFX(const std::string& pack, const long id)
                {
                    try
                    {
                        Node& node(m_nodes[pack].second->find(id));
                        MemoryRessource<sf::Texture>* res = new MemoryRessource<sf::Texture>(node.get(m_nodes[pack].first->stream()));
                m_loaded_gfx.insert(std::make_pair(MemoryKey(node.getId(), node.getOffset()), res));
                    }
                    catch(...)
                    {
                        throw false;
                    }
                }


                Node& operator [] (const std::string& key) { return *(m_nodes[key].second); }
        Node& operator [] (const char* key) { return *(m_nodes[std::string(key)].second); }

                inline bool isLoaded(const MemoryKey& key) { return m_loaded_gfx.find(key) != m_loaded_gfx.end(); }

        template<class S>
                static inline S& getGFX(const long id) /// longer to perform ...!
                {
                    std::for_each(std::begin(m_loaded_gfx), std::end(m_loaded_gfx), [&](std::pair<MemoryKey, MemoryRessource<sf::Texture>*> res)
            {
                if(res.first.first == id) { return res.second->get(); }
            });
                }

        /// Retournera un sf::Texture
        template<class S>
                static inline S& getGFX(const MemoryKey& key)
                {
                    return m_loaded_gfx[key]->get();
                }

        private:

                static std::map<std::string, std::pair<Reader*, Node*>> m_nodes;

                static std::map<MemoryKey, MemoryRessource<sf::Texture>*> m_loaded_gfx;
};

En premier, je fais un void preload(), pas important, cela va remplir le membre m_nodes.
Ensuite, je vais faire loadGFX() avec un identifiant. Cela va charger une sf::Texture dans m_loaded_gfx.
Voici la classe MemoryRessource:

template<class S>
class MemoryRessource
{
public:
    MemoryRessource() {}
    MemoryRessource(const std::vector<char>& bytes) :
        m_buffer()
        {
            if(!m_buffer.loadFromMemory(&bytes[0], bytes.size()))
            {
                std::cout << "Failed to load from memory ! " << std::endl;
                throw false;
            }
            else
            {
                std::cout << "Loaded " << bytes.size() << std::endl;
            }
        }
    ~MemoryRessource()
    {
        std::cout << "Destroying !"<<std::endl;
    }

    inline const S& get() const { return m_buffer; }
private:
    S m_buffer;
};

On remarquera que si le loadFromMemory est mauvais, une exception est levée, et attrapée dans loadGFX.
Jusqu'ici , tout va bien.
Voici maintenant le main :

short SplashScreen::Run()
{


    /// Preloading archives
    std::for_each(std::begin(Config::ARCHIVES), std::end(Config::ARCHIVES), [&](const std::string& pack)
    {
        std::string full_name = pack;
        full_name += Config::EXT;
        m_game.getMemory().preload(full_name); // Tout va bien ...
    });

    Memory mem;

    Node& gfx(mem["Graphics"]);

    std::vector<long> ids_to_load = {2, 5};

    std::for_each(std::begin(ids_to_load), std::end(ids_to_load), [&](long id)
    {
        try
        {
            mem.loadGFX("Graphics", id);
        }
        catch(...)
        {
            std::cout << "Could not load: " << "Graphics:" << id << std::endl;
        }
    });
/// Aucune exception levée, nous avons donc nos sf::Texture chargés en mémoire

    std::cout << "loading texture into sprite ......."<<std::endl;
    sf::Sprite s_sprite(mem.getGFX<sf::Texture>(static_cast<long>(2)));
    std::cout << "OK loaded"<<std::endl;


    /// Rendering loop
    while(m_game.getRenderer().getApp().isOpen() && m_game.isRunning())
    {
        /// Clearing the window
        m_game.getRenderer().getApp().clear();
        sf::Event event;

        while(m_game.getRenderer().getApp().pollEvent(event))
        {
            /// Event handling

                /// SFML
            if(event.type == sf::Event::Closed)
            {
                /// This will automatically terminate the networker thread & nicely exit the game
                m_game.crash();
            }
        }

        /// Drawings (SFML)
            /// The sprite (background)
        m_game.getRenderer().getApp().draw(s_sprite);

        /// Displayings
        m_game.getRenderer().getApp().display();

    }

    return -1;
}

Bref, aucune erreur d'affichée malgrès les nombreuses conditions et try{}, pourtant: écran blanc :|

Une idée quelqu'un ?

Merci d'avance, nico

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : Ecran blanc & loadFromMemory
« Réponse #1 le: Octobre 18, 2012, 08:17:24 am »
Il y a pourtant une chose essentielle que tu ne testes jamais : la recherche par clé dans ton conteneur (find, operator[]). Par contre je ne sais pas si c'est ça qui merde (ton code est court mais compliqué à décoder !).

Et sinon, c'est normal que tu précharges dans m_game.getMemory(), mais ensuite utilises une toute nouvelle instance de Memory pour le reste ?
Laurent Gomila - SFML developer

nicooomg

  • Jr. Member
  • **
  • Messages: 66
    • Voir le profil
Re : Ecran blanc & loadFromMemory
« Réponse #2 le: Octobre 18, 2012, 02:24:56 pm »
la fonction find() lance une exception si long id n'est pas trouvé, donc c'est pas ca!

lezebulon

  • Full Member
  • ***
  • Messages: 235
    • Voir le profil
Re : Ecran blanc & loadFromMemory
« Réponse #3 le: Octobre 18, 2012, 02:58:45 pm »
ouais mais le operator[] ne jette pas d'exception et il va te construire un objet par défaut quand il trouve pas la clé...

nicooomg

  • Jr. Member
  • **
  • Messages: 66
    • Voir le profil
Re : Ecran blanc & loadFromMemory
« Réponse #4 le: Octobre 18, 2012, 11:52:51 pm »
le probleme venait de find () :

En effet, l'algorithme STL std::for_each() ne prend pas en compte les "return" , du coup mon return marchait pas, d'ou la texture vide.

voila ^^

merci quand meme !

nico

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : Ecran blanc & loadFromMemory
« Réponse #5 le: Octobre 19, 2012, 08:06:39 am »
Et ton compilo ne t'a pas averti à propos de ça ? Tu devrais monter le niveau de warnings ;)

Et sinon, simple curiosité, pourquoi utilises-tu std::for_each + lambda au lieu du mot-clé foreach ?
Laurent Gomila - SFML developer

kamui

  • Sr. Member
  • ****
  • Messages: 291
    • Voir le profil
Re : Ecran blanc & loadFromMemory
« Réponse #6 le: Octobre 19, 2012, 09:46:08 am »
il y a également l'inférence de type et les range-based for qui pourrait simplifier le code, si je ne me trompe pas :
for (auto& pack : Config::ARCHIVES)
{
   //[...]
}
 

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : Ecran blanc & loadFromMemory
« Réponse #7 le: Octobre 19, 2012, 10:15:29 am »
Oui pardon, j'ai dit "mot-clé foreach" mais ça n'existe pas, il fallait comprendre "range-based for" :)
Laurent Gomila - SFML developer

kamui

  • Sr. Member
  • ****
  • Messages: 291
    • Voir le profil
Re : Ecran blanc & loadFromMemory
« Réponse #8 le: Octobre 19, 2012, 11:41:42 am »
Ok^^

à l'OP, j'ai mi un '&' devant le auto pour travailler avec des références, mais tu peux l'enlever si tu n'as besoin que de copies (ce qui sur des std::string est toujours suffisant je penses). Si tes chaines ne sont pas trop lourdes ça pourrait même optimiser légèrement tes performances.

nicooomg

  • Jr. Member
  • **
  • Messages: 66
    • Voir le profil
Ecran NOIR & loadFromMemory
« Réponse #9 le: Octobre 23, 2012, 01:16:11 am »
Petit changement.... Maintenant j'ai un écran noir :/

Voici, la boucle principale:

short SplashScreen::Run()
{

    sf::Sprite splash_screen;

    bool connect_attempt = false, splash_load = false;

    /// Running loading thread
    m_game.runPreloader();

    /// Rendering loop
    while(m_game.getRenderer().getApp().isOpen() && m_game.isRunning())
    {
        /// Clearing the window
        m_game.getRenderer().getApp().clear();
        sf::Event event;

        while(m_game.getRenderer().getApp().pollEvent(event))
        {
            /// Event handling
                /// SFGUI
            m_desktop.HandleEvent(event);
                /// SFML
            if(event.type == sf::Event::Closed)
            {
                /// This will automatically terminate the networker thread & nicely exit the game
                m_game.crash();
            }
        }

        if(!splash_load)
        {
            try
            {
                Memory& memory(m_game.getMemory());
                splash_screen.setTexture(memory.getTexture(static_cast<long>(5)));
                splash_load = true;

                std::cout << "Set Texture!"<<std::endl;
            }
            catch(bool)
            {
                std::cout << "Failed to set texture"<<std::endl;
            }

        }

        /// Drawings (SFML)
            /// The sprite (background)
        if(splash_load)
        {
            m_game.getRenderer().getApp().draw(splash_screen);
        }
        m_game.getRenderer().getApp().resetGLStates();

        /// Displayings
        m_desktop.Update(0.f);
        m_game.getRenderer().display(m_game.getRenderer().getApp());
        m_game.getRenderer().getApp().display();
    }

    return -1;
}

La fonction m_game.runPreloader(); va precharger les images dans l'instance de m_game.getMemory().

Ensuite, voici le header de la classe Memory:
typedef std::pair<long, long> MemoryKey;
                // ID, Offset
template<class S>
class MemoryRessource
{
public:
    MemoryRessource() {}
    MemoryRessource(const std::vector<char>& bytes) :
        m_buffer()
        {
            if(!m_buffer.loadFromMemory(&bytes[0], bytes.size()))
            {
                std::cout << "Failed to load from memory ! " << std::endl;
                throw false;
            }
            else
            {
                std::cout << "loadFromMemory: OK. @ address: " << &m_buffer << std::endl;
            }
        }
    ~MemoryRessource()
    {
        std::cout << "Destroying !"<<std::endl;
    }

    inline S& get() {
        std::cout << "Get texture (width=" << m_buffer.getSize().x << "; height=" << m_buffer.getSize().y << ")" << std::endl;
        return m_buffer;
        }
private:
    S m_buffer;
};

class Memory
{
        public:
                Memory() :
                    m_nodes(),
                    m_loaded_gfx(),
                    m_mtx_loader(PTHREAD_MUTEX_INITIALIZER),
                    m_percent(0)
            {}
                ~Memory()
                {
                    std::cout << "Call ~Memory() " << std::endl;
                }

                void loadPackage(const std::string& pack)
                {
                    Reader* own_reader = new Reader();
                    Node* child = own_reader->Read(pack);

                    m_nodes.insert(std::make_pair(Filesystem::extractFilename(pack),
                                    std::make_pair(own_reader, child)));
                }

                void loadGraphic(const long id)
                {
            try
            {
                Node& node(m_nodes[m_graphicPackage].second->find(id));
                MemoryRessource<sf::Texture>* res = new MemoryRessource<sf::Texture>(node.get(m_nodes[m_graphicPackage].first->stream()));
                m_loaded_gfx.insert(std::make_pair(MemoryKey(node.getId(), node.getOffset()), res));
            }
            catch(bool)
            {
                throw false;
            }
        }

        Node& operator[] (const std::string& key) { return *(m_nodes[key].second); }

        inline sf::Texture& getTexture(const MemoryKey& key) { return m_loaded_gfx[key]->get(); }
        inline sf::Texture& getTexture(const long key)
        {
            for(auto& res : m_loaded_gfx)
            {
                if(res.first.first == key)
                {
                    return res.second->get();
                }
            }
            /// In case we didn't found id... !
            throw false;
        }



                inline bool isLoaded(const MemoryKey& key) { return m_loaded_gfx.find(key) != m_loaded_gfx.end(); }
                inline pthread_mutex_t* getMutex() { return &m_mtx_loader; }
                inline long& getPercent() { return m_percent; }

        private:

                std::map<std::string, std::pair<Reader*, Node*>> m_nodes;

                std::map<MemoryKey, MemoryRessource<sf::Texture>*> m_loaded_gfx;

                pthread_mutex_t m_mtx_loader;
                long m_percent;
                const std::string m_graphicPackage = "Graphics";
};


Le chargement se passe bien.

En tout cas, voici le debug...:


Le truc vraiment etrange, c'est que c'est la meme adresse apres chargement, et quand je tente d'y acceder.
De plus, la taille affichée sur la console est la bonne.

Une idée d'où vient le probleme ?

merci, nico

nicooomg

  • Jr. Member
  • **
  • Messages: 66
    • Voir le profil
Re : Ecran blanc & loadFromMemory
« Réponse #10 le: Octobre 23, 2012, 04:22:23 am »
De plus:

Dans le getter de MemoryRessource,
j'ai ajotué:
m_buffer.copyToImage().saveToFile("test.jpg");
-> Image noire..... Problème !!

Ensuite j'ai remonté un peu, j'ai mis la meme chose dans le constructeur !
-> Bonne image, et en plus, l'image s'affiche à l'écran !

Je comprend plus rien maintenant :(