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

时间:2024-03-22 18:11:52

Day01

 

1.打开VS,选择【新建】-【visual C++】-【win32】-【win32控制台应用程序】。

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

 

 

 

2.在解决资源方案管理器中, 右击【源文件】-【添加】-【新建项】 -【C++文件.cpp】

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

3右键项目,选择“属性”,选择“VC++目录”,

在包含目录添加:C:\OSG\include

在库目录添加:C:\OSG\lib.

(以上两个目录所在文件均为此前配置环境时设置的路径)

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

 

 

 

 

 

4.打开项目【属性】-【链接器】-【输入】-【附加依赖项】加上:

OpenThreadsd.lib

osgd.lib

osgDBd.lib

osgUtild.lib

osgGAd.lib

osgViewerd.lib

osgTextd.lib

osgFXd.lib

osgManipulatord.lib

osgParticled.lib

osgShadowd.lib

osgSimd.lib

osgTerraind.lib

 

 

 

 

 

 

 

 

 

 

 

 

5. 在 main.cpp 中输入以下代码:

 

#include <osgDB/ReadFile>

#include <osgViewer/Viewer>

void main()

{

    osgViewer::Viewer viewer;

    viewer.setSceneData(osgDB::readNodeFile("glider.osg"));

    viewer.realize();

    viewer.run();

}

 

运行后显示为一架滑翔机:(一)OSG初学者入门基础教程

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

6.代码解释:

 

#include <osgDB/ReadFile>

#include <osgViewer/Viewer>

这里是包含头文件,可以打开 OSG 的安装目录,发现应该存在 osgViewer 和 osgDB 的文件夹, 而 ReadFile 和 Viewer 都是其中的头文件。

 

osgViewer::Viewer viewer;

这里申请了一个 viewer,这里要解释一下,为什么要 osgViewer::Viewer, osgViewer 是名字空间, 与 std::的地位是一样的,关于名字间是 C++防止重名的很重要的一个机制,从而使程序看起来井井有条。 这里你可以理解为申请一个观察器,该观察可以查看模型就可以了,在现实中我们也是叫 Viewer 的。 比如,你的 Viewer 写的有问题,用 Viewer 等等打招乎语。注意这里申请的并非一个指针,而实是一个 对象实体。

 

viewer.setSceneData(osgDB::readNodeFile("glider.osg"));

这里是设置观察器Viewer中的数据,"glider.osg"即为所要观察的数据,观察的数据要有路径,比如:viewer.setSceneData(osgDB::readNodeFile("C://glider.osg")); 其中//为转义字符,编译器会识别为/。不要设置中文路径及空格。

 

viewer.realize();

这个语句表达的意思非常多,事实上可以定位到 Viewer.cpp 的第 377 行,会发现里面的操作非常 多,可以理解为这是在渲染前的最后一步,会检查和设置图形上下文,屏幕啊什么的,会让你以前的 设置,对 Viewer 的设置都生效。

 

viewer.run();

 开始渲染。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

7.改进刚才的HelloWorld项目的代码,增加以下功能需求,点击 S 键会显示帧速,点击 W 键会显示网格,点击 L 键灯光会开启等功能。

 

8.代码添加及修改

#include <osgDB/ReadFile>

#include <osgViewer/Viewer>

#include <osgViewer/ViewerEventHandlers>

#include <osgGA/StateSetManipulator>

void main()

{

    osgViewer::Viewer viewer;

    viewer.setSceneData(osgDB::readNodeFile("glider.osg"));

 

    //添加状态事件

    viewer.addEventHandler( new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) );

    //窗口大小变化事件

    viewer.addEventHandler(new osgViewer::WindowSizeHandler);

    //添加一些常用状态设置

    viewer.addEventHandler(new osgViewer::StatsHandler);

   

    viewer.realize();

    viewer.run();

}

 

运行后会按相应按键会有相应效果出现。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

9.代码解释:

//添加状态事件

viewer.addEventHandler( new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) );

从函数的意思上来看是添加一个事件句柄,可以理解为添加一个响应,鼠标或是键盘的,这个响 应可以看做响应键盘或是鼠标事件,故函数名字叫:addEventHandler[添加事件句柄]。这个事件是库 中自己写好的,叫做状态设置

(new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet())),其中我们点击 L 键时有操作器 的味道,所以叫状态设置操作器。众所周知,灯光是状态控制的,所以这句话可以控制 L 键开启与关 闭灯光,至于为什么定位在 L 键上,怎么搞的,可以查看 StateSetManipulator 源码,我们以后也会写自 己的操作器。发现默认的灯光比加强的 L 灯光好看一些,这是这个模型,大多数情况下都不是这样的。

 

//窗口大小变化事件

viewer.addEventHandler(new osgViewer::WindowSizeHandler);

添加的是窗口大小改变的句柄,这里响应的是 F 键,与上面的原理是差不多。

 

//添加一些常用状态设置

viewer.addEventHandler(new osgViewer::StatsHandler);

添加常用的状态操作,这里会响应 S 键,W 键等等,原理与上述两个是一样的。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 10.设置操作器,代码如下:

#include <osgDB/ReadFile>

#include <osgViewer/Viewer>

#include <osgViewer/ViewerEventHandlers>

#include <osgGA/TrackballManipulator>

#include <osgGA/FlightManipulator>

#include <osgGA/DriveManipulator>

#include <osgGA/KeySwitchMatrixManipulator>

#include <osgGA/StateSetManipulator>

#include <osgGA/AnimationPathManipulator>

#include <osgGA/TerrainManipulator>

void main()

{

    osgViewer::Viewer viewer;

viewer.setSceneData(osgDB::readNodeFile("glider.osg"));

 

    //添加状态事件

    viewer.addEventHandler( new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) );

    //窗口大小变化事件

    viewer.addEventHandler(new osgViewer::WindowSizeHandler);

    //添加一些常用状态设置

    viewer.addEventHandler(new osgViewer::StatsHandler);

 

    {

         osg::ref_ptr<osgGA::KeySwitchMatrixManipulator> keyswitchManipulator = new osgGA::KeySwitchMatrixManipulator;

 

        keyswitchManipulator->addMatrixManipulator( '1', "Trackball", new osgGA::TrackballManipulator() );

        keyswitchManipulator->addMatrixManipulator( '2', "Flight", new osgGA::FlightManipulator() );

        keyswitchManipulator->addMatrixManipulator( '3', "Drive", new osgGA::DriveManipulator() );

        keyswitchManipulator->addMatrixManipulator( '4', "Terrain", new osgGA::TerrainManipulator() );

    viewer.setCameraManipulator( keyswitchManipulator.get() );

    }

    //添加路径记录

    viewer.addEventHandler(new osgViewer::RecordCameraPathHandler);

    viewer.realize();

    viewer.run();

}

 

按下按键1、2、3、4后,模型会根据鼠标操作产生不同的动作,按下大写Z,然后鼠标拖动模型,再按下小写鼠标z,就会记录你刚才的模型运动轨迹。

如:"Trackball" "Flight" "Drive" "Terrain"均为不同的运动轨迹模式。

 

11.代码解释:

osg::ref_ptr<osgGA::KeySwitchMatrixManipulator> keyswitchManipulator = new osgGA::KeySwitchMatrixManipulator;

申请一个使用按键来换操作器的类,即:osgGA::KeySwitchMatrixManipulator,意思是往这个类中添操作器,添的时候带标识符和快捷键,然后再把这个类添加到 viewer 当中,这样 viewer 运行的时候就可以通过按键来换操作器了。

keyswitchManipulator->addMatrixManipulator( '1', "Trackball", new osgGA::TrackballManipulator() );

keyswitchManipulator->addMatrixManipulator( '2', "Flight", new osgGA::FlightManipulator() );

keyswitchManipulator->addMatrixManipulator( '3', "Drive", new osgGA::DriveManipulator() );

keyswitchManipulator->addMatrixManipulator( '4', "Terrain", new osgGA::TerrainManipulator() );

申请一些操作器,把这些操作器加入到“用按键来换操作器的类”中。

在osg的帮助文档中可以查看到关于addMatrixManipulator方法的相关信息:

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

方法的第三个参数类型为 CameraManipulator,为一个抽象类,与代码中的 TrackballManipulator FlightManipulator DriveManipulator TerrainManipulator方法关系如下:

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

viewer.setCameraManipulator( keyswitchManipulator.get() );

把这个“用按键来换操作器的类”添加到 viewer 当中去,这样就可以用键来**这些操作器。

viewer.addEventHandler(new osgViewer::RecordCameraPathHandler);

把路径记录的功能添加到 viewer 当中,和添加状态是一样的。