2017-08-13 5 views
0

Je travaille sur un moteur graphique. Le moteur a un std::vector de drawables. Un Drawable est un objet qui contient un Model et un DrawableObject, qui à son tour contient un programme de shaders et un bouquet de sommets provenant d'un modèle 2D ou 3D. L'ajout de nouveaux Drawables se passe bien, le problème se produit lorsque j'essaie de retirer un Drawable. Le dernier Drawable sera toujours supprimé et l'avant-dernier aura ses valeurs modifiées.Un mauvais élément est supprimé après avoir quitté la méthode qui a utilisé std :: erase avec succès

code

Drawable.h

class Drawable 
{ 
public: 
    Drawable& operator=(const Drawable& other) 
    { 
     Drawable tmp(other); 
     std::swap(model, other.model); 
     std::swap(drawableObject, other.drawableObject); 
     return *this; 
    } 

    Drawable(domain::Model& model, DrawableObject& drawableObject) : 
     model(model), 
     drawableObject(drawableObject) 
    {} 

    domain::Model& model; 
    DrawableObject& drawableObject; 
}; 

game.cpp

void Game::init_game() 
{ 
    human = domain::Model(glm::vec3(0, 0, -3)); 
    moveables.push_back(&human); 
    room = domain::Model(glm::vec3(0, 0, -10)); 
    props.push_back(&room); 
    cube = domain::Model(glm::vec3(0, 0, 0)); 
    props.push_back(&cube); 
} 

void Game::init_graphics_engine() 
{ 
    // ... load graphics models 

    // add drawables 
    graphicsEngine->add(cube, Drawable::CUBE); 
    graphicsEngine->add(human, Drawable::HUMAN); 
    graphicsEngine->add(room, Drawable::ROOM); 
    graphicsEngine->add(topDownScene->cursor, Drawable::MARKER); 
} 

graphics_engine/engine.cpp

void Engine::add(domain::Model& model, unsigned int object) 
{ 
    auto drawableObject = drawableObjects[object]; 
    // make sure not to add a model that already is represented 
    auto it = std::find_if(drawables.begin(), drawables.end(), [&model](Drawable& drawable) {return &drawable.model == &model;}); 
    if(drawableObject && it == drawables.end()) 
     drawables.push_back(Drawable(model, *drawableObject)); 
} 

void Engine::remove(domain::Model& model) 
{ 
    auto predicate = [&model](Drawable& drawable) 
    { 
     return &drawable.model == &model; 
    }; 
    drawables.erase(std::remove_if(drawables.begin(), drawables.end(), predicate), drawables.end()); 
} 

Scènes

C'est ce que la scène ressemble quand je commence l'application:

scene on startup

C'est ce que la scène ressemble après avoir tenté d'effacer le petit cube « humain » dans le milieu:

enter image description here

le code supprime le dernier Drawable, qui est le marqueur blanc, à la place du cube «humain», et a changé la position z de la pièce. Cela arrive presque toujours, il supprime le dernier élément et a changé le z de la seconde pour durer. Cela ne fonctionne que si j'ajoute le cube 'human' en dernier dans la méthode init.

points d'arrêt

Avant de retirer l'objet:

enter image description here

Après avoir retiré l'objet:

enter image description here

Ceci est correct.

Quitter la méthode remove et jeter un oeil dans la boucle de rendu:

enter image description here

D'une certaine façon changé. J'ai changé les membres de la classe en pointeurs.

+3

Attendez, votre opérateur d'affectation de copie modifie le côté droit? Et quoi de neuf avec 'tmp'? – NPE

+0

@NPE [idiome de copie et d'échange] (https://stackoverflow.com/questions/3279543/what-is-the-copy-and-swap-idiom). – LogicStuff

+0

@LogicStuff: C'est ce que je suppose que c'est * signifié * être, mais ce n'est pas si vous lisez le code de près (à moins que je ne vois pas quelque chose, ce qui est bien sûr aussi une possibilité). – NPE

Répondre

0

Maintenant ça marche. Les commentaires étaient corrects, je n'ai rien fait avec la variable tmp.

class Drawable 
{ 
public: 
    Drawable& operator=(const Drawable& other) 
    { 
     this->model = other.model; 
     this->drawableObject = other.drawableObject; 
     return *this; 
    } 

    Drawable(domain::Model* model, std::shared_ptr<DrawableObject> drawableObject) : 
     model(model), 
     drawableObject(drawableObject) 
    {} 

    domain::Model* model; 
    std::shared_ptr<DrawableObject> drawableObject; 
};