若该文为原创文章,未经允许不得转载

原博主博客地址: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漫游之平移与转向相关推荐

  1. 【Visual C++】游戏开发笔记二十四 由DirectX的几个版本说开去

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 本系列文 ...

  2. OSG开发笔记(十九):OSG文字显示

    若该文为原创文章,未经允许不得转载 本文章博客地址:https://blog.csdn.net/qq21497936/article/details/97262841 各位读者,知识无穷而人力有穷,要 ...

  3. OSG开发笔记(十六):OSG视口、相机和视点

    若该文为原创文章,未经允许不得转载 本文章博客地址:https://blog.csdn.net/qq21497936/article/details/96836876 各位读者,知识无穷而人力有穷,要 ...

  4. 树莓派开发笔记(十四):入手研华ADVANTECH工控树莓派UNO-220套件(三):使用研发自带系统测试rtc、gpio、232和485套件接口

    若该文为原创文章,转载请注明原文出处 本文章博客地址:https://hpzwl.blog.csdn.net/article/details/124754769 红胖子(红模仿)的博文大全:开发技术集 ...

  5. 【Visual C++】游戏开发笔记三十四 浅墨DirectX提高班之三 起承转合的艺术:Direct3D渲染五步曲...

    本系列文章由zhmxy555(毛星云)编写,转载请注明出处. 文章链接: http://blog.csdn.net/zhmxy555/article/details/8223965 作者:毛星云(浅墨 ...

  6. 【Visual C++】游戏开发笔记二十六 DirectX 11各组件的介绍 第一个DirectX 11 Demo的创建

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 本系列文 ...

  7. 【Visual C++】游戏开发笔记二十六 DirectX 11各组件的介绍第一个DirectX 11 Demo的创建

    本系列文章由zhmxy555(毛星云)编写,转载请注明出处. http://blog.csdn.net/zhmxy555/article/details/7688515 作者:毛星云    邮箱: h ...

  8. 【Visual C++】游戏开发笔记三十四 浅墨DirectX提高班之三 起承转合的艺术:Direct3D渲染五步曲

    本系列文章由zhmxy555(毛星云)编写,转载请注明出处. 文章链接: http://blog.csdn.net/zhmxy555/article/details/8223965 作者:毛星云(浅墨 ...

  9. 【Visual C++】游戏开发笔记二十六 DirectX 11各组件的介绍第一个DirectX 11 Demo的创建...

    本系列文章由zhmxy555(毛星云)编写,转载请注明出处. http://blog.csdn.net/zhmxy555/article/details/7688515 作者:毛星云 邮箱: happ ...

  10. Android开发笔记(十四)圆弧进度动画CircleAnimation

    一个好看的APP,都有不少精致的动画效果.熟练运用各种动画技术,可让我们的APP灼灼生辉.Android在技术上把动画分为了三类,分别是帧动画FrameAnimation.补间动画TweenAnima ...

最新文章

  1. Kernel Video Converter中文版
  2. 判斷作業系統為 64bit 或 32bit z
  3. 给笔记本更换SSD硬盘
  4. Android应用视觉效果设计技巧
  5. Matlab图像处理应用举例2
  6. ABB码垛算法程序与设计接口参考案例
  7. vue中使用海康插件实现视频监控-前端给视频画面中添加文字
  8. Industry工业软件开发平台设计A-1
  9. Linux命令之sed批量替换字符串
  10. 一边裁员、一边招聘,领导到底想干啥?
  11. 存储容量及相关计算单位
  12. 空间直角坐标系、大地坐标系、平面坐标系、高斯平面直角坐标系
  13. 送小公主——哆啦A梦(Python代码实现)
  14. vba 添加outlook 签名_outlook2007使用vba签名的问题
  15. Dynamic GCN:Dynamic GCN: Context-enriched Topology Learning for Skeleton-based Action Recognition
  16. 解决home end pgup pgdn没有独立,需要键盘映射的问题
  17. 计算机是如何跑起来的--读书笔记
  18. 李彦宏派出自家司机,央视主持人彻底被惊到了:人呢?人呢?
  19. 研究方向确定:移动网络优化
  20. seo之我们网站的用户都是哪些人

热门文章

  1. 微信小程序 阻止 onshow请求数据
  2. 玩转路由之 AsusWRT-Merlin 与 Entware
  3. ios 生成字母加数字的随机数
  4. 使用anaconda创建虚拟环境
  5. 学习笔记整理_Linux基本命令
  6. Linux系统中使用Nginx实现反向代理
  7. boolean的使用
  8. 首个高温红色预警来了,气象预警你了解多少?
  9. 树、二叉树、满二叉树、完全二叉树概念分清
  10. 职称计算机考试用友u8试题答案,2013年职称计算机考试用友U8模拟试题及答案(8)...