IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
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

Boost C++ Discussion :

[BOOST] Problème de sérialisation.


Sujet :

Boost C++

  1. #1
    Invité
    Invité(e)
    Par défaut [BOOST] Problème de sérialisation.
    Bonjour,
    j'essaye d'utiliser boost pour la sérialisation d'objets.

    Par contre ça ne semble pas fonctionner très bien pour les vecteurs de pointeurs, voici un code ou je veux sauvegarder un vecteur de pointeurs :

    Code cpp : 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
     
    #ifndef T_GROUND
    #define T_GROUND
    #include "../../../../include/odfaeg/Graphics/2D/tile.h"
     
    namespace odfaeg {
        namespace g2d {
    class BigTile : public Entity, public Selectable {
        friend class boost::serialization::access;
    public :
        BigTile() : Entity (Vec3f(0, 0, 0), Vec3f (0, 0, 0), Vec3f (0, 0, 0), "E_BIGTILE") {}
        BigTile  (Vec3f pos);
        bool operator== (Entity &entity);
        void addTile (Tile *tile);
        void removeTile (Tile *tile);
        std::vector<Tile*> getTiles ();
        template <typename Archive>
        void serialize(Archive &ar, const unsigned int version) {
             ar & boost::serialization::base_object<Entity>(*this);
             ar & tiles;
        }
        bool isAnimated() const {
            return false;
        }
        bool isModel() const {
            return false;
        }
        bool selectable() const {
            return true;
        }
        bool isLight() const {
            return false;
        }
        bool isShadow() const {
            return false;
        }
        bool isLeaf() const {
            return false;
        }
    private :
        void recomputeSize();
        std::vector<Tile*> tiles;
    };
    }
    }
    #endif // T_GROUND

    Ca se sérialise bien pour la classe tile toute seule :

    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    void serialize(Archive & ar, const unsigned int version) {
                ar & boost::serialization::base_object<Entity>(*this);
            }

    mais une fois que j'ai des objets qui contiennent des vecteurs de pointeurs vers des autres entités, là, ça ne marche plus, En fait ici, j'ai bien la taille du vecteur de tiles qui vaut un lorsque je rajoute une tile à ma grande tile.

    Le problème c'est que lors de la désérialisation, boost appelle le constructeur par défaut, du coup, la tile de ma grande tile ne conserve pas sa position, sa taille, etc...

    A la compilation j'ai même du déclarer ce constructeur sinon ça ne marchait pas :

    Code cpp : 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
     
    Tile::Tile() : Entity (Vec3f(0, 0, 0), Vec3f(1, 1, 1),Vec3f(0.5f, 0.5f, 0.5f),"E_TILE"){
        Face* face = new Face(sf::TrianglesFan, getTransform());
        Vec3f size(1, 1, 0);
        Vec3f position(0, 0, 0);
        Vec3f origin (0.5f, 0.5f, 0);
        Vertex v1(sf::Vector3f(position.x, position.y, position.z));
        Vertex v2(sf::Vector3f(position.x + size.x, position.y, position.z));
        Vertex v3(sf::Vector3f(position.x + size.x, position.y + size.y, position.z));
        Vertex v4(sf::Vector3f(position.x, position.y + size.y,position.z));
        face->append(v1, 0);
        face->append(v2, 1);
        face->append(v3, 2);
        face->append(v4, 3);
        addFace(face);
    }

    Voici le main :

    Code cpp : 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
     
    #include "odfaeg/Graphics/2D/tGround.h"
    #include "odfaeg/Core/boost/serialization/export.hpp"
    #include "boost/archive/text_oarchive.hpp"
    #include "boost/archive/text_iarchive.hpp"
    BOOST_CLASS_EXPORT_GUID(odfaeg::g2d::Tile, "Tile")
    BOOST_CLASS_EXPORT_GUID(odfaeg::g2d::BigTile, "BigTile")
    int main(int argc, char* args[])
    {
        odfaeg::g2d::Tile tile(nullptr, odfaeg::Vec3f(0, 0, 0), odfaeg::Vec3f(120, 60, 0),sf::IntRect(0, 0, 100, 50));
        odfaeg::g2d::BigTile bt(odfaeg::Vec3f(0, 0, 0));
        bt.addTile(&tile);
        std::ostringstream oss;
        {
            boost::archive::text_oarchive oa(oss);
            oa<<bt;
        }
        std::istringstream iss(oss.str());
        {
            boost::archive::text_iarchive ia(iss);
            ia>>bt;
        }
        odfaeg::g2d::Tile* t = bt.getTiles()[0];
        std::cout<<"tile : "<<t->getPosition()<<t->getSize();
        MyAppli app(sf::VideoMode(800, 600, 32), "Test odfaeg");
     
        return app.exec();
    }

    Donc pas de soucis pour sérialiser les objets sauf pour les vecteurs de pointeurs.

  2. #2
    Invité
    Invité(e)
    Par défaut
    Bon bah j'ai trouvé!

    Il suffisait de fouiller dans la documentation :

    http://www.boost.org/doc/libs/1_55_0...l#constructors

    Donc pour les vecteurs de pointeurs (et les pointeurs), boost appelle le constructeur par défaut pour reconstruire les objets, et si on veut utiliser un autre constructeur alors il faut redéfinir deux fonctions :

    Code cpp : 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
    55
    56
    57
     
    namespace boost { namespace serialization {
    template<class Archive>
    inline void save_construct_data(
        Archive & ar, const odfaeg::g2d::Tile * t, const unsigned int file_version) {
        float x = t->getPosition().x;
        float y = t->getPosition().y;
        float z = t->getPosition().z;
        float w = t->getSize().x;
        float h = t->getSize().y;
        float d = t->getSize().z;
        ar<<x;
        ar<<y;
        ar<<z;
        ar<<w;
        ar<<h;
        ar<<d;
        std::vector<odfaeg::Face*> faces = t->getFaces();
        ar<<faces;
        /*odfaeg::BoundingVolume<odfaeg::BoundingBox>* bv = t->getCollisionVolume();
        ar<<bv;*/
        odfaeg::g2d::Entity* parent = t->getParent();
        ar<<parent;
        std::vector<odfaeg::g2d::Entity*> children = t->getChildren();
        ar<<children;
    }
     
    template<class Archive>
    inline void load_construct_data(
        Archive & ar, odfaeg::g2d::Tile * t, const unsigned int file_version
    ){
        float x = t->getPosition().x;
        float y = t->getPosition().y;
        float z = t->getPosition().z;
        float w = t->getSize().x;
        float h = t->getSize().y;
        float d = t->getSize().z;
        ar>>x;
        ar>>y;
        ar>>z;
        ar>>w;
        ar>>h;
        ar>>d;
        std::vector<odfaeg::Face*> faces;
        ar>>faces;
        /*odfaeg::BoundingVolume* bv = t->getCollisionVolume();
        ar<<bv;*/
        odfaeg::g2d::Entity* parent;
        ar>>parent;
        std::vector<odfaeg::g2d::Entity*> children;
        ar>>children;
        // invoke inplace constructor to initialize instance of my_class
        ::new(t)odfaeg::g2d::Tile(nullptr,odfaeg::Vec3f(x, y, z), odfaeg::Vec3f(w, h, d),faces[0]->getMaterial().getTexRect(),parent);
        for (unsigned int i = 0; i < children.size(); i++)
            t->addChild(children[i]);
    }
    }} // namespace .

    Voilà ce code-ci reconstruit bien mon vecteur de tiles.

  3. #3
    Invité
    Invité(e)
    Par défaut
    Par contre il y a quelque chose de bizarre :

    Lorsque j'applique une transformation à l'entité et que je veux la sauvegarder, ça ne marche pas bien :

    Code cpp : 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
    55
    56
    57
    58
    59
    60
    61
    62
     
    namespace boost { namespace serialization {
    template<class Archive>
    inline void save_construct_data(
        Archive & ar, const odfaeg::g2d::Tile * t, const unsigned int file_version) {
        odfaeg::Vec3f position = t->getLocalBounds().getPosition();
        odfaeg::Vec3f size = t->getLocalBounds().getSize();
        odfaeg::Vec3f scale = t->getScale();
        odfaeg::Vec3f origin = t->getOrigin();
        float rotation = t->getRotation();
        odfaeg::Vec3f translation = t->getTranslation();
        ar<<position;
        ar<<size;
        ar<<scale;
        ar<<origin;
        ar<<rotation;
        ar<<translation;
        std::vector<odfaeg::Face*> faces = t->getFaces();
        ar<<faces;
        odfaeg::BoundingVolume<odfaeg::BoundingBox>* bv = t->getCollisionVolume();
        ar<<bv;
        odfaeg::g2d::Entity* parent = t->getParent();
        ar<<parent;
        std::vector<odfaeg::g2d::Entity*> children = t->getChildren();
        ar<<children;
    }
     
    template<class Archive>
    inline void load_construct_data(
        Archive & ar, odfaeg::g2d::Tile * t, const unsigned int file_version
    ){
        odfaeg::Vec3f position;
        odfaeg::Vec3f size;
        odfaeg::Vec3f origin;
        float rotation;
        odfaeg::Vec3f scale;
        odfaeg::Vec3f translation;
        ar>>position;
        ar>>size;
        ar>>origin;
        ar>>rotation;
        ar>>scale;
        ar>>translation;
        std::vector<odfaeg::Face*> faces;
        ar>>faces;
        odfaeg::BoundingVolume<odfaeg::BoundingBox>* bv;
        ar>>bv;
        odfaeg::g2d::Entity* parent;
        ar>>parent;
        std::vector<odfaeg::g2d::Entity*> children;
        ar>>children;
        // invoke inplace constructor to initialize instance of my_class
        ::new(t)odfaeg::g2d::Tile(nullptr,position, size,faces[0]->getMaterial().getTexRect(),parent);
        for (unsigned int i = 0; i < children.size(); i++)
            t->addChild(children[i]);
        t->setOrigin(origin);
        t->scale(scale);
        t->rotate(rotation);
        t->move(translation);
     
    }
    }} // namespace ...

    En effet, ici ça m'affiche que la position de la tile est de : 87, 76, 0.

    Hors que normalement je devrais avoir une position de 100, 100, 0 vu que je la bouge de 100 en x et en y!

    Code cpp : 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
     
    int main(int argc, char* args[]) {
        odfaeg::g2d::BigTile test(odfaeg::Vec3f (0, 0, 0));
        odfaeg::g2d::Tile *tile = new odfaeg::g2d::Tile(nullptr, odfaeg::Vec3f(0, 0, 0), odfaeg::Vec3f(120, 60, 0), sf::IntRect(0, 0, 100, 50));
        tile->setPosition(odfaeg::Vec3f(100, 100, 0));
        test.addTile(tile);
        std::ofstream ofs ("SerialisationTest");
        {
            boost::archive::text_oarchive oa(ofs);
            oa<<test;
        }
        std::ifstream ifs("SerialisationTest");
        {
            boost::archive::text_iarchive ia(ifs);
            ia>>test;
        }
        std::vector<odfaeg::g2d::Tile*> tiles = test.getTiles();
     
        for (unsigned int i = 0; i < tiles.size(); i++) {
            std::cout<<"position : "<<tiles[i]->getPosition()<<std::endl;       
        }
        return 0;
    }

  4. #4
    Invité
    Invité(e)
    Par défaut
    Bon je pense que je vais revenir à mon ancien système sans sérialisation.

    La sérialisation m'a l'air assez galère à faire surtout lorsqu'on utilise des pointeurs, des buffers et l'héritage.

    Surtout que j'utilise en plus des vertex buffer object donc faut que lorsque j'envoie mes données du serveur vers le client, tout soit bon pour que ça s'affiche bien. (Hors ici dans mon cas il n'y a plus rien qui s'affiche.

    Donc retour à la bonne vieille méthode (qui elle fonctionne bien) :

    Côté serveur :

    Code cpp : 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
     
    if (request == "GETTILES") {
                    std::string response;
                    odfaeg::SymEncPacket packet;
                    BigTile* bt = static_cast<BigTile*>(World::getEntities<Entity>("E_BIGTILE")[0]);
     
                    /*std::ostringstream oss;
                    {
                        boost::archive::text_oarchive oa(oss);
                        oa<<(*bt);
                    }
                    response = oss.str();
                    /*istringstream iss(response);
                    {
                        boost::archive::text_iarchive ia(iss);
                        ia>>(*bt);
                    }*/
                    std::vector<Tile*> tiles = bt->getTiles();
                    response = conversionIntString(tiles.size())+"*";
                    for (unsigned int i = 0; i < tiles.size(); i++) {
                        odfaeg::Vec2f position = odfaeg::Vec2f(tiles[i]->getPosition().x, tiles[i]->getPosition().y);
                        odfaeg::Vec2f size = odfaeg::Vec2f(tiles[i]->getSize().x, tiles[i]->getSize().y);
                        sf::IntRect texRect = tiles[i]->getFaces()[0]->getMaterial().getTexRect();
                        response+=tiles[i]->getFaces()[0]->getMaterial().getTexId()+"*";
                        response+=odfaeg::conversionIntString(position.x)+"*"+odfaeg::conversionIntString(position.y)+"*";
                        response+=odfaeg::conversionIntString(size.x)+"*"+odfaeg::conversionIntString(size.y)+"*";
                        response+=odfaeg::conversionIntString(texRect.left)+"*"+odfaeg::conversionIntString(texRect.top)+"*"+odfaeg::conversionIntString(texRect.width)+"*"+odfaeg::conversionIntString(texRect.height);
                        if (i != tiles.size() - 1)
                            response += "*";
                    }
                    packet<<response;
                    user->sendTcpPacket(packet);

    Et côté client :

    Code cpp : 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
     
     std::string request = "GETTILES";
            packet<<request;
            Network::sendTcpPacket(packet);
            std::string response = Network::getLastResponse();
     
            if (response == "") {
                std::cerr<<"error : failed to load tiles";
            } else {
                /*BigTile* bt = new BigTile(Vec3f(0, 0, 0));
                std::istringstream iss(response);
                {
                    boost::archive::text_iarchive ia (iss);
                    ia>>(*bt);
                }
                std::vector<Tile*> tiles = bt->getTiles();
                std::cout<<tiles.size()<<std::endl;
                for(unsigned int i = 0; i < tiles.size(); i++) {
     
                    Material &material = tiles[i]->getFaces()[0]->getMaterial();
                    material.addTexture(tm.getResourceByAlias(material.getTexId()), material.getTexRect());
                    //std::cout<<"textCoord: "<<material.getTexRect().left<<" "<<material.getTexRect().top<<" "<<material.getTexRect().width<<" "<<material.getTexRect().height<<std::endl;
                    std::cout<<"position : "<<tiles[i]->getPosition()<<std::endl;
                }
                World::addEntity(bt);*/
                std::vector<std::string> infos = split(response, "*");
                int size = conversionStringInt(infos[0]);
                BigTile* bt = new BigTile(Vec3f(0, 0, 0));
                for (int i = 0; i < size; i++) {
                    std::string texId = infos[i*9+1];
                    Vec2f position(conversionStringInt(infos[i*9+2]), conversionStringInt(infos[i*9+3]));
                    Vec2f size(conversionStringInt(infos[i*9+4]), conversionStringInt(infos[i*9+5]));
                    IntRect rect(conversionStringInt(infos[i*9+6]),conversionStringInt(infos[i*9+7]),conversionStringInt(infos[i*9+8]),conversionStringInt(infos[i*9+9]));
                    Tile* tile = new Tile(tm.getResourceByAlias(texId),Vec3f(position.x, position.y, position.y + size.y * 0.5f),Vec3f(size.x, size.y, 0),rect);
                    bt->addTile(tile);
                }
                World::addEntity(bt);
            }

    Il est vrai que les objets sont assez complexe et là je n'ai pas encore tout transférer (il me reste encore les volumes englobants à transférer pour les tests de collisions) mais je pense que c'est plus simple de faire comme ça plutôt que de sérialiser tout ça surtout que j'ai des vectors avec des pointeurs sur un objet d'une classe dérivée et que cette même classe peut aussi contenir des vectors avec des pointeurs sur des objets dérivés et ainsi de suite...

Discussions similaires

  1. Réponses: 2
    Dernier message: 14/11/2009, 03h17
  2. [boost] problème de compilation
    Par r0d dans le forum Bibliothèques
    Réponses: 1
    Dernier message: 06/12/2006, 14h47
  3. [BOOST] Problème avec les threads
    Par SOAD08 dans le forum Dev-C++
    Réponses: 7
    Dernier message: 08/10/2006, 11h23
  4. Problème de sérialisation
    Par CheryBen dans le forum Entrée/Sortie
    Réponses: 18
    Dernier message: 15/09/2005, 12h55
  5. [Boost] Problème de compilation (io_fwd.hpp)
    Par bigquick dans le forum MFC
    Réponses: 3
    Dernier message: 22/04/2005, 10h48

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