OsgEarth 设计的思想介绍
我们知道,我们站在某一个地方看眼前的世界,我们看到的东西其实是眼前的3维世界在我们眼球上的投影,
OsgEarth或者 Osg在电脑的屏幕上的显示也是类似,其实就是世界在一个摄像头上的投影,然后再将这个投影缩放到我们的窗口中。
我们的眼睛不能360度上下左右无死角的看,所以会有一些限制,也不能无限的看到最远方,所以也有距离限制。
所以我们为了让一个窗口显示3维世界,就需要设置2方面的参数
1.Camera自身的属性
2.Camera与要显示窗口的比例关系
Osg对去们要显示的进行了一个抽象化,其一个世界就一个viewer,世界里有什么,就给Viewer对易用中加入就行,但怎么看,或者看到的是什么就由其viewer下的Camera来决定了。
在平时用mfc或duilib来开发的时候,都是按标准的流程来做。
1.首先New 一个Camera,
2.根据需要设置相关参数和绑定的窗口参数
3.参数与Camera绑定
4.视置Camera的视角信息
5.将Camera加入到Viewer中或增加其从Camera
6.调用realize对其进行才上的参数进行初始化(一般调用于帧渲染前)
7.帧渲染前
完整代码如下:
bool CUtils3dEngine::Init(HWND hWnd, const char* pStrEarthFile)
{
bool isok = false;
do
{
m_root = new osg::Group();
if (!m_root.valid())
{
break;
}
m_SenceGroup = new osg::Group();
if (!m_SenceGroup.valid())
{
break;
}
m_root->addChild(m_SenceGroup);
m_EarthNode = osgDB::readNodeFile(pStrEarthFile);
m_root->addChild(m_EarthNode.get());
RECT rect;
::GetClientRect(hWnd, &rect);
osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
osg::ref_ptr<osg::Referenced> windata = new osgViewer::GraphicsWindowWin32::WindowData(hWnd);
if (!traits.valid() || !windata.valid())
{
break;
}
traits->x = 0;
traits->y = 50;
traits->width = rect.right - rect.left - 0;
traits->height = rect.bottom - rect.top - 0;
traits->windowDecoration = false;
traits->doubleBuffer = true;
traits->sharedContext = 0;
traits->setInheritedWindowPixelFormat = true;
traits->inheritedWindowData = windata;
osg::ref_ptr<osg::GraphicsContext> pGC = osg::GraphicsContext::createGraphicsContext(traits);
osg::ref_ptr<osg::Camera> camera = new osg::Camera;
if (!camera.valid())
{
break;
}
camera->setGraphicsContext(pGC.get());
traits->x = 0;
traits->y = 0;
osg::ref_ptr<osg::Viewport> vieport = new osg::Viewport(traits->x, traits->y, traits->width, traits->height);
camera->setViewport(vieport.get());
camera->setProjectionMatrixAsPerspective(30.0f, static_cast<double>(traits->width) / static_cast<double>(traits->height), 1.0f, 1000.0f);
m_Viewer = new osgViewer::Viewer();
if (!m_Viewer.valid())
{
break;
}
m_Viewer->setCamera(camera.get());
m_Viewer->setSceneData(m_root.get());
m_Viewer->realize();
m_em = new osgEarth::Util::EarthManipulator;
if (!m_em.valid())
{
break;
}
m_em->setNode(m_EarthNode.get());
m_em->getSettings()->setArcViewpointTransitions(true);
m_Viewer->setCameraManipulator(m_em.get());
isok = true;
} while (0);
return isok;
}