添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

实现目标:当鼠标向某个方向移动时,视角向其反方向移动,相当于对模型整体进行拖拽的感觉。
示意图:

如图,在屏幕平面上,鼠标从m_1位置移动到m_0位置,两个点坐标的x方向差值为dx,y方向差值为dy
在过相机位置(eye)且垂直于相机于y轴夹角方向向量(图中x-o-y平面紫色的向量)的平面中,要将屏幕上鼠标的移动对应到相机上,在图中鼠标是向屏幕左上方移动的,相机应该向右下方移动到目标位置,为了方便理解,我们先计算相机移动到左上方的目标反方向位置(点p):
假设相机移动步长为move_len, 那么相机z轴方向位移z_len为:move_len·sin(theta)
相机在平行于x-o-y面的移动距离xy_len为move_len·cos(theta)

如上图,在x-o-y面,相当于相机向左平移move_len · cos(theta)
则相机x轴方向平移距离:|move_len · cos(theta) · cos(theta_y)| theta_y为相机视角与y轴夹角
则相机y轴方向平移距离:|move_len·cos(theta)·sin(theta_y)|
那么若将相机移动到图1 p点 其移动可表示为:
eye += osg::Vec3f(-|move_len·cos(theta)·cos(theta_y)|,|move_len·cos(theta)·sin(theta_y)| ,move_len·sin(theta))
将相机移动到目标位置就是移动到点p的反方向:
eye += -osg::Vec3f(-|move_len·cos(theta)·cos(theta_y)|,|move_len·cos(theta)·sin(theta_y)| ,move_len*sin(theta))

附部分代码:

.h中定义两个临时事件指针
osg::ref_ptr< const osgGA::GUIEventAdapter > _ga_t1;//旧事件
osg::ref_ptr< const osgGA::GUIEventAdapter > _ga_t0;//新事件
//保存事件函数:
void addMouseEvent(const osgGA::GUIEventAdapter& ea)
	_ga_t1 = _ga_t0;//上次事件
	_ga_t0 = &ea;//最新事件
//handle处理按键事件
case osgGA::GUIEventAdapter::PUSH:
		if (ea.getButton() == osgGA::GUIEventAdapter::MIDDLE_MOUSE_BUTTON)
			addMouseEvent(ea);
		return false;
//handle处理拖拽事件
case osgGA::GUIEventAdapter::DRAG:
		if (_ga_t0 == NULL)
			return false;
		unsigned int buttonMask = _ga_t0->getButtonMask();
		if(buttonMask == osgGA::GUIEventAdapter::MIDDLE_MOUSE_BUTTON)
			addMouseEvent(ea);//添加事件
			//计算x y偏移
			int delX = _ga_t0->getX() - _ga_t1->getX();
			int delY = _ga_t0->getY() - _ga_t1->getY();
			//计算sin theta 及 cos theta
			int abs_x = abs(delX);
			int abs_y = abs(delY);
			float sin_theta = abs_y / sqrt(abs_x*abs_x + abs_y * abs_y);
			float cos_theta = abs_x / sqrt(abs_x*abs_x + abs_y * abs_y);
			int range = 3;灵敏度
			osg::Vec3f move(0, 0, node_radius * 0.05);//相机对应移动长度 此处设置为模型包围球半径*0.05
			if (delY > 0 && delX >0 && abs_x > range && abs_y > range)
			{//鼠标右上移动 视角左下移动
				move.x() = -node_radius * 0.05*cos_theta*cosf(m_rotate[2]);//m_rotate[2]是相机与y轴夹角 正负号与该角度相关
				move.y() = -node_radius * 0.05*cos_theta*sinf(m_rotate[2]);
				move.z() = -move.z()*sin_theta;
				m_Position += move;//m_Position为相机位置
			else if (delY < 0 && delX < 0 && abs_x > range && abs_y > range)
			{//鼠标 左下 视角 右上
				move.x() = node_radius * 0.05*cos_theta*cosf(m_rotate[2]);
				move.y() = node_radius * 0.05*cos_theta*sinf(m_rotate[2]);
				move.z() = move.z()*sin_theta;
				m_Position += move;
			else if (delY < 0 && delX > 0 && abs_x > range && abs_y > range)
			{//鼠标右下 视角 左上
				move.x() = -node_radius * 0.05*cosf(m_rotate[2]);
				move.y() = -node_radius * 0.05*sinf(m_rotate[2]);
				move.z() = move.z()*sin_theta;
				m_Position += move;
			else if (delY > 0 && delX < 0 && abs_x > range && abs_y > range)
			{//鼠标 左上 视角 右下
				move.x() = node_radius * 0.05 * cosf(m_rotate[2]);
				move.y() = node_radius * 0.05 * sinf(m_rotate[2]);
				move.z() = -move.z()*sin_theta;
				m_Position += move;
			else if (delY > 0 && delX == 0)//abs_x < range)// && abs_y >= range)
			{//鼠标向上 视角向下
				//move.x() = move_step * 0.3*cosf(m_rotate[2]);
				//move.y() = -move_step * 0.3*sinf(m_rotate[2]);
				move.z() = -move.z();
				m_Position += move;
			else if (delY < 0 && delX == 0)// && abs_y >= range)
			{//鼠标向下 视角向上
				//move.x() = move_step * 0.3*cosf(m_rotate[2]);
				//move.y() = -move_step * 0.3*sinf(m_rotate[2]);
				//move.z() = -move.z();
				m_Position += move;
			else if (delX < 0 && delY == 0)// abs_y < range && abs_x >= range)
			{//鼠标向左 视角向右移动
				move.x() = node_radius * 0.05*cosf(m_rotate[2]);
				move.y() = node_radius * 0.05*sinf(m_rotate[2]);
				move.z() = 0;
				m_Position += move;
			else if (delX > 0 && delY == 0) //abs_y < range && abs_x >= range)
			{//鼠标向右 视角向左移动
				move.x() = -node_radius * 0.05*cosf(m_rotate[2]);
				move.y() = -node_radius * 0.05*sinf(m_rotate[2]);
				move.z() = 0;
				m_Position += move;
	break;
                    实现目标:当鼠标向某个方向移动时,视角向其反方向移动,相当于对模型整体进行拖拽的感觉。示意图:如图,在屏幕平面上,鼠标从m_1位置移动到m_0位置,两个点坐标的x方向差值为dx,y方向差值为dy在过相机位置(eye)且垂直于相机于y轴夹角方向向量(图中x-o-y平面紫色的向量)的平面中,要将屏幕上鼠标的移动对应到相机上,在图中鼠标是向屏幕左上方移动的,相机应该向右下方移动到目标位置,为了方...
				
点击鼠标实现对模型移动,旋转功能,需要用到漫游器。在实现的过程中的需要用到osgGA模块的知识, 重写osgGA下的该函数virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us);可以实现对模型的操作。 1、模型移动: static Matrixd translate ...
1.创建两个模型,并且把这两个模型放到Group中,并且注册鼠标点击事件处理 void mousePick2() { osg::ref_ptr&lt;osgViewer::Viewer&gt; viewer = new osgViewer::Viewer(); viewer-&gt;addEventHandler(new osgViewer... 首先介绍一下拖拽器: (1):TabPlaneDragger平面拖拽器:其边、顶点上都有拖拽点,可以进行某个2D平面上的缩放; (2):TabPlaneTrackballDragger平面轨迹球拖拽器:除了平面拖拽器的功能外,还多了个轨迹球拖拽功能; (3):TrackballDragger轨迹球拖拽器:即旋转操纵器,没有缩放功能 (4):Transla...
viewer->getEventQueue()->mouseButtonPress(0,0,1); viewer->getEventQueue()->mouseMotion(10,0); 以上代码模拟了鼠标左键从窗口(0,0)拖拽到窗口坐标(10,0) viewer->getEventQueue()->mouseScroll(osgGA::GUIEventAdapter::SCROLL_DOWN); 以上代码模拟了向上滚动滚轮
移动和缩放以及旋转都是对矩阵进行操作,这些操作如果要叠加直接矩阵相乘就可以了。 下面的示例代码中,加入了四个bignathan,一个是默认加入在最中间,一个向上移2单位,一个是向下移2单位且缩放0.5倍,另一个是向右4单位,缩放0.5且平躺45度。 #include<osgDB\ReadFile> #include<osgViewer\Viewer> #includ...
OSG鼠标选择求交 ////求交方法一:(用WINDOW坐标值,在相机下求交)            //osg::ref_ptr picker = new osgUtil::LineSegmentIntersector(            //  osgUtil::Intersector::WINDOW, ea.getX(), ea.getY());            //osg
之前的一篇博文是有一篇对点选物体进行平移、缩放旋转。那一篇是很简单的调用了OSG中定义的一些dragger,但这些dragger都有坐标轴或者tapbox等在模型上,与我最近要做的事情的需求不同。网上也找了好久,最终还是自己一点一点,参考老师之前写的代码,然后在亲爱的童童师兄的帮助下,实现了这么一个小小的功能。虽然代码写的乱糟糟的。 这里就简单记录一下整个思路吧。 1、构造一个事件处理器,也就
在使用 OpenSceneGraph(简称OSG)库进行模型渲染时,我们可以通过鼠标点击来获取模型的方位角。方位角指的是模型在三维空间中相对于某个参考方向的角度。 要实现此功能,我们首先需要设置鼠标点击的事件,并在事件处理函数中编写相应的代码。当鼠标被点击时,可以通过使用 OSG 库提供的函数来获取点击位置的屏幕坐标。 然后,我们需要将屏幕坐标转换为世界坐标。为此,可以使用 OSG 提供的函数将屏幕坐标转换为射线,然后对射线进行相交测试,从而得到与模型相交的点的世界坐标。 接下来,我们可以使用模型的世界坐标和相机的位置来计算模型的方位角。可以使用 OSG 提供的几何计算函数来进行此计算。根据具体需求,比如计算相对于参考方向的水平角度或者垂直角度,可以选择合适的函数进行计算。 最后,可以根据具体的应用需求将方位角信息进行展示或者进一步应用,比如根据方位角实现模型的自动旋转或者相关约束等功能。 总而言之,使用 OSG 鼠标点击模型方位角的过程包括设置鼠标点击事件、将屏幕坐标转换为世界坐标、计算模型方位角,并根据实际需求进行后续处理。这个过程需要合理利用 OSG 提供的函数和工具,确保模型方位角的准确性和可靠性。