osg中没有正交视图的控制器,但是我们经常会遇到2D的项目应用,我也不知道如何申请成为osg社区的会员,就写在这里,以免忘掉,拿去不谢.
#ifndef OSGGA_ORTHO_MANIPULATOR
#define OSGGA_ORTHO_MANIPULATOR 1
#include <osgGA\StandardManipulator>
#include <osg\BoundingBox>
#include <osgViewer\Viewer>
#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 <osg\Math> #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<CXPCLDrawable *> 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<CXPCLDrawable *>::iterator itr = pcls.begin(); itr != pcls.end(); itr++) { CXPCLDrawable* pcl = *itr; osg::BoundingSphere sphere = pcl->getBound(); bounding.expandBy(sphere); } } return bounding; }