matlab火星漫游车转向控制,OSG开发笔记(二十四):OSG漫游之平移与转向
若该文为原创文章,未经允许不得转载
原博主博客地址:https://blog.csdn.net/qq21497936
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/98964269
目录
前言
Demo工程实现功能
Demo运行效果
操作器概述
初始化默认位置
移动位置
实现简单的漫游器
漫游器代码
MyCameraMainpulator.h
MyCameraMainpulator.cpp
OSG 3.4.0 中的漫游器概览
OSG三维开发专栏
《OSG开发笔记(一):OSG介绍、编译》
《OSG开发笔记(二):OSG帮助文档编译》
《OSG开发笔记(三):OSG使用osgQt嵌入Qt应用程序》
《OSG开发笔记(四):OSG不使用osgQt重写类嵌入Qt应用程序》:
《OSG开发笔记(五):OSG场景理解与基础类概述》
《OSG开发笔记(六):OSG内存管理》
《OSG开发笔记(七):OSG复现OpenGL入门示例和OSG坐标系》
《OSG开发笔记(八):OSG模型文件存储与读取》
《OSG开发笔记(九):OSG模型的基本操作之添加/删除、显示/隐藏、开关节点开/关》:
《OSG开发笔记(十):OSG模型的变换之平移、旋转和缩放》
《OSG开发笔记(十一):OSG渲染状态与2D纹理映射》
《OSG开发笔记(十二):OSG基本几何图形、内置几何类型》
《OSG开发笔记(十三):OSG三维纹理映射(体渲染)》
《OSG开发笔记(十四):OSG交互》
《OSG开发笔记(十五):OSG光照》
《OSG开发笔记(十六):OSG视口、相机和视点》
《OSG开发笔记(十七):OSG中的相机移动》
《OSG开发笔记(十八):OSG鼠标拾取pick、拽托球体以及多光源》
《OSG开发笔记(十九):OSG文字显示》
《OSG开发笔记(二十):OSG使用HUD显示文字》
《OSG开发笔记(二十一):OSG使用HUD绘制图形以及纹理混合模式》
《OSG开发笔记(二十二):OSG场景背景》
《OSG开发笔记(二十三):Qt使用QOpenGLWidget渲染OSG和地球仪》
《OSG开发笔记(二十四):OSG漫游之平移、转向和低抬头》
《OSG开发笔记(二十五):OSG漫游之CS移动、碰撞检测与跳跃》
《OSG开发笔记(二十六):OSG漫游之上下楼梯》
《OSG开发笔记(二十七):OSG路径漫游之录制播放固定路径动画》
《OSG开发笔记(二十八):OSG模型固定路径动画》
持续补充中…
OSG开发笔记(二十四):OSG漫游之平移、转向和低抬头
前言
80后典型的使用三维技术的游戏代表作就是CS,CS中可以使用WSAD移动,移动的过程就是漫游。
Demo工程实现功能
WSAD:向前后左右移动
QE/方向键左右:向左右移动视角
方向键上下:向上下移动视角(抬头、低头)
Demo运行效果
操作器概述
在场景中有一个重要的概念,漫游。漫游就是在场景中移动,漫游可以按照用户的要求漫游也可以按照预先的计划漫游(路线)。在之前的开发中,都是用的是OSG自带的操作器Trackball,大众而好用,满足基本需求。但是无法实现CS中的漫游方式(移动还有碰撞等等)。
场景的核心管理类是viewer,想要自定义漫游则必须相应事件,比如鼠标动了,场景也在动。响应事件的类是osgGA::GUIEventHandler,实现漫游使用的响应事件的类是事件响应类的子类,类名osgGA::MatrixManipulator,控制漫游实际就是矩阵变换,这个类有一些设置矩阵的公共接口,通过接口控制viewer了。OSG自带的几个操作器,操作都相同,漫游的主要流程如下:
在1时,使用setCameraManipulator设置操作器;
在2时,每次更新场景都会调用操作器获取矩阵变换;
在3时,每次接收到消息都会触发操作器的handle事件;
操作器必须从osgGA:MatrixManipulator派生而来,而该类提供的接口如下:
virtual void setByMatrix(const osg::Matrixd &matrix) = 0;
virtual void setByInverseMatrix(const osg::Matrixd &matrix) = 0;
// 当场景更新时,会被管理类调用
virual osg::Matrixd getMatrix() const = 0;
// 当场景更新时,会被管理类调用
virtual osg::Matrixd getInverseMatrix() const = 0;
以上四个接口可以向viewer传递矩阵的相关信息。
然后通过handle接口对消息进行处理。
初始化默认位置
初始化操作其实,需要带上当前视口默认的操作位置与旋转矩阵。
由上图,最值得注意的是视口摄像机的默认方向为向下,所以需要绕X轴旋转90度调整视口方向。
移动位置
如上图,若向右旋转45度后,那么走一段距离,需要进行三角函数计算,得到两个轴上的位移,然后对原位置进行修改。
实现简单的漫游器
步骤一:继承自osgGA::CameraMainpulator
步骤二:重新实现4个纯虚函数
步骤三:设置初始位置、旋转角度、移动步长、旋转步长
步周四:处理消息函数handle
漫游器代码
MyCameraMainpulator.h
#ifndef MYCAMERAMAINPULATOR_H
#define MYCAMERAMAINPULATOR_H
#include #include #include class MyCameraMainpulator : public osgGA::CameraManipulator
{
public:
MyCameraMainpulator();
~MyCameraMainpulator();
public:
virtual void setByMatrix(const osg::Matrixd& matrix); // 设置相机的位置姿态矩阵
virtual void setByInverseMatrix(const osg::Matrixd& matrix); // 设置相机的视图矩阵
virtual osg::Matrixd getMatrix() const; // 获取相机的姿态矩阵
virtual osg::Matrixd getInverseMatrix() const; // 获取相机的视图矩阵
virtual bool handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &us);
private:
osg::Vec3 _position; // 视点当前位置
osg::Vec3 _rotation; // 朝向
float _moveStep; // 移动步长5
float _rotateStep; // 旋转步长
float _originAngleX; // X轴初始化时偏移角度
float _originAngleY; // Y轴初始化时偏移角度
float _originAngleZ; // Z轴初始化时偏移角度
float _offsetAngleX; // X轴当前旋转角度
float _offsetAngleY; // Y轴当前旋转角度
float _offsetAngleZ; // Z轴当前旋转角度
};
#endif // MYCAMERAMAINPULATOR_H
MyCameraMainpulator.cpp
#include "MyCameraMainpulator.h"
#include #include "osg/Math"
MyCameraMainpulator::MyCameraMainpulator()
: _originAngleX(90.0f),
_originAngleY(0.0f),
_originAngleZ(0.0f),
_offsetAngleX(0.0f),
_offsetAngleY(0.0f),
_offsetAngleZ(0.0f)
{
// 使用漫游器的初始化位置
_position = osg::Vec3( -0.0f, -5.0f, 0.0f);
_rotation = osg::Vec3( osg::DegreesToRadians(_originAngleX + _offsetAngleX),
osg::DegreesToRadians(_originAngleY + _offsetAngleY),
osg::DegreesToRadians(_originAngleZ + _offsetAngleZ));
_moveStep = 0.01f;
_rotateStep = 0.1f;
}
MyCameraMainpulator::~MyCameraMainpulator()
{
}
void MyCameraMainpulator::setByMatrix(const osg::Matrixd &matrix)
{
}
void MyCameraMainpulator::setByInverseMatrix(const osg::Matrixd &matrix)
{
computeHomePosition();
}
osg::Matrixd MyCameraMainpulator::getMatrix() const
{
osg::Matrixd mat;
mat.makeTranslate(_position);
return osg::Matrixd::rotate(_rotation.x(), osg::X_AXIS,
_rotation.y(), osg::Y_AXIS,
_rotation.z(), osg::Z_AXIS) * mat;
}
osg::Matrixd MyCameraMainpulator::getInverseMatrix() const
{
osg::Matrixd mat;
mat.makeTranslate(_position);
return osg::Matrixd::inverse(osg::Matrixd::rotate(_rotation.x(), osg::X_AXIS,
_rotation.y(), osg::Y_AXIS,
_rotation.z(), osg::Z_AXIS) * mat);
}
bool MyCameraMainpulator::handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &us)
{
switch (ea.getEventType())
{
case osgGA::GUIEventAdapter::KEYDOWN:
switch (ea.getKey()) {
case osgGA::GUIEventAdapter::KEY_E:
case osgGA::GUIEventAdapter::KEY_Right:
_offsetAngleZ = _offsetAngleZ + _rotateStep;
_rotation[2] = osg::DegreesToRadians(_originAngleZ + _offsetAngleZ);
break;
case osgGA::GUIEventAdapter::KEY_Q:
case osgGA::GUIEventAdapter::KEY_Left:
_offsetAngleZ = _offsetAngleZ - _rotateStep;
_rotation[2] = osg::DegreesToRadians(_originAngleZ + _offsetAngleZ);
break;
case osgGA::GUIEventAdapter::KEY_W:
_position[1] += _moveStep * cos(osg::DegreesToRadians(-_offsetAngleZ));
_position[0] += _moveStep * sin(osg::DegreesToRadians(-_offsetAngleZ));
break;
case osgGA::GUIEventAdapter::KEY_S:
_position[1] -= _moveStep * cos(osg::DegreesToRadians(-_offsetAngleZ));
_position[0] -= _moveStep * sin(osg::DegreesToRadians(-_offsetAngleZ));
break;
case osgGA::GUIEventAdapter::KEY_A:
_position[0] -= _moveStep * cos(osg::DegreesToRadians(-_offsetAngleZ));
_position[1] += _moveStep * sin(osg::DegreesToRadians(-_offsetAngleZ));
break;
case osgGA::GUIEventAdapter::KEY_D:
_position[0] += _moveStep * cos(osg::DegreesToRadians(-_offsetAngleZ));
_position[1] -= _moveStep * sin(osg::DegreesToRadians(-_offsetAngleZ));
break;
case osgGA::GUIEventAdapter::KEY_Up:
_offsetAngleX += _rotateStep;
_rotation[0] = osg::DegreesToRadians(_originAngleX + _offsetAngleX);
break;
case osgGA::GUIEventAdapter::KEY_Down:
_offsetAngleX -= _rotateStep;
_rotation[0] = osg::DegreesToRadians(_originAngleX + _offsetAngleX);
break;
default:
break;
}
qDebug() << "position: " << _position.x() << "," << _position.y() << "," << _position.z()
<< "rotation: " << _rotation.x() << "," << _rotation.y() << "," << _rotation.z();
break;
default:
break;
}
return true;
}
OSG 3.4.0 中的漫游器概览
漫游器在osgGA库中实现,这个库主要是用来处理用户与三维场景的交互(包括鼠标、键盘、手势、操纵杆等),之前我们设置是可以添加消息处理的,详情见《OSG开发笔记(十四):OSG交互》,在添加的消息类中处理hand中返回true,则消息不会传递到漫游器当中去,返回false则消息会传到漫游器中。
消息处理类中处理与漫游器处理的区别,消息处理中需要获取osg::Viewer直接对模型进行操作,而漫游器中是直接操作矩阵。
在OSG3.4.0版本中的漫游器类型,如下图:
设置纯漫游器的效果如下表:
序号
漫游器
详细描述
效果
0
不使用
没有漫游器则没有视图
1
osgGA::CameraManipulator
抽象类,无法使用
无
2
osgGA::StandardManipulator
抽象类,无法使用
无
3
osgGA::OrbitManipulator
鼠标控制,绕X轴只能翻转180,持续旋转
4
osgGA::TrackballManipulator
常用的漫游方式,基于轨迹球理论进行设计。鼠标控制,全方位旋转,持续旋转
同上
5
osgGA::MultiTouchTrackballManipulator
鼠标控制,全方位旋转,持续旋转,触屏未测
同上
6
osgGA::NodeTrackerManipulator
鼠标控制,全方位旋转,持续旋转,触屏未测
同上
7
osgGA::TerrainManipulator
固定绕一个点动,鼠标控制,全方位旋转,持续旋转,触屏未测
8
osgGA::FirstPersonManipulator
鼠标移动视角,持续旋转
9
osgGA::FlightManipulator
模拟飞机飞行的漫游方式
先整中间,鼠标放入窗口飞行
10
osgGA::AnimationPathManipulator
根据指定的路径自动执行场景的漫游
11
osgGA::SphericalManipulator
模拟球面浏览的漫游方式。鼠标控制,绕X轴只能翻转180,持续旋转
12
osgGA::CameraViewSwitchManipulator
可以切换相机视角的漫游器
13
osgGA::DriveManipulator
模拟汽车驾驶的漫游方式
14
osgGA::KeySwitchMatrixManipulator
测试挂,需要其他配合
15
osgGA::UFOManipulator
模拟UFO飞行漫游方式
16
osgGA::StateSetManipulator
非cameraManipulator子类
原博主博客地址:https://blog.csdn.net/qq21497936
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/98964269
matlab火星漫游车转向控制,OSG开发笔记(二十四):OSG漫游之平移与转向相关推荐
- 【Visual C++】游戏开发笔记二十四 由DirectX的几个版本说开去
分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 本系列文 ...
- OSG开发笔记(十九):OSG文字显示
若该文为原创文章,未经允许不得转载 本文章博客地址:https://blog.csdn.net/qq21497936/article/details/97262841 各位读者,知识无穷而人力有穷,要 ...
- OSG开发笔记(十六):OSG视口、相机和视点
若该文为原创文章,未经允许不得转载 本文章博客地址:https://blog.csdn.net/qq21497936/article/details/96836876 各位读者,知识无穷而人力有穷,要 ...
- 树莓派开发笔记(十四):入手研华ADVANTECH工控树莓派UNO-220套件(三):使用研发自带系统测试rtc、gpio、232和485套件接口
若该文为原创文章,转载请注明原文出处 本文章博客地址:https://hpzwl.blog.csdn.net/article/details/124754769 红胖子(红模仿)的博文大全:开发技术集 ...
- 【Visual C++】游戏开发笔记三十四 浅墨DirectX提高班之三 起承转合的艺术:Direct3D渲染五步曲...
本系列文章由zhmxy555(毛星云)编写,转载请注明出处. 文章链接: http://blog.csdn.net/zhmxy555/article/details/8223965 作者:毛星云(浅墨 ...
- 【Visual C++】游戏开发笔记二十六 DirectX 11各组件的介绍 第一个DirectX 11 Demo的创建
分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 本系列文 ...
- 【Visual C++】游戏开发笔记二十六 DirectX 11各组件的介绍第一个DirectX 11 Demo的创建
本系列文章由zhmxy555(毛星云)编写,转载请注明出处. http://blog.csdn.net/zhmxy555/article/details/7688515 作者:毛星云 邮箱: h ...
- 【Visual C++】游戏开发笔记三十四 浅墨DirectX提高班之三 起承转合的艺术:Direct3D渲染五步曲
本系列文章由zhmxy555(毛星云)编写,转载请注明出处. 文章链接: http://blog.csdn.net/zhmxy555/article/details/8223965 作者:毛星云(浅墨 ...
- 【Visual C++】游戏开发笔记二十六 DirectX 11各组件的介绍第一个DirectX 11 Demo的创建...
本系列文章由zhmxy555(毛星云)编写,转载请注明出处. http://blog.csdn.net/zhmxy555/article/details/7688515 作者:毛星云 邮箱: happ ...
- Android开发笔记(十四)圆弧进度动画CircleAnimation
一个好看的APP,都有不少精致的动画效果.熟练运用各种动画技术,可让我们的APP灼灼生辉.Android在技术上把动画分为了三类,分别是帧动画FrameAnimation.补间动画TweenAnima ...
最新文章
- Kernel Video Converter中文版
- 判斷作業系統為 64bit 或 32bit z
- 给笔记本更换SSD硬盘
- Android应用视觉效果设计技巧
- Matlab图像处理应用举例2
- ABB码垛算法程序与设计接口参考案例
- vue中使用海康插件实现视频监控-前端给视频画面中添加文字
- Industry工业软件开发平台设计A-1
- Linux命令之sed批量替换字符串
- 一边裁员、一边招聘,领导到底想干啥?
- 存储容量及相关计算单位
- 空间直角坐标系、大地坐标系、平面坐标系、高斯平面直角坐标系
- 送小公主——哆啦A梦(Python代码实现)
- vba 添加outlook 签名_outlook2007使用vba签名的问题
- Dynamic GCN:Dynamic GCN: Context-enriched Topology Learning for Skeleton-based Action Recognition
- 解决home end pgup pgdn没有独立,需要键盘映射的问题
- 计算机是如何跑起来的--读书笔记
- 李彦宏派出自家司机,央视主持人彻底被惊到了:人呢?人呢?
- 研究方向确定:移动网络优化
- seo之我们网站的用户都是哪些人