六、OSG学习笔记-漫游(操作器)
一、实例代码操作器
Travel.h
#pragma once
#include<windows.h>
#include<osg/Node>
#include<osgViewer/Viewer>
#include<osgViewer/ViewerEventHandlers>
#include<osgDB/ReadFile>
#include<osgGA/TrackballManipulator>
// 图元库
#include<osg/Geode>
#include<osg/ShapeDrawable>
#include<osg/Matrix>
#include<osg/MatrixTransform>
#include<osg/PositionAttitudeTransform>
// 回调
#include<osg/AnimationPath>
#include<osgGA/GUIEventAdapter>
#include <osgGA/StandardManipulator>
// 自定义操作器类
class TravelManipulator : public osgGA::CameraManipulator
{
public:
TravelManipulator();
~TravelManipulator();
public:
// 实现得到和设置矩阵的接口
/** 设置当前视口 using a 4x4 Matrix.*/
void setByMatrix(const osg::Matrixd& matrix) override;
/** 设置当前视口 using a 4x4 Matrix.*/
void setByInverseMatrix(const osg::Matrixd& matrix) override;
/** 得到当前矩阵 4x4 Matrix.*/
osg::Matrixd getMatrix() const override;
/** 得到当前逆矩阵 used as a model view matrix.*/
osg::Matrixd getInverseMatrix() const override;
// 响应事件
bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us )override;
private:
// 视点
osg::Vec3 m_vPosition;
// 朝向
osg::Vec3 m_vRotation;
// 移动步长
int m_vStep;
// 旋转步长
float m_vRotateStep;
};
Travel.cpp
#include "Travel.h"
#include <osgGA/GUIEventAdapter>
TravelManipulator::TravelManipulator()
{
// 视点Z 值越小,模型文件越靠近放大,Z值越大,越缩小
m_vPosition = osg::Vec3(0, 0, 1);
m_vRotation = osg::Vec3(0, 0, 0);
m_vStep = 0;
m_vRotateStep = 0.0;
}
TravelManipulator::~TravelManipulator()
{
}
void TravelManipulator::setByMatrix(const osg::Matrixd& matrix)
{
}
void TravelManipulator::setByInverseMatrix(const osg::Matrixd& matrix)
{
}
osg::Matrixd TravelManipulator::getMatrix() const
{
osg::Matrixd mat;
mat.makeTranslate(m_vPosition);
osg::Matrixd retMat = mat * osg::Matrixd::rotate(m_vRotation[0], osg::X_AXIS, m_vRotation[1], osg::Y_AXIS, m_vRotation[2], osg::Z_AXIS);
return retMat;
}
osg::Matrixd TravelManipulator::getInverseMatrix() const
{
osg::Matrixd mat;
mat.makeTranslate(m_vPosition);
osg::Matrixd retMat = mat * osg::Matrixd::rotate(m_vRotation[0], osg::X_AXIS, m_vRotation[1], osg::Y_AXIS, m_vRotation[2], osg::Z_AXIS);
return osg::Matrixd::inverse(retMat);
}
bool TravelManipulator::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us)
{
switch (ea.getEventType())
{
case osgGA::GUIEventAdapter::KEYDOWN:
{
if (ea.getKey() == 'w')
{
m_vPosition[2] += 2; // 前进
}
else if (ea.getKey() == 's')
{
m_vPosition[2] -= 2; // 后退
}
}
default:
break;
}
return false;
}
main.cpp
#include "Travel.h"
int main()
{
osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer;
viewer->setUpViewInWindow(100, 100, 1500, 1000);
osg::ref_ptr<osg::Node> node = osgDB::readNodeFile("glider.osg");
viewer->setSceneData(node.get());
// 加入操作器
osgGA::CameraManipulator* pCameraPlator = new TravelManipulator();
viewer->setCameraManipulator(pCameraPlator);
return viewer->run();
}
二、漫游,操作器实例代码
代码:CuiQingCheng/OsgStudy - Gitee.com
Travel.h
#pragma once
#include<windows.h>
#include<osg/Node>
#include<osgViewer/Viewer>
#include<osgViewer/ViewerEventHandlers>
#include<osgDB/ReadFile>
#include<osgGA/TrackballManipulator>
// 图元库
#include<osg/Geode>
#include<osg/ShapeDrawable>
#include<osg/Matrix>
#include<osg/MatrixTransform>
#include<osg/PositionAttitudeTransform>
// 回调
#include<osg/AnimationPath>
#include<osgGA/GUIEventAdapter>
#include <osgGA/StandardManipulator>
// 自定义操作器类
class TravelManipulator : public osgGA::CameraManipulator
{
public:
TravelManipulator();
~TravelManipulator();
public:
// 实现得到和设置矩阵的接口
/** 设置当前视口 using a 4x4 Matrix.*/
void setByMatrix(const osg::Matrixd& matrix) override;
/** 设置当前视口 using a 4x4 Matrix.*/
void setByInverseMatrix(const osg::Matrixd& matrix) override;
/** 得到当前矩阵 4x4 Matrix.*/
osg::Matrixd getMatrix() const override;
/** 得到当前逆矩阵 used as a model view matrix.*/
osg::Matrixd getInverseMatrix() const override;
// 响应事件
bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us )override;
// 设置步长
void setStep(int iStep);
// 获得步长
int getStep() const;
// 设置到某一点
void setPosition(osg::Vec3d pos);
// 得到当前坐标
osg::Vec3d getPosition();
private:
// 改变位置
void ChangePosition(const osg::Vec3d& delta);
private:
// 视点
osg::Vec3 m_vPosition;
// 朝向
osg::Vec3 m_vRotation;
// 移动步长
int m_vStep;
// 旋转步长
float m_vRotateStep;
// 记录坐标
int m_iLeftX;
int m_iLeftY;
bool m_bLeftDown{false};
};
Travel.cpp
#include "Travel.h"
#include <osgGA/GUIEventAdapter>
TravelManipulator::TravelManipulator()
{
m_vPosition = osg::Vec3(0, 0, 5);
// 围绕X轴转转90度
m_vRotation = osg::Vec3(osg::PI_2, 0, 0);
m_vStep = 2;
m_vRotateStep = 0.0;
}
TravelManipulator::~TravelManipulator()
{
}
void TravelManipulator::setByMatrix(const osg::Matrixd& matrix)
{
}
void TravelManipulator::setByInverseMatrix(const osg::Matrixd& matrix)
{
}
osg::Matrixd TravelManipulator::getMatrix() const
{
osg::Matrixd mat;
mat.makeTranslate(m_vPosition);
osg::Matrixd retMat = osg::Matrixd::rotate(m_vRotation[0], osg::X_AXIS, m_vRotation[1], osg::Y_AXIS, m_vRotation[2], osg::Z_AXIS) * mat;
return retMat;
}
osg::Matrixd TravelManipulator::getInverseMatrix() const
{
osg::Matrixd mat;
mat.makeTranslate(m_vPosition);
osg::Matrixd retMat = osg::Matrixd::rotate(m_vRotation[0], osg::X_AXIS, m_vRotation[1], osg::Y_AXIS, m_vRotation[2], osg::Z_AXIS) * mat;
return osg::Matrixd::inverse(retMat);
}
bool TravelManipulator::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us)
{
switch (ea.getEventType())
{
case osgGA::GUIEventAdapter::KEYDOWN:
{
if ((ea.getKey() == 'w') || (ea.getKey() == 'W') || (ea.getKey() == osgGA::GUIEventAdapter::KEY_Up))
{
osg::Vec3d delta = osg::Vec3d(m_vStep * cosf(osg::PI_2 + m_vRotation._v[2]), m_vStep * sinf(osg::PI_2 + m_vRotation._v[2]), 0);
ChangePosition(delta);
return true;
}
else if ((ea.getKey() == 's') || (ea.getKey() == 'S') || (ea.getKey() == osgGA::GUIEventAdapter::KEY_Down))
{
osg::Vec3d delta = osg::Vec3d(-m_vStep * cosf(osg::PI_2 + m_vRotation._v[2]), -m_vStep * sinf(osg::PI_2 + m_vRotation._v[2]), 0);
ChangePosition(delta);
return true;
}
else if ((ea.getKey() == 'a') || (ea.getKey() == 'A'))
{
osg::Vec3d delta = osg::Vec3d(m_vStep * sinf(osg::PI_2 + m_vRotation._v[2]), m_vStep * cosf(osg::PI_2 + m_vRotation._v[2]), 0);
ChangePosition(delta);
return true;
}
else if ((ea.getKey() == 'd') || (ea.getKey() == 'D'))
{
osg::Vec3d delta = osg::Vec3d(-m_vStep * sinf(osg::PI_2 + m_vRotation._v[2]), -m_vStep * cosf(osg::PI_2 + m_vRotation._v[2]), 0);
ChangePosition(delta);
return true;
}
else if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Left)
{
m_vRotation[2] += 0.2;
return true;
}
else if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Right)
{
m_vRotation[2] -= 0.2;
return true;
}
else if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Home)
{
ChangePosition(osg::Vec3d(0, 0, m_vStep));
return true;
}
else if (ea.getKey() == osgGA::GUIEventAdapter::KEY_End)
{
ChangePosition(osg::Vec3d(0, 0, -m_vStep));
return true;
}
}
break;
case osgGA::GUIEventAdapter::PUSH: // 鼠标按下
{
if (ea.getButton() == osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON)
{
m_iLeftX = ea.getX();
m_iLeftY = ea.getY();
m_bLeftDown = true;
}
return false;
}
break;
case osgGA::GUIEventAdapter::DRAG: // 鼠标拖动
{
if (m_bLeftDown)
{
int delX = ea.getX() - m_iLeftX;
m_vRotation[2] -= osg::DegreesToRadians(0.005 * delX);
int delY = ea.getY() - m_iLeftY;
m_vRotation[0] -= osg::DegreesToRadians(0.005 * delY);
if (m_vRotation[0] > osg::PI)
{
m_vRotation[0] = osg::PI;
}
else if (m_vRotation[0] < 0)
{
m_vRotation[0] = 0;
}
}
}
break;
case osgGA::GUIEventAdapter::RELEASE: // 鼠标释放
{
if (ea.getButton() == osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON)
{
m_bLeftDown = false;
}
}
break;
default:
break;
}
return false;
}
void TravelManipulator::setStep(int iStep)
{
m_vStep = iStep;
}
int TravelManipulator::getStep() const
{
return m_vStep;
}
void TravelManipulator::setPosition(osg::Vec3d pos)
{
m_vPosition = pos;
}
osg::Vec3d TravelManipulator::getPosition()
{
return m_vPosition;
}
void TravelManipulator::ChangePosition(const osg::Vec3d& delta)
{
m_vPosition += delta;
}
main.cpp
#include "Travel.h"
#include "../NodeMatrix/NodeMatrix.h"
// 导入静态库
#ifdef _DEBUG
#pragma comment (lib, "../x64/Debug/NodeMatrix.lib")
#else
#pragma comment (lib, "../x64/Release/NodeMatrix.lib")
#endif // DEBUG
int main()
{
osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer;
viewer->setUpViewInWindow(100, 100, 1500, 1000);
osg::ref_ptr<NodeMatrix> nm = new NodeMatrix;
nm->addsChild(osgDB::readNodeFile("ceep.ive"));
//osg::ref_ptr<osg::Node> node = osgDB::readNodeFile("ceep.ive");
viewer->setSceneData(nm.get());
// 加入操作器
osgGA::CameraManipulator* pCameraPlator = new TravelManipulator();
viewer->setCameraManipulator(pCameraPlator);
return viewer->run();
}
这里静态库为前一节中矩阵变换封装的静态库;
运行效果: