MFC下的第一个osg程序

MFC下的第一个osg程序
MFC下的osg程序的关键是创建一个渲染上下文。

以我的程序VirtualHand为例。

首先创建一个多窗口的MFC程序。

MainFrm.h



// MainFrm.h : interface of the CMainFrame class
//


#pragma once

class CMainFrame : public CMDIFrameWnd
{
DECLARE_DYNAMIC(CMainFrame)
public:
CMainFrame();

// Attributes
public:

// Operations
public:

// Overrides
public:
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);

// Implementation
public:
virtual ~CMainFrame();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif

protected: // control bar embedded members
CStatusBar m_wndStatusBar;
CToolBar m_wndToolBar;
CReBar m_wndReBar;
CDialogBar m_wndDlgBar;

// Generated message map functions
protected:
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnTimer(UINT nIDEvent);
DECLARE_MESSAGE_MAP()
};



MFC_OSG.h

#pragma once

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

class cOSG
{
public:
cOSG(HWND hWnd);
~cOSG();

void InitOSG(std::string filename);
void InitManipulators(void);
void InitSceneGraph(void);
void InitCameraConfig(void);
void SetupWindow(void);
void SetupCamera(void);
void PreFrameUpdate(void);
void PostFrameUpdate(void);
void Done(bool value) { mDone = value; }
bool Done(void) { return mDone; }
static void Render(void* ptr);

osgViewer::Viewer* getViewer() { return mViewer; }

private:
bool mDone;
std::string m_ModelName;
HWND m_hWnd;
osgViewer::Viewer* mViewer;
osg::ref_ptr mRoot;
osg::ref_ptr mModel;
osg::ref_ptr trackball;
osg::ref_ptr keyswitchManipulator;
};



VirtualHand.h

// VirtualHandDoc.h : interface of the CVirtualHandDoc class
//


#pragma once


class CVirtualHandDoc : public CDocument
{
protected: // create from serialization only
CVirtualHandDoc();
DECLARE_DYNCREATE(CVirtualHandDoc)

// Attributes
public:

// Operations
public:

// Overrides
public:
virtual void Serialize(CArchive& ar);
virtual BOOL OnOpenDocument(LPCTSTR lpszPathName);
CString GetFileName() const { return m_csFileName; }

// Implementation
public:
virtual ~CVirtualHandDoc();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif

protected:
CString m_csFileName;

// Generated message map functions
protected:

DECLARE_MESSAGE_MAP()
};



VirtualHandView.h

// VirtualHandView.h : interface of the CVirtualHandView class
//
#pragma once

#include "MFC_OSG.h"

class CVirtualHandView : public CView
{
protected: // create from serialization only
CVirtualHandView();
DECLARE_DYNCREATE(CVirtualHandView)

// Attributes
public:
CVirtualHandDoc* GetDocument() const;

// Operations
public:

// Overrides
public:
virtual void OnDraw(CDC* pDC); // overridden to draw this view
virtual void OnInitialUpdate();
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
protected:

// Implementation
public:
virtual ~CVirtualHandView();
#ifdef _DEBUG
virtual void AssertValid() const;
virtual void Dump(CDumpContext& dc) const;
#endif

protected:
cOSG* mOSG;
HANDLE mThreadHandle;

// Generated message map functions
protected:
DECLARE_MESSAGE_MAP()

afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnDestroy();
afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
};

#ifndef _DEBUG // debug version in VirtualHandView.cpp
inline CVirtualHandDoc* CVirtualHandView::GetDocument() const
{ return reinterpret_cast(m_pDocument); }
#endif



MFC_OSG.cpp

// MFC_OSG.cpp : implementation of the cOSG class
//
#include "stdafx.h"
#include "MFC_OSG.h"


cOSG::cOSG(HWND hWnd) :
m_hWnd(hWnd)
{
}

cOSG::~cOSG()
{
mViewer->setDone(true);
Sleep(1000);
mViewer->stopThreading();

delete mViewer;
}

void cOSG::InitOSG(std::string modelname)
{
// Store the name of the model to load
m_ModelName = modelname;

// Init different parts of OSG
InitManipulators();
InitSceneGraph();
InitCameraConfig();
}

void cOSG::InitManipulators(void)
{
// Create a trackball manipulator
trackball = new osgGA::TrackballManipulator();

// Create a Manipulator Switcher
keyswitchManipulator = new osgGA::KeySwitchMatrixManipulator;

// Add our trackball manipulator to the switcher
keyswitchManipulator->addMatrixManipulator( '1', "Trackball", trackball.get());

// Init the switcher to the first manipulator (in this case the only manipulator)
keyswitchManipulator->selectMatrixManipulator(0); // Zero based index Value
}


void cOSG::InitSceneGraph(void)
{
// Init the main Root Node/Group
mRoot = new osg::Group;

// Load the Model from the model name
mModel = osgDB::readNodeFile(m_ModelName);

// Optimize the model
osgUtil::Optimizer optimizer;
optimizer.optimize(mModel.get());
optimizer.reset();

// Add the model to the scene
mRoot->addChild(mModel.get());
}

void cOSG::InitCameraConfig(void)
{
// Local Variable to hold window size data
RECT rect;

// Create the viewer for this window
mViewer = new osgViewer::Viewer();


// Add a Stats Handler to the viewer
mViewer->addEventHandler(new osgViewer::StatsHandler);

// Get the current window size
::GetWindowRect(m_hWnd, &rect);

// Init the GraphicsContext Traits
osg::ref_ptr traits = new osg::GraphicsContext::Traits;

// Init the Windata Variable that holds the handle for the Window to display OSG in.
osg::ref_ptr windata = new osgViewer::GraphicsWindowWin32::WindowData(m_hWnd);

// Setup the traits parameters
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;

// Create the Graphics Context
osg::GraphicsContext* gc = osg::GraphicsContext::createGraphicsContext(traits.get());

// Init a new Camera (Master for this View)
osg::ref_ptr camera = new osg::Camera;

// Assign Graphics Context to the Camera
camera->setGraphicsContext(gc);

// Set the viewport for the Camera
camera->setViewport(new osg::Viewport(traits->x, traits->y, traits->width, traits->height));

// Add the Camera to the Viewer
mViewer->addSlave(camera.get());

// Add the Camera Manipulator to the Viewer
mViewer->setCameraManipulator(keyswitchManipulator.get());

// Set the Scene Data
mViewer->setSceneData(mRoot.get());

// Realize the Viewer
mViewer->realize();
}

void cOSG::PreFrameUpdate()
{
// Due any preframe updates in this routine
}

void cOSG::PostFrameUpdate()
{
// Due any postframe updates in this routine
}

void cOSG::Render(void* ptr)
{
cOSG* osg = (cOSG*)ptr;

osgViewer::Viewer* viewer = osg->getViewer();

// You have two options for the main viewer loop
// viewer->run() or
// while(!viewer->done()) { viewer->frame(); }

//viewer->run();
while(!viewer->done())
{
osg->PreFrameUpdate();
viewer->frame();
osg->PostFrameUpdate();
//Sleep(10); // Use this command if you need to allow other processes to have cpu time
}

// For some reason this has to be here to avoid issue:
// if you have multiple OSG windows up
// and you exit one then all stop rendering
AfxMessageBox("Exit Rendering Thread");

_endthread();
}

VirtualHandDoc.cpp

// VirtualHandDoc.cpp : implementation of the CVirtualHandDoc class
//

#include "stdafx.h"
#include "VirtualHand.h"

#include "VirtualHandDoc.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// CVirtualHandDoc

IMPLEMENT_DYNCREATE(CVirtualHandDoc, CDocument)

BEGIN_MESSAGE_MAP(CVirtualHandDoc, CDocument)
END_MESSAGE_MAP()


// CVirtualHandDoc construction/destruction

CV

irtualHandDoc::CVirtualHandDoc()
{
}

CVirtualHandDoc::~CVirtualHandDoc()
{
}

BOOL CVirtualHandDoc::OnOpenDocument(LPCTSTR lpszPathName)
{
m_csFileName = lpszPathName;

if (!CDocument::OnOpenDocument(lpszPathName))
return FALSE;

return TRUE;
}


// CVirtualHandDoc serialization

void CVirtualHandDoc::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
// TODO: add storing code here
}
else
{
// TODO: add loading code here
}
}


// CVirtualHandDoc diagnostics

#ifdef _DEBUG
void CVirtualHandDoc::AssertValid() const
{
CDocument::AssertValid();
}

void CVirtualHandDoc::Dump(CDumpContext& dc) const
{
CDocument::Dump(dc);
}
#endif //_DEBUG


// CVirtualHandDoc commands

VirtualHandView.cpp

// VirtualHandView.cpp : implementation of the CVirtualHandView class
//

#include "stdafx.h"
#include "VirtualHand.h"
#include "VirtualHandDoc.h"
#include "VirtualHandView.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


IMPLEMENT_DYNCREATE(CVirtualHandView, CView)

BEGIN_MESSAGE_MAP(CVirtualHandView, CView)
ON_WM_CREATE()
ON_WM_DESTROY()
ON_WM_KEYDOWN()
ON_WM_ERASEBKGND()
END_MESSAGE_MAP()

CVirtualHandView::CVirtualHandView() :
mOSG(0L)
{
}

CVirtualHandView::~CVirtualHandView()
{
}

BOOL CVirtualHandView::PreCreateWindow(CREATESTRUCT& cs)
{
return CView::PreCreateWindow(cs);
}

void CVirtualHandView::OnDraw(CDC* /*pDC*/)
{
CVirtualHandDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
}

#ifdef _DEBUG
void CVirtualHandView::AssertValid() const
{
CView::AssertValid();
}

void CVirtualHandView::Dump(CDumpContext& dc) const
{
CView::Dump(dc);
}

CVirtualHandDoc* CVirtualHandView::GetDocument() const // non-debug version is inline
{
ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CVirtualHandDoc)));
return (CVirtualHandDoc*)m_pDocument;
}
#endif //_DEBUG


int CVirtualHandView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
// Let MFC create the window before OSG
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;

// Now that the window is created setup OSG
mOSG = new cOSG(m_hWnd);

return 1;
}

void CVirtualHandView::OnDestroy()
{
if(mOSG != 0) delete mOSG;

WaitForSingleObject(mThreadHandle, 1000);

CView::OnDestroy();
}

void CVirtualHandView::OnInitialUpdate()
{
CView::OnInitialUpdate();

// Get Filename from DocumentOpen Dialog
CString csFileName = GetDocument()->GetFileName();

// Init the osg class
mOSG->InitOSG(csFileName.GetString());

// Start the thread to do OSG Rendering
mThreadHandle = (HANDLE)_beginthread(&cOSG::Render, 0, mOSG);
}

void CVirtualHandView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// Pass Key Presses into OSG
mOSG->getViewer()->getEventQueue()->keyPress(nChar);

//

Close Window on Escape Key
if(nChar == VK_ESCAPE)
{
GetParent()->SendMessage(WM_CLOSE);
}
}


BOOL CVirtualHandView::OnEraseBkgnd(CDC* pDC)
{
/* Do nothing, to avoid flashing on MSW */
return true;
}

其他的代码不需要改动,这样,编译运行,第一个osgMFC程序就诞生了。


相关文档
最新文档