开发OSG桌面程序,有很多种框架,最常用的有OSG自身的窗口系统,以及MFC、Win32,还有基于Qt图形视图等。严格意义上讲,MFC与Win32属于同一类,都是基于Windows的SDK程序,但是由于MFC框架的繁琐机制,并且结构复杂,因此本文以win32程序为例,建立最简单的OSG程序开发框架,进行说明。
第一步:建立一个Win32的空工程,然后添加一个源文件;
第二步:win32程序主要有两部分,一个是WinMain()函数,另一个是消息循环函数WndProc();
第三步:OSG图形渲染部分在WndProc()消息循环中完成。
第四步:设置包含路径,和库文件路径;
第五步:编译运行。
完整代码如下:
#include <Windows.h>
#include <process.h>
#include <osgViewer/Viewer>
#include <osgGA/TrackballManipulator>
#include <osgViewer/api/Win32/GraphicsWindowWin32>
#include <osgDB/ReadFile>
#ifdef _DEBUG
#pragma comment(lib,"OpenThreadsd.lib")
#pragma comment(lib,"osgd.lib")
#pragma comment(lib,"osgDBd.lib")
#pragma comment(lib,"osgFXd.lib")
#pragma comment(lib,"osgGAd.lib")
#pragma comment(lib,"osgManipulatord.lib")
#pragma comment(lib,"osgParticled.lib")
#pragma comment(lib,"osgShadowd.lib")
#pragma comment(lib,"osgSimd.lib")
#pragma comment(lib,"osgTerraind.lib")
#pragma comment(lib,"osgTextd.lib")
#pragma comment(lib,"osgUtild.lib")
#pragma comment(lib,"osgViewerd.lib")
#else
#pragma comment(lib,"OpenThreads.lib")
#pragma comment(lib,"osg.lib")
#pragma comment(lib,"osgDB.lib")
#pragma comment(lib,"osgFX.lib")
#pragma comment(lib,"osgGA.lib")
#pragma comment(lib,"osgManipulator.lib")
#pragma comment(lib,"osgParticle.lib")
#pragma comment(lib,"osgShadow.lib")
#pragma comment(lib,"osgSim.lib")
#pragma comment(lib,"osgTerrain.lib")
#pragma comment(lib,"osgText.lib")
#pragma comment(lib,"osgUtil.lib")
#pragma comment(lib,"osgViewer.lib")
#endif
//全局变量
osg::ref_ptr<osgViewer::Viewer> g_viewer;
bool g_finished;
//渲染函数,有进程调用
void render(void*)
{
while (!g_viewer->done())
{
g_viewer->frame();
}
g_finished = true;
}
//消息循环函数
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
{
osg::ref_ptr<osg::Referenced> windata = new osgViewer::GraphicsWindowWin32::WindowData(hwnd);
//设置窗口属性
osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
traits->x = 0;
traits->y = 0;
traits->width = 800;
traits->height = 600;
traits->windowDecoration = false;
traits->doubleBuffer = true;
traits->inheritedWindowData = windata;
//或许上下文
osg::ref_ptr<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(0, 0, 800, 600));
//定义场景并加载数据
g_viewer = new osgViewer::Viewer;
g_viewer->addSlave(camera.get());
//g_viewer->setSceneData(osgDB::readNodeFile("cessna.osg"));
g_viewer->setSceneData(osgDB::readNodeFile("mymap.earth"));
g_viewer->setCameraManipulator(new osgGA::TrackballManipulator);
g_viewer->setThreadingModel(osgViewer::Viewer::SingleThreaded);
g_finished = false;
_beginthread(render, 0, NULL);
return 0;
}
break;
case WM_DESTROY:
{
g_viewer->setDone(true);
while (!g_finished)
{
Sleep(10);
}
PostQuitMessage(0);
return 0;
}
break;
default:
break;
}
//返回Windows的默认消息处理函数
return DefWindowProc(hwnd, message, wParam, lParam);
}
//Windows程序的入口函数
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT("gui");
//定义窗口类
WNDCLASS wndclass;
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szAppName;
//注册窗口
if (!RegisterClass(&wndclass))
{
return 0;
}
//创建窗口
HWND hwnd = CreateWindow(
szAppName,
TEXT("OSG WIN32"),
WS_OVERLAPPEDWINDOW,
100, 100,
800, 600,
NULL,
NULL,
hInstance,
NULL);
//显示窗口
ShowWindow(hwnd, iCmdShow);
//更新窗口
UpdateWindow(hwnd);
//消息循环
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
运行结果如下:
本程序设计到osgEarth的知识,其中mymap.earth文件内容如下:
<map name="MyMap" type="geocentric" version="2">
<image name="bluemarble" driver="gdal">
<url>world.tif</url>
</image>
</map>
其中世界地图影像地图“world.tif”可以在NASA官网上下载。
参考文献:王锐,钱学雷.OpenSceneGraph三位渲染引擎设计与实现.清华大学出版社,2009.