如何应用DOP并保持良好的用户界面?

发布于 2024-09-26 19:15:31 字数 1505 浏览 3 评论 0原文

目前我想稍微优化一下控制台的 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,我会在这里看到两个问题。 首先,如何在不让用户使用 ID、索引等的情况下保持良好的用户界面?

其次,当某些向量调整大小而不让用户界面指针指向涅槃时,如何处理属性的重定位?

目前我的想法是实现一种handle_vector,从中您可以获得持久“指针”的句柄:

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

因此,当实习生 std::vector 调整大小时,它会更新其句柄。 “句柄”存储指向实际对象的指针和“->”运算符被重载以实现良好的包装。但这种方法对我来说听起来有点复杂?!

你怎么认为?如何保持良好的界面,同时保持内存中的连续性以更好地使用缓存?

感谢您的帮助!

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!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

孤独岁月 2024-10-03 19:15:31

您将需要使用比原始指针更智能的句柄。 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 的被指向者的生命周期是另一个问题:-)

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

演出会有结束 2024-10-03 19:15:31

对于那些对 DOP 实际示例感兴趣的人,请观看 Niklas Frykholm 的精彩演示=> http://bitsquid.blogspot.com/2010/05 /practical-examples-in-data-orient.html

这帮助我以面向数据的方式实现我的场景图。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文