以下内容来自:
1、《OpenSceneGraph三维渲染引擎编程指南》肖鹏 刘更代 徐明亮 清华大学出版社
2、《OpenSceneGraph三维渲染引擎设计与实践》王锐 钱学雷 清华大学出版社
3、自己的总结
创建C++项目后,首先需要配置OSG环境,具体步骤看OSG学习:WIN10系统下OSG+VS2017编译及运行第六步:新建OSG项目测试。
OSG中主要使用osgGA库来处理用户的交互工作(详细见OSG学习:OSG组成(一)——组成模块和OSG学习:OSG组成(三)——组成模块(续):OSG核心库中的一些类和方法)。GA全称为GUI Abstraction,图形接口抽象层。即由OSG负责与不同地层窗口的交互工作,而在更高层级为用户提供一套统一的操作接口,方便用户处理,因而构成了OSG与MFC/Qt/wxWidgets等各种窗口系统工具的交互方案。
在OSG学习:几何体的操作(一)——交互事件、简化几何体、OSG学习:纹理映射(六)——灯光两个例子中,都是使用事件监听或事件响应进行人机交互。在开关节点中展示了着火的飞机,在本例中,使用人机交互方式(键盘按键)来切换正常的飞机与着火的飞机。
下面来看具体的例子:
// stdafx.h
#include <osg/Switch> //控制子类的显示与隐藏,这种隐藏不消耗内存
#include <osgGA/GUIEventHandler> //OSG键盘和鼠标交互事件的处理终端
#include <osgDB/ReadFile>
#include <osgUtil/Optimizer>
#include <osgViewer/Viewer>
//.cpp
/*
*定义人机交互事件处理器
*/
class KeyboardHandler :public osgGA::GUIEventHandler
{
public:
virtual bool handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &aa, osg::Object *, osg::NodeVisitor *)
{
osgViewer::Viewer *viewer = dynamic_cast<osgViewer::Viewer *>(&aa); //将动作适配器us转换为场景视图,通常作为动作适配器的对象都是当前的场景视图
if (!viewer)
return false;
switch (ea.getEventType())
{
case osgGA::GUIEventAdapter::KEYDOWN:
//按下空格键时,获取窗口大小,并把鼠标光标限制到窗口中心
//KEY_Space 空格
if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Space)
{
//获取事件所来源的图形窗口的位置和尺寸信息,如果该事件来源于窗口的话
int width = ea.getWindowWidth();
int height = ea.getWindowHeight();
viewer->requestWarpPointer(width * 0.5, height * 0.5);
}
else
{
//按下1或2键,切换开关节点的两个子节点,按1键显示正常飞机,按2键显示着火飞机
//主键盘上的字母键、数字键,及各种标点符号键都以各自本身来代表,如下面的1就代表主键盘上的1
osg::Switch *root = dynamic_cast<osg::Switch *>(viewer->getSceneData());
if (!root)
return false;
if (ea.getKey() == '1')
{
root->setValue(0, true);
root->setValue(1, false);
}
else if (ea.getKey() == '2')
{
root->setValue(0, false);
root->setValue(1, true);
}
return true;
}
break;
default:break;
}
return false;
}
};
int main()
{
osg::ref_ptr<osg::Switch> root = new osg::Switch();
root->addChild(osgDB::readNodeFile("cessna.osg"), true);
root->addChild(osgDB::readNodeFile("cessnafire.osg"), false);
//优化场景数据
osgUtil::Optimizer optimizer;
optimizer.optimize(root.get());
osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();
viewer->addEventHandler(new KeyboardHandler); //将时间处理器使用addEventHandler()方法传递给当前视景器
viewer->setSceneData(root.get());
viewer->realize();
return viewer->run();
}
按下空格键后模型和鼠标都回到窗口中心,按下主键盘上的1键显示正常飞机,按下主键盘上的2键显示着火飞机。