OSG下鼠标点击实现对模型的移动,旋转(漫游器)

点击鼠标实现对模型的移动,旋转功能,需要用到漫游器。在实现的过程中的需要用到osgGA模块的知识,
重写osgGA下的该函数virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us);可以实现对模型的操作。
1、模型的移动:

static Matrixd 	translate (const Vec3f &dv)

2、模型的缩放

static Matrixd 	scale (const Vec3f &sv)

3、模型的旋转

 static Matrixd 	rotate (const Vec3f &from, const Vec3f &to)

4、可以直接用MatrixTransform操作矩阵,来控制模型的平移、缩放和旋转

osg::ref_ptr mt = new osg::MatrixTransform;
osg::ref_ptr cow= osgDB::readNodeFile("cow.osg");
mt->addChild(cow);
//先向x轴移动30, 绕x轴旋转90度, 再缩放到原来的0.2倍
mt->setMatrix(osg::Matrix::translate(osg::Vec3(30, 0, 0)) *
osg::Matrix::rotate(90, osg::Vec3d(1, 0, 0)) *   
osg::Matrix::scale(osg::Vec3(0.2, 0.2, 0.2)) );

如何实现?
可以通过按W、A、S 、D去实现模型的移动,可以按鼠标左键进行物体位置的拖移,按鼠标右键拖移可以实现物体的旋转。
在实现的过程有一个屏幕坐标向世界坐标转换的过程。以下部分代码的函数和变量并未有用到。

#include "stdafx.h"
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

class TravelManipulator :public osgGA::CameraManipulator 
{
public:
	TravelManipulator();
	~TravelManipulator();

public:
	//设置当前视口
	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);

	osg::Vec3 screen2World(float x, float y);


private:
	//视点
	osg::Vec3 mPosition;
	//朝向
	osg::Vec3 mRotation;

	osg::ref_ptr view;

	bool lbuttonDown;
	bool m_rButtonDown;

	float m_leftX;
	float m_leftY;
	float m_leftZ;

	float m_rightX;
	float m_rightY;
	float m_rightZ;
};

TravelManipulator::TravelManipulator()
{
	mPosition = osg::Vec3(0, 0, 50);
	mRotation = osg::Vec3(0, 0, 0);

	m_rButtonDown = false;
	lbuttonDown = false;
	m_leftX = 0;
	m_leftY = 0;
	m_rightX = 0;
	m_rightY = 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(mPosition);
	return mat*osg::Matrixd::rotate(mRotation[0], osg::X_AXIS, mRotation[1], osg::Y_AXIS, mRotation[2], osg::Z_AXIS);
}

osg::Matrixd TravelManipulator::getInverseMatrix() const 
{
	osg::Matrixd mat;
	mat.makeTranslate(mPosition);
	return osg::Matrixd::inverse(mat*osg::Matrixd::rotate(mRotation[0], osg::X_AXIS, mRotation[1], osg::Y_AXIS, mRotation[2], osg::Z_AXIS));
}

bool TravelManipulator::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us)
{
	view = dynamic_cast(&us);
	if (!view)return false;

	switch (ea.getEventType()) {
	case osgGA::GUIEventAdapter::KEYDOWN:
		if (ea.getKey() == 'w') {
			mPosition[2] += 2;
		}
		else if (ea.getKey() == 's') {
			mPosition[2] -= 2;
		}
		else if (ea.getKey() == 'a') {
			mPosition[0] -= 2;
		}
		else if (ea.getKey() == 'd') {
			mPosition[0] += 2;
		}
		break;

	case osgGA::GUIEventAdapter::PUSH:
	{
		if (ea.getButton() == osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON)
		{

			osg::Vec3 vec1 = screen2World(ea.getX(), ea.getY());
			/*m_leftX = ea.getX();
			m_leftY = ea.getY();*/
			m_leftZ = vec1.z();
			m_leftX = vec1.x();
			m_leftY = vec1.y();

			lbuttonDown = true;
			
		}

		if (ea.getButton()==osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON)
		{

			m_rightX = ea.getX();
			m_rightY = ea.getY();
			m_rButtonDown = true;
		}
		return false;
	}
	case osgGA::GUIEventAdapter::DRAG:
	{
		if (lbuttonDown)
		{
			osg::Vec3 vec1 = screen2World(ea.getX(), ea.getY());
			float ix = vec1.x() - m_leftX;
			float iy = vec1.y() - m_leftY;
			float iz = vec1.z() - m_leftZ;
			mPosition[2] += 0.1*iz;
			mPosition[1] -= 0.1*iy;
			mPosition[0] -= 0.1*ix;
		}

		if (m_rButtonDown)
		{
			float ix = ea.getX() - m_rightX;
			float iy = ea.getY() - m_rightY;
			mRotation[2] += osg::DegreesToRadians(0.1*ix);
			mRotation[0] -= osg::DegreesToRadians(0.1*iy);

		}
		return false;
	}

	case osgGA::GUIEventAdapter::RELEASE:
	{
		if (ea.getButton() == osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON)
		{
			lbuttonDown = false;
		}

		if (ea.getButton() == osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON)
		{
			m_rButtonDown = false;
		}
	}
	default:
		break;
	}
	return false;
}


osg::Vec3 TravelManipulator::screen2World(float x, float y)
{
	osg::Vec3 vec3;
	osg::ref_ptr camera = view->getCamera();
	osg::Vec3 vScreen(x, y, 0);
	osg::Matrix mVPW = camera->getViewMatrix() * camera->getProjectionMatrix() * camera->getViewport()->computeWindowMatrix();
	osg::Matrix invertVPW;
	invertVPW.invert(mVPW);
	vec3 = vScreen * invertVPW;
	return vec3;
}


int main(int argc, char** argv) 
{
	
	osg::ref_ptr viewer = new osgViewer::Viewer();
	viewer->addEventHandler(new osgViewer::WindowSizeHandler);
	viewer->addEventHandler(new osgViewer::StatsHandler);

	osg::ref_ptr root = new osg::Group;

	root->addChild(osgDB::readNodeFile("cow.osg"));	
	viewer->setSceneData(root);

	viewer->setCameraManipulator(new TravelManipulator());
	viewer->realize();
	viewer->run();

	return 0;
}

注意:mat 放置前后位置不同,会出现不同的现象

mat*osg::Matrixd::rotate(mRotation[0], osg::X_AXIS, mRotation[1], osg::Y_AXIS, mRotation[2], osg::Z_AXIS);

你可能感兴趣的:(OSG)