一、效果演示
demo
二、逻辑分析
利用osg的主从视图osgViewer::CompositeViewer,实现从视图实时显示主视图的相机在空间中的坐标位置变化;
首先获取主视图的相机逆矩阵,也就是相机的矩阵
osg::Matrixd masterViewMat =viewMaster->getCamera()->getInverseViewMatrix();
从相机的矩阵中获取当前的旋转的四元数
osg::Quat masterR = masterViewMat.getRotate();
再获取当前的位置偏移量
osg::Vec3d masterT = masterViewMat.getTrans();
根据上述得到的参数,设置从视图的相机离中心点的位置为固定的值l,经过如下计算可得对应的变换矩阵
int l = 8;
osg::Vec3d newT = masterT * l / masterT.length();
osg::Matrixd mat = osg::Matrixd(osg::Matrixd::rotate(masterR) * osg::Matrixd::translate(newT));
最后设置到从视图
view1->getCameraManipulator()->setByMatrix(mat);
三、整体代码实现
#include <iostream>
#include <osg/Group>
#include <osg/MatrixTransform>
#include <osgDB/ReadFile>
#include <osgViewer/Viewer>
#include <osgViewer/CompositeViewer>
#include <osgGA/TrackballManipulator>
#include <osgGA/GUIEventAdapter>
using namespace std;
osg::ref_ptr<osgViewer::View> viewMaster;
osg::ref_ptr<osgViewer::View> view1;
osg::ref_ptr<osgViewer::CompositeViewer> CreateCompositeViewer();
//主函数入口
int main()
{
osg::ref_ptr<osgViewer::CompositeViewer> pComViewer = CreateCompositeViewer();
if(pComViewer)
{
pComViewer->run();
}
return 0;
}
class AxesEvent : public osgGA::GUIEventHandler
{
virtual bool handle(const osgGA::GUIEventAdapter&, osgGA::GUIActionAdapter&)
{
//屏蔽从视口的事件
return true;
}
};
class MasterViewEvent : public osgGA::GUIEventHandler
{
virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& ee)
{
(void)ee;
//拖拽时从视图的操作器视点位置要跟随主视图的位置变化
if(ea.getEventType() == osgGA::GUIEventAdapter::DRAG)
{
osg::Matrixd masterViewMat =viewMaster->getCamera()->getInverseViewMatrix();
osg::Quat masterR = masterViewMat.getRotate();
osg::Vec3d masterT = masterViewMat.getTrans();
//此处l为相机到视图场景中心点的直线距离
int l = 8;
osg::Vec3d newT = masterT * l / masterT.length();
osg::Matrixd mat = osg::Matrixd(osg::Matrixd::rotate(masterR)*
osg::Matrixd::translate(newT));
view1->getCameraManipulator()->setByMatrix(mat);
}
return false;
}
};
osg::ref_ptr<osgViewer::CompositeViewer> CreateCompositeViewer()
{
// osg::GraphicsContext::WindowingSystemInterface* pWsi
// = osg::GraphicsContext::getWindowingSystemInterface();
// if(!pWsi)
// {
// return pComViewer;
// }
// //获取桌面系统窗口分辨率
// unsigned int w, h;
// pWsi->getScreenResolution(osg::GraphicsContext::ScreenIdentifier(0), w, h);
osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
traits->x = 100;
traits->y = 100;
traits->width = 800;
traits->height = 600;
traits->windowDecoration = true;
traits->doubleBuffer = true;
traits->sharedContext = 0;
osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(traits);
if(!gc)
{
return nullptr;
}
gc->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
gc->setClearColor(osg::Vec4(1.0, 0.5, 0.5, 1));
osg::ref_ptr<osgViewer::CompositeViewer> pComViewer = new osgViewer::CompositeViewer;
//创建主视图
viewMaster = new osgViewer::View;
viewMaster->setName("Master");
pComViewer->addView(viewMaster.get());
viewMaster->setSceneData(osgDB::readNodeFile("cow.osg"));
viewMaster->getCamera()->setViewport(new osg::Viewport(0, 0, traits->width, traits->height));
viewMaster->getCamera()->setGraphicsContext(gc);
viewMaster->getCamera()->setClearMask(GL_COLOR_BUFFER_BIT);
viewMaster->getCamera()->setClearColor(osg::Vec4(0.5, 0.5, 0.5, 1));
viewMaster->setCameraManipulator(new osgGA::TrackballManipulator);
viewMaster->addEventHandler(new MasterViewEvent);
//创建从视图
view1 = new osgViewer::View;
view1->setName("view1");
pComViewer->addView(view1.get());
view1->setSceneData(osgDB::readNodeFile("axes.osgt"));
view1->getCamera()->setViewport(new osg::Viewport(0, 0, 300, 300));
view1->getCamera()->setClearMask(GL_DEPTH_BUFFER_BIT);
view1->getCamera()->setGraphicsContext(gc);
view1->setCameraManipulator(new osgGA::TrackballManipulator);
view1->addEventHandler(new AxesEvent);
return pComViewer;
}