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

使用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加载的模型或地球显示的位置往上偏了。

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

相关推荐
扶尔魔ocy18 天前
【qt openGL入门笔记】windows编译MinGW版本的osgearth(2.10.1)
qt·opengl·osg
扶尔魔ocy19 天前
【QT OpenGL】知识点编目及传送门
qt·opengl·osg
扶尔魔ocy1 个月前
【qt openGL入门笔记】OSG实现飞机模型在网格图上飞行并进行态势标绘(四)
qt·opengl·osg
扶尔魔ocy1 个月前
【qt openGL入门笔记】OSG实现显示飞机模型飞行的点迹(二)
qt·opengl·osg
扶尔魔ocy1 个月前
【qt openGL入门笔记】OSG实现飞机模型在网格图上飞行(三)
opengl·osg
扶尔魔ocy1 个月前
【qt openGL入门笔记】OSG实现飞机模型在网格图上飞行
qt·opengl·osg
directx3d_beginner9 个月前
10,cookbook的lod示例
osg
directx3d_beginner9 个月前
8,将0级简模文件和精模文件同时放入pagedlod
osg
directx3d_beginner9 个月前
9,0级建模文件和0级精模文件写成根节点
osg
directx3d_beginner9 个月前
5,保存4个一级节点
osg