首页 文章

场景图更新回调设计

提问于
浏览
2

所以我使用Open Scene图创建一个应用程序,我有一个从OSG的回调类扩展的回调类 . 它只是一个回调,在场景图节点的更新事件遍历中称为每个帧 .

我需要不同的回调类,它们在附加到的节点上执行不同的操作 . 所以我有一个基本的回调类,我称之为控制器基:

class ControllerBase : public osg::NodeCallback
{
public:
    ControllerBase();
private:
    // operator is overridden here from NodeCallback and is called each frame.
    virtual void operator()(osg::Node * n, osg::NodeVisitor * nv);
}

operator()为我提供了附加回调的节点和节点访问者 . 现在,根据节点,它可能是一个不同的类,如变换或开关 .

所以我需要进行动态转换,但对于每个可能的类型,节点可能是 . 所以:

class ControllerBase : public osg::NodeCallback
{
public:
    ControllerBase();
private:
    virtual void operator()(osg::Node * n, osg::NodeVisitor * nv)
    {
      Type1 * t1 = dynamic_cast<Type1*>(node);
      Type2 * t2 = dynamic_cast<Type1*>(node);
      Type3 * t3 = dynamic_cast<Type1*>(node);

    }
}

然后通过虚拟方法将它们发送出去,由我将附加到节点的特定控制器类继承 .

class ControllerBase : public osg::NodeCallback
{
public:
    ControllerBase();
protected:

private:

    virtual void On_Frame(Type1*, osg::NodeVisitor) = 0;
    virtual void On_Frame(Type2*, osg::NodeVisitor) = 0;
    virtual void On_Frame(Type3*, osg::NodeVisitor) = 0;

    virtual void operator()(osg::Node * n, osg::NodeVisitor * nv)
    {
      Type1 * t1 = dynamic_cast<Type1*>(node);
      Type2 * t2 = dynamic_cast<Type1*>(node);
      Type3 * t3 = dynamic_cast<Type1*>(node);

      if(t1)
        On_Frame(t1, nv);
      if(t2)
        On_Frame(t2, nv);
      if(t3)
        On_Frame(t3, nv);

    }
}

class Type1_Controller
{
    public:
        Type1_Controler();
    private:
        virtual void On_Frame(Type1 * type, osg::NodeVisitor *nv) override
        {
            // Do type 1 related stuff here. 
        }
        virtual void On_Frame(Type2 * type, osg::NodeVisitor *nv) override
        {
            // Leave empty, not needed. 
        }

        virtual void On_Frame(Type3 * type, osg::NodeVisitor *nv) override
        {
            // Leave empty, not needed. 
        }
}

所以现在对于我所拥有的每种类型的控制器,我必须实现剩余的空方法 . 这感觉就像糟糕的设计,但我无法弄清楚如何编写更好的实现 . 也许它不是那么糟糕的3种类型,但随着我的进展,我可能还需要添加更多内容 . 我想过使用模板类,但如果我没弄错,我就不能在模板类中使用虚方法 . 我可以使用非纯虚方法和空实现,我想可以在选择时重写 . 什么是好的方法或建议?

2 回答

  • 1

    osg :: NodeVisitor或多或少是访问者设计模式的教科书实现 . (有关原始"Gang of Four"或GoF书籍的更多信息,请参阅http://en.wikipedia.org/wiki/Design_Patterns) .

    您可以覆盖t1节点类中的accept(NodeVisitor)以尝试转换为您的t1访问者类型,例如:

    Type1_Visitor* vis = dynamic_cast<NodeVisitor> nv;
     if(vis)
        vis->Type1Apply(*this);
     else
        nv->apply(*this);
    

    当然,还有一点,但这是GoF书中提出的双重调度的一般概念 .

  • 0

    根据您的设计,它看起来像类 - Type1, Type2, Type3 都来自 osg::Node . 在这种情况下,为什么要使用dynamic_cast并尝试确定operator()重载中的类型?你可以在 ControllerBase 中执行此操作 -

    virtual void operator()(osg::Node * n, osg::NodeVisitor * nv)
    {
      On_Frame(n, nv);
    }
    

    然后在 Type1_ControllerType2_Controller 等每一个中都有一个On_Frame方法 -

    virtual void On_Frame(osg::Node * n, osg::NodeVisitor *nv) override
    {
       Type1 * t1 = dynamic_cast<Type1*>(n);
        if(t1)
        {
           // only if t1 do something
        }
     }
    

相关问题