【问题标题】:How to apply DOP and keep a nice user interface?如何应用 DOP 并保持良好的用户界面?
【发布时间】:2011-04-21 19:16:53
【问题描述】:

目前我想稍微优化一下我的游戏机 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 调整大小时,它会更新其句柄。 “句柄”存储指向实际对象的指针,并且“->”运算符被重载以实现良好的包装。但是这种方法对我来说听起来有点复杂?!

你怎么看?如何保持良好的界面,但在内存中保持连续思考以更好地使用缓存?

感谢您的帮助!

【问题讨论】:

  • 在我的示例中,面向数据的编程是从结构数组到数组结构的转换。虚拟 Update() 方法从 SceneNode 中提取出来,然后成为 SceneNodes 结构的成员。所以我可以线性地遍历我感兴趣的数组。

标签: c++ caching vector relocation data-oriented-design


【解决方案1】:

如果对 DOP 的实际示例感兴趣,请查看 Niklas Frykholm 的精彩演示 => http://bitsquid.blogspot.com/2010/05/practical-examples-in-data-oriented.html

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 是的,我也想过这个方向,但对我来说似乎不是很优雅……但我想我会选择这样的解决方案,并对用户隐藏索引。在我的设计中,所有“经理”都是全球性的。所以在调试模式下一个简单的 assert() 来确保我们有一个有效的管理器就足够了。这是 DOP 的一大缺点。谢谢!
    • @VitaminCpp:就我而言,这并不是一个真正的缺点,因为我在设计界面时总是使用智能手柄。更容易发展,可能包括透明的引用计数,保护内容并且可能更容易提供二进制兼容性。
    • 确实这是一个强有力的论据!现在最困难的部分是改造场景节点本身 DOP... :( 非常感谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-06-30
    • 1970-01-01
    • 1970-01-01
    • 2014-09-03
    • 2015-08-02
    • 2016-05-21
    • 1970-01-01
    相关资源
    最近更新 更多