您的位置:首页 > 其它

一个简单的osg控件开发例子

2010-03-17 08:56 495 查看
作者:boqing

经常需要在对话框上添加osg的浏览功能,一开始是仿照osgviewerMFC的例子去写,可是每次在对话框上添加此功能的时候都要重复复制很多处代码,且位置和大小控制也不是很方便。因此写了个简单的OSG Active控件解决此问题。

开发工具:vc2005

OSG版本:osg2.2

具体开发步骤:

一 建立Active工程
项目类型选择:MFC,模板选择MFC ActiveX Control

下一步的向导中保持默认,点完成

二 配置viewer
定义viewer为成员函数

osg::ref_ptr<osgViewer::Viewer>viewer;

构造函数中初始化

viewer=new osgViewer::Viewer;

为了使得其能正常显示在拖动的空间中,大小和位置与拖出区域的大小和位置一致。编写configViewer函数

#include <osgViewer/api/win32/GraphicsWindowWin32>

void COSGControlCtrl::configViewer(HWND m_hWnd)

{

RECT rect;

//得到控件的大小

::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.get());

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

viewer.addSlave(camera.get());

}

三 添加自定义方法setSceneData
在类视图中展开OSGControlLib,右键单击_DOSGControl,选择添加->添加方法,按照下图进行填写

确定后,在类COSGControlCtrl的实现中添加以下代码:

void COSGControlCtrl::setSceneData(ULONG* data)

{

AFX_MANAGE_STATE(AfxGetStaticModuleState());

// TODO: Add your dispatch handler code here

if (!isSetSceneData)

{

configViewer(m_hWnd);

}

osg::Node *node=(osg::Node *)data;

viewer->setSceneData(node);

isSetSceneData=true;

}

isSetSceneData是类成员,构造函数中初始化为false,记录着是否曾经调用过viewer->setSceneData函数

四 写静态线程函数
在函数里主要是加入viewer.run()语句,这样的话osg的运行和程序的其它响应才能同时进行。

声明:

static UINT ThreadRun(LPVOID lparam);

实现:

UINT COSGControlCtrl::ThreadRun(LPVOID lparam)//请求状态。

{

((osgViewer::Viewer *)(lparam))->run();

return 0;

}

五 启动线程
本来想在OnInitDialog函数中启动,可是检查后发现,COSGControlCtrl类并不提供此函数的重载,因此,只好写在OnDraw函数里,因为OnDraw函数一旦当前区域移动、被遮挡等情况下都要调用,因此我们还要保证OnDraw只运行一次。

void COSGControlCtrl::OnDraw(

CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid)

{

if (!pdc)

return;

// TODO: Replace the following code with your own drawing code.

static bool flag=true;

if (flag)

{

MessageBox("OnDraw");

flag=false;



if(!isSetSceneData)

{

configViewer(m_hWnd);//配置默认的viewer

viewer->setSceneData(osgDB::readNodeFile("cow.osg"));//默认数据

}

HANDLE hHandle=CreateThread(NULL,0,ThreadRun,(LPVOID)(viewer.get()),0,NULL);

CloseHandle(hHandle);

}

}

六 程序退出后结束run函数的循环


void COSGControlCtrl::OnDestroy()

{

COleControl::OnDestroy();

// TODO: Add your message handler code here

viewer->setDone(true);

Sleep(1000);

viewer->stopThreading();

}

七 测试
F7,编译通过,生成了解决方案,新打开vc,建一个对话框程序,右键点击“插入Active控件”,选择“OSGControl”,确定

在对话框上拖出一个合适的区域,Ctrl+F5,运行,结果如下:

给控件添加变量m_osg

在合适的位置调用

m_osg.setSceneData((ULONG*)(osgDB::readNodeFile("axes.osg")));

就可以改变viewer的数据了



本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/yangdelong/archive/2009/07/14/4348212.aspx
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: