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;
}