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();return 0;}
?
#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(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(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[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 -= 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(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){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;}// 向右轉if (ea.getKey() == 0xFF53){m_vRotation._v[2] -= osg::DegreesToRadians(m_fAngle);}// 向左轉if (ea.getKey() == 0xFF51){m_vRotation._v[2] += 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):if (ea.getButton() == 1){m_fpushX = mouseX;m_fpushY = mouseY;m_bLeftButtonDown = true;}return true;// 拖動case(osgGA::GUIEventAdapter::DRAG):if (m_bLeftButtonDown){m_vRotation._v[2] -= osg::DegreesToRadians(m_fAngle * (mouseX - m_fpushX)) / 200;m_vRotation._v[0] += osg::DegreesToRadians(1.1 * (mouseY - m_fpushY)) / 200;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; }
總結
- 上一篇: uniapp 微信小程序 swiper修
- 下一篇: 程序员求职面试三部曲之一:选择合适的工作