OSG场景漫游(一)
一、編寫動態鏈接庫TravelManipulator.DLL
第一步:新建->項目->WIN32/WIN32控制臺應用程序,項目名稱填入:TravelManipulator在應用程序設置中選DLL與空項目選項。
第二步:在菜單項目->屬性->配置屬性->鏈接器->命令行中添加下列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
第三步:菜單項目->添加類,類名填入TravelManipulator
在文件TravelManipulator.h中加如如下代碼:
#ifdef TRAVEL_DLL
#define TRAVEL_DLL _declspec(dllexport)?
#else
#define TRAVEL_DLL _declspec(dllimport)
#pragma comment(lib, "TravelManipulator.lib") // 引號里面是你dll對應的lib文件名。如果名字不是這個,你改成實際的。
#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 ? ? ? //用一個接口函數導出
{
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();
};
現在來看一下TraverManipulator.CPP中的實現:
#define TRAVEL_DLL _declspec(dllexport)
#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;
}
完成后編譯運行,如果成功會出現如下頁面:
這是測試控件用的東西,類似于測試ActiveX的容器。我們關掉,不予理會。
此時已經生成一個鏈接文件(.LIB),一個頭文件(.H),一個庫文件(.DLL),下一步就要測試一下這個Travel操作器是否好用。
總結
以上是生活随笔為你收集整理的OSG场景漫游(一)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: EC-PCA: 利润中心会计配置
- 下一篇: 最大化参数 火车头_火车头采集器菜鸟使用