OSG可绘制体Drawable

1. 简介

OSG使用场景树的方式来组织场景结构,在场景树的最底端是叶子节点(Geode),叶子节点用来存储场景中可以被渲染的对象,这些对象包括几何体、图片、文字等。用来表达所有这些可绘制体的对象就是本文提到的Drawable。

Drawable是所有可绘制对象的基类,提供了操作这些可绘制对象的方法和属性,Drawable派生的类如下图所示(OSG3.4.0):

DrawableInheritance

本文及后续的文章会详细介绍所有的派生类类型,并对这些类的使用场景和使用方式给出说明。

2. 原理

在编写OpenGL代码的时候,所有需要绘制的代码,都是写在glutDisplayFunc回调函数中的,可绘制的类型有很多,比如使用顶点数据绘制的几何体、使用像素绘制的图片等,它们会被最终转换成Drawable的派生类,并添加到场景中,典型的转换方式如下图所示:

这里写图片描述

也就是说Drawable将场景真正需要渲染的部分(写在渲染函数体内),根据不同的渲染类型,转换成不同的类来描述。

3. 回调

osg::Drawable在3.4版本之前继承自osg::Object,在3.4版本以后继承自osg::Node,在osg3.4版本之前,osg::Drawable使用的回调和osg::Node使用的回调是不同的,在3.4版本之后,由于osg::Drawable继承自osg::Node,因此回调函数将二者统一起来了。

3.1 旧式的回调处理方式

具体来说,在3.4版本之前,编写回调的方式:

//Node节点的回调 (更新、事件、筛选回调:三种都是使用NodeCallback)
class MyNodeCallback : public osg::NodeCallback
{
    //必须实现的成员
    virtual void  operator() (Node *node, NodeVisitor *nv);
}
//设置回调的函数:
void  setUpdateCallback (NodeCallback *nc);
void  setEventCallback (NodeCallback *nc);
void  setCullCallback (NodeCallback *nc) ;
//-------------------------------------------------------------

//Drawable节点的回调(更新回调)
class MyDrawableUpdateCallback : public osg::Drawable::UpdateCallback
{
  //必须实现的成员
  virtual void  update (osg::NodeVisitor *, osg::Drawable *);
}
//Drawable节点的回调(事件回调)
class MyDrawableEventCallback : public osg::Drawable::EventCallback
{
 //必须实现的成员
 virtual void  event (osg::NodeVisitor *, osg::Drawable *);
}
//Drawable节点的回调(筛选回调)
class MyDrawableCullCallback : public osg::Drawable::CullCallback
{
//必须实现的成员
virtual bool  cull (osg::NodeVisitor *nv, osg::Drawable *drawable, osg::RenderInfo *renderInfo) const;
}
//Drawable节点的回调(绘制[渲染]回调)
public MyDrawableDrawCallback : public osg::Drawable::DrawCallback 
{
//必须实现的成员
virtual void  drawImplementation (osg::RenderInfo &, const osg::Drawable *) const;
}

可以看到在3.4版本之前的处理方式:
1. osg::Node有3种回调(对应一帧渲染过程中的3个阶段):更新、事件、筛选
2. osg::Drawable有4种回调(相比Node多出来一个绘制,因为Drawable就是场景中可绘制的对象,自然比Node多一个渲染过程)
3. 每一个不同的回调类都需要实现特定的方法,这个方法会在回调过程中被调用。

3.2 新式的回调处理方式

在3.4版本之后,OSG由于将Drawable的父类修改为osg::Node,也同时调整了回调的类继承结构,现在OSG中大部分的回调都继承自一个统一的回调类——osg::Callback,同时由于调整了Node类中加载回调的函数参数,使得这些函数可以被Drawable使用,也就是将参数统一调整为Callback类型:

void  setUpdateCallback (Callback *nc);
void  setEventCallback (Callback *nc);
void  setCullCallback (Callback *nc) ;

这样Drawable类中不需要重新实现这些函数,同时Drawable自己的UpdateCallback由于继承自Callback,也可以传入到这些函数中。

新的Callback类需要所有继承它的类都实现一个方法

virtual bool  run (osg::Object *object, osg::Object *data) 

这个方法会在回调中被调用。这样就省去了3.1种每一个不同的回调类都有一个需要实现的方法(并且这些方法名字不同)。在3.4版本中,原来的osg::NodeCallback被标记为Deprecated。

OSG通过修改Drawable的继承关系,同时调整了回调的类结构,让整个代码看起来更加清晰,代码的复用率更高。

4. 访问器与遍历

在OSG中大量使用了访问者设计模式(Visitor Pattern),在Drawable中,使用这种方式来获取内部的属性。

Drawable定义了2个仿函数的类:
1. AttributeFunctor
2. ConstAttributeFunctor
同时也定义了与这两个仿函数类相关的两个访问器:
1. AttributeFunctorArrayVisitor
2. ConstAttributeFunctorArrayVisitor

Drawable还定义了接收仿函数的几个类成员函数:
1. virtual void accept(AttributeFunctor&)
2. virtual void accept(ConstAttributeFunctor&) const
3. virtual void accept(PrimitiveFunctor&) const
4. virtual void accept(PrimitiveIndexFunctor&) const

这4种专门用于可绘制对象数据访问的仿函数类,其中AttributeFunctor和ConstAttributeFunctor是用来获取顶点属性数组、PrimitiveFunctor是用来获取图元数据、PrimitiveIndexFunctor用来获取图元索引数据,通过继承和重写其中的成员函数,可以在获取几何体顶点数据的同时对它们进行一些自定义的操作。

从这些定义来看,这些遍历器需要访问的是顶点的各种数据信息,很显然并不是每一个Drawable的子类都可以使用这些函数和访问器,它只供有顶点数据的子类,具体来说就是osg::Geometry子类,其他的如osg::DrawPixels由于是像素数据,因此并不能使用,字体类osg::TextBase及其派生类同样无法使用这些函数。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值