7 votes

Comment appliquer le DOP tout en conservant une interface utilisateur agréable ?

Actuellement, je souhaite optimiser un peu mon moteur 3D pour les consoles. Plus précisément, je veux être plus compatible avec le cache et aligner mes structures plus orientées vers les données, mais je veux aussi conserver ma 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...
}

L'utilisateur peut donc travailler avec des pointeurs d'interface dans son code.

MAIS
Dans mon moteur, je stocke actuellement des pointeurs vers les nœuds de la scène.

boost::ptr_vector<SceneNode> m_nodes

Dans le cadre d'une conception orientée données, il est donc préférable d'avoir des structures de tableaux et non des tableaux de structures. Ainsi, mon nœud obtient de...

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

std::vector<SceneNode> m_nodes;

à cela...

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

Je vois donc deux problèmes si je veux appliquer la DOP. Tout d'abord, comment puis-je conserver mon interface utilisateur agréable sans que l'utilisateur ait à travailler avec des ID, des index, etc.

Deuxièmement, comment gérer la relocalisation des propriétés lorsque certains vecteurs sont redimensionnés sans laisser les pointeurs de l'interface utilisateur pointer vers le nirvana ?

Actuellement, mon idée est d'implémenter une sorte de handle_vector à partir duquel on obtient un handle pour les "pointeurs" persistants :

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

Ainsi, lorsque le std::vector interne se redimensionne, il met à jour ses handles. Un "handle" stocke un pointeur sur l'objet réel et l'opérateur "->" est surchargé pour réaliser un joli wrapping. Mais cette approche me semble un peu compliquée !

Qu'en pensez-vous ? Comment conserver une interface agréable, mais garder les pensées contiguës en mémoire pour une meilleure utilisation du cache ?

Merci de votre aide !

5voto

Matthieu M. Points 101624

Vous devrez utiliser des poignées plus intelligentes que des pointeurs bruts. Il n'y a aucun moyen de contourner ce problème avec DOP.

Cela signifie que :

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 accidentellement delete sur l'un des pointeurs que vous avez renvoyés maintenant. C'est pourquoi les poignées intelligentes sont toujours préférables.

D'autre part, comment allez-vous gérer la durée de vie du pointeur de mManager est un autre problème :-)

1voto

VitaminCpp Points 294

Pour ceux qui sont intéressés par un exemple pratique de DOP, jetez un coup d'œil à cette fantastique présentation de Niklas Frykholm => http://bitsquid.blogspot.com/2010/05/practical-examples-in-data-oriented.html

Cela m'a aidé à mettre en œuvre mon graphique de scène d'une manière orientée vers les données.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X