Как применить DOP и сохранить приятный пользовательский интерфейс? - PullRequest
7 голосов
/ 06 октября 2010

В настоящее время я хочу немного оптимизировать свой 3d движок для консолей. Точнее, я хочу быть более дружественным к кешу и выровнять свои структуры, ориентируясь на данные, но также хочу сохранить мой приятный пользовательский интерфейс.

Например:

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...
}

Таким образом, пользователь может работать с указателями интерфейса в своем коде.

НО
В моем движке в настоящее время я храню указатели на узлы сцены.

boost::ptr_vector<SceneNode> m_nodes

Так что в ориентированном на данные проектировании рекомендуется иметь структуры массивов, а не массивы структур. Таким образом, мой узел получает от ...

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

std::vector<SceneNode> m_nodes;

к этому ...

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

Так что я вижу здесь две проблемы, если я хочу применить DOP. Во-первых, как мне сохранить свой приятный пользовательский интерфейс, не заставляя пользователя работать с идентификаторами, индексами и так далее?

Во-вторых, как мне управлять перемещением свойств, когда некоторые векторы изменяют размер, не позволяя указателям интерфейса пользователя указывать на нирвану?

В настоящее время моя идея заключается в реализации своего рода handle_vector, из которого вы получаете дескриптор для постоянных «указателей»:

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

Таким образом, при изменении размера intern std :: vector он обновляет свои дескрипторы. «Дескриптор» хранит указатель на реальный объект, а оператор «->» перегружен, чтобы получить красивую упаковку. Но этот подход кажется мне сложным?!

Что ты думаешь? Как сохранить приятный интерфейс, но держать мысли непрерывными в памяти для лучшего использования кэша?

Спасибо за любую помощь!

Ответы [ 2 ]

5 голосов
/ 06 октября 2010

Вам нужно будет использовать более умные ручки, чем необработанные указатели. Обойтись без DOP невозможно.

Это означает:

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;
};

Еще один очень хороший момент: пользователь не может случайно вызвать delete по одному из указателей, которые вы вернули сейчас. Вот почему умные ручки всегда лучше.

С другой стороны: как вы собираетесь справляться со временем жизни пуантиста mManager - это еще одна проблема: -)

1 голос
/ 07 октября 2010

Для тех, кто интересуется практическим примером DOP, взгляните на эту фантастическую презентацию от Никласа Фрикхольма => http://bitsquid.blogspot.com/2010/05/practical-examples-in-data-oriented.html

Это помогло мне реализовать мой граф сцены ориентированным на данные способом.

...