osg demo14 漫游
生活随笔
收集整理的這篇文章主要介紹了
osg demo14 漫游
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
main.cpp
//DEMO14
//功能:正常的漫游,WASD鍵前進(jìn)后退左右,UP DOWN LEFT RIGHT鍵前進(jìn)后退左進(jìn)右退
// HOME向上移,END向下移。+加速,-減速#include <osgDB/ReadFile>
#include <osgViewer/Viewer>
#include <osg/Node>
#include "South.h"void main()
{osgViewer::Viewer viewer;viewer.setSceneData(osgDB::readNodeFile("ceep.ive"));viewer.setCameraManipulator(new CSouth());viewer.realize();viewer.run();
}
South.h
#pragma once#include <osgViewer/Viewer>
#include <osgGA/CameraManipulator>
#include <osgUtil/IntersectVisitor>
#include <osg/LineSegment>class CSouth:public osgGA::CameraManipulator
{
public :CSouth(void);~CSouth(void);private ://結(jié)點值,用來測試碰撞檢測的:osg::ref_ptr<osg::Node> m_node;//相機操作器unsigned m_nID;//移動速度float m_fMoveSpeed;//位置osg::Vec3 m_vPosition;//旋轉(zhuǎn)角度osg::Vec3 m_vRotation;//左鍵是否按下bool m_bLeftButtonDown;//左鍵點下時屏幕坐標(biāo)float m_fpushX;//碰撞檢測開啟狀態(tài)查詢bool m_bPeng;//右鍵點下時屏幕坐標(biāo)float m_fpushY;public ://碰撞檢測是否開啟void setPeng(bool peng);//得到碰撞檢測開啟狀態(tài)bool getPeng();//如果碰撞檢測開啟則關(guān)閉,如果關(guān)閉則開啟void setFpeng();//設(shè)置要進(jìn)行碰撞檢測的數(shù)據(jù)virtual void setNode(osg::Node*);//虛函數(shù)virtual void setByMatrix(const osg::Matrixd & matrix);//虛函數(shù)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;//位置變換函數(shù)void ChangePosition(osg::Vec3& delta);//得到當(dāng)前速度float getSpeed();//設(shè)置當(dāng)前速度void setSpeed(float);//設(shè)置視點位置void SetPosition(osg::Vec3 &position);void SetPosition(double *);//得到當(dāng)前視點位置osg::Vec3 GetPosition();//計算家的位置void computeHomePosition();
};
South.cpp
#include "South.h"//設(shè)置一些初始值
CSouth::CSouth(void):m_fMoveSpeed(1.5f)
//左鍵沒有按下
,m_bLeftButtonDown(false)
//左鍵點下時初始坐標(biāo)為0
,m_fpushX(0)
//初始角度是2.5
,m_fAngle(2.5) // 開始時碰撞檢測關(guān)閉 , m_bPeng(false) //右鍵點下時初始坐標(biāo)也為0 , m_fpushY(0) { // 出生點為000 m_vPosition = osg::Vec3(0.0f, 0.0f,5.0f); //初始角度 m_vRotation = osg::Vec3(osg::PI_2, 0.0f, 0.0f); } // 析構(gòu)函數(shù) CSouth::~CSouth(void) { } void CSouth::setByMatrix(const osg::Matrixd & matrix) { } void CSouth::setByInverseMatrix(const osg::Matrixd& matrix) {
}
//得到矩陣,這是標(biāo)準(zhǔn)接口,用于控制場景 osg::Matrixd CSouth::getMatrix(void) const { //得到旋轉(zhuǎn)后的矩陣,其實也就是視口矩陣,用此控制場景 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); } //------------------------------//------------------------------ //得到逆矩陣,標(biāo)準(zhǔn)接口,控制場景 osg::Matrixd CSouth::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)); } //------------------------------//------------------------------ //handle bool CSouth::handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &us) { //得到x 的初始屏幕坐標(biāo) float mouseX = ea.getX(); //得到y(tǒng)的初始屏幕坐標(biāo) float mouseY = ea.getY(); //判斷事件類型 switch(ea.getEventType()) { // 如果是鼠標(biāo)按下的事件 case(osgGA::GUIEventAdapter::KEYDOWN): { // 如果是空格 if (ea.getKey() == 0x20)//' ' { // 重繪 us.requestRedraw(); us.requestContinuousUpdate(false); return true; } // 如果是home鍵,則視點向上移動 if (ea.getKey() == 0xFF50)//home { ChangePosition(osg::Vec3 (0, 0, m_fMoveSpeed)) ; return true; } // 如果是end鍵,同視點向下移動 if (ea.getKey() == 0xFF57) //end { 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; } // 向前走,W鍵,或者UP鍵 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; } // 向后退,S鍵,或者DOWN鍵 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; } //A 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; } //D 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)//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 ): // 如果是左鍵,記錄下來,因為左鍵拖動時場景也要轉(zhuǎn)的 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 CSouth::ChangePosition(osg::Vec3 &delta) { if (m_bPeng) { //看新值與舊值之間的連線是否與模型有交點!如果要到達(dá)的位置與現(xiàn)在的位置有交點的話,如果碰撞檢測也開啟 了,就不移動。 osg::Vec3 newPos = m_vPosition + 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.0f, 0.0f, m_fMoveSpeed), newPos - osg::Vec3(0.0f, 0.0f, m_fMoveSpeed)); iv.addLineSegment(lineZ.get()); iv.addLineSegment (line.get()) ; //接受碰撞的檢測node m_node ->accept(iv); if (!iv.hits()) { // 如果沒有碰撞,則移動舊位置到新的位置上 m_vPosition += delta; } } else // 如果碰撞檢測根本沒開,則直接移過去, m_vPosition += delta; } //------------------------------//------------------------------ //得到移動速度 float CSouth::getSpeed() { return m_fMoveSpeed ; } //------------------------------//------------------------------ // 設(shè)置移動速度 void CSouth::setSpeed(float sp) { m_fMoveSpeed = sp ; } //------------------------------//------------------------------ // 設(shè)置視口所在位置 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 ; } //------------------------------//------------------------------ // 設(shè)置碰撞檢測所起作用的物體 void CSouth::setNode(osg::Node* node) { m_node = node ; } //------------------------------//------------------------------ //計算家的位置,其實是包圍球的球心處
void CSouth::computeHomePosition() { // 如果有模型,則計算包圍球的球心 if(m_node.get()) { const osg::BoundingSphere& boundingSphere=m_node ->getBound(); osg::Vec3 bp = boundingSphere._center; SetPosition(bp) ; } } //------------------------------//------------------------------ // 設(shè)置碰撞檢測為開啟或者關(guān)閉 void CSouth::setPeng(bool peng) { m_bPeng = peng ; } //------------------------------//------------------------------ //得到碰撞檢測的狀態(tài) bool CSouth::getPeng() { return m_bPeng ; } //------------------------------//------------------------------ // 如果碰撞測試在開啟,則關(guān)閉它,如果在關(guān)閉,則開啟它 void CSouth::setFpeng() { m_bPeng = !m_bPeng ; } //------------------------------//------------------------------
總結(jié)
以上是生活随笔為你收集整理的osg demo14 漫游的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [Place 30-51] IDELAY
- 下一篇: 漫漫漫游路(七)