博客
关于我
OSG:从源码看Viewer::run() 一
阅读量:794 次
发布时间:2023-02-26

本文共 3203 字,大约阅读时间需要 10 分钟。

OSG入门:探索渲染与交互机制

作为OpenSceneGraph(OSG)框架的新手,我一直困惑于它如何将一张图片展示到屏幕上,以及它背后的渲染与交互逻辑。通过深入源码分析,我逐渐揭开了这个神秘面纱。

一、从简单示例到运行机制

在OSG程序中,简单展示一副图片的代码如下:

osg::ref_ptr
viewer = new osgViewer::Viewer;
osg::ref_ptr
node = osgDB::readNodeFile("glider.osg");
viewer->setSceneData(node);
return viewer->run();

运行这段代码后,滑翔机模型会出现在屏幕中央。通过鼠标和滚轮,可以实现旋转、缩放和平移等交互操作。令人惊叹的是,只需几行代码就能实现OpenGL中通常需要复杂配置才能完成的功能。

二、深入分析run()函数

Viewer::run()函数是OSG渲染过程的核心。在Viewer.cpp中找到它的实现:

int Viewer::run() {
if (!getCameraManipulator() && getCamera()->getAllowEventFocus()) {
setCameraManipulator(new osgGA::TrackballManipulator());
}
setReleaseContextAtEndOfFrameHint(false);
return ViewerBase::run();
}
  • 默认漫游器初始化

    run函数中,首先检查是否存在默认的TrackballManipulator。如果不存在,则创建一个。TrackballManipulator的默认构造函数设置了垂直轴的固定状态:

    TrackballManipulator::TrackballManipulator(int flags)
    : inherited(flags) {
    setVerticalAxisFixed(false);
    }

    这个漫游器是OSG中默认的相机控制器,它支持通过鼠标和滚轮进行旋转、缩放和平移操作。

  • 相机控制器的设置

    setCameraManipulator函数负责设置相机的交互逻辑。其源码如下:

    void View::setCameraManipulator(osgGA::CameraManipulator* manipulator, bool resetPosition) {
    _cameraManipulator = manipulator;
    if (_cameraManipulator.valid()) {
    _cameraManipulator->setCoordinateFrameCallback(new ViewerCoordinateFrameCallback(this));
    if (getSceneData()) {
    _cameraManipulator->setNode(getSceneData());
    }
    if (resetPosition) {
    osg::ref_ptr
    dummyEvent = _eventQueue->createEvent();
    _cameraManipulator->home(*dummyEvent, *this);
    }
    }
    }

    这个函数不仅设置了相机的坐标系,还通过home方法初始化了漫游器的初始位置。

  • 三、深入探讨ViewerBase::run()函数

    ViewerBase::run()是渲染循环的核心。其源码如下:

    int ViewerBase::run() {
    if (!isRealized()) {
    realize();
    }
    const char* run_frame_count_str = getenv("OSG_RUN_FRAME_COUNT");
    unsigned int runTillFrameNumber = run_frame_count_str == 0 ? osg::UNINITIALIZED_FRAME_NUMBER : atoi(run_frame_count_str);
    while (!done() && (run_frame_count_str == 0 || getViewerFrameStamp()->getFrameNumber() < runTillFrameNumber)) {
    double minframetime = _runMaxFrameRate == 0.0 ? 1.0 / _runMaxFrameRate : 0.0;
    osg::Timer_t startFrameTick = osg::Timer::instance()->tick();
    if (_runFrameScheme == ON_DEMAND) {
    if (checkNeedToDoFrame()) {
    frame();
    } else {
    if (minFrameTime == 0.0) minFrameTime = 0.01;
    }
    } else {
    frame();
    }
    osg::Timer_t endFrameTick = osg::Timer::instance()->tick();
    double frameTime = osg::Timer::instance()->delta_s(startFrameTick, endFrameTick);
    if (frameTime < minFrameTime) {
    OpenThreads::Thread::microSleep(static_cast
    (1000000.0 * (minFrameTime - frameTime)));
    }
    return 0;
    }
    }
  • 帧率控制

    该函数实现了帧率控制。通过minFrameTime设置每秒渲染帧数,确保渲染循环不会消耗过多CPU资源。

  • 帧处理

    frame()函数是渲染过程的核心。它负责处理事件、更新场景并进行渲染。每个帧的处理包括:

    • 事件遍历:eventTraversal()
    • 状态更新:updateTraversal()
    • 渲染:renderingTraversals()

    这些函数共同完成了OSG的渲染与交互逻辑。

  • 四、总结

    通过对OSG的源码分析,我们可以清晰地看到其渲染与交互机制的工作原理。TrackballManipulator作为默认的相机控制器,通过设置坐标系和初始位置,实现了复杂的相机操作。ViewerBase::run()则负责帧率控制和渲染循环,确保了高效的渲染性能。

    OSG的强大之处在于其支持丰富的交互操作,同时通过简洁的代码实现复杂的渲染效果。这为开发者提供了一个高效、灵活的3D图形展示框架。

    转载地址:http://iuvfk.baihongyu.com/

    你可能感兴趣的文章
    ORA-06575: 程序包或函数 NO_VM_DROP_PROC 处于无效状态
    查看>>
    ORA-08102的错误
    查看>>
    ORA-12505, TNS:listener does not currently know of SID given in connect descriptor异常
    查看>>
    ora-12541:tns:no listener
    查看>>
    【docker知识】联合文件系统(unionFS)原理
    查看>>
    ORACEL学习--理解over()函数
    查看>>
    oracle 10g crs命令,Oracle 10g CRS安装问题解决一例
    查看>>
    oracle 10g的安装配置
    查看>>
    Oracle 11.2.0.4 x64 RAC修改public/private/vip/scan地址
    查看>>
    Oracle 11G INDEX FULL SCAN 和 INDEX FAST FULL SCAN 对比分析
    查看>>
    Oracle 11g 使用RMAN备份数据库
    查看>>
    Oracle 11g 单实例安装文档
    查看>>
    Oracle 11gR2学习之二(创建数据库及OEM管理篇)
    查看>>
    Oracle 11gR2构建RAC之(2)--配置共享存储
    查看>>
    Oracle 11g中的snapshot standby特性
    查看>>
    Oracle 11g忘记sys、system、scott密码该这样修改!
    查看>>
    Oracle 11g数据库安装和卸载教程
    查看>>
    Oracle 11g超详细安装步骤
    查看>>
    Oracle 12c中的MGMTDB
    查看>>
    oracle avg、count、max、min、sum、having、any、all、nvl的用法
    查看>>