OSG场景漫游(一)
一、編寫(xiě)動(dòng)態(tài)鏈接庫(kù)TravelManipulator.DLL
第一步:新建->項(xiàng)目->WIN32/WIN32控制臺(tái)應(yīng)用程序,項(xiàng)目名稱(chēng)填入:TravelManipulator在應(yīng)用程序設(shè)置中選DLL與空項(xiàng)目選項(xiàng)。
第二步:在菜單項(xiàng)目->屬性->配置屬性->鏈接器->命令行中添加下列LIB: OpenThreadsWin32d.lib Producerd.lib osgd.lib?
osgDBd.lib osgFXd.lib osgGAd.lib osgParticled.lib osgProducerd.lib osgSimd.lib osgTerraind.lib osgTextd.lib osgUtild.lib
第三步:菜單項(xiàng)目->添加類(lèi),類(lèi)名填入TravelManipulator
在文件TravelManipulator.h中加如如下代碼:
#ifdef TRAVEL_DLL
#define TRAVEL_DLL _declspec(dllexport)?
#else
#define TRAVEL_DLL _declspec(dllimport)
#pragma comment(lib, "TravelManipulator.lib") // 引號(hào)里面是你dll對(duì)應(yīng)的lib文件名。如果名字不是這個(gè),你改成實(shí)際的。
#endif
#include <osgViewer/Viewer>
#include <osg/LineSegment>
#include <osg/Point>
#include <osg/Geometry>
#include <osg/Node>
#include <osg/Geode>
#include <osg/Group>
#include <osgGA/CameraManipulator>
#include <osgUtil/IntersectVisitor>
#include <vector>
class TRAVEL_DLL ?TravelManipulator:public osgGA::CameraManipulator ? ? ? //用一個(gè)接口函數(shù)導(dǎo)出
{
public:
TravelManipulator(void);
~TravelManipulator(void);
// 把漫游器添加到場(chǎng)景中
static TravelManipulator * TravelToScence(osg::ref_ptr<osgViewer::Viewer>viewer);
private:
osg::ref_ptr<osgViewer::Viewer>m_pHostViewer;
// 移動(dòng)速度
float m_fMoveSpeed;
// 當(dāng)前位置
osg::Vec3 m_vPosition;
// 旋轉(zhuǎn)角度
osg::Vec3 m_vRotation;
public:
// 鼠標(biāo)左鍵狀態(tài)
bool m_bLeftButtonDown;
// 鼠標(biāo)位置
float m_fpushX;
float m_fpushY;
// 設(shè)置矩陣
virtual void setByMatrix(const osg::Matrix &matrix);
// 設(shè)置逆矩陣
virtual void setByInverseMatrix(const osg::Matrix &matrix);
// 獲取矩陣
virtual osg::Matrixd getMatrix() const;
// 獲取逆矩陣
virtual osg::Matrixd getInverseMatrix() const;
// 事件處理函數(shù)
virtual bool handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &us);
// 屏幕角度
float m_fAngle;
// 位置變換
void ChangePosition(osg::Vec3 &delta);
// 碰撞檢測(cè)狀態(tài)
bool m_bPeng;
// 設(shè)置速度
float getSpeed();
void setSpeed(float &);
// 設(shè)置初始位置
void SetPosition(osg::Vec3 &position);
osg::Vec3 GetPosition();
};
現(xiàn)在來(lái)看一下TraverManipulator.CPP中的實(shí)現(xiàn):
#define TRAVEL_DLL _declspec(dllexport)
#include "TravelManipulator.h"
// 構(gòu)造函數(shù)
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)
{
}
// 把漫游器添加到場(chǎng)景中
TravelManipulator *TravelManipulator::TravelToScence(osg::ref_ptr<osgViewer::Viewer> viewer)
{
TravelManipulator* camera = new TravelManipulator;
viewer->setCameraManipulator(camera);
camera->m_pHostViewer = viewer;
return camera;
}
// 設(shè)置矩陣
void TravelManipulator::setByMatrix(const osg::Matrix &matrix)
{
}
// 設(shè)置逆矩陣
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));
}
// 事件處理函數(shù)
bool TravelManipulator::handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &us)
{
// 獲取鼠標(biāo)位置
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;
}
// 前進(jìn)
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;
}
// 向右轉(zhuǎn)
if (ea.getKey() == 0xFF53)
{
m_vRotation._v[2] -= osg::DegreesToRadians(m_fAngle);
}
// 向左轉(zhuǎn)
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;
// 拖動(dòng)
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;
// 鼠標(biāo)釋放
case(osgGA::GUIEventAdapter::RELEASE):
if (ea.getButton() == 1)
{
m_bLeftButtonDown = false;
}
return false;
default:
return false;
? ?}
}
// 位置變換函數(shù)
void TravelManipulator::ChangePosition(osg::Vec3 &delta)
{
// 碰撞檢測(cè)
if (m_bPeng)
{
// 得到新的位置
osg::Vec3 newPos1 = m_vPosition + delta;
osgUtil::IntersectVisitor ivXY;
// 根據(jù)新的位置得到兩條線段檢測(cè)
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());
// 結(jié)構(gòu)交集檢測(cè)
m_pHostViewer->getSceneData()->accept(ivXY);
// 如果沒(méi)有碰撞
if (!ivXY.hits())
{
m_vPosition += delta;
}
}
else
{
m_vPosition += delta;
}
}
// 設(shè)置速度
void TravelManipulator::setSpeed(float &sp)
{
m_fMoveSpeed = sp;
}
// 獲得當(dāng)前速度
float TravelManipulator::getSpeed()
{
return m_fMoveSpeed;
}
// 設(shè)置起始的位置
void TravelManipulator::SetPosition(osg::Vec3 &position)
{
m_vPosition = position;
}
// 得到當(dāng)前所在位置
osg::Vec3 TravelManipulator::GetPosition()
{
return m_vPosition;
}
完成后編譯運(yùn)行,如果成功會(huì)出現(xiàn)如下頁(yè)面:
這是測(cè)試控件用的東西,類(lèi)似于測(cè)試ActiveX的容器。我們關(guān)掉,不予理會(huì)。
此時(shí)已經(jīng)生成一個(gè)鏈接文件(.LIB),一個(gè)頭文件(.H),一個(gè)庫(kù)文件(.DLL),下一步就要測(cè)試一下這個(gè)Travel操作器是否好用。
總結(jié)
以上是生活随笔為你收集整理的OSG场景漫游(一)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: EC-PCA: 利润中心会计配置
- 下一篇: 最大化参数 火车头_火车头采集器菜鸟使用