场景图更新回调设计
Scene Graph Update Callback Design
所以我使用开放场景图创建一个应用程序,我有一个从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 种类型还不错,但随着我的进行,我可能还有更多要添加。 我想过使用模板类,但如果我没记错的话,我不能在模板类中使用虚拟方法。 我可以只使用带有空实现的非纯虚拟方法,我想然后可以选择覆盖。 什么是好的方法或建议?
osg::NodeVisitor 或多或少是 Visitor 设计模式的教科书实现。 (有关原始"四人帮"或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书中提出的双重调度的一般思想。
设计,看起来像类 - Type1, Type2, Type3
都派生自osg::Node
。在这种情况下,为什么要使用dynamic_cast并尝试确定运算符()重载中的类型?您可以在ControllerBase
中执行此操作 -
virtual void operator()(osg::Node * n, osg::NodeVisitor * nv)
{
On_Frame(n, nv);
}
那么在Type1_Controller
中,Type2_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
}
}
- 架构决策:返回std::future还是提供回调
- 正在为Xtensa simcall函数编写回调函数
- 如何在C++中使用非静态成员函数作为回调函数
- FLTK:按下哪个按钮 - 将数字传递给按钮的回调 (lambda)
- 在简单示例中,Python3 + ctypes 回调会导致内存泄漏
- 用于在回调中调用解析器的设计模式
- 如何使用C++对象的成员函数作为 C 样式回调?
- Java从C++回调到C++回调
- 如何将成员函数作为回调参数传递给需要"typedef-ed"自由函数指针的函数?
- 从不同的 cpp 调用回调函数会导致bad_function_call
- pcap_handler回调仅在使用 NPCAP v0.9991 时包含空数据包
- 不带轮询的 SDL2 事件回调
- C++存储带有可变参数的回调
- 更新 Visual Studio 2017,现在出现编译错误 C7510:"回调":使用依赖模板名称必须以 'template' 为前缀
- GUI滑块的动态数量,该数量更新具有回调中值的std ::向量
- 一个回调函数应该如何更新/返回值
- 当更新值用作回调时,如何处理 QT/C++ 中的进度条
- 场景图更新回调设计
- 如何链接到 Lua 中的回调函数,以便在重新加载脚本时更新回调
- 通过回调更新类属性