【OSG源码阅读】Day 2: 初始化流程
昨天阅读了启动的过程,今天我们深入阅读下初始化的过程。
初始化流程
开始之前我们来看下这里的类图,结合类图来看本文的介绍:
init函数流程
frame
函数其中有个viewerInit()
它的实现也很简单,就是去调用了init
函数.
virtual void viewerInit() { init(); }
从这里就调用到了它的父类的init
函数,init
函数实现如下:
// View 类初始化函数实现
void View::init()
{// 输出调试信息,标记当前进入 View 初始化流程OSG_INFO<<"View::init()"<<std::endl;// 创建一个初始化用的事件对象(FRAME 类型事件)// 使用 ref_ptr 智能指针管理事件对象生命周期,防止内存泄漏osg::ref_ptr<osgGA::GUIEventAdapter> initEvent = _eventQueue->createEvent();initEvent->setEventType(osgGA::GUIEventAdapter::FRAME); // 设置事件类型为帧事件// 如果相机操作器有效,则用初始化事件对其进行初始化// CameraManipulator 负责处理相机视角控制(如鼠标键盘交互等)if (_cameraManipulator.valid()) // 检查相机操作器是否有效{// 调用相机操作器的初始化方法// 传入初始化事件和当前 View 对象的引用(*this)// 这允许操作器根据视图特性进行初始化设置_cameraManipulator->init(*initEvent, *this);}
}
这个函数也主要干了两件事:
1. 使用_eventQueue创建的事件对象
2. 初始化_cameraManipulator并传入该对象
我们继续来一个个介绍。
_eventQueue队列创建事件对象
_eventQueue是一个队列,它的声明在view
类里。
osg::ref_ptr<osgGA::EventQueue> _eventQueue;
其中EventQueue
类的createEvent()都干了什么?让我们继续往下看:
/*** 创建新的事件对象实例* @return GUIEventAdapter* 新创建的事件对象指针,由调用方管理内存*/
GUIEventAdapter* EventQueue::createEvent()
{// 检查是否存在累积的事件状态if (_accumulateEventState.valid()) // 判断累积事件状态是否有效{// 当存在有效累积状态时:// 1. 使用拷贝构造函数基于当前累积状态创建新事件// 2. get() 方法从 ref_ptr 中获取原始指针// 3. 通过拷贝构造保证新事件继承当前所有状态(如鼠标位置、按键状态等)return new GUIEventAdapter(*_accumulateEventState.get());}else {// 当没有累积状态时:// 创建全新的默认初始化事件对象return new GUIEventAdapter();}
}
可见就是创建了个GUIEventAdapter
对象。
源码路径:(include/osgGA/GUIEventAdapter.h)
GUIEventAdapter
:
GUIEventAdapter 是 OpenSceneGraph (OSG) 中处理用户输入事件的核心类,它封装了所有与图形用户界面(GUI)相关的事件(如鼠标、键盘、窗口事件等),并将这些事件标准化为统一的接口。
初始化_cameraManipulator并传入该对象
先来看看_cameraManipulator
是来干嘛的。
osg::ref_ptr<osgGA::CameraManipulator> _cameraManipulator;
CameraManipulator
:
osgGA::CameraManipulator 是 OpenSceneGraph (OSG) 中的一个类,用于控制场景中的相机行为。
它是 OSG 的事件处理和交互框架的一部分,属于 osgGA(Graphics Application)命名空间。
通过继承和实现 CameraManipulator,开发者可以创建自定义的相机控制器,用于实现第一人称视角、轨道视角、飞行模式等常见的 3D 场景导航方式。
嗯,这玩意原来就是用来控制camera
的。
内置的 CameraManipulator
OSG 为我们提供了一些内置的 CameraManipulator 子类,用于实现不同的相机控制模式:
- osgGA::TrackballManipulator
实现了类似 3D 轨道球的操作,允许用户通过鼠标拖动来旋转、平移和缩放场景。
- osgGA::FlightManipulator
模拟飞行模式,用户可以通过鼠标和键盘控制相机的飞行方向和速度。
- osgGA::DriveManipulator
模拟驾驶模式,适合于地面导航,例如车辆驾驶或步行。
- osgGA::TerrainManipulator
专为地形导航设计,支持第一人称视角和地形跟随功能。
- osgGA::FirstPersonManipulato
提供第一人称视角控制,常用于游戏开发。
嗯~,这样还是蛮方便的。当然我们也可以基于这个类自定义一个漫游器。
不过我们这里只是讲源码的流程,就不展示如何自定义了。
_cameraManipulator
对象的值是通过View::setCameraManipulator
函数来传入的。
从源码中我们可以看到有很多的直接设置的osgGA::TrackballManipulator
这个内置漫游器。
我们就来看看它的init
函数。
TrackballManipulator的init函数
TrackballManipulator
的代码路径:include/osgGA/TrackballManipulator.h
看看它的类图关系:
其中又有两个新的类,我们一个一个介绍。
osgGA::OrbitManipulator
是 OpenSceneGraph(OSG)
图形库里 osgGA::CameraManipulator
的一个派生类。它为用户提供了一种基于轨道的相机控制方式,允许用户围绕一个中心点旋转、缩放以及平移相机,从而实现对 3D 场景不同视角的观察。
osgGA::StandardManipulator
是 OpenSceneGraph(OSG
)中 osgGA::CameraManipulator
的一个派生类。它集成了多种常用的相机操作方式,为用户提供了一套标准化、便捷且功能丰富的相机控制方案,方便用户对 3D 场景进行不同视角的观察与交互。
最后其实调用的是StandardManipulator
的`
void StandardManipulator::init( const GUIEventAdapter& /*ea*/, GUIActionAdapter& us )
{flushMouseEventStack();// stop animation_thrown = false;us.requestContinuousUpdate(false);
}
这里可以看到,我们传入的GUIEventAdapter
居然都没被使用。
看起来并不是所有的漫游器都需要处理这个GUIEventAdapter
事件。
虽然init
函数就那么几行,但是巴拉下来,还是内容挺多的。
好了,今天就到这里,明天见。_