OSG 自定义场景漫游示例
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OSG 自定义场景漫游示例相关的知识,希望对你有一定的参考价值。
一下代码可以简单实现osg中视角的简单自由漫游.并且可以进行简单的碰撞检测
mian.cpp
1 #include <osgViewer/Viewer> 2 3 #include <osg/Node> 4 #include <osg/Geode> 5 #include <osg/Group> 6 7 #include <osgDB/ReadFile> 8 #include <osgDB/WriteFile> 9 10 #include <osgUtil/Optimizer> 11 12 #include "ManipulatorTravel.h" 13 14 int main() 15 { 16 //创建Viewer对象,场景浏览器 17 osgViewer::Viewer* viewer = new osgViewer::Viewer(); 18 19 //把漫游器加入到场景中 20 TravelManipulator::TravelToScene(viewer); 21 22 osg::Group* root = new osg::Group(); 23 24 //读取地形模型 25 osg::Node* node = new osg::Node(); 26 node = osgDB::readNodeFile("lz.osg"); 27 28 //添加到场景 29 root->addChild(node); 30 31 //优化场景数据 32 osgUtil::Optimizer optimizer ; 33 optimizer.optimize(root) ; 34 35 viewer->setSceneData(root); 36 37 viewer->realize(); 38 39 viewer->run(); 40 41 return 0 ; 42 }
ManipulatorTravel.h
#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::CameraManipulator { public: //构造函数 TravelManipulator (); //析构函数 ~TravelManipulator(void); // 把漫游加入到场景之中 static TravelManipulator * TravelToScene(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 ; //鼠标X,Y float m_fpushY; float m_fpushX; //设置矩阵 virtual void setByMatrix(const osg::Matrixd& matrix); //设置逆矩阵 virtual void setByInverseMatrix(const osg::Matrixd& matrix); //得到矩阵 virtual osg::Matrixd getMatrix(void) const; //得到逆矩阵 virtual osg::Matrixd getInverseMatrix(void)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() ; } ;
ManipulatorTravel.cpp
#include "ManipulatorTravel.h" //构造函数 TravelManipulator::TravelManipulator(): m_fMoveSpeed(1.0f) , m_bLeftButtonDown(false) , m_fpushX(0) , m_fAngle(2.5) , m_bPeng(true) , m_fpushY(0) { m_vPosition = osg::Vec3(-22.0f, -274.0f, 100.0f); m_vRotation = osg::Vec3(osg::PI_2, 0.0f, 0.0f); } //析构函数 TravelManipulator::~TravelManipulator() { // } // 把漫游加入到场景之中 TravelManipulator * TravelManipulator::TravelToScene(osg::ref_ptr <osgViewer::Viewer> viewer) { TravelManipulator* camera = new TravelManipulator; viewer->setCameraManipulator(camera) ; camera->m_pHostViewer =viewer ; return camera; } // 设置矩阵 void TravelManipulator::setByMatrix(const osg::Matrixd& matrix) { // } //设置逆矩阵 void TravelManipulator::setByInverseMatrix(const osg::Matrixd& matrix) { // } //得到矩阵 osg::Matrixd TravelManipulator::getMatrix(void) const { osg::Matrixd mat; mat.makeRotate(m_vRotation._v[0], osg::Vec3(1.0f, 0.0f, 0.0f), m_vRotation._v[1], osg::Vec3(0.0f, 1.0f, 0.0f), m_vRotation._v[2], 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[0], osg::Vec3(1.0f, 0.0f, 0.0f), m_vRotation._v[1], osg::Vec3(0.0f, 1.0f, 0.0f), m_vRotation._v[2], 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 (0, 0, m_fMoveSpeed)) ; return true; } //下移动 if (ea.getKey() == 0xFF57) { ChangePosition(osg::Vec3 (0, 0, -m_fMoveSpeed)) ; return true; } //增加速度 if (ea.getKey() == 0x2B) { m_fMoveSpeed += 1.0f; return true; } //减少速度 if (ea.getKey() == 0x2D) { m_fMoveSpeed -= 1.0f; if (m_fMoveSpeed < 1.0f) { m_fMoveSpeed = 1.0f; } return true; } //前进 if (ea.getKey() == 0xFF52 || ea.getKey () == 0x57 || ea.getKey () == 0x77)//up { ChangePosition(osg::Vec3 (0, m_fMoveSpeed * sinf(osg::PI_2+m_vRotation._v[2]), 0)) ; ChangePosition(osg::Vec3 (m_fMoveSpeed * cosf(osg::PI_2+m_vRotation._v[2]), 0, 0)) ; return true; } //后退 if (ea.getKey() == 0xFF54 || ea.getKey () == 0x53 || ea.getKey () == 0x73 )//down { ChangePosition(osg::Vec3 (0, -m_fMoveSpeed * sinf(osg::PI_2+m_vRotation._v[2]), 0)) ; ChangePosition(osg::Vec3(-m_fMoveSpeed * cosf(osg::PI_2+m_vRotation._v[2]), 0, 0)) ; return true; } //向左 if (ea.getKey () == 0x41||ea.getKey () == 0x61) { ChangePosition(osg::Vec3 (0, m_fMoveSpeed * cosf(osg::PI_2+m_vRotation._v[2]), 0)) ; ChangePosition(osg::Vec3 (-m_fMoveSpeed * sinf(osg::PI_2+m_vRotation._v[2]), 0, 0)) ; return true; } //向右 if (ea.getKey () == 0x44||ea.getKey () == 0x64) { ChangePosition(osg::Vec3 (0,-m_fMoveSpeed * cosf(osg::PI_2+m_vRotation._v[2]), 0)) ; ChangePosition(osg::Vec3 (m_fMoveSpeed * sinf(osg::PI_2+m_vRotation._v[2]), 0, 0)) ; return true; } //Right if (ea.getKey() == 0xFF53) { m_vRotation._v[2] -= osg::DegreesToRadians(m_fAngle); } //Left if (ea.getKey()== 0xFF51) { m_vRotation._v[2] += osg::DegreesToRadians(m_fAngle); } //改变屏角 if (ea.getKey() == 0x46 || ea.getKey() == 0x66)//F { 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-m_fpushY)) ; 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 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 自定义场景漫游示例的主要内容,如果未能解决你的问题,请参考以下文章