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实现场景漫游(转载)的更多相关文章
- 【Unity入门】场景编辑与场景漫游快捷键
版权声明:本文为博主原创文章,转载请注明出处. 打开Unity主窗口,选择顶部菜单栏的“GameObject”->“3D Object”->“Plane”在游戏场景里面添加一个面板对象.然 ...
- Unity3d场景漫游---iTween实现
接触U3D以来,我做过的场景漫游实现方式一般有以下几种: Unity3d中的Animation组件,通过设置摄像机的关键点实现场景漫游 第一人称或第三人称控制器 编写摄像机控制脚本 iTween iT ...
- Unity3d 简单的小球沿贝塞尔曲线运动(适合场景漫游使用)
简单的小球沿贝塞尔曲线运动,适合场景漫游使用 贝塞尔曲线:(贝塞尔曲线的基本想法部分摘自http://blog.csdn.net/u010019717/article/details/4768 ...
- 基于SketchUp和Unity3D的虚拟场景漫游和场景互动
这是上学期的一次课程作业,难度不高但是也一并记录下来,偷懒地拿课程报告改改发上来. 课程要求:使用sketchUp建模,在Unity3D中实现场景漫游和场景互动. 知识点:建模.官方第一人称控制器.网 ...
- osg 场景漫游
#ifdef _WIN32 #include <Windows.h> #endif // _WIN32 #include <osg/Group> #include <os ...
- OSG开发概览(转载)
OSG开发概览 1 OSG基础知识 Ø OSG是Open Scene Graphic 的缩写,OSG于1997年诞生于以为滑翔机爱好者之手,Don burns 为了对滑翔机的飞行进行模拟,对open ...
- OSG 3D场景渲染编程概述
OSG是Open Scene Graphic的缩写,是基于C++平台的使用OpenGL技术的开源3D场景开发. vs环境安装或者是在Ubuntu中环境的安装网上教程很多,都是大同小异的,认真操作容易成 ...
- PHP(Mysql/Redis)消息队列的介绍及应用场景案例--转载
郑重提示:本博客转载自好友博客,个人觉得写的很牛逼所以未经同意强行转载,原博客连接 http://www.cnblogs.com/wt645631686/p/8243438.html 欢迎访问 在进行 ...
- 【NS2】有线和无线混合场景 (转载)
1. 创建简单的有线-无线混合场景 上一节建立的无线仿真可以支持多跳adhoc网络或wirelesslan.但是,我们可能需要对经过有线网络连接的多个无线网络进行仿真,或者说我们需要对有线-无线混合网 ...
随机推荐
- 详细讲解MOSFET管驱动电路(转)
作者: 来源:电源网 关键字:MOSFET 结构 开关 驱动电路 在使用MOS管设计开关电源或者马达驱动电路的时候,大部分人都会考虑MOS的导通电阻,最大电压等,最大电流等,也有很多人仅仅考虑这些 ...
- C#入门经典第六章函数-2-委托
委托:
- public private proteccted区别
public公共,加上这个修饰的类或属性,可以在同一个包或者别的包里面访问 private私有的,加上这个修饰的类或属性,只能在同类里访问,同包和别的包不能访问 protected保护,加上这个修饰的 ...
- 关于sqlserver还原不了数据库的原因
因为备份文件需要在服务器上打成压缩包,才能进行传输,不然会丢失数据..
- struts1.x中web.xml文件的配置
1.配置欢迎文件清单 当客户访问Web应用时,如果仅仅给出Web应用的Root URL,没有指定具体的文件名.Web容器会自动调用Web应用的欢迎文件.<welcome-file-li ...
- 我的android学习脚步----------- 的第一个应用
刚刚开始学android开发,以前都是在别人调好的应用中修改JNI,现在需要自己一步步走 开发环境:Eclipse+ADT 配置不多讲了,引自:http://www.cnblogs.com/allen ...
- App installation failed There was an internal API error.
工程名为汉字的时候,真机调试会出现这种问题.模拟器没有问题. 如图: 解决办法:
- 可信执行环境(TEE)介绍
可信执行环境(TEE)是Global Platform(GP)提出的概念.针对移动设备的开放环境,安全问题也越来越受到关注,不仅仅是终端用户,还包括服务提供者,移动运营商,以及芯片厂商.TEE是与设备 ...
- js中:Date.utc()方法与getTime()方法返回值不相等的原因
// Date.UTC() 方法接受的参数同日期构造函数接受最多参数时一样,返回从1970-1-1 00:00:00 UTC到指定日期的的毫秒数. var utcDate = Date.UTC(201 ...
- Firebug Console 与命令行全集
Console API 当打开 firebug (也包括 Chrome 等浏览器的自带调试工具),window 下面会注册一个叫做 console 的对象,它提供多种方法向控制台输出信息,供开发人员调 ...