osg实现正交视图控制器

osg中没有正交视图的控制器,但是我们经常会遇到2D的项目应用,我也不知道如何申请成为osg社区的会员,就写在这里,以免忘掉,拿去不谢.

#ifndef OSGGA_ORTHO_MANIPULATOR
#define OSGGA_ORTHO_MANIPULATOR 1


#include 
#include 
#include 
#include "osg_export.h"

namespace osgGA{

	class XOSG_EXPORT OrthoManipulator : public osgGA::CameraManipulator
	{
public:
	OrthoManipulator(osgViewer::Viewer* viewer, osg::Node* root);
	virtual ~OrthoManipulator(void);
	virtual void setHomePosition(const osg::Vec3d& center);
	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 );
	const double& getScaleRation();
	const osg::Vec3d& getEye();
	void setEye(osg::Vec3d& eye);
	void home(double);
protected:
	void updateOrthoProject();
	void zoomOn(const osgGA::GUIEventAdapter& ea);
	void addMouseEvent(const osgGA::GUIEventAdapter& ea);
	void flushMouseEventStack();
	osg::BoundingBox computeCloudCenter();
private:
	osg::Vec3d _eye;
	osgViewer::Viewer* _viewer;
	osg::Node* _root;
	double _scaleRatio;
	double _zoom_radio;
	osg::ref_ptr< const osgGA::GUIEventAdapter > _ga_t1;
	osg::ref_ptr< const osgGA::GUIEventAdapter > _ga_t0;
};

inline const double& OrthoManipulator::getScaleRation() { return _scaleRatio; }
inline const osg::Vec3d& OrthoManipulator::getEye() { return _eye; }
}

#endif
#include "OrthoManipulator.h"
#include 
#include "XPCLDrawable.h"

using namespace osgGA;

OrthoManipulator::OrthoManipulator(osgViewer::Viewer* viewer, osg::Node* root)
	: _viewer(viewer), _scaleRatio(1.0)
	, _zoom_radio(0.9), _root(root), _eye(0, 0, 1000)
{
	setName("ortho");
}


OrthoManipulator::~OrthoManipulator(void)
{
}


void OrthoManipulator::setByMatrix( const osg::Matrixd& matrix )
{
	
}

void OrthoManipulator::setByInverseMatrix( const osg::Matrixd& matrix )
{
	
}

osg::Matrixd OrthoManipulator::getMatrix() const
{
	return	osg::Matrix::translate(_eye);
}

osg::Matrixd OrthoManipulator::getInverseMatrix() const
{
	return osg::Matrixd::inverse(osg::Matrix::translate(_eye));
}

bool OrthoManipulator::handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us )
{
	if (ea.getHandled()) return false;

	if(ea.getEventType() == osgGA::GUIEventAdapter::FRAME)
	{
		updateOrthoProject();
	}
	if(ea.getEventType() == osgGA::GUIEventAdapter::SCROLL)
	{
		zoomOn(ea);
		return true;
	}
	if(ea.getEventType() == osgGA::GUIEventAdapter::PUSH)
	{
		flushMouseEventStack();
		addMouseEvent(ea);
		return true;
	}
	if(ea.getEventType() == osgGA::GUIEventAdapter::DRAG)
	{
		addMouseEvent(ea);

		if( _ga_t0.get() == NULL || _ga_t1.get() == NULL )
			return false;

		double deltaX = _ga_t1->getX() - _ga_t0->getX();
		double deltaY = _ga_t1->getY() - _ga_t0->getY();

		double transX = deltaX * _scaleRatio;
		double transY = deltaY * _scaleRatio;

		_eye += osg::Vec3d(transX, transY, 0);
		return true;
	}
	return false;
}

void OrthoManipulator::updateOrthoProject()
{
	int viewWidth = _viewer->getCamera()->getViewport()->width();
	int viewHeight = _viewer->getCamera()->getViewport()->height();

	double left = -double(viewWidth)/2.0 * _scaleRatio ;
	double right = double(viewWidth)* _scaleRatio + left;
	double bottom = double(-viewHeight)/2.0 *_scaleRatio;
	double top = double(viewHeight) * _scaleRatio + bottom;

	_viewer->getCamera()->setProjectionMatrixAsOrtho(left, right,
		bottom, top, -10000.0f, 10000.0f);
}

void OrthoManipulator::home( double )
{
	osg::BoundingBox bounding = computeCloudCenter();

	double xSize = bounding.xMax() - bounding.xMin();
	double ySize = bounding.yMax() - bounding.yMin();

	int viewWidth = _viewer->getCamera()->getViewport()->width();
	int viewHeight = _viewer->getCamera()->getViewport()->height();

	double maxSize = osg::maximum(xSize, ySize);
	double minWidth = osg::minimum(viewWidth,viewHeight);
	double ratio = maxSize/double(minWidth);

	_scaleRatio = ratio;
	_eye = bounding.center() + osg::Vec3d(0, 0, 1000);
}

void OrthoManipulator::zoomOn( const osgGA::GUIEventAdapter& ea )
{
	osgGA::GUIEventAdapter::ScrollingMotion sm = ea.getScrollingMotion();
	double zoom_radio = sm == osgGA::GUIEventAdapter::SCROLL_UP ? _zoom_radio : 1.0 / _zoom_radio;
	double ratio_ = _scaleRatio * zoom_radio;

	int viewWidth = _viewer->getCamera()->getViewport()->width();
	int viewHeight = _viewer->getCamera()->getViewport()->height();

	double x = ea.getX();
	double y = ea.getY();

	double transX =  (ea.getX() - viewWidth / 2 ) * _scaleRatio * (1 - zoom_radio);
	double transY =  (ea.getY() - viewHeight / 2 ) * _scaleRatio * (1 - zoom_radio);

	_eye += osg::Vec3d(transX, transY, 0);

	_scaleRatio = ratio_;
}

void OrthoManipulator::addMouseEvent( const osgGA::GUIEventAdapter& ea )
{
	_ga_t1 = _ga_t0;
	_ga_t0 = &ea;
}

void OrthoManipulator::flushMouseEventStack()
{
	_ga_t1 = 0L;
	_ga_t0 = 0L;
}

void OrthoManipulator::setHomePosition( const osg::Vec3d& center )
{
	_scaleRatio = 0.2;
	_eye = center + osg::Vec3d(0, 0, 50);
}

void OrthoManipulator::setEye(osg::Vec3d& eye)
{
	_eye = eye;
}

osg::BoundingBox osgGA::OrthoManipulator::computeCloudCenter()
{
	FindPCLDrawableVistor fpclv;
	osg::BoundingBox bounding;

	_root->accept(fpclv);
	std::vector pcls = fpclv.getPCLDrawableList();
	if (pcls.empty())
	{
		osg::BoundingSphere sphere = _root->getBound();
		sphere.radius() = osg::maximum(sphere.radius(), 100.0f);
		bounding.expandBy(sphere);
	}
	else
	{
		for (std::vector::iterator itr = pcls.begin(); itr != pcls.end(); itr++)
		{
			CXPCLDrawable* pcl = *itr;
			osg::BoundingSphere sphere = pcl->getBound();
			bounding.expandBy(sphere);
		}
	}
	return bounding;
}


 
  

 
 

你可能感兴趣的:(c++技术文章,计算机图形学)