OSG实现场景漫游

下面的代码将可以实现场景模型的导入,然后在里面任意行走,于此同时还实现了碰撞检测。

源代码下载地址:

 /*
  * File        : Travel.cpp
  * Description :
  * Author      : GuoShaoHao
  * E-mail      : gsh0913@qq.com
  * Date        : 2011/01/08
  *
  * CopyRight @ South China Institute of Software Engineering,.GZU
  *
  */

 #include <iostream>
 #include <osgViewer/Viewer>
 #include <osg/Node>
 #include <osg/Geode>
 #include <osg/Group>

 #include <osgDB/ReadFile>
 #include <osgDB/WriteFile>

 #include <osgUtil/Optimizer>

 #include <osg/MatrixTransform>
 #include <osgViewer/ViewerEventHandlers>
 #include <osgGA/StateSetManipulator>

 #include "TravelManipulator.h"

 using namespace std;

 int main()
 {
     //创建Viewer对象
     osg::ref_ptr<osgViewer::Viewer>viewer = new osgViewer::Viewer();

     //添加状态事件
     //viewer.get()->addEventHandler( new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) );
     //窗口大小变化事件
     viewer.get()->addEventHandler(new osgViewer::WindowSizeHandler);
     //添加一些常用状态设置
     viewer.get()->addEventHandler(new osgViewer::StatsHandler);

     // 把漫游器加入到场景中
     TravelManipulator::TravelToScence(viewer.get());

     osg::ref_ptr<osg::Group>root = new osg::Group();

     // 读取地形
     osg::ref_ptr<osg::Node>node = osgDB::readNodeFile("D://OSG//data//lz.osg");

     // 读取飞机
     //osg::ref_ptr<osg::Node>tank = osgDB::readNodeFile("F://Models//Amx30//Amx30.IVE");
     osg::ref_ptr<osg::Node>B25 = osgDB::readNodeFile("Models//B25//B25.IVE");

     osg::ref_ptr < osg::MatrixTransform> scale = new osg::MatrixTransform ;
     scale ->setMatrix(osg::Matrix::scale(0.1, 0.1, 0.1)*osg::Matrix::translate(-10.0f, -250.0f, 99.0f)) ;
     scale ->addChild(B25.get()) ;

     // 添加到场景
     root->addChild(node.get());
     root->addChild(scale.get());
     //root->addChild(B25.get());

     // 优化场景数据
     osgUtil::Optimizer optimizer;
     optimizer.optimize(root.get());

     viewer->setSceneData(root.get());

     viewer->realize();

     viewer->run();

     ;

 }
 #pragma once

 #include <osgViewer/Viewer>

 #include <osg/LineSegment>
 #include <osg/Point>
 #include <osg/Geometry>
 #include <osg/Node>
 #include <osg/Geode>
 #include <osg/Group>

 #include <osgGA/MatrixManipulator>

 #include <osgUtil/IntersectVisitor>

 #include <vector>

 class TravelManipulator:public osgGA::MatrixManipulator
 {

 public:

     TravelManipulator(void);
     ~TravelManipulator(void);

     // 把漫游器添加到场景中
     static TravelManipulator * TravelToScence(osg::ref_ptr<osgViewer::Viewer>viewer);

 private:

     osg::ref_ptr<osgViewer::Viewer>m_pHostViewer;

     // 移动速度
     float m_fMoveSpeed;

     // 当前位置
     osg::Vec3 m_vPosition;

     // 旋转角度
     osg::Vec3 m_vRotation;

 public:

     // 鼠标左键状态
     bool m_bLeftButtonDown;

     // 鼠标位置
     float m_fpushX;
     float m_fpushY;

     // 设置矩阵
     virtual void setByMatrix(const osg::Matrix &matrix);

     // 设置逆矩阵
     virtual void setByInverseMatrix(const osg::Matrix &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 ChangePosition(osg::Vec3 &delta);

     // 碰撞检测状态
     bool m_bPeng;

     // 设置速度
     float getSpeed();

     void setSpeed(float &);

     // 设置初始位置
     void SetPosition(osg::Vec3 &position);

     osg::Vec3 GetPosition();

 };
 #include "TravelManipulator.h"

 // 构造函数
 TravelManipulator::TravelManipulator():m_fMoveSpeed(1.0f),
                                       m_bLeftButtonDown(false),
                                       m_fpushX(),
                                       m_fAngle(2.5),
                                       m_bPeng(true),
                                       m_fpushY()
 {
     m_vPosition = osg::Vec3(-22.0f, -274.0f, 100.0f);
     m_vRotation = osg::Vec3(osg::PI_2, 0.0f, 0.0f);
 }

 TravelManipulator::~TravelManipulator(void)
 {
 }

 // 把漫游器添加到场景中
 TravelManipulator *TravelManipulator::TravelToScence(osg::ref_ptr<osgViewer::Viewer> viewer)
 {
     TravelManipulator* camera = new TravelManipulator;

     viewer->setCameraManipulator(camera);

     camera->m_pHostViewer = viewer;

     return camera;
 }

 // 设置矩阵
 void TravelManipulator::setByMatrix(const osg::Matrix &matrix)
 {

 }

 // 设置逆矩阵
 void TravelManipulator::setByInverseMatrix(const osg::Matrix &matrix)
 {

 }

 // 得到矩阵
 osg::Matrixd TravelManipulator::getMatrix(void)const
 {
     osg::Matrixd mat;

     mat.makeRotate(m_vRotation._v[], osg::Vec3(1.0f, 0.0f, 0.0f),
                    m_vRotation._v[], osg::Vec3(0.0f, 1.0f, 0.0f),
                    m_vRotation._v[], osg::Vec3(0.0f, 0.0f, 1.0f));

     return mat * osg::Matrixd::translate(m_vPosition);

 }

 // 得到逆矩阵
 osg::Matrixd TravelManipulator::getInverseMatrix(void) const
 {
     osg::Matrixd mat;

     mat.makeRotate(m_vRotation._v[], osg::Vec3(1.0f, 0.0f, 0.0f),
         m_vRotation._v[], osg::Vec3(0.0f, 1.0f, 0.0f),
         m_vRotation._v[], osg::Vec3(0.0f, 0.0f, 1.0f));

     return osg::Matrixd::inverse(mat * osg::Matrixd::translate(m_vPosition));
 }

 // 事件处理函数
 bool TravelManipulator::handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &us)
 {
     // 获取鼠标位置
     float mouseX = ea.getX();
     float mouseY = ea.getY();

     switch(ea.getEventType())
     {
     case(osgGA::GUIEventAdapter::KEYDOWN):
         {
             // 空格键
             if(ea.getKey() == 0x20)
             {
                 us.requestRedraw();
                 us.requestContinuousUpdate(false);

                 return true;

             }

             // 上移键
             if (ea.getKey() == 0xFF50)
             {
                 ChangePosition(osg::Vec3(, , m_fMoveSpeed));

                 return true;
             }

             // 下移键
             if (ea.getKey() == 0xFF57)
             {
                 ChangePosition(osg::Vec3(, , -m_fMoveSpeed));

                 return true;
             }

             // 加速
             if (ea.getKey() == 0x2B)
             {
                 m_fMoveSpeed += 1.0f;

                 return true;
             }

             // 减少速度
             if (ea.getKey() == 0x2D)
             {
                 m_fMoveSpeed -= 0.1f;

                 if(m_fMoveSpeed < 1.0f)
                 {
                     m_fMoveSpeed = 1.0f;
                 }

                 return true;
             }

             // 前进
             if (ea.getKey() == 0xFF52 || ea.getKey() == 0x57 || ea.getKey() == 0x77)
             {
                 ChangePosition(osg::Vec3(, m_fMoveSpeed * sinf(osg::PI_2 + m_vRotation._v[]), ));
                 ChangePosition(osg::Vec3(m_fMoveSpeed * cosf(osg::PI_2 + m_vRotation._v[]),,));

                 return true;
             }

             // 后退
             if (ea.getKey() == 0xFF54 || ea.getKey() == 0x53 || ea.getKey() == 0x73)
             {
                 ChangePosition(osg::Vec3(, -m_fMoveSpeed * sinf(osg::PI_2 + m_vRotation._v[]), ));
                 ChangePosition(osg::Vec3(-m_fMoveSpeed * cosf(osg::PI_2 + m_vRotation._v[]),,));

                 return true;
             }

             // 向左
             if (ea.getKey() == 0x41 || ea.getKey() == 0x61)
             {
                 ChangePosition(osg::Vec3(, m_fMoveSpeed * cosf(osg::PI_2 + m_vRotation._v[]),));
                 ChangePosition(osg::Vec3(-m_fMoveSpeed * sinf(osg::PI_2 + m_vRotation._v[]),,));

                 return true;
             }

             // 向右
             if (ea.getKey() == 0x44 || ea.getKey() == 0x64)
             {
                 ChangePosition(osg::Vec3(, -m_fMoveSpeed * cosf(osg::PI_2 + m_vRotation._v[]),));
                 ChangePosition(osg::Vec3(m_fMoveSpeed * sinf(osg::PI_2 + m_vRotation._v[]),,));

                 return true;
             }

             // 向右转
             if (ea.getKey() == 0xFF53)
             {
                 m_vRotation._v[] -= osg::DegreesToRadians(m_fAngle);
             }

             // 向左转
             if (ea.getKey() == 0xFF51)
             {
                 m_vRotation._v[] += osg::DegreesToRadians(m_fAngle);
             }

             // 改变屏幕角度F键
             if (ea.getKey() == 0x46 || ea.getKey() == 0x66)
             {
                 m_fAngle -= 0.2;

                 return true;
             }

             //G键
             if (ea.getKey() == 0x47 || ea.getKey() == 0x66)
             {
                 m_fAngle += 0.2;

                 return true;
             }

             return true;
     }
         case(osgGA::GUIEventAdapter::PUSH):

         )
         {
             m_fpushX = mouseX;
             m_fpushY = mouseY;

             m_bLeftButtonDown = true;
         }

         return true;

         // 拖动
     case(osgGA::GUIEventAdapter::DRAG):

         if (m_bLeftButtonDown)
         {
             m_vRotation._v[] -= osg::DegreesToRadians(m_fAngle * (mouseX - m_fpushX)) / ;
             m_vRotation._v[] += osg::DegreesToRadians(;

             ] >= 3.14)
             {
                 m_vRotation._v[] = 3.14;
             }

             ] <= )
             {
                 m_vRotation._v[] = ;
             }
         }

         return false;

         // 鼠标释放
     case(osgGA::GUIEventAdapter::RELEASE):

         )
         {
             m_bLeftButtonDown = false;
         }

         return false;

     default:

         return false;
 }

 }

 // 位置变换函数
 void TravelManipulator::ChangePosition(osg::Vec3 &delta)
 {
     // 碰撞检测
     if (m_bPeng)
     {
         // 得到新的位置
         osg::Vec3 newPos1 = m_vPosition + delta;

         osgUtil::IntersectVisitor ivXY;

         // 根据新的位置得到两条线段检测
         osg::ref_ptr<osg::LineSegment>lineXY = new osg::LineSegment(newPos1, m_vPosition);

         osg::ref_ptr<osg::LineSegment>lineZ = new osg::LineSegment(newPos1 + osg::Vec3(0.0f, 0.0f, 10.0f), newPos1 - osg::Vec3(0.0f, 0.0f, -10.0f));

         ivXY.addLineSegment(lineZ.get());
         ivXY.addLineSegment(lineXY.get());

         // 结构交集检测
         m_pHostViewer->getSceneData()->accept(ivXY);

         // 如果没有碰撞
         if (!ivXY.hits())
         {
             m_vPosition += delta;
         }

     }
     else
     {
         m_vPosition += delta;
     }
 }

 // 设置速度
 void TravelManipulator::setSpeed(float &sp)
 {
     m_fMoveSpeed = sp;
 }

 // 获得当前速度
 float TravelManipulator::getSpeed()
 {
     return m_fMoveSpeed;
 }

 // 设置起始的位置
 void TravelManipulator::SetPosition(osg::Vec3 &position)
 {
     m_vPosition = position;
 }

 // 得到当前所在位置
 osg::Vec3 TravelManipulator::GetPosition()
 {
     return m_vPosition;
 }

OSG实现场景漫游(转载)的更多相关文章

  1. 【Unity入门】场景编辑与场景漫游快捷键

    版权声明:本文为博主原创文章,转载请注明出处. 打开Unity主窗口,选择顶部菜单栏的“GameObject”->“3D Object”->“Plane”在游戏场景里面添加一个面板对象.然 ...

  2. Unity3d场景漫游---iTween实现

    接触U3D以来,我做过的场景漫游实现方式一般有以下几种: Unity3d中的Animation组件,通过设置摄像机的关键点实现场景漫游 第一人称或第三人称控制器 编写摄像机控制脚本 iTween iT ...

  3. Unity3d 简单的小球沿贝塞尔曲线运动(适合场景漫游使用)

        简单的小球沿贝塞尔曲线运动,适合场景漫游使用 贝塞尔曲线:(贝塞尔曲线的基本想法部分摘自http://blog.csdn.net/u010019717/article/details/4768 ...

  4. 基于SketchUp和Unity3D的虚拟场景漫游和场景互动

    这是上学期的一次课程作业,难度不高但是也一并记录下来,偷懒地拿课程报告改改发上来. 课程要求:使用sketchUp建模,在Unity3D中实现场景漫游和场景互动. 知识点:建模.官方第一人称控制器.网 ...

  5. osg 场景漫游

    #ifdef _WIN32 #include <Windows.h> #endif // _WIN32 #include <osg/Group> #include <os ...

  6. OSG开发概览(转载)

    OSG开发概览 1 OSG基础知识 Ø OSG是Open Scene Graphic 的缩写,OSG于1997年诞生于以为滑翔机爱好者之手,Don burns  为了对滑翔机的飞行进行模拟,对open ...

  7. OSG 3D场景渲染编程概述

    OSG是Open Scene Graphic的缩写,是基于C++平台的使用OpenGL技术的开源3D场景开发. vs环境安装或者是在Ubuntu中环境的安装网上教程很多,都是大同小异的,认真操作容易成 ...

  8. PHP(Mysql/Redis)消息队列的介绍及应用场景案例--转载

    郑重提示:本博客转载自好友博客,个人觉得写的很牛逼所以未经同意强行转载,原博客连接 http://www.cnblogs.com/wt645631686/p/8243438.html 欢迎访问 在进行 ...

  9. 【NS2】有线和无线混合场景 (转载)

    1. 创建简单的有线-无线混合场景 上一节建立的无线仿真可以支持多跳adhoc网络或wirelesslan.但是,我们可能需要对经过有线网络连接的多个无线网络进行仿真,或者说我们需要对有线-无线混合网 ...

随机推荐

  1. Servlet程序开发-- 取得其他内置对象

    servlet本身提供的只有request和response对象,如果要取得session对象,只能依靠request对象,因为session属于HTTP协议范畴,而且在每次发送请求的时候,服务器都会 ...

  2. C# 中的内存管理,摘自网络

    C#编程的一个优点是程序员不需要关心具体的内存管理,尤其是垃圾收集器会处理所有的内存清理工作.虽然不必手工管理内存,但如果要编写高质量的代码,还是要理解后台发生的事情,理解C#的内存管理.本文主要介绍 ...

  3. PL/SQL DEVELOPER 导出表数据

    http://jingyan.baidu.com/album/fcb5aff78e6a48edab4a7146.html?picindex=4 1. 导出表数据 打开pl/sql客户端 在左侧 点击t ...

  4. CentOS 修改Mysql的root密码

    1.知道密码 第一次登陆(无密码) mysqladmin -u root password NEWPASSWORD 修改过密码 mysqladmin -u root -p 'oldpassword' ...

  5. 自己写的angularJs排序指令【原创】

    首先,给大家看看指令完成的效果.(请注意区分下面几张图片中,对象值的变化) 好了,效果图已经看完了,如果大家有兴趣的话可以继续往下看,接下来要讲的是关于angularJs中filter内置好的orde ...

  6. 2304: Lights Out(枚举)

    枚举第一行所有可能的的情况 #include<iostream> #include<cstdio> #include<cstring> #include<al ...

  7. ARM系统中函数调用过程中的参数传递-转

    在 嵌入式软件编程中,经常会用到函数调用,之前在学习如何在C语言中嵌入汇编时有了解到C语言之前的参数调用是使用寄存器R0传递第一个参数,R1传递到第 二个..一直到R3传递第四个参数.但是实际上有时可 ...

  8. Qt5:不规则按钮的实现---通过贴图实现

    在应用开发中,有时候为了美观会在UI界面中增加不规则的按钮 现在我们就来看看Qt中是怎么实现不规则按钮的 /////////////////////////////////////////////// ...

  9. 基于M9K块配置ROM的LCD12864图片显示实验

    先上传三张图片在说                             由于串口传输速度较慢,故此实验是在“LCD12864 液晶显示-汉字及自定义显示(并口)”基础上进一步修改而来.在写代码之前 ...

  10. 深入理解setTimeout的作用域

    看了一篇关于setTimeout作用域的问题,其实之前在<javascript高级程序设计>时也看到了,分享给大家: 先总结下: 一.setTimeout中的延迟执行代码中的this永远都 ...