osg窗口的创建(一)

osgearth3.2配合osgQOpenGL在qt中显示地球 主要借助osgQOpenGL,将osg的窗口嵌入qt,osgQopenGL库的编译方法,可以参考。 阅读详情

使用osg时我们首先需要做的第一件事就是创建一个渲染窗口,当我们配置好一个osg的开发环境,一般会编写以下一段测试程序:

#include <osg/Node>
#include <osgDB/ReadFile>
#include <osgViewer/Viewer>

int main()
{
	osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer;
	//配置OSG_FILE_PATH环境变量指向glider.osg文件所在的目录
	osg::ref_ptr<osg::Node> gliderNode = osgDB::readNodeFile("glider.osg");
	viewer->setSceneData(gliderNode);
	viewer->run();
}

osg的窗口创建过程是在viewer->run() 中实现的,下面我们就对该过程做一个完整的剖析。

  • osg的一帧

在osg中,一帧的渲染过程在osgViewer::ViewerBase中,实现如下:
void ViewerBase::frame(double simulationTime)
{
    if (_done) return;

    if (_firstFrame)
    {
        viewerInit();

        if (!isRealized())
        {
            realize();
        }

        _firstFrame = false;
    }
    advance(simulationTime);

    eventTraversal();
    updateTraversal();
    renderingTraversals();
}

osgViewer::Viewer继承于osgViewer::ViewerBase,它并没有改写VIewerBase中的实现,这两个类的继承关系图如下:


函数实现中的变量_firstFrame表示是否是第一帧,如果是渲染开始的第一帧那么需要做一些设置,我们可以猜想窗口的创建过程就在这里(毕竟没有窗口就无法进行窗口渲染),那么让我们看看这几行代码的实现内容

  • viewerInit

viewerInit是osgViewer::ViewerBase中的一个纯虚函数,它必然会在子类osgViewer::Viewer中实现,在osgViewer::Viewer中的实现如下:
 void viewerInit() 
  { 
    init(); 
  }
viewerInit直接调用了osgViewer::Viewer中的init方法,但是查看osgViewer::viewer的源码发现它的实现文件中并没有init函数,说明在父类中有实现,osgViewer::Viewer只是直接调用了父类的实现,查看代码发现确实如此,在osgViewer::View中实现了init方法,它的实现代码如下:

void View::init()
{
    OSG_INFO<<"View::init()"<<std::endl;

    osg::ref_ptr<osgGA::GUIEventAdapter> initEvent = _eventQueue->createEvent();
    initEvent->setEventType(osgGA::GUIEventAdapter::FRAME);

    if (_cameraManipulator.valid())
    {
        _cameraManipulator->init(*initEvent, *this);
    }
}

  从变量的名称可以猜测出_eventQueue 的功能,它用于储存该视景器的事件队列。OSG中代表事件的类是osgGA::GUIEventAdapter,它可以用于表达各种类型的鼠标、键盘、触压笔和窗口事件。在用户程序中,我们往往通过继承osgGA::GUIEventHandler 类,并重写handle函数的方法, 获取实时的鼠标/ 键盘输入, 并进而实现相应的用户代码( 参见osgkeyboardmouse)。

_eventQueue 除了保存一个GUIEventAdapter 的链表之外,还提供了一系列对链表及其元素的操作函数,这其中,createEvent 函数的作用是分配和返回一个新的GUIEventAdapter事件的指针。随后,这个新事件的类型被指定为 FRAME 事件,即每帧都会触发的一个事件。

_cameraManipulator是视景器中所用的场景漫游器的实例。通常我们都会使用setCameraManipulator 来设置这个变量的内容, 例如轨迹球漫游器(TrackballManipulator)可以使用鼠标拖动来观察场景,而驾驶漫游器(DriveManipulator)则使用类似于汽车驾驶的效果来实现场景的漫游。上面的代码将新创建的 FRAME 事件和Viewer 对象本身传递给_cameraManipulator 的init 函数,不同的漫游器(如TrackballManipulator、DriveManipulator)会重写各自的init 函数,实现自己所需的初始化工作。如果读者希望自己编写一个场景的漫游器,那么覆写并使用osgGA::CameraManipulator::init 就可以灵活地初始化自定义漫游器的功能了,它的调用时机就在这里。

  • isRealized

该函数主要用来判断场景中的窗口设置是否已经准备就绪,它在ViewerBase中同样是一个纯虚函数,在osgViewer::Viewer中实现:
bool Viewer::isRealized() const
{
    Contexts contexts;
    const_cast<Viewer*>(this)->getContexts(contexts);

    unsigned int numRealizedWindows = 0;

    // clear out all the previously assigned operations
    for(Contexts::iterator citr = contexts.begin();
        citr != contexts.end();
        ++citr)
    {
        if ((*citr)->isRealized()) ++numRealizedWindows;
    }

    return numRealizedWindows > 0;
}
首先我们看一看 Contexts是什么? Contexts的定义:
 typedef std::vector<osg::GraphicsContext*> Contexts;
它是一个osg::GraphicsContext的列表,GraphicsContext是什么呢,它是图形渲染上下文。说的更清楚一点就是:这个GrahicsContext是一个可以让OpenGL在它上面就行绘制的目标,它可以是一个窗口、也可以是一个内存空间,所有OpenGL的渲染结果都会在它上面呈现。就像我们在绘画的时候需要知道我的画会画在什么地方?是纸上、墙上、还是地板上?这个GraphicsContext就是这样一个绘制载体的一种抽象的说法。 我们可以看一下它的继承关系图:



可以看到,OpenGL的渲染可以是在GrahicsContext的子类 GraphicsWindow中(窗口上),也可以是在PixelBuffer中(内存上)在内存中的渲染可以做很多事情,比如离屏渲染和渲染到纹理技术就是这样一个原理,将绘制的内容并不显示在窗口上来实现某些特殊的效果。

让我们在看一看 getContexts的实现

    typedef std::set<osg::GraphicsContext*> ContextSet;
    ContextSet contextSet;

    contexts.clear();

    if (_camera.valid() &&
        _camera->getGraphicsContext() &&
        (_camera->getGraphicsContext()->valid() || !onlyValid))
    {
        contextSet.insert(_camera->getGraphicsContext());
        contexts.push_back(_camera->getGraphicsContext());
    }

    for(unsigned int i=0; i<getNumSlaves(); ++i)
    {
        Slave& slave = getSlave(i);
        osg::GraphicsContext* sgc = slave._camera.valid() ? slave._camera->getGraphicsContext() : 0;
        if (sgc && (sgc->valid() || !onlyValid))
        {
            if (contextSet.count(sgc)==0)
            {
                contextSet.insert(sgc);
                contexts.push_back(sgc);
            }
        }
    }
代码还是比较清晰的,osg会搜集 Viewer视景器中相机(一个视景器Viewer类包含一个主相机和多个从相机(Slave))的所有渲染上下文,并将这些渲染上下文添加到数组中。

继续看viewer中isRealized函数体接下来的代码

    for(Contexts::iterator citr = contexts.begin();
        citr != contexts.end();
        ++citr)
    {
        if ((*citr)->isRealized()) ++numRealizedWindows;
    }

可以看到viewer中的isRealized会调用GraphicsContext中的isRealized,GraphicsContext中的isRealized的实现如下:
inline bool isRealized() const { return isRealizedImplementation(); }
接着追溯下去可以看到 isRealziedImplementation的实现就有很多了,它在GraphicsContext类中是一个纯虚函数,实现需要追溯到平台相关的实现中,包括了前面所绘制的类的继承关系图中的  GraphicsWindowQt 、GraphicsWindowWin32、GraphicsWindowCocoa、GraphcisWindowCarbon、GraphicsWindowIOS、GraphicsWindowX11,分别对应Qt、Win32、MacOS X、IOS、以及Linux的实现,

关于GraphicsContext实现的后续内容可以继续阅读《osg窗口的创建(二)》


OSG-Win32窗口显示osg 上一节是入门: OSG+VS2015+Win10配置win32控制台程序下使用osg 为了方便,在上一节中,我们使用VS创建了一个win32控制台程序,然后添加代码:写法一#include<osgViewer/Viewer>#include<osgDB/ReadFile>int main(int argc, char **argv){ osgViewer::Viewer viewer; vi 阅读详情

相关推荐

一、QT中创建OSG项目运行实例,初步实现版本

一般osg在vs2019编译器运行,只要配置相应的环境就能正常运行,但是如果要在qt中运行需要自己手动配置类才能正常运行,以下是qt中运行osg的一个示例。

qq_43605401的博客 2414

OSG开发概览

1OSG基础知识 ØOSG是OpenSceneGraphic的缩写,OSG于1997年诞生于以为滑翔机爱好者之手,Donburns为了对滑翔机的飞行进行模拟,对openGL的库进行了封装,osg的雏形就这样诞生了,1998年Donburns遇到了同样喜欢滑翔机和计算机图形学的RobertOsfield,从此RobertOsfield加入了osg小组的开发并一直...

weixin_30319097的博客 528

【OSG】将显示的图形窗口化

窗口化原理有时为了方便控制场景渲染,需要设置一个合适的图形环境窗口(即窗口化)。 创建图形环境的主要步骤如下: (1)通过WindowingSystemInterface类得到系统窗口接口,该系统接口主要是为了关联窗口系统与图形环境。 (2)下面是OSG中图形环境的主要特性,但在实际应用的过程中,没有必要设置每一个参数,只需根据实际需要来设置合理的参数即可。x,y,width,height;/

花海的专栏 4235

编写一个最简单的osg遇到的坑

编写一个最简单的osg遇到的坑 osg 的环境搭建好后,编写一个简单的程序,代码如下: #include <osgViewer/Viewer> #include <osgDB/ReadFile> int main(int argc, char **argv) { osgViewer::Viewer viewer; viewer.setSceneData(o...

csp123258的专栏 557

(一)OSG初学者入门基础教程

Day01 1.打开VS,选择【新建】-【visual C++】-【win32】-【win32控制台应用程序】。 2.在解决资源方案管理器中, 右击【源文件】-【添加】-【新建项】 -【C++文件.cpp】 3右键项目,选择“属性”,选择“VC++目录”, 在包含目录添加:C:\OSG\include 在库目录添加:C:\OSG\lib. (以上两个目录...

qq_36119499的博客 2万+

osg相机(基础篇)

在计算机的三维世界中,相机如同我们的眼睛,捕捉眼前的每一副画面,反过来物体要能够被相机在指定的距离和角度下观看到,并通过屏幕像素绘制出来。 在这个过程中,物体的三维空间坐标需要经过好几层矩阵变换,最终转换到二维平面坐标,并通过像素呈现在屏幕中。我们将这几层矩阵变换过程简称为MVPW矩阵变换。 下面我们展开介绍MVPW具体内容 ~ 模型(Model) MVPW中的M是模型顶点在三维场景中的位置。 一...

lavanana的博客 7192

osg节点函数功能汇总

1 virtual Object * cloneType () const 说明:只是返回一个和调用对象类型相同的同类型对象,仅此而已,调用对象的其它属性等不拷贝。如下代码: int main(int argc, char** argv) { osg::ref_ptr<osgViewer::Viewer> spViewer = new osgViewer::Viewer(); osg::ref_ptr<osg::Group> spRoot = new osg::Group();

danshiming的博客 1990

osg demo24 多窗口渲染

#include #include #include #include #include #include #include //实现多窗口渲染 void multipleWindowMultipleCameras(osgViewer::Viewer& viewer,bool multipleScreens) { osg::GraphicsContext::WindowingSy

analyst_yuci 1859

OSG模型控制

OSG模型控制标签

小猿一枚的专栏 2191

OSG和OSGEarth嵌入到qt窗口的几种方式

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 OSG和OSGEarth嵌入到qt窗口的几种方式前言一、pandas是什么?二、使用步骤1.引入库2.读入数据总结 前言 提示:这里可以添加本文要记录的大概内容: 例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。 提示:以下是本篇文章正文内容,下面案例可供参考 一、pandas是什么? 示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而

qq_38697743的博客 8592

OSG基础教程(二)osg嵌入Qt窗口(兼容Qt5)

将osg嵌入Qt。

hongfei_163的博客 4428

osg中NDC坐标转换为世界坐标

讲述NDC坐标转换为世界坐标的原理,并使用osg实现,进一步制作一个例子,鼠标点击屏幕绘制一条由相机发射向“鼠标”的射线

Zhihui Tang的专栏 3103

OSG在Win32下窗口形成的过程

OSG窗口在Win32下形成的过程 Main函数创建全局变量,创建系统接口,识别平台(Win32,Linux,Apple),可获取系统的一些属性(如分辨率等);系统接口创建后,在run的时候会绘制当前帧Frame,如果没有图形上下文则创建上下文,在创建上下文的时候会创建窗口,获取创建窗口句柄即可对窗口属性设置。

周陽讀書 840

VS下OSG嵌入QT指定窗口

VS下OSG嵌入QT指定窗口1.编译osgqt2.osg中绘制窗口3.osg嵌入qt指定窗口1.新建QT工程2.添加QT窗口部件3.osg嵌入QT 1.编译osgqt 忘记了,自己搜一下吧。记得当时是又改了cmake编译的。之前的源码没有osgqt工程。 2.osg中绘制窗口 在osg中用qt绘制窗口,即qt嵌入osg。 在osg源码当中有案例Examples osgviewerQt 直接复制过...

lemon_haha的博客 2637

三维引擎实践 - OSG引擎窗口创建过程

以GraphicsWindowX11为例,在Linux上用这个窗口类,Windows上用GraphicsWindows32类。一个3D应用程序,要想显示渲染结果,首先要创建一个窗口,本节就分析下OSG源码中窗口创建的过程。二: OSG中的窗口类介绍。三:OSG窗口建立过程。

GPU全栈博主 1251

保姆级教程:用vxe-grid给管理后台加个「智能筛选」功能(支持模糊搜索/多选/范围查询)

本文提供了一份详细的Vxe-Grid智能筛选功能实现教程。通过自定义筛选器渲染,文章逐步指导开发者为后台管理系统添加支持模糊搜索、多选下拉和数值范围查询的智能筛选功能,并分享了性能优化与移动端适配等实战经验。

weixin_29021291的博客 536

osg窗口的创建(三)

前面两篇文章的分析只是讲述了窗口创建过程,但是里面还有部分细节并没有涉及,本文接着介绍这些内容,并详细讲述如何将osg嵌入到常用的窗口系统中: 窗口的创建补充 在窗口创建过程中还有一个地方并没有讲述清楚,就是:为什么osg可以识别我想创建的窗口是Win32的?为什么它不会创建其他的窗口设备(如GraphicsWindowCocoa、GraphicsWindowX11)。

Frank的专栏 8819

Java对接海康威视明眸门禁设备

海康威视合作生态致力打造一个能力开放体系、两个生态圈,Hikvision AI Cloud开放平台是能力开放体系的核心内容。它是海康威视基于多年在视频及物联网核心技术积累之上,融合AI、大数据、云计算等技术,为合作伙伴提供的一个二次开发及创新的平台。的SDK复制到linux的lib目录下(如果是docker发布,记得做好共享映射哦)大家有没有想过,windows版的SDK为什么要复制到项目根目录的lib文件夹下?所以发布到linux的时候,我们需要将。打开AcsMain文件。................

Good Luck 7875

OSG 之学习十:OSG 显示点云一

文章目录说明代码 说明 本文来源于返回主页 准前端工程师的博客:osg之显示点云 osg虽然不是很火,但是对于非计算机专业的人来说确实是一个神器,osg其实也是来自于opengl,它可以理解为一个高度封装的opengl图像库,由于其没有太多太多的技术门槛以及扩展性不高,导致其市场一直不温不火,但是其封装的LOD技术,多线程技术以及显示还是为急需做平台又不想投入大量时间的人提供了便利。博主就...

Neverland_LY‘s Domain 6213

基于CST的PCB通孔三维建模实例

本文简明扼要地描述了如何利用CST的参数化脚本快速生成PCB的通孔三维模型,非常适合于进行快速精准的PCB参数分析。

一只豌豆象的博客 1834

4、分布式发电系统中用于改善电能质量的有源、无源和混合滤波器

本文探讨了分布式发电系统中,尤其是光伏(PV)系统运行过程中引入的电能质量问题,并分析了有源滤波器、无源滤波器及混合滤波器在改善电能质量方面的应用。文章详细介绍了光伏系统的建模、最大功率点跟踪(MPPT)技术,以及谐波、电压波动等技术问题,同时对各类滤波器的拓扑结构和控制方法进行了系统性总结。通过仿真实例比较了不同滤波器在减少谐波方面的效果,为实际工程应用提供了参考依据。

transformer2023的博客 89
上一篇: glCopyBufferSubData
下一篇: osg窗口的创建(二)
csxiaoshui
博客等级 码龄16年 873粉丝 158原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值