OpenSceneGraph之一:CWnd中显示

OpenSceneGraph之一:封装osg到CWnd子类中

        上周刚接到一任务,需要对室内装修进行三维模拟,然后就想到了OpenSceneGraph,以前了解过OpenSceneGraph,但从来没编程实现过什么内容,今天打算继承一个CWnd类,在该类中渲染场景,用google检索了下,基本没有,但还有OpenSceneGraph自带了一个多文档的例子,看了下例子,然后就试了试,随便记录下。

        其实蛮简单的,先在Win32下测试了一个例子:

int main(int , char **)
{
    osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer;

    viewer->setSceneData( osgDB::readNodeFile( "D:\\cessna.osg" ) );

    return viewer->run();
}


结果死活没有出现飞机模型,只有背景颜色,显示读取文件错误,郁闷呀。试了试编译好的osgviewer.exe显示,一切正常;发现在bin目录下osgPlugins-3.0.0文件夹,内有多个DLL,感觉应该是DLL的问题,拷贝过去,显示正常。结果如下:

 

OpenSceneGraph之一:CWnd中显示_第1张图片

        正常后,接着生成  class osgWnd : public CWnd,然后再OnCreate中添加如下代码: 

         ::GetWindowRect(m_hWnd, &rect);         

         osg::ref_ptr<osg::Referenced> m_Windata = new osgViewer::GraphicsWindowWin32::WindowData(this->m_hWnd);
	osg::ref_ptr<osg::GraphicsContext::Traits> m_Traits  = new osg::GraphicsContext::Traits;
	m_Traits->x = 0;
	m_Traits->y = 0;
	m_Traits->width = rect.right - rect.left;
	m_Traits->height= rect.bottom - rect.top;
	m_Traits->windowDecoration = false;
	m_Traits->doubleBuffer=true;
	m_Traits->inheritedWindowData = m_Windata;

	osg::ref_ptr<osg::GraphicsContext> m_Gcontext = osg::GraphicsContext::createGraphicsContext(m_Traits.get());

	osg::ref_ptr<osg::Camera> m_Camera = new osg::Camera;
	m_Camera->setGraphicsContext(m_Gcontext);
	m_Camera->setViewport(new osg::Viewport(m_Traits->x, m_Traits->y, m_Traits->width, m_Traits->height));

	m_Viewer = new osgViewer::Viewer;
	m_Viewer->addSlave(m_Camera.get());
	m_Viewer->setSceneData(osgDB::readNodeFile("D:\\cessna.osg"));
	m_Viewer->setCameraManipulator(new osgGA::TrackballManipulator);
	m_Viewer->setThreadingModel(osgViewer::Viewer::SingleThreaded);


        这部分和MFC中使用OpenGL中切换上下文功能相同。

         然后在OnPaint中添加:

void osgWnd::OnPaint()
{
	CPaintDC dc(this); // device context for painting
	if(m_Viewer != 0) {
		m_Viewer->frame();
	}	
}


      关键内容就这些吧!

     最后贴出完整代码:

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

class osgWnd : public CWnd
{
	DECLARE_DYNAMIC(osgWnd)

public:
	osgWnd(CWnd *parent);
	virtual ~osgWnd();

	osg::ref_ptr<osgViewer::Viewer> m_Viewer;
	osg::ref_ptr<osg::Referenced> m_Windata;
	osg::ref_ptr<osg::GraphicsContext::Traits> m_Traits;
	osg::ref_ptr<osg::GraphicsContext> m_Gcontext;
	osg::ref_ptr<osg::Camera> m_Camera;

protected:
	DECLARE_MESSAGE_MAP()
public:
	afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
	afx_msg void OnDestroy();
	afx_msg void OnPaint();
};
// osgWnd

IMPLEMENT_DYNAMIC(osgWnd, CWnd)

osgWnd::osgWnd(CWnd *parent) :
m_finished(false)
{

}

osgWnd::~osgWnd()
{
	m_Viewer->setDone(true);
	while(!m_finished) Sleep(10);


	delete m_Viewer;
	//delete m_Windata;
	//delete m_Traits;
	//delete m_Gcontext;
	//delete m_Camera;
}


BEGIN_MESSAGE_MAP(osgWnd, CWnd)
	ON_WM_CREATE()
	ON_WM_DESTROY()
	ON_WM_PAINT()
END_MESSAGE_MAP()



// osgWnd message handlers



int osgWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CWnd::OnCreate(lpCreateStruct) == -1)
		return -1;

	// TODO:  Add your specialized creation code here

	osg::ref_ptr<osg::Referenced> m_Windata = new osgViewer::GraphicsWindowWin32::WindowData(this->m_hWnd);
	osg::ref_ptr<osg::GraphicsContext::Traits> m_Traits  = new osg::GraphicsContext::Traits;
	m_Traits->x = 0;
	m_Traits->y = 0;
	m_Traits->width = rect.right - rect.left;
	m_Traits->height= rect.bottom - rect.top;
	m_Traits->windowDecoration = false;
	m_Traits->doubleBuffer=true;
	m_Traits->inheritedWindowData = m_Windata;

	osg::ref_ptr<osg::GraphicsContext> m_Gcontext = osg::GraphicsContext::createGraphicsContext(m_Traits.get());

	osg::ref_ptr<osg::Camera> m_Camera = new osg::Camera;
	m_Camera->setGraphicsContext(m_Gcontext);
	m_Camera->setViewport(new osg::Viewport(m_Traits->x, m_Traits->y, m_Traits->width, m_Traits->height));

	m_Viewer = new osgViewer::Viewer;
	m_Viewer->addSlave(m_Camera.get());
	m_Viewer->setSceneData(osgDB::readNodeFile("D:\\cessna.osg"));
	m_Viewer->setCameraManipulator(new osgGA::TrackballManipulator);
	m_Viewer->setThreadingModel(osgViewer::Viewer::SingleThreaded);

	return 0;
}

void osgWnd::OnDestroy()
{
	CWnd::OnDestroy();

	// TODO: Add your message handler code here
}

void osgWnd::OnPaint()
{
	CPaintDC dc(this); // device context for painting
	// TODO: Add your message handler code here
	// Do not call CWnd::OnPaint() for painting messages

	if(m_Viewer != 0) {
		m_Viewer->frame();
	}


	
}

 

 贴出来的过程中,精简了下,并有内存泄露的问题。

下一步就要分离窗口类和模型了。





   

你可能感兴趣的:(OpenSceneGraph之一:CWnd中显示)