Pergunta

Atualmente, quero otimizar um pouco meu mecanismo 3D para consoles. Mais precisamente, quero ser mais amigável ao cache e alinhar minhas estruturas mais orientadas a dados, mas também quero manter minha boa interface de usuário.

Por exemplo:

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

Portanto, o usuário pode trabalhar com ponteiros de interface em seu código.

MAS
No meu motor, atualmente guardo ponteiros para nós de cena.

boost::ptr_vector<SceneNode> m_nodes

Portanto, no design orientado a dados, é uma boa prática ter estruturas de matrizes e não matrizes de estruturas. Então, meu nó é de ...

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

std::vector<SceneNode> m_nodes;

para isso...

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

Então, vejo dois problemas aqui se quiser aplicar o DOP. Em primeiro lugar, como eu poderia manter minha boa interface de usuário sem que o usuário trabalhe com IDs, índices e assim por diante?

Em segundo lugar, como lidar com as realocações das propriedades quando alguns vetores redimensionam sem deixar os usuários interface os ponteiros apontam para o Nirvana?

Atualmente, minha idéia é implementar um tipo de handle_vector do qual você obtém uma alça para "ponteiros" persistentes:

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

Então, quando o vetor estagiário estagiário redimensiona, ele atualiza suas alças. Um operador de "alça" armazena um ponteiro para o objeto real e o operador "->" está sobrecarregado para alcançar um bom embrulho. Mas essa abordagem me parece complicada?!

O que você acha? Como manter uma boa interface, mas mantenha pensa em contíguo na memória para melhor uso do cache?

Obrigado por qualquer ajuda!

Foi útil?

Solução

You will need to use smarter handles than raw pointers. There is no way around it with DOP.

This means:

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

One very good point though: the user cannot accidently call delete on one of the pointer you returned now. That's why smart handles are always better.

On the other hand: how are you going to deal with the lifetime of the pointee of mManager is another issue :-)

Outras dicas

For those interested in a practical example of DOP, have a look at this fantastic presentation from Niklas Frykholm => http://bitsquid.blogspot.com/2010/05/practical-examples-in-data-oriented.html

This helped me to implement my scene graph in a data oriented manner.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top