osg::Drawable类通过setDrawCallback函数设置回调函数的说明

文章介绍了osg::Drawable类的DrawCallback机制,允许用户通过设置回调函数并在drawImplementation中实现特定绘制需求。示例代码展示了一个更新文本值的回调类,根据帧间隔改变字符串显示。同时强调了setUseDisplayList(false)的必要性,以及可能需要编译FreeType库作为osg插件来支持字体显示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

       osg::Drawable类可以通过该类的setDrawCallback函数设置回调函数类对象。被设置的回调类对象必须从osg::Drawable::DrawCallback类派生,并重写drawImplementation函数,以实现自己特定的需求。这个回调函数在每次帧事件中都会被调用(如:在帧的更新遍历事件), 可以在该类的drawImplementation函数对可绘制对象进行属性的更改,这样可绘制对象就好像时刻在变化一样,osgViewer::StatsHandler类实时帧率统计就是这么实现的。osg::Drawable::DrawCallback类定义如下:

struct DrawCallback : public virtual osg::Object
{
   DrawCallback() {}
   DrawCallback(const DrawCallback& org,const CopyOp& copyop):
                Object(org, copyop) {}

   META_Object(osg,DrawCallback);

  /** do customized draw code.*/
   virtual void drawImplementation(osg::RenderInfo& /*renderInfo*/,const osg::Drawable* /*drawable*/) const {}
};

        这个类中最重要的就是虚函数drawImplementation,该函数参数说明如下:

  1. 第1个参数是类型为osg::RenderInfo的引用。osg::RenderInfo是渲染信息类。这个类负责保存和管理与场景绘制息相关的几个重要数据:当前场景的视景器当前场景对应的所有摄像机、以及当前osg::State对象。这些数据将在场景筛选和渲染时为 OSG 系统后台的工作提供重要依据,并从中取出跟踪此图形上下文的当前OpenGL状态的State对象。可以说,需要涉及绘制有关的视景器、场景类、状态类、摄像机类都可以从渲染信息类对象获取到。
  2. 第2个参数就是指向被绘制对象的指针

     下面举例说明,如下代码:

#include<osgViewer/Viewer>
#include<osg/ArgumentParser>
#include<osg/ShapeDrawable>
#include<osgText/Text3D>
#include<osg/Timer>
class CUpdateTextValue : public osg::Drawable::DrawCallback
{
public:
    CUpdateTextValue()
    {
        _lastTimer_t = osg::Timer::instance()->tick();
    }
    virtual void drawImplementation(osg::RenderInfo& renderInfo, const osg::Drawable* drawable) const
    {
        auto pText3D = (osgText::Text3D*)(drawable);

        osg::Timer_t tCurTick = osg::Timer::instance()->tick();
        double delta = osg::Timer::instance()->delta_m(_lastTimer_t, tCurTick);
       
        char szValue[10]{0};
        itoa(_value, szValue, 10);
        if (delta > 20)
        {
            ++_value;
        }
        else
        {
            --_value;
        }

        // 防止越界、溢出
        if (_value >= INT_MAX)
        {
            _value = INT_MAX;
        }
        if (_value <= INT_MIN)
        {
            _value = INT_MIN;
        }

        pText3D->setText(szValue);
        pText3D->drawImplementation(renderInfo);
        _lastTimer_t = tCurTick;
    }
private:

// 注意用mutable修饰符,因为函数是const函数,否则不能对该值修改,下同。
    mutable  osg::Timer_t _lastTimer_t{ 0 };
    mutable  int _value{0};  
};

int main(int argc, char *argv[])
{
    osg::ArgumentParser arg(&argc, argv);
    osgViewer::Viewer viewer(arg);

    auto spRoot = new osg::Group;
    auto pGeode = new osg::Geode;
    
    auto pText3D = new osgText::Text3D;  
    pGeode->addDrawable(pText3D);

    pText3D->setFont("Verdana\\verdana.ttf");
    pText3D->setText(" 0");
    pText3D->setDrawCallback(new CUpdateTextValue);
    pText3D->setUseDisplayList(false); // 这个要最好设置为false,否则对某些可绘制几何体如球体,drawImplementation函数只会调用一次
    spRoot->addChild(pGeode);
    viewer.setSceneData(spRoot);

    return viewer.run();
}

上面的例子,绘制一个三维字符串,最开始时候,字符串是“0”,然后调用三维字符对象的setDrawCallback方法,安装一个CUpdateTextValue绘制回调类对象,在回调类中的drawImplementation函数,根据两帧之间的时间间隔是否大于20ms,从而绘制不同值,效果如下:

 说明:

 setUseDisplayList(false); // 这个要最好设置为false,否则对某些可绘制几何体如球体,drawImplementation函数只会调用一次。

      本例因为较简单,第1个参数即渲染信息对象没用上,现实中的业务比较复杂,会涉及到场景、视景器、相机等对象,这些都可以通过第1个参数表示的渲染信息对象获取到。本例用到字体,需要编译freetype到osg,作为osg的插件,否则字符串不会显示。请从

                                    FreeType Downloads

下载freetype。关于如何编译字体作为osg的插件,请参照

osg第三方插件的编译方法(以jpeg插件来讲解)      博文。

osg (OpenSceneGraph) 中,判断一个 osg::ShapeDrawable 是否是一个有效的 osg::Drawable,你可以通过检查它的成员变量或者状态来完成。首先,确保 ShapeDrawable 的构造函数已经被正确地调用,并且它不是 nullptr。 以下是几个步骤: 1. 检查指针是否为空:确保 `shapeDrawable` 不是 NULL 或空指针,即 `shapeDrawable.get() != nullptr`。 ```cpp osg::ShapeDrawable* shapeDrawable = ...; if (!shapeDrawable) { // 报告错误或异常,形状Drawable 无效 return false; } ``` 2. 状态管理:osg::Drawable 需要正确的状态设置才能渲染。可以检查其当前的状态堆栈(`stateSet`)是否已经初始化并且包含必要的渲染属性(如颜色、纹理等): ```cpp if (shapeDrawable->getStateSet()) { if (!shapeDrawable->getStateSet()->valid()) { std::cerr << "State set is not valid" << std::endl; return false; } } else { std::cerr << "No state set attached to the drawable" << std::endl; return false; } ``` 3. 渲染准备:ShapeDrawable 需要有几何数据,比如顶点数组、索引等。你可以访问 `shapeDrawable->getVertexArray()` 或其他相关接口,如果它们不存在或者无法访问,则可能是无效的: ```cpp if (!shapeDrawable->getVertexArray()) { std::cerr << "No vertex array attached to the drawable" << std::endl; return false; } ``` 总之,在osg::ShapeDrawable是有效的前提下,以上条件都应满足。如果任何一步返回 false,那么该 Drawable 就被认为无效。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值