Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to apply DOP and keep a nice user interface?

Currently I want to optimize my 3d engine for consoles a bit. More precisely I want to be more cache friendly and align my structures more data oriented, but also want to keep my nice user interface.

For example:

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

So the user can work with interface pointers in his code.

BUT
In my engine I currently store pointers to scene nodes.

boost::ptr_vector<SceneNode> m_nodes

So in data oriented design it's good practice to have structs of arrays and not arrays of structs. So my node gets from...

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

std::vector<SceneNode> m_nodes;

to this...

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

So I see two problems here if I want to apply DOP. Firstly how could I keep my nice user interface without having the user to work with IDs, indexes and so on?

Secondly how do I handle relocations of properties when some vectors resize without letting users interface pointers point to nirvana?

Currently my idea is to implement a kind of handle_vector from which you get a handle for persistent "pointers":

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

So when the intern std::vector resizes, it updates its handles. A "handle" stores a pointer to the actual object and the "->" operator is overloaded to achive a nice wrapping. But this approach sounds a bis complicated to me?!

What do you think? How to keep a nice interface, but keep thinks contiguous in memory for better cache usage?

Thanks for any help!

like image 946
VitaminCpp Avatar asked Oct 06 '10 12:10

VitaminCpp


2 Answers

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 :-)

like image 117
Matthieu M. Avatar answered Nov 13 '22 21:11

Matthieu M.


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.

like image 31
VitaminCpp Avatar answered Nov 13 '22 20:11

VitaminCpp