数字地球程序框架搭建(三)

使用vs2015建立MFC单文档程序,记得添加包含目录、库目录以及附加依赖项。

关键代码如下:

DigitalEarthView.h

cpp 复制代码
// 这段 MFC 示例源代码演示如何使用 MFC Microsoft Office Fluent 用户界面 
// ("Fluent UI")。该示例仅供参考,
// 用以补充《Microsoft 基础类参考》和 
// MFC C++ 库软件随附的相关电子文档。
// 复制、使用或分发 Fluent UI 的许可条款是单独提供的。
// 若要了解有关 Fluent UI 许可计划的详细信息,请访问  
// http://msdn.microsoft.com/officeui。
//
// 版权所有(C) Microsoft Corporation
// 保留所有权利。

// 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:

// 实现
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

DigitalEarthView.cpp

cpp 复制代码
// 这段 MFC 示例源代码演示如何使用 MFC Microsoft Office Fluent 用户界面 
// ("Fluent UI")。该示例仅供参考,
// 用以补充《Microsoft 基础类参考》和 
// MFC C++ 库软件随附的相关电子文档。
// 复制、使用或分发 Fluent UI 的许可条款是单独提供的。
// 若要了解有关 Fluent UI 许可计划的详细信息,请访问  
// http://msdn.microsoft.com/officeui。
//
// 版权所有(C) Microsoft Corporation
// 保留所有权利。

// 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_WM_CONTEXTMENU()
	ON_WM_RBUTTONUP()
    ON_WM_CREATE()
    ON_WM_ERASEBKGND()
    ON_WM_DESTROY()
END_MESSAGE_MAP()

// CDigitalEarthView 构造/析构

CDigitalEarthView::CDigitalEarthView()
{
	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: 在此处为本机数据添加绘制代码
}

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 诊断

#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


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

OSGObject.h

cpp 复制代码
#pragma once

#include <osgViewer/Viewer>
#include <osgDB/ReadFile>
#include <osgViewer/api/win32/GraphicsWindowWin32>
#include <osgGA/TrackballManipulator>

class COSGObject
{
public:
    COSGObject(HWND hWnd);
    ~COSGObject(void);

    void InitOSG();
    void InitSceneGraph();
    void InitCameraConfig();
    void PreFrameUpdate();
    void PostFrameUpdate();
    static void Render(void * ptr);

    osgViewer::Viewer *getViewer();
private:
    HWND m_hWnd;
    osgViewer::Viewer * mViewer;
    osg::ref_ptr<osg::Group> mRoot;

};

OSGObject.cpp

cpp 复制代码
#include "StdAfx.h"
#include "OSGObject.h"


COSGObject::COSGObject(HWND hWnd)
{
    m_hWnd = hWnd;
}


COSGObject::~COSGObject(void)
{
}

void COSGObject::InitOSG()
{
    InitSceneGraph();
    InitCameraConfig();

}

void COSGObject::InitSceneGraph()
{
    mRoot = new osg::Group;
	//mRoot->addChild(osgDB::readNodeFile("clock.osgt"));
    mRoot->addChild(osgDB::readNodeFile("D:/Project/OSG/bili35/builder/earthfile/china-simple.earth"));
    //mRoot->addChild(osgDB::readNodeFile("D:/Project/OSG/bili35/DemoCode/老路径/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);
	traits->x = 0;
	traits->y = 0;
    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;
}

有图有真相,程序运行效果如下图所示:


这个章节,主要遇到的问题有两个:

1.osg加载的模型或地球不显示,设置了法线和光源都不行;

2.osg加载的模型或地球显示的位置往上偏了。

问题的解决已经在代码注释中了。

相关推荐
长沙红胖子Qt16 天前
OSG开发笔记(三十二):深入理解相机视口、制作支持与主视图同步变换旋转的相机HUD
qt·osg·三维开发·hud相机·前景hud旋转坐标
长沙红胖子Qt2 个月前
项目实战:Qt+OSG爆破动力学仿真三维引擎测试工具v1.1.0(加载.K模型,子弹轨迹模拟动画,支持windows、linux、国产麒麟系统)
qt·osg·动力三维仿真·三维.k文件解析
charlee443 个月前
CMake构建学习笔记10-OsgQt库的构建
c++·qt·学习·cmake·构建·osg
bdbox@qq.com8 个月前
关于OSGConv转换osgb为obj时,无法指定输出贴图路径的问题及解决
c++·贴图·实景三维·osg·倾斜摄影·osgb
PHP代码9 个月前
osg qt5.15 osg3.6.3 osgEarth3.1 编译爬山
开发语言·qt·osg
荆楚闲人10 个月前
CMake生成osg的FFMPEG插件及Windows下不生成VS工程问题解决
ffmpeg·osg
bcbobo21cn1 年前
OSG读取和添加节点学习
node·osg
杨石兴1 年前
lesson01-在osgEarth上实时的贴地显示无人机或卫星传回的图片
osgearth·osg
欧特克_Glodon1 年前
OSG编程指南<十七>:OSG光照与材质
材质·osg·osg光照·osg材质