osg 自己写地面操作器
来源:互联网 发布:revit软件插件探索者 编辑:程序博客网 时间:2024/04/29 05:05
地面操作器,继承自osg自身的轨迹球操作器(osgGA::OrbitManipulator),参考osgEarth的操作器的实现。
特性:
放大缩小视点始终在指定的地面高度上。(旋转中心点一直在那个高度的平面上)
地面始终与视线平行,即在操作过程中地面上的物体不会歪。
放大到指定的视线距离后,距离不再放大;(即距离地面,实际上是距离视点一定距离后不再升高,改为后退)。
缩小到一定距离后,距离不再缩小;(即距离视点一定距离后不再变小,继续缩放的话,就是前进)。
下面给出类的实现
// 文件名:GroundManipulator.h// 作者:mingjun;日期:2015-11-05// 描述: 地面操作器// //////////////////////////////////////////////////////////////////////////// 历史记录/////////////////////////////////////////////////////////////////////////#ifndef _GROUNDMANIPULATOR_H_#define _GROUNDMANIPULATOR_H_class CGroundManipulator : public osgGA::OrbitManipulator{typedef OrbitManipulator inherited;public:COCSGroundManipulator();virtual ~COCSGroundManipulator(); // 见父类virtual void setCenter( const osg::Vec3d& center );// 见父类virtual void setByMatrix( const osg::Matrixd& matrix );// 见父类virtual void zoomModel( const float dy, bool pushForwardIfNeeded = true );// 见父类virtual bool performMovementLeftMouseButton( const double eventTimeDelta, const double dx, const double dy );// 见父类virtual bool performMovementMiddleMouseButton( const double eventTimeDelta, const double dx, const double dy );// 见父类virtual void panModel( const float dx, const float dy, const float dz = 0.f );// 见父类virtual void rotateTrackball( const float px0, const float py0,const float px1, const float py1, const float scale );public:// 地面法向osg::Vec3d GetUpVector() const;void SetUpVector(const osg::Vec3d &vecUp);// 最大距离void SetMaxDistance(double dDistance);double GetMaxDistance() const;private:osg::Vec3d _upVector;// 垂直地面向上的向量 double _maxDistance;// 定义一个最大距离,当超过这个距离,就不在放大了};#endif
类的实现:
里面设置的视点距离地面高度为5000;假定y轴为地面法向设置的。如果你的不是则哪里需要修改一下。
// 文件名:GroundManipulator.cpp// 作者:mingjun;日期:2015-11-05// 描述:// //////////////////////////////////////////////////////////////////////////// 历史记录/////////////////////////////////////////////////////////////////////////#include "StdAfx.h"#include "GroundManipulator.h"COCSGroundManipulator::COCSGroundManipulator():inherited(DEFAULT_SETTINGS){_upVector = osg::Vec3d(0.0, 1.0, 0.0);setVerticalAxisFixed( false );setAllowThrow(false);// 设置其放大缩小方式与cad一样double dOld = getWheelZoomFactor();setWheelZoomFactor(-1.0 * dOld);// 设置当缩放到这个大小后,在缩放的时候,同时移动centersetMinimumDistance( 1000, false );SetMaxDistance(100000.0);}COCSGroundManipulator::~COCSGroundManipulator(){}osg::Vec3d COCSGroundManipulator::GetUpVector() const{return _upVector;}void COCSGroundManipulator::SetUpVector( const osg::Vec3d &vecUp ){_upVector = vecUp;}void COCSGroundManipulator::setByMatrix( const osg::Matrixd& matrix ){_center = osg::Vec3d( 0., 0., -_distance ) * matrix;_center.y() = 5000.0;// 应该让y轴投影到视平面上后,是竖直的 计算上比较麻烦,所以直接给一个osg::Vec3d f = -getUpVector(matrix);//( 1.0, -1.0, 0.0 );//f.normalize();osg::Vec3d s = getSideVector(matrix);//( 0.0, 0.0, 1.0 );osg::Vec3d u(_upVector);//u( 1.0, 1.0, 0.0 );s = f^u;//u.normalize();osg::Matrixd rotation_matrix( s[0], u[0], -f[0], 0.0f,s[1], u[1], -f[1], 0.0f,s[2], u[2], -f[2], 0.0f,0.0f, 0.0f, 0.0f, 1.0f );_rotation = rotation_matrix.getRotate().inverse();}void COCSGroundManipulator::zoomModel( const float dy, bool pushForwardIfNeeded /*= true */ ){// dy 放大为正,缩小为负// scalefloat scale = 1.0f + dy;// minimum distancefloat minDist = _minimumDistance;if( getRelativeFlag( _minimumDistanceFlagIndex ) )minDist *= _modelSize;double dResult = _distance * scale;if( dResult > minDist ){if ( dResult < GetMaxDistance()){_distance = dResult;}else{float scale = -_distance;osg::Matrix rotation_matrix;rotation_matrix.makeRotate( _rotation );osg::Vec3d sideVector = getSideVector(rotation_matrix);osg::Vec3d localUp(0.0f,1.0f,0.0f);osg::Vec3d forwardVector =localUp^sideVector;forwardVector.normalize();osg::Vec3d dv = forwardVector * (dy * scale);_center += dv;}// regular zoom//_distance *= scale;}else{if( pushForwardIfNeeded ){// push the camera forwardfloat scale = -_distance;osg::Matrix rotation_matrix;rotation_matrix.makeRotate( _rotation );osg::Vec3d sideVector = getSideVector(rotation_matrix);osg::Vec3d localUp(0.0f,1.0f,0.0f);osg::Vec3d forwardVector =localUp^sideVector;forwardVector.normalize();osg::Vec3d dv = forwardVector * (dy * scale);_center += dv;}else{// set distance on its minimum value_distance = minDist;}}}void COCSGroundManipulator::panModel( const float dx, const float dy, const float dz ){double scaley = 1;//0.001 * _distance;double scalex = 1;//0.0003 * _distance;osg::Matrix rotation_matrix;rotation_matrix.makeRotate( _rotation );// compute look vector.//osg::Vec3d lookVector = -getUpVector(rotation_matrix);osg::Vec3d sideVector = getSideVector(rotation_matrix);//osg::Vec3d upVector = getFrontVector(rotation_matrix);osg::Vec3d localUp(_upVector);osg::Vec3d forwardVector =localUp^sideVector;sideVector = forwardVector^localUp;forwardVector.normalize();sideVector.normalize();osg::Vec3d dv = forwardVector * (dy*scaley) + sideVector * (dx*scalex);_center += dv;}void COCSGroundManipulator::rotateTrackball( const float px0, const float py0,const float px1, const float py1, const float scale ){double dx = px0 - px1;double dy = py0 - py1;if ( ::fabs(dx) > ::fabs(dy) )dy = 0.0;elsedx = 0.0;osg::Matrix rotation_matrix;rotation_matrix.makeRotate(_rotation);//osg::Vec3d lookVector = -getUpVector(rotation_matrix);osg::Vec3d sideVector = getSideVector(rotation_matrix);//osg::Vec3d upVector = getFrontVector(rotation_matrix);osg::Vec3d localUp(_upVector);osg::Vec3d forwardVector = localUp^sideVector;sideVector = forwardVector^localUp;forwardVector.normalize();sideVector.normalize();osg::Quat rotate_elevation;rotate_elevation.makeRotate(dy,sideVector);osg::Quat rotate_azim;rotate_azim.makeRotate(-dx,localUp);_rotation = _rotation * rotate_elevation * rotate_azim;}bool COCSGroundManipulator::performMovementLeftMouseButton( const double eventTimeDelta, const double dx, const double dy ){// pan modelfloat scale = -0.3f * _distance * getThrowScale( eventTimeDelta );panModel( dx*scale, dy*scale );return true;}bool COCSGroundManipulator::performMovementMiddleMouseButton( const double eventTimeDelta, const double dx, const double dy ){rotateTrackball( _ga_t0->getXnormalized(), _ga_t0->getYnormalized(),_ga_t1->getXnormalized(), _ga_t1->getYnormalized(),getThrowScale( eventTimeDelta ) );return true;}void COCSGroundManipulator::setCenter( const osg::Vec3d& center ){_center = center;_center.y() = 5000.0;}void COCSGroundManipulator::SetMaxDistance(double dValue){_maxDistance = dValue;}double COCSGroundManipulator::GetMaxDistance() const{return _maxDistance;}
0 0
- osg 自己写地面操作器
- osg for android 操作器
- 自己写的单链表操作
- OSG 添加操作器及功能列表
- osg自定义操作器实现视图缩放
- osg animate 操作
- osg 相机操作
- osg 矩阵操作
- 自己写的字符串操作类
- 自己写的操作 RMS类
- Exe8 自己写的字符串操作函数
- 自己写的文件操作工具类
- 自己写的一个 ini 操作类
- SQLite3自己写的一些操作语句
- OSG漫游:实现按键控制的操作器
- osg视图操作关于Manipulator
- 自己写调试器 初探
- 自己写调试器 进阶
- Android手机自动化测试工具介绍
- java 缓存
- 简单说一下RecyclerView
- CentOS6.7 RabbitMQ的安装和配置
- Android分享:如何高效率开发App
- osg 自己写地面操作器
- andriod SnackBar使用
- cmake 与 make
- Oracle OS备份了解
- 搭建mysql主从数据库实现双机热备架构
- Android中文件选择器的实现
- EventBus使用详解(一)——初步使用EventBus
- 4.5.2 非常好的 Good Android 学习之开源项目PullToRefresh的使用
- RGB24与YUV420之间的互相转换