版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/github_39611196/article/details/87706102
本文主要介绍基于MFC创建osgEarth桌面端程序。
1、新建MFC应用程序DigitalEarth,选择单个文档。
2、实现osgEarth相关功能。
2.1、创建OSGObject.h文件,输入如下代码:
#pragma once
#include <osgViewer/Viewer>
#include <osgDB/ReadFile>
#include <osgViewer/api/win32/GraphicsWindowWin32>
#include <osgGA/TrackballManipulator>
#include <osgEarth/MapNode>
#include <osgEarthUtil/EarthManipulator>
//#include <osgEarthUtil/SkyNode>
class COSGObject
{
public:
COSGObject(HWND hWnd);
~COSGObject(void);
void InitOSG();
void InitSceneGraph();
void InitCameraConfig();
void PreFrameUpdate();
void PostFrameUpdate();
static void Render(void * ptr);
void InitOsgEarth();
osgViewer::Viewer *getViewer();
private:
HWND m_hWnd;
osgViewer::Viewer * mViewer;
osg::ref_ptr<osg::Group> mRoot;
osg::ref_ptr<osgEarth::MapNode> mapNode;
osg::ref_ptr<osgEarth::Util::EarthManipulator> em;
};
2.2、创建OSGObject.cpp,输入如下代码:
#include "StdAfx.h"
#include "OSGObject.h"
COSGObject::COSGObject(HWND hWnd)
{
m_hWnd = hWnd;
}
COSGObject::~COSGObject(void)
{
}
void COSGObject::InitOSG()
{
InitSceneGraph();
InitCameraConfig();
InitOsgEarth();
}
void COSGObject::InitSceneGraph()
{
mRoot = new osg::Group;
osg::ref_ptr<osg::Node> mp = osgDB::readNodeFile("arcgisonline.earth");
mRoot->addChild(mp);
mapNode = dynamic_cast<osgEarth::MapNode*>(mp.get());
//mRoot->addChild(osgDB::readNodeFile("H:/002.OpenSceneGraph/019.Earth/003.第三讲-VPB用法详解与常见问题处理/vpbtest/TestCommon10/output.ive"));
}
void COSGObject::InitCameraConfig()
{
RECT rect;
mViewer = new osgViewer::Viewer;
::GetWindowRect(m_hWnd, &rect);
osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
osg::ref_ptr<osg::Referenced> windata = new osgViewer::GraphicsWindowWin32::WindowData(m_hWnd);
traits->x = 0;
traits->y = 0;
traits->width = rect.right - rect.left;
traits->height = rect.bottom - rect.top;
traits->windowDecoration = false;
traits->doubleBuffer = true;
traits->sharedContext = 0;
traits->setInheritedWindowPixelFormat = true;
traits->inheritedWindowData = windata;
osg::GraphicsContext * gc = osg::GraphicsContext::createGraphicsContext(traits);
osg::ref_ptr<osg::Camera> camera = new osg::Camera;
camera->setGraphicsContext(gc);
camera->setViewport(new osg::Viewport(traits->x, traits->y, traits->width, traits->height));
camera->setProjectionMatrixAsPerspective(30.0f, static_cast<double>(traits->width) / static_cast<double>(traits->height), 1.0, 1000.0);
mViewer->setCamera(camera);
//mViewer->setCameraManipulator(new osgGA::TrackballManipulator);
mViewer->setSceneData(mRoot);
mViewer->realize();
mViewer->getCamera()->setComputeNearFarMode(osg::CullSettings::COMPUTE_NEAR_FAR_USING_PRIMITIVES);
mViewer->getCamera()->setNearFarRatio(0.000003f);
}
void COSGObject::PreFrameUpdate()
{
}
void COSGObject::PostFrameUpdate()
{
}
void COSGObject::Render(void * ptr)
{
COSGObject *osg = (COSGObject*)ptr;
osgViewer::Viewer * viewer = osg->getViewer();
while (!viewer->done())
{
osg->PreFrameUpdate();
viewer->frame();
osg->PostFrameUpdate();
}
_endthread();
}
osgViewer::Viewer *COSGObject::getViewer()
{
return mViewer;
}
void COSGObject::InitOsgEarth()
{
//初始化操作器
em = new osgEarth::Util::EarthManipulator;
if (mapNode.valid())
{
em->setNode(mapNode);
}
em->getSettings()->setArcViewpointTransitions(true);
mViewer->setCameraManipulator(em);
////初始化天空
//osgEarth::Config skyConf;
//double hours = skyConf.value("hours", 12.0);
//osg::ref_ptr<osgEarth::Util::SkyNode> sky_node = new osgEarth::Util::SkyNode(mapNode->getMap());
//sky_node->setDateTime(2012, 1, 27, hours);
//sky_node->attach(mViewer, 1);
//sky_node->setAmbientBrightness(1.0, mViewer);
//mRoot->addChild(sky_node);
}
三、将osgEarth程序运行结果在MFC文档视图中显示。
3.1、修改DigitalEarthView.h为如下代码:
// DigitalEarthView.h : CDigitalEarthView 类的接口
//
#pragma once
#include "DigitalEarthDoc.h"
#include "OSGObject.h"
class CDigitalEarthView : public CView
{
protected: // 仅从序列化创建
CDigitalEarthView();
DECLARE_DYNCREATE(CDigitalEarthView)
// 特性
public:
CDigitalEarthDoc* GetDocument() const;
public:
COSGObject* mOSG;
HANDLE mThreadHandle;
// 操作
public:
// 重写
public:
virtual void OnDraw(CDC* pDC); // 重写以绘制该视图
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
protected:
virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);
// 实现
public:
virtual ~CDigitalEarthView();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif
protected:
// 生成的消息映射函数
protected:
afx_msg void OnFilePrintPreview();
afx_msg void OnRButtonUp(UINT nFlags, CPoint point);
afx_msg void OnContextMenu(CWnd* pWnd, CPoint point);
DECLARE_MESSAGE_MAP()
public:
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
afx_msg void OnDestroy();
virtual void OnInitialUpdate();
};
#ifndef _DEBUG // DigitalEarthView.cpp 中的调试版本
inline CDigitalEarthDoc* CDigitalEarthView::GetDocument() const
{ return reinterpret_cast<CDigitalEarthDoc*>(m_pDocument); }
#endif
3.2、修改DigitalEarthView.cpp为如下代码:
// DigitalEarthView.cpp : CDigitalEarthView 类的实现
//
#include "stdafx.h"
// SHARED_HANDLERS 可以在实现预览、缩略图和搜索筛选器句柄的
// ATL 项目中进行定义,并允许与该项目共享文档代码。
#ifndef SHARED_HANDLERS
#include "DigitalEarth.h"
#endif
#include "DigitalEarthDoc.h"
#include "DigitalEarthView.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CDigitalEarthView
IMPLEMENT_DYNCREATE(CDigitalEarthView, CView)
BEGIN_MESSAGE_MAP(CDigitalEarthView, CView)
// 标准打印命令
ON_COMMAND(ID_FILE_PRINT, &CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CView::OnFilePrintPreview)
ON_WM_CONTEXTMENU()
ON_WM_RBUTTONUP()
ON_WM_CREATE()
ON_WM_ERASEBKGND()
ON_WM_DESTROY()
END_MESSAGE_MAP()
// CDigitalEarthView 构造/析构
CDigitalEarthView::CDigitalEarthView()
{
// TODO: 在此处添加构造代码
mOSG = 0;
mThreadHandle = 0;
}
CDigitalEarthView::~CDigitalEarthView()
{
}
BOOL CDigitalEarthView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: 在此处通过修改
// CREATESTRUCT cs 来修改窗口类或样式
return CView::PreCreateWindow(cs);
}
// CDigitalEarthView 绘制
void CDigitalEarthView::OnDraw(CDC* /*pDC*/)
{
CDigitalEarthDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
// TODO: 在此处为本机数据添加绘制代码
}
// CDigitalEarthView 打印
BOOL CDigitalEarthView::OnPreparePrinting(CPrintInfo* pInfo)
{
// 默认准备
return DoPreparePrinting(pInfo);
}
void CDigitalEarthView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: 添加额外的打印前进行的初始化过程
}
void CDigitalEarthView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: 添加打印后进行的清理过程
}
// CDigitalEarthView 诊断
#ifdef _DEBUG
void CDigitalEarthView::AssertValid() const
{
CView::AssertValid();
}
void CDigitalEarthView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}
CDigitalEarthDoc* CDigitalEarthView::GetDocument() const // 非调试版本是内联的
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CDigitalEarthDoc)));
return (CDigitalEarthDoc*)m_pDocument;
}
#endif //_DEBUG
void CDigitalEarthView::OnRButtonUp(UINT /* nFlags */, CPoint point)
{
ClientToScreen(&point);
OnContextMenu(this, point);
}
void CDigitalEarthView::OnContextMenu(CWnd* /* pWnd */, CPoint point)
{
#ifndef SHARED_HANDLERS
//theApp.GetContextMenuManager()->ShowPopupMenu(IDR_POPUP_EDIT, point.x, point.y, this, TRUE);
#endif
}
// CDigitalEarthView 消息处理程序
int CDigitalEarthView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
mOSG = new COSGObject(m_hWnd);
return 0;
}
BOOL CDigitalEarthView::OnEraseBkgnd(CDC* pDC)
{
if (0 == mOSG)
{
return CView::OnEraseBkgnd(pDC);
}
else
{
return FALSE;
}
return CView::OnEraseBkgnd(pDC);
}
void CDigitalEarthView::OnDestroy()
{
CView::OnDestroy();
if (mOSG != 0) delete mOSG;
WaitForSingleObject(mThreadHandle, 1000);
}
void CDigitalEarthView::OnInitialUpdate()
{
CView::OnInitialUpdate();
mOSG->InitOSG();
mThreadHandle = (HANDLE)_beginthread(&COSGObject::Render, 0, mOSG);
}
// CDigitalEarthView 消息处理程序