OSG相机漫游

实现功能

		自定义相机的位置位于世界坐标系下的Y轴正方向斜向下45度观察水平面。
		通过按键实现向前(按W)向后(按S)向左(按A)向右(按D)
		向上(按PageUp)向下(按PageDown)
		相机左右旋转(J/L)、相机上下旋转(I/K)

观察效果如图:

在这里插入图片描述

基础知识

	实现相机我们所要用到的知识点有
	1.向量,矩阵,四元素等概念
	2.OSG坐标系统的知识。
	3.视图与相机, 键盘事件消息处理的相关知识。
	最重要的需要自己的空间思维能力,如果对以上的知识点不熟悉的话,可以去相关的网站看看。

实现原理

	一.新建一个类共有继承 osgGA::CameraManipulator,并且重写四个虚函数,具体的代码需要根据要求来进行编写。
	1.virtual void setByMatrix(const osg::Matrixd& matrix);
	2.virtual void setByInverseMatrix(const osg::Matrixd& matrix) ;
	3.virtual osg::Matrixd getMatrix() const ;
	4.virtual osg::Matrixd getInverseMatrix() const ;
	二.进行键盘事件处理我们需要重写handle函数
	1.virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& us) ;

代码实现

.h文件

class TraveManipulator :public osgGA::CameraManipulator
{
public:
	//构造函数
	TraveManipulator(osg::ref_ptr<osg::Node> node1);
	//析构函数
	~TraveManipulator();
	//设置矩阵
	virtual void setByMatrix(const osg::Matrixd& matrix);
	//设置逆矩阵
	virtual void setByInverseMatrix(const osg::Matrixd& matrix) ;
	//得到矩阵
	virtual osg::Matrixd getMatrix() const ;
	//得到逆矩阵
	virtual osg::Matrixd getInverseMatrix() const ;
	//键盘事件处理函数
	virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& us) ;
private:
	//视点位置
	osg::Vec3d  m_Eye;
	//参照物中心
	osg::Vec3d	m_Center;
	//方向向量
	osg::Vec3d	m_Up;
	//距离
	double	m_Distense;
 	//移动步长
	float	m_Step;
	//旋转矩阵
	osg::Matrix	m_RotationMatrix;
	//相机上下旋转的绕轴
	osg::Vec3 m_CameraRotation;
};

.cpp文件

TraveManipulator::TraveManipulator(osg::ref_ptr<osg::Node> node1) :m_Distense(4000.0), m_Step(30)
{
	//保存物体的中心点
	osg::Vec3d  node_Center = node1->getBound().center();
	osg::Matrix rotation_Anngle;
	//绕x轴旋转45°
	rotation_Anngle = osg::Matrix::rotate(osg::Quat(-osg::PI_4,osg::Vec3f(1.0f, 0.0f, 0.0f)));
	//设置视点的位置,
	m_Eye = osg::Vec3d(0.0, 0.0, m_Distense);
	//设置中心点的位置
	m_Center = node_Center;
	//up向量
	m_Up = osg::Vec3d(0.0,- 1.0, 0.0);
	//视点位于Y轴的正方向斜向上45°
	m_Eye = m_Eye * rotation_Anngle;
	m_Up = m_Up * rotation_Anngle;
	m_CameraRotation = osg::Vec3(1.0f,0.0f,0.0f);
}
TraveManipulator::~TraveManipulator()
{	 
	//
}
//设置矩阵
void TraveManipulator::setByMatrix(const osg::Matrixd& matrix)
{
	//
}
//设置逆矩阵
void TraveManipulator::setByInverseMatrix(const osg::Matrixd& matrix)
{
	// 
}
//得到矩阵,用于控制场景
osg::Matrixd TraveManipulator::getMatrix() const
{
	return osg::Matrixd();	
}
//得到逆矩阵
osg::Matrixd TraveManipulator::getInverseMatrix() const
{
	return osg::Matrixd::lookAt(m_Eye,m_Center,m_Up);
}
//键盘事件处理函数
bool TraveManipulator::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& us)
{
	//获取事件
	switch (ea.getEventType())
	{
		//如果是一个键盘事件
		case osgGA::GUIEventAdapter::KEYDOWN:
		{
			//向前移动(按W)
			if(ea.getKey() == 'w' || ea.getKey() == 'W')
			{
				m_Eye = m_Eye * osg::Matrix::translate(osg::Vec3(0.0,m_Step,0.0) * m_RotationMatrix);
				m_Center = m_Center * osg::Matrix::translate(osg::Vec3(0.0,m_Step,0.0) * m_RotationMatrix);
			} 
			//向后移动(按s)
			else if (ea.getKey() == 's' || ea.getKey() == 'S')
			{
				m_Eye = m_Eye * osg::Matrix::translate(osg::Vec3(0.0,-m_Step,0.0) * m_RotationMatrix);
				m_Center = m_Center * osg::Matrix::translate(osg::Vec3(0.0,-m_Step,0.0) * m_RotationMatrix);
			}
			//向左移动(按a)
			else if (ea.getKey() == 'a' || ea.getKey() == 'A')
			{
				m_Eye = m_Eye * osg::Matrix::translate(osg::Vec3(-m_Step,0.0,0.0) * m_RotationMatrix);
				m_Center = m_Center * osg::Matrix::translate(osg::Vec3(-m_Step,0.0,0.0) * m_RotationMatrix);
			}
			//向右移动(按d)
			else if (ea.getKey() == 'd' || ea.getKey() == 'D')
			{
				m_Eye = m_Eye * osg::Matrix::translate(osg::Vec3(m_Step,0.0,0.0) * m_RotationMatrix);
				m_Center = m_Center * osg::Matrix::translate(osg::Vec3(m_Step,0.0,0.0) * m_RotationMatrix);
			}
			//向上移动(按Page UP)
			else if (ea.getKey() == 0XFF55)
			{
				m_Eye = m_Eye * osg::Matrix::translate(osg::Vec3(m_Step,0.0,0.0) * m_RotationMatrix)*
								osg::Matrix::translate(osg::Vec3(0.0,m_Step,0.0) * m_RotationMatrix)*
								osg::Matrix::translate(osg::Vec3(0.0,0.0, m_Step) * m_RotationMatrix)*
								osg::Matrix::translate(osg::Vec3(-m_Step,0.0,0.0)* m_RotationMatrix);
			}
			//向下移动(按Page Down)
			else if (ea.getKey() == 0xFF56)
			{
				m_Eye = m_Eye * osg::Matrix::translate(osg::Vec3(m_Step,0.0,0.0)  * m_RotationMatrix)*
								osg::Matrix::translate(osg::Vec3(0.0,-m_Step,0.0) * m_RotationMatrix)*
								osg::Matrix::translate(osg::Vec3(0.0,0.0,-m_Step) * m_RotationMatrix)*
								osg::Matrix::translate(osg::Vec3(-m_Step,0.0,0.0) * m_RotationMatrix);
			}   
			//相机向左旋转
			else if (ea.getKey() == 'j' || ea.getKey() == 'J')
			{
				osg::Matrix mt; 
				//设置旋转轴
				mt = osg::Matrixd::rotate(-osg::DegreesToRadians(15.0),osg::Vec3(0.0f,0.0f,1.0f));
				m_CameraRotation = m_CameraRotation * mt;
				m_RotationMatrix = m_RotationMatrix * mt   ;
				m_Eye = m_Eye * mt;
				m_Up = m_Up * mt;
				m_Center = m_Center * mt;
			}
			//相机向右旋转
			else if (ea.getKey() == 'l' || ea.getKey() == 'L')
			{
				osg::Matrix mt;
				//设置旋转轴
				mt = osg::Matrixd::rotate(osg::DegreesToRadians(15.0),osg::Vec3(0.0f,0.0f,1.0f));
				m_CameraRotation = m_CameraRotation * mt;
				m_RotationMatrix = m_RotationMatrix * mt;
				m_Eye = m_Eye * mt;
				m_Up = m_Up * mt;
				m_Center = m_Center * mt;
			}
			//相机向上旋转
			else if (ea.getKey() == 'i' || ea.getKey() == 'I')
			{
				osg::Matrix mt;
				//设置旋转轴
				mt = osg::Matrix::rotate(osg::DegreesToRadians(15.0),m_CameraRotation);
				m_RotationMatrix = m_RotationMatrix* mt;
				m_Eye = m_Eye * osg::Matrix::rotate(osg::DegreesToRadians(15.0),m_CameraRotation);
				m_Up = m_Up * osg::Matrix::rotate(osg::DegreesToRadians(15.0),m_CameraRotation);
				m_Center = m_Center * osg::Matrix::rotate(osg::DegreesToRadians(15.0),m_CameraRotation);
			}
			//相机向下旋转
			else if (ea.getKey() == 'k' || ea.getKey() == 'K')
			{
				osg::Matrix mt;
				//设置旋转矩阵
				mt = osg::Matrix::rotate(-osg::DegreesToRadians(15.0),m_CameraRotation);
				m_RotationMatrix = m_RotationMatrix * mt;
				m_Eye = m_Eye * osg::Matrix::rotate(-osg::DegreesToRadians(15.0),m_CameraRotation);
				m_Up = m_Up * osg::Matrix::rotate(-osg::DegreesToRadians(15.0),m_CameraRotation);
				m_Center = m_Center * osg::Matrix::rotate(-osg::DegreesToRadians(15.0),m_CameraRotation);
			}
		}
		default:
			break;
	return false;
	}
	return false;
}

main.cpp文件

#include "Trave.h"
#include "Setup.h"
int main()
{
	osg::ref_ptr<osgViewer::Viewer>viewer = new osgViewer::Viewer();
	osg::ref_ptr<osg::Group> root = new osg::Group();
	Changeport a(viewer);
	a.changeport();
	osg::ref_ptr<osg::Node> node = a.createNode();
	root->addChild(a.createTexture2DState(node));
	//添加漫游器
	viewer->setCameraManipulator(new TraveManipulator(node));
	osgUtil::Optimizer optimizer;
	optimizer.optimize(root.get());
	//设置场景数据
	viewer->setSceneData(root.get());
	viewer->realize();
	viewer->run();   
	return 0;
}

这是我对相机的理解和看法,代码仅供参考。如果大家有什么不同的意见,欢迎评论区留言

  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值