Day01
1.打开VS,选择【新建】-【visual C++】-【win32】-【win32控制台应用程序】。
2.在解决资源方案管理器中, 右击【源文件】-【添加】-【新建项】 -【C++文件.cpp】
3右键项目,选择“属性”,选择“VC++目录”,
在包含目录添加:C:\OSG\include
在库目录添加:C:\OSG\lib.
(以上两个目录所在文件均为此前配置环境时设置的路径)
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();
}
运行后显示为一架滑翔机:
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方法的相关信息:
方法的第三个参数类型为 CameraManipulator,为一个抽象类,与代码中的 TrackballManipulator FlightManipulator DriveManipulator TerrainManipulator方法关系如下:
viewer.setCameraManipulator( keyswitchManipulator.get() );
把这个“用按键来换操作器的类”添加到 viewer 当中去,这样就可以用键来**这些操作器。
viewer.addEventHandler(new osgViewer::RecordCameraPathHandler);
把路径记录的功能添加到 viewer 当中,和添加状态是一样的。