• osg 拖拽器


    漫游器中世界不动,观察者相机在动。再三维世界中需要对对象的平移、选择缩放操作,
    注意:需要对三维物体设置一个父对象,对父节点操作很桥当
    为了便于用户操作,引入Command设计模式,它属于一种对象行为模式。将一系列对象操作push到一个队列中。

    包括:

    • 接收者 Receiver
    • 触发者 Invoker
    • 命令本身 Command

    在osgManipulator中,可以将Dragger本身定义为触发者 Invoker,它负责用户的平移、选择缩放灯。
    接收者为Selection类,它是实际待操作对象的父节点;
    控制命令使用 MotionCommand表达
    并使用一个 CommandManager对所有操控命令以及拖拽器与接收者进行绑定关系。
    osgManipulator::MotionCommand 类

    MotionCommand() 默认构造函数
    
    bool execute() 虚函数 执行/撤销一个命令
    
    bool unexecute()
    void applyConstraint(const Constraint *) 虚函数。添加命令的约束条件
    void addSelection(Selection *) 添加/删除一个命令作用的备选对象
    void removeSelection(Selection *)
    osg::Matrix getMotionMatrix() const 虚函数。获取命令的结果的矩阵
    

    void setStage(const Stage s) 设置/获取设置的执行阶段类型,包括START MOVE FINISH 3种
    执行命令阶段包括 鼠标按下选中 START 、拖拽 MOVE 以至于FINISH 这一过程。不同执行阶段的输出结果不一样。
    Constraint类表示约束条件,用户通过自定义来实现约束功能。
    一个命令的执行可以作用在多个备选对象上。

    osgManipulator::CommandManager 类

    CommandManager() 默认构造函数
    bool connect(Dragger& dragger,Selection& selection) 虚函数,绑定拖拽器与一个备选对象
    bool connect(Dragger& dragger,Constraint& constrain) 虚函数,绑定拖拽器或一个约束对象
    bool disconnect(Dragger & dragger) 虚函数 取消所有与当前拖拽器有关的备选对象和约束对象
    void dispath(MotionCommand &) 虚函数 分发一个命令,即执行一个命令
    
    void addSelectionsToCommand(MotionCommand& command,Dragger& dragger) 设置一个命令的发送者和接收者
    

    注意:一个对象不能被多个多拽器影响。可以使用 CompositeDragger实现这一功能。
    当命令执行的时候,接收者Selections负责接收和实现命令效果。由于Selection节点是作为被操控的物体的父节点催你在的。

    osgManipulator::Selection 类

    Selection() 默认构造函数
    bool receive(const MotionCommand&) 对各种命令(MotionCommand及其派生类)的接收函数
    

    osgManipulator::Dragger类

    void setCommandManager(CommandManager*)
    CommandManager * getCommandManager() 设置/获取命令管理器,用于分发命令
    void setParentDragger(Dragger*) 设置/获取父拖拽器。对于一个单独的拖拽器,其父拖拽器就是它自己
    bool handle(const PointerInfo&,const GUIEventAdapter&,GUIActionAdapter&) 虚函数,根据用户交互事件,触发操控命令
    

    注意:PointerInfo表示鼠标选中待操控对象上的某个点,以及当前相机的观察矩阵和投影矩阵等,都需要及时反馈到这个输入参数种,以便
    实例:、
    PickModelHandler

    //PickModelHandler.h
    #pragma once
    #include <windows.h>
    #include <osg/Node>
    #include <osgDB/ReadFile>
    #include <osgViewer/Viewer>
    #include <osgManipulator/CommandManager>
    #include <osgManipulator/Dragger>
    #include <osg/NodeVisitor>
    #include <osgGA/GUIEventHandler>
    #include <osgUtil/LineSegmentIntersector>
    class PickModelHandler :public osgGA::GUIEventHandler
    {
    public:
    	PickModelHandler();
    	~PickModelHandler();
    	bool handle(const osgGA::GUIEventAdapter & ea,osgGA::GUIActionAdapter& aa,osg::Object*,osg::NodeVisitor*);
    protected:
    	osgManipulator::Dragger* _activeDragger;
    	osgManipulator::PointerInfo* _pointer ;//拖拽器 输入的信息集合 Dragger类种的handler参数
    
    };
    
    
    
    

    PickModelHandler.cpp

    #include "PickModelHandler.h"
    
    PickModelHandler::PickModelHandler() :_activeDragger(0) {
    	_pointer = new osgManipulator::PointerInfo;
    }
    
    PickModelHandler::~PickModelHandler() {}
     
    bool PickModelHandler::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa, osg::Object*, osg::NodeVisitor*) {
    	osgViewer::View * view = dynamic_cast<osgViewer::View*>(&aa);
    	if (!view)return false;
    
    	switch (ea.getEventType())
    	{
    		case osgGA::GUIEventAdapter::PUSH: {
    			_pointer->reset();
    			//创建线条?
    			osgUtil::LineSegmentIntersector::Intersections hits;
    			if (view->osgViewer::View::computeIntersections(ea.getX(), ea.getY(), hits)) {
    				_pointer->setCamera(view->getCamera());
    				_pointer->setMousePosition(ea.getX(), ea.getY());
    
    				osgUtil::LineSegmentIntersector::Intersections::iterator hitr;//线段访问器
    				for (hitr = hits.begin(); hitr != hits.end(); ++hitr) {
    					_pointer->addIntersection(hitr->nodePath, hitr->getLocalIntersectPoint());//添加线段信息
    				}
    				osg::NodePath::iterator itr;
    				for (itr = _pointer->_hitList.front().first.begin();
    					itr != _pointer->_hitList.front().first.end();
    					++itr) {
    					osgManipulator::Dragger* dragger = dynamic_cast<osgManipulator::Dragger*>(*itr);//获取输入参数 Dragger
    					if (dragger) {
    						dragger->handle((*_pointer), ea, aa);
    						_activeDragger = dragger;
    						break;
    					}
    
    				} 
    			}
    			break;
    		}
    		case osgGA::GUIEventAdapter::DRAG:
    		case osgGA::GUIEventAdapter::RELEASE: {
    			if (_activeDragger) {
    				_pointer->_hitIter = _pointer->_hitList.begin();
    				_pointer->setCamera(view->getCamera());
    				_pointer->setMousePosition(ea.getX(), ea.getY());
    				_activeDragger->handle((*_pointer),ea,aa);
    			}
    			if (ea.getEventType() == osgGA::GUIEventAdapter::RELEASE) {
    				_activeDragger = NULL;
    				_pointer->reset();
    			}
    			break;
    		}
    		default:
    			break;
    	}
    	return true;
    }
    

    main

    /**
    * 拖拽器示例 实现使用鼠标拖动物体上X Y轴箭头
    * 继承 osgGA::GUIEventHandler 的 handler 方法
    * 1 使用 view->computeIntersections 判断鼠标与场景中的对象交点
    * 2 将交点位置传染 PointerInfo对象,作为拖拽器的对象参数
    * 3 实现 handler 的 PUSH 鼠标按下 REALSE 鼠标释放事件
    * 在main方法中 
    * 1 将对象放入 Selection 之下
    * 2 定义 XYZ的拖拽器 TranslateAxisDragger (三个方向的箭头,可以相应事件的交点)
    * 3 定义命令管理器 CommandManager 实现拖拽器和Selection关联
    */
    int main(int argc, char** argv) {
    	osg::ArgumentParser arguments(&argc,argv);
    	osg::Node* model = osgDB::readNodeFiles(arguments);
    	if (!model) {
    		model = osgDB::readNodeFile("cow.osg");
    	}
    	//定义接收者
    	osg::ref_ptr<osgManipulator::Selection> selection = new osgManipulator::Selection;
    	//添加备用节点
    	selection->addChild(model);
    	//缩放比例
    	float scale = model->getBound().radius() * 1.6;
    	osg::ref_ptr<osgManipulator::TranslateAxisDragger> dragger = new osgManipulator::TranslateAxisDragger;
    	dragger->setupDefaultGeometry();
    	dragger->setMatrix(osg::Matrix::scale(scale, scale, scale) *
    		osg::Matrix::translate(model->getBound().center()));
    
    	osg::ref_ptr<osg::Group> root = new osg::Group;
    	root->addChild(dragger.get());
    	root->addChild(selection.get());
    	root->addChild(osgDB::readNodeFile("axes.osg"));
    	
    	osg::ref_ptr<osgManipulator::CommandManager> manager = new osgManipulator::CommandManager;
    	manager->connect(*dragger,*selection);
    
    	osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();
    	viewer->addEventHandler(new PickModelHandler);
    	viewer->setSceneData(root.get());
    	return viewer->run();
    
    }
    
    
  • 相关阅读:
    什么是em?
    数据结构与算法:快速排序
    flex中flexshrink的理解
    前端的padding是参照父元素的宽度还是高度?
    子元素的border不能通过百分比设置的
    数据库去重的简易方法
    windows2003 iis6.0站点打不开,找不到服务器或 DNS 错误。
    常用WebServices返回数据的4种方法比较
    手机身份证IP地址开放接口(很实用哦)
    从创业失败中学到的七条教训
  • 原文地址:https://www.cnblogs.com/fishpro/p/16044424.html
Copyright © 2020-2023  润新知