2010-10-06 3 views
6

Actuellement, je veux optimiser mon moteur 3D pour les consoles un peu. Plus précisément, je veux être plus amical de cache et aligner mes structures plus axées sur les données, mais je veux aussi garder ma belle interface utilisateur.Comment appliquer DOP et conserver une belle interface utilisateur?

Par exemple:

bool Init() 
{ 
    // Create a node 
    ISceneNode* pNode = GetSystem()->GetSceneManager()->AddNode("viewerNode"); 

    // Create a transform component 
    ITransform* pTrans = m_pNode->CreateTransform("trans"); 
    pTrans->SetTranslation(0,1.0f,-4.0f); 
    pTrans->SetRotation(0,0,0); 

    // Create a camera component 
    ICamera* pCam = m_pNode->CreateCamera("cam", pTrans); 
    pCam->LookAt(Math::Vec3d(0,0,0)); 

    // And so on... 
} 

Ainsi, l'utilisateur peut travailler avec des pointeurs d'interface dans son code.

MAIS
Dans mon moteur je stocke actuellement des pointeurs vers des noeuds de scène.

boost::ptr_vector<SceneNode> m_nodes 

Ainsi, dans la conception orientée données, il est bon d'avoir struct de tableaux et non des tableaux de struct. Donc, mon noeud obtient de ...

class SceneNode 
{ 
private: 
    Math::Vec3d m_pos; 
}; 

std::vector<SceneNode> m_nodes; 

à cette ...

class SceneNodes 
{ 
    std::vector<std::string> m_names; 
    std::vector<Math::Vec3d> m_positions; 
    // and so on... 
}; 

Je vois deux problèmes ici si je veux appliquer DOP. Tout d'abord, comment pourrais-je conserver ma belle interface utilisateur sans que l'utilisateur doive travailler avec des ID, des index, etc.?

Deuxièmement comment gérer les relocations de propriétés lorsque certains vecteurs se redimensionnent sans laisser les pointeurs d'interface pointent vers nirvana?

Actuellement, mon idée est de mettre en œuvre une sorte de handle_vector à partir duquel vous obtenez une poignée pour « pointeurs » persistants:

typedef handle<ISceneNodeData> SceneNodeHandle; 
SceneNodeHandle nodeHandle = nodeHandleVector.get_handle(idx); 

Ainsi, lorsque le stagiaire std :: vector redimensionne, il met à jour ses poignées. Un "handle" stocke un pointeur sur l'objet réel et l'opérateur "->" est surchargé pour obtenir un bel emballage. Mais cette approche me semble compliquée ?!

Qu'en pensez-vous? Comment conserver une interface sympa, mais continuer à penser contigu en mémoire pour une meilleure utilisation du cache?

Merci pour toute aide!

+0

Qu'est-ce que 'DOP' dans votre utilisation? –

+0

La programmation orientée données est dans mon exemple la conversion de tableaux de structs en une structure de tableaux. La méthode virtuelle Update() est extraite d'un SceneNode et est alors membre de la structure SceneNodes. Je peux donc avancer linéairement sur mes tableaux auxquels je suis intéressé. – VitaminCpp

Répondre

5

Vous devrez utiliser des poignées plus intelligentes que les pointeurs bruts. Il n'y a pas moyen de contourner cela avec DOP.

Cela signifie:

class SceneNode 
{ 
public: 
    std::string const& getName() const { mManager->getSceneName(mId); } 
    void setName(std::string const& name) { mManager->setSceneName(mId, name); } 

    // similar with other data 
private: 
    ISceneManager* mManager; 
    size_t mId; 
}; 

Un très bon point cependant: l'utilisateur ne peut pas appeler par mégarde sur un delete du pointeur vous revenez maintenant. C'est pourquoi les poignées intelligentes sont toujours meilleures.

D'autre part: comment allez-vous faire face à la durée de vie du mManager de est pointée un autre problème :-)

+0

Oui j'ai aussi pensé dans ce sens, mais ça ne me semble pas très élégant ... Mais je pense que je vais choisir une telle solution et cacher l'indexation de l'utilisateur. Dans ma conception, tous les «managers» sont globaux. Donc, un simple assert() en mode débogage pour s'assurer que nous avons un gestionnaire valide est suffisant. C'est un gros inconvénient de DOP. Je vous remercie! – VitaminCpp

+0

@VitaminCpp: ce n'est pas vraiment un inconvénient, en ce qui me concerne, car j'utilise toujours des poignées intelligentes de toute façon lors de la conception d'une interface. Beaucoup plus facile à faire évoluer, peut inclure le comptage de références de manière transparente, protège le contenu et peut fournir une compatibilité binaire beaucoup plus facilement. –

+0

En effet, c'est un argument fort! Maintenant, le plus dur est de remodeler le nœud de la scène lui-même DOP ... :(Merci beaucoup! – VitaminCpp

Questions connexes