效果图如下:

以下是South.h文件的源码

//操作器管理类,用来管理操作器
#include <osgViewer/Viewer>
#include <osgGA/CameraManipulator>
#include <osgUtil/IntersectVisitor>
#include <osg/LineSegment>
class CSouth:public osgGA::CameraManipulator
{
public:CSouth();
public:~CSouth();
private://节点值,用来测试碰撞检测的osg::ref_ptr<osg::Node> m_node;//相机操作器unsigned int m_nID;//移动速度float m_fMoveSpeed;//位置osg::Vec3 m_vPosition;//旋转角度osg::Vec3 m_vRotation;//左键是否按下bool m_bLeftButtonDown;//左键点下时屏幕坐标float m_fpushX;//碰撞检测开启状态查询。bool m_bPeng;//右键点下时屏幕坐标float m_fpushY;
public://碰撞检测是否开启void setPeng(bool peng);//得到碰撞检测开启状态bool getPeng();//如果碰撞检测开启则关闭,如果关闭则开启void setFpeng();//设置要进行碰撞检测的数据virtual void setNode(osg::Node *);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);//屏幕角度float m_fAngle;//位置变换函数void changePostition(osg::Vec3 &delta);//得到当前速度float getSpend();//设置当前速度void setSpend(float);//设置视点位置void setPosition(osg::Vec3 &position);void setPosition(double *);//得到当前视点位置osg::Vec3 getPosition();//计算家的位置void computeHomePosition();
};

以下是South.cpp文件的源码:

#include "stdafx.h"
#include "South.h"
//设置一些初始值 左键没有按下,左键点下时初始坐标为0,初始角速度是2.5,开始时碰撞检测关闭,右键点下时初始坐标也为0
CSouth::CSouth():m_fMoveSpeed(1.5),m_bLeftButtonDown(false),m_fpushX(0),m_fAngle(2.5),m_bPeng(false),m_fpushY(0)
{//出生点为000m_vPosition=osg::Vec3(0.0,0.0,5.0);//初始角度m_vRotation=osg::Vec3(osg::PI_2,0.0,0.0);
}
CSouth::~CSouth()
{}
//碰撞检测是否开启
void CSouth::setPeng(bool peng)
{m_bPeng=peng;
}
//得到碰撞检测开启状态
bool CSouth::getPeng()
{return m_bPeng;
}
//如果碰撞检测开启则关闭,如果关闭则开启
void CSouth::setFpeng()
{m_bPeng=!m_bPeng;
}
//设置要进行碰撞检测的数据
void CSouth::setNode(osg::Node *node)
{m_node=node;
}
void CSouth::setByMatrix(const osg::Matrixd &matrix)
{}
void CSouth::setByInverseMatrix(const osg::Matrixd &matrix)
{}
//得到矩阵,这是标准接口,用于控制场景
osg::Matrixd CSouth::getMatrix() const
{//得到旋转后的矩阵,其实也就是视口矩阵,用此控制场景osg::Matrixd mat;mat.makeRotate(m_vRotation._v[0],osg::Vec3(1.0,0.0,0.0),m_vRotation._v[1],osg::Vec3(0.0,1.0,0.0),m_vRotation._v[2],osg::Vec3(0.0,0.0,1.0));return mat*osg::Matrixd::translate(m_vRotation);
}
//得到逆矩阵,标准接口,控制场景
osg::Matrixd CSouth::getInverseMatrix() const
{osg::Matrixd mat;mat.makeRotate(m_vRotation._v[0],osg::Vec3(1.0,0.0,0.0),m_vRotation._v[1],osg::Vec3(0.0,1.0,0.0),m_vRotation._v[2],osg::Vec3(0.0,0.0,1.0));return osg::Matrixd::inverse(mat*osg::Matrixd::translate(m_vPosition));
}
//主要事件控制器
bool CSouth::handle(const osgGA::GUIEventAdapter &ea,osgGA::GUIActionAdapter &us)
{//得到x的初始屏幕坐标float mouseX=ea.getX();//得到y的初始屏幕坐标float mouseY=ea.getY();//判断事件类型switch(ea.getEventType()){case osgGA::GUIEventAdapter::KEYDOWN:{//如果是空格,重绘if (ea.getKey()==0x20){us.requestRedraw();us.requestContinuousUpdate(false);return true;}//如果是home键,则视点向上移动if (ea.getKey()==0xFF50){changePostition(osg::Vec3(0,0,m_fMoveSpeed));return true;}//如果是end键,同视点向下移动if (ea.getKey()==0xFF57){changePostition(osg::Vec3(0,0,-m_fMoveSpeed));return true;}//如果是加号键则加速if (ea.getKey()==0x2B){m_fMoveSpeed+=1.0;return true;}//如果是减号键则减速if (ea.getKey()==0x2D){m_fMoveSpeed-=1.0;if (m_fMoveSpeed<1.0){m_fMoveSpeed=1.0;}return true;}//向前走,W键,或者UP键if (ea.getKey()==0xFF52||ea.getKey()==0x57||ea.getKey()==0x77){changePostition(osg::Vec3(0,m_fMoveSpeed*sinf(osg::PI_2+m_vRotation._v[2]),0));changePostition(osg::Vec3(m_fMoveSpeed*cosf(osg::PI_2+m_vRotation._v[2]),0,0));return true;}//向后退,S键,或者DOWN键if (ea.getKey()==0xFF54||ea.getKey()==0x53||ea.getKey()==0x73){changePostition(osg::Vec3(0,-m_fMoveSpeed*sinf(osg::PI_2+m_vRotation._v[2]),0));changePostition(osg::Vec3(-m_fMoveSpeed*cosf(osg::PI_2+m_vRotation._v[2]),0,0));return true;}//Aif (ea.getKey()==0x41||ea.getKey()==0x61){changePostition(osg::Vec3(0,m_fMoveSpeed*cosf(osg::PI_2+m_vRotation._v[2]),0));changePostition(osg::Vec3(m_fMoveSpeed*sinf(osg::PI_2+m_vRotation._v[2]),0,0));return true;}//Dif (ea.getKey () == 0x44||ea.getKey () == 0x64) { changePostition(osg::Vec3 (0,-m_fMoveSpeed * cosf(osg::PI_2+m_vRotation._v[2]), 0)) ;changePostition(osg::Vec3 (m_fMoveSpeed * sinf(osg::PI_2+m_vRotation._v[2]), 0, 0)) ; return true; }if (ea.getKey() == 0xFF53)//Right { m_vRotation._v[2] -= osg::DegreesToRadians(m_fAngle); }if (ea.getKey()== 0xFF51)//Left { m_vRotation._v[2] += osg::DegreesToRadians(m_fAngle); }if (ea.getKey() == 0x46 || ea.getKey() == 0x66)//F { computeHomePosition(); m_fAngle -= 0.2 ; return true ; }if (ea.getKey() == 0x47 || ea.getKey() == 0x67)//G { m_fAngle += 0.2 ; return true ; }return false;}case osgGA::GUIEventAdapter::PUSH:if (ea.getButton()==1){//如果是左键,记录下来,因为左键拖动时场景也要转的m_fpushX=mouseX;m_fpushY=mouseY;m_bLeftButtonDown=true;}return false;case osgGA::GUIEventAdapter::DRAG://拖动if (m_bLeftButtonDown){m_vRotation._v[2]-=osg::DegreesToRadians(m_fAngle*(mouseX-m_fpushX));m_vRotation._v[0]+=osg::DegreesToRadians(1.1*(mouseY-mouseY));//防止背过去if (m_vRotation._v[0]>=3.14){m_vRotation._v[0]=3.14;}if (m_vRotation._v[0]<=0){m_vRotation._v[0]=0;}}return false;case osgGA::GUIEventAdapter::RELEASE://键弹起if (ea.getButton()==1){m_bLeftButtonDown=false;}return false;default:return false;}
}
//位置变换函数
void CSouth::changePostition(osg::Vec3 &delta)
{if (m_bPeng){//看新值与旧值之间的连线是否与模型有交点!如果要到达的位置与现在的位置有交点的话,如果碰撞检测也开启了,就不移动。osg::Vec3 newPos=m_vRotation+delta;osgUtil::IntersectVisitor iv;//前后的线段osg::ref_ptr<osg::LineSegment> line=new osg::LineSegment(newPos,m_vPosition);//上下移动的线段,加入两条线段来检测碰撞osg::ref_ptr<osg::LineSegment> lineZ=new osg::LineSegment(newPos+osg::Vec3(0.0,0.0,m_fMoveSpeed),newPos-osg::Vec3(0.0,0.0,m_fMoveSpeed));iv.addLineSegment(lineZ.get());iv.addLineSegment(line.get());//接受碰撞的检测nodem_node->accept(iv);if(!iv.hits()){//如果没有碰撞,则移动旧位置到新的位置上m_vPosition+=delta;}}else{//如果碰撞检测根本没开,则直接移过去m_vPosition+=delta;}
}
//得到当前速度
float CSouth::getSpend()
{return m_fMoveSpeed;
}
//设置当前速度
void CSouth::setSpend(float sp)
{m_fMoveSpeed=sp;
}
//设置视点位置
void CSouth::setPosition(osg::Vec3 &position)
{m_vPosition=position;
}
void CSouth::setPosition(double *position)
{m_vPosition._v[0]=position[0];m_vPosition._v[1]=position[1];m_vPosition._v[2]=position[2];
}
//得到当前视点位置
osg::Vec3 CSouth::getPosition()
{return m_vPosition;
}
//计算家的位置,其实是包围球的球心处
void CSouth::computeHomePosition()
{//如果有模型,则计算包围球的球心if (m_node.get()){const osg::BoundingSphere &boundingSphere=m_node->getBound();osg::Vec3 bp=boundingSphere._center;setPosition(bp);}
}

以下是main函数文件的源码:

// HideModel.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <osgDB/ReadFile>
#include <osgViewer/Viewer>
#include <osg/Node>
#include "South.h"
int _tmain(int argc, _TCHAR* argv[])
{osgViewer::Viewer viewer;osg::ref_ptr<osg::Group> root=new osg::Group();root->addChild(osgDB::readNodeFile("ceep.ive"));viewer.setSceneData(root.get());viewer.setCameraManipulator(new CSouth());viewer.realize();return viewer.run();
}

以下是ceep.ive文件的下载链接: http://pan.baidu.com/s/1kUgdUmV 密码:umnc

注意:在此的ceep.ive我是放在了data目录下的,因此不用加路径

9、osg3.2.1中漫游相关推荐

  1. 虚拟现实中漫游方式的分类

    虚拟现实中漫游方式的分类 1 完全动作线索:一比一的物理运动 2 部分动作线索:原地运动 3 无动作线索:虚拟运动(virtual travel),用户不是真的在进行相应的运动,只是进行操作 4 总结 ...

  2. 【转】osg中漫游器的原理

    在osg中,编写以下简单代码: 1 osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer(); 2 viewer-& ...

  3. 他爱在黑暗中漫游(来自《德国诗选》)

    他爱在黑暗中漫游,黝黑的树荫 重重的树荫会冷却他的梦影. 可是他的心里却燃烧着一种愿望,渴慕光明!渴慕光明! 使他痛苦异常. 他不知道,在他头上,碧空晴朗, 充满了纯洁的银色的星光. [@more@] ...

  4. linux查看无线网卡漫游,在Linux中漫游用户配置文件

    解决这个问题的方法实际上不是一个,而是一个数以万计的形式. Active Directory的单点登录无非是Kerberos和凭据委派.我们也可以使用Linux KDC或您的旧域控制器来做到这一点.没 ...

  5. osg中漫游器的原理(一)

    在osg中,编写以下简单代码 osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer(); viewer->se ...

  6. 【转】在OpenGL场景中实现小地图功能

    http://www.c3dn.net/archiver/?tid-48.html 想象一下,我们在原始森林里寻找宝藏,没有地图,没有GPS,那结果应该只有一种:不但找不到目标地点,而且很容易迷失方向 ...

  7. J2ME下漫游(追逐)AI的实现

    漫游(追逐)AI的实现 作为游戏开发者,要给玩家制造挑战,只要使游戏的难度有所增加,使游戏中的假想敌人像玩家一样机智,一样具有人类的智慧和应变能力.这就需要使用一种计算机专业领域新兴的一门科学AI(a ...

  8. 航飞原始影像外方位元素_【技术】无人机倾斜摄影建模技术在虚拟现实中的应用...

    (如有侵权,请联系删除) 摘 要 针对于虚拟现实平台中构建三维场景的费时费力问题,基于无人机倾斜摄影建模技术构建三维模型,利用 3DS Max 建模软件进行模型优化,并结合 Unity 3D 引擎构建 ...

  9. 在WebGL场景中进行棋盘操作的实验

    这篇文章讨论如何在基于Babylon.js的WebGL场景中,建立棋盘状的地块和多个可选择的棋子对象,在点选棋子时显示棋子的移动范围,并且在点击移动范围内的空白地块时向目标地块移动棋子.在这一过程中要 ...

最新文章

  1. mybatis mapper xml文件的导入方式和查询方式
  2. .+filename的作用
  3. Java中resource文件夹
  4. 猿辅导 python_关于猿辅导机器学习项目ytk-learn和ytk-mp4j分布式机器学习库
  5. VS2017专业版使用最新版Qt5.9.2教程(转载)
  6. 模式对话框与非模式对话框的创建方法
  7. Atitit 物联网体系图 感知层 条码:物联网的第一代身份证 65二维码 4 电子标签:物联网的第二代身份证 78 4 传感器:物联网的神经元 92 4 自动识别技术 光学字符识别技术
  8. 短视频系统行业分析,短视频源码功能剖析
  9. iOS获取本地音乐文件
  10. 沧海一声笑,移动应用的CRASH原因我找到! --记最新款数字化测试“星云测试“的使用攻略
  11. iOS16.0:屏幕旋转
  12. 苹果IOS14版本自建服务器无法下载解决方法
  13. C++基础知识(上)
  14. 计算机安装调试维修员中级习题,计算机安装调试维修员培训计划(三级)
  15. java封装、继承和多态练习题
  16. 大脑笔记:快速记忆之三大方法记忆圆周率前一百位
  17. JSP页面的日期控件可以弹出选择框选择日期
  18. iptables 端口转发
  19. 四川512 7.8级 地震图片
  20. 【附源码】Python计算机毕业设计网络调查问卷系统

热门文章

  1. 将AAB(Android App Bundle)转换为APK
  2. t5810做虚拟服务器,戴尔Precision T5810工作站选用CPU的问题 | 小迪的生产力工具室...
  3. UiPath估值超百亿!这家来自罗马尼亚深耕中国市场的公司已进入市场高增长期...
  4. 如何计算EEG信号的香农熵Shannon entropy(附Matlab程序)
  5. 在使用集合中的contains(),要根据实际情况改写集合中对象的equals(Object obj)方法------改写List集合中equals(Object obj)的方法
  6. 杨白劳 or 黄世仁
  7. 省一级计算机ppt,江苏省计算机一级PPT课件.ppt
  8. Docker - 使用Docker Compose部署应用
  9. 2020年薪酬排行榜为何程序员遥遥领先?
  10. 加勒比海盗船——最优装载问题(趣学算法C++代码和python代码)