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操作器是否好用。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值