文章目录
一、OSG层次结构:
图形硬件->OpenGL->OSG->应用程序
二、OSG组成模块+注意事项:
1.OSG核心库
主要功能是实现最核心的场景数据库的组织和管理,对场景图形的操作以及外部数据库导入提供接口,提供了基本的场景图形和渲染功能,以及3d图形程序所需的某些特定功能实现。
- osg库:基本数据类,负责提供基本场景图类,构建场景图形节点,如节点类(创建场景图形)、状态类、绘制类、几何类、向量和矩阵数学计算以及一般的数据类。还有特定功能类,例如命令行解析和错误调试信息等。
- osgUtil库:工具类库,提供通用的公用类,用于操作场景图形及内容,如更新、裁剪、遍历、数据统计及场景的一些优化、渲染器的创建。还包括几何操作类,delaunay三角面片化,三角面片条带化,纹理坐标生成等。
- osgDB库:数据的读写类,负责提供场景中数据的读写工作,提供了一个文件工具类。建立和渲染3d数据库的类和函数,允许用户程序加载,使用和写入3d数据库。
- osgViewer库:视窗管理库,可以集中各种窗体系统,提供OSG与各种GUI的结合,是跨平台的3d管理窗口库。
- osgGA库:用于改写界面事件。
2.OSG节点工具库(NodeKit)
- osgFX库:用于特效的渲染,例如异向光照,凹凸贴图,卡通着色等。
- osgParticle库:提供了基于粒子的渲染特效,如各种天气或者自然现象效果,爆炸,火焰,烟雾。
- osgSim库:虚拟仿真效果的节点工具,以及渲染OpenFlight数据库所需的特殊渲染功能,例如地形高程图,光点节点,DOF变换节点等。
- osgText库:此类库提供了向场景中添加文字的得力工具,可以完全支持TrueType字体。
- osgShadow库:提供了支持阴影渲染的框架结构,用于向场景添加实时阴影,提高场景渲染的真实性。
- osgTerrain库:生成地形数据的节点工具,用于渲染高程数据,一般通过开源库GDAL读取这些高程数据。
- osgdem库:一个工具程序 用于读取地理空间图像 和 高程图,生成大规模的3D地形数据库
- osgAnimation库
3.OSG插件库(特点)
通过各种第三方库,OSG能够直接或者间接导入3D模型或图片等场景数据。具体见第五章(没看
4.OSG内省库(OsgIntrospection)
为了确保osg可以在更多环境中运行,osg提供了一个与语言无关的,可供运行时访问的接口。
5.建议使用OSG提供的智能指针
osg::Geode* geode = new osg::Geode();// 指针的写法
osg::ref_ptr<Geode> geode = new osg::Geode();// 智能指针
6.建议对头文件进行分类处理+基础测试代码
#include <osgViewer/Viewer>
#include <osgDB/ReadFile>
int main()
{
osgViewer::Viewer viewer;
osg::Node *node = new osg::Node;
node = osgDB::readNodeFile("glider.osg");
viewer.setSceneData(node);
return viewer.run();
}
三、场景浏览器osgViewer
1.在osgViewer中添加帮助事件(osgGA)
#include <osgViewer/ViewerEventHandlers>
...
osgViewer::Viewer viewer;
// 或osg::ref_ptr<osgViewer::Viewer> viewer = new...
...
viewer.addEventHandler(new osgViewer::HelpHandler);
// 先打印查找到的所有的event,再打印自定义的内容。
// 自定义内容参见HelpeHandler::handle中setUpScene语句中的getUsage语句
...
注意大小写敏感。
可以仿照helpHandler写一个类当作事件,试着替代“添加帮助事件”功能。
class demo :public osgGA::GUIEventHandler
{
public:
virtual void getUsage(osg::ApplicationUsage &usage) const
{
usage.addKeyboardMouseBinding("d","dankokoko");
}
};
....
viewer.addEventHandler(new osgViewer::HelpHandler);
viewer.addEventHandler(new demo );
...
如果只想响应demo事件,是由HelpeHandler::handle的返回值决定的。
class demo :public osgGA::GUIEventHandler
{
...
bool handle (const osgGA::GUIEventAdapter &ea,osgGA::GUIActionAdapter &aa)
{
return true;// 此时到这个事件进入这个handler就结束了,不会处理这个类下面的事件了。
// return false;
}
...
};
viewer.addEventHandler(new demo );
viewer.addEventHandler(new osgViewer::HelpHandler);
...
除了helpeHandler,还有statsHandler,WindowSizeHandler等,更多见osgGA::GUIEventHandler.
其中osgViewer::RecordCameraPathHandler,可以生成一个文件路径,这个文件可以执行,实际上就是按照指定的动画(你的动作)和代码绘制顺序执行。可以来控制场景。
2.通过osg::Timer获得帧速
osg::Timer应用:
// 申请一个定时器
//osg::ref_ptr<osg::Timer> timer = new osg::Timer;// 错误,有些是没有ref_ptr的
osg::Timer *timer = new osg::Timer;
// 得到一个tick值为多少s
std::cout << timer->getSecondsPerTick() << std::endl;
// 计算读取模型时间
// 方法一:
osg::Timer_t start_time = 0;
osg::Timer_t end_time = 0;
start_time = timer->tick();
/*读取模型*/
end_time = timer->tick();
std::cout << "读取模型时间为:" << timer->delta_s(start_time,end_time) << std::endl;
// 这里使用相减
//方法二:
timer->setStartTick();
/*读取模型*/
std::cout << "读取模型时间为:" << timer->time_s() << std::endl;
// 这里使用获得流逝时间
// 方法三:
start_time = viewer->elapsedTime();
/*读取模型*/
end_time = viewer->elapsedTime();
std::cout << "读取模型时间为:" << osg::Timer::instance()->delta_s(start_time,end_time)<< std::endl;
// 但是这里osg::Timer_t是longlong,这里获得时差为0,所以应该改成float
其实viewer.run()是执行主帧循环,等同于:
while (!viewer.done()) viewer.frame();
//Also calls realize() if the viewer is not already realized, and installs trackball //manipulator if one is not already assigned.
// 上面注释内容建议看viewer.run()源码。
``
如果设定了这个系统变量,则会根据帧数来结束。
可以将return viewer.run()改成,并计算帧速:
// 加操作器
viewer->setCameraManipulator(new osgGA::TrackballManioulator());
int count =0;
while(!viewer.done())
{
if(count == 0)
start_time = timer->tick();
count++;
viewer.frame();
if(count == 3)
{
count = 0;
end_time = timer->tick();
std::cout <<"当前帧速:" << 3/(timer->delta_s(start_time,end_time)) << std::endl;
}
}
return 0;
3.控制帧速(OpenThreads::Thread::microSleep())
microSleep单位是百万分之一秒
float sleep_time = 0.0,last_time = 0.0;
while(!viewer.done())
{
per_start_time = timer->tick();
viewer.frame();
per_end_time = timer->tick();
// 想限制帧速为10,及每帧绘制1/10 = 0.1s
sleep_time = 0.1 - (timer->delta_s(per_start_time,per_end_time));
if(sleep_time < 0)
sleep_time = last_time*0.8;
last_time = sleep_time;
OpenThreads::Thread::microSleep(sleep_time*1000000);// 第一帧不睡
}
四、场景图形压缩归档工具osgArchive(打包) ???
生成的压缩文件可以在OSG程序(如osgViewer)运行使用。
五、数据转换工具osgConv ???
用于读取3D数据,执行基本操作,并重新保存为新的3D数据文件。
例如可以读取标准3D文件格式,如OpenFilght,3DS,Alias,OBJ等,并将其转换为OSG本地格式(ASCII形式的.osg或者而精致形式的.ive文件)。
压缩的同时可以生成细化纹理。