osg 自己写地面操作器



地面操作器,继承自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);
	
	//  设置当缩放到这个大小后,在缩放的时候,同时移动center
	setMinimumDistance( 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 放大为正,缩小为负
	// scale
	float scale = 1.0f + dy;

	// minimum distance
	float 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 forward
			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;
		}
		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;
	else
		dx = 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 model
	float 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;
}


  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
如果您在使用 osgEarth 时遇到地面下数据不可见的问题,可以考虑以下解决方案: 1. 数据源:确保您的数据源包含地面下的数据,并且数据源的配置正确。您可以使用地理信息系统文件格式(如 shapefile、GeoJSON)或其他支持的格式来存储地面下数据。 2. 图层设置:在 osgEarth 中,您可以创建图层并将其与特定的数据源相关联。确保您已正确设置图层的属性,如图层类型、渲染选项等。对于地面下数据,您可以选择合适的图层类型来表示,如模型图层或矢量图层。 3. 高度设置:osgEarth 使用高程数据来确定地球表面的高度。对于地面下数据,您可以尝试调整高程数据以使其适应地面下几何结构。您可以使用高程数据编辑工具或编程方式来修改高程数据。 4. 可视化效果:osgEarth 支持各种可视化效果,如纹理映射、光照等。您可以尝试调整可视化效果以改善地面下数据的可见性,如调整不透明度、颜色等。 5. 相机视角:确保相机的位置和朝向适合您想要查看的地区。有时,调整相机的视角可以帮助您更好地观察地面下数据。 如果您遇到了特定的问题或错误消息,请提供更多细节,以便我能够提供更具体的帮助。osgEarth 是一个灵活且功能强大的工具包,具体的解决方案可能会因情况而异。建议您参考 osgEarth 的文档和示例代码,以了解更多关于数据可视化和调整的详细信息。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值