上一节是入门:
OSG+VS2015+Win10配置
win32控制台程序下使用osg
为了方便,在上一节中,我们使用VS创建了一个win32控制台程序,然后添加代码:
写法一
#include
#include
int main(int argc, char **argv)
{
osgViewer::Viewer viewer;
viewer.setSceneData(osgDB::readNodeFile("cessna.osg"));
return viewer.run();
}
写法二
更加优雅一点,使用了智能指针。
#include<osgViewer/Viewer>
#include<osg/Node>
#include<osg/Geode>
#include<osg/Group>
#include<osgDB/ReadFile>
#include<osgDB/WriteFile>
#include<osgUtil/Optimizer>
int main(int argc, char **argv)
{
osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();
osg::ref_ptr<osg::Group> root = new osg::Group();
osg::ref_ptr<osg::Node> node = osgDB::readNodeFile("cessna.osg");
root->addChild(node.get());
osgUtil::Optimizer optimizer;
optimizer.optimize(root.get());
viewer->setSceneData(root.get());
viewer->realize();
viewer->run();
return 0;
}
Win32 Project下使用osg
首先回顾一下,一个win32窗口是如何创建的:
1.1 入口函数WinMain
1.2 窗口处理函数
当窗口处理消息事件时,系统调用该函数
LRESULT CALLBACK WindowProc(
HWND hwnd, // 窗口的句柄
UINT uMsg, // 消息的ID号
WPARAM wParam, // 消息所对应的参数
LPARAM lParam // 消息所对应的参数
);
1.3 注册窗口类型
typedef struct _WNDCLASS {
UINT style; //窗口类的风格:不是窗口类型的风格
WNDPROC lpfnWndProc; //窗口处理函数
int cbClsExtra; //窗口类附加数据大小
int cbWndExtra; //窗口附加数据大小
HANDLE hInstance; //当前应用程序的实例句柄
HICON hIcon; //窗口图标
HCURSOR hCursor; //窗口的鼠标
HBRUSH hbrBackground; //窗口的背景画刷
LPCTSTR lpszMenuName; //菜单
LPCTSTR lpszClassName; //类型名称:不是窗口标题的名称,只是注册的名称
} WNDCLASS;
注册函数 RegisterClass
1.4 创建窗口
HWND CreateWindow(
LPCTSTR lpClassName, //窗口类型名称
LPCTSTR lpWindowName, //窗口名称
DWORD dwStyle, //窗口类型
int x, //窗口的左上角X坐边
int y, //窗口的左上角X坐边
int nWidth, //窗口的宽度
int nHeight, //窗口的高度
HWND hWndParent, //父窗口句柄
HMENU hMenu, //窗口菜单句柄
HANDLE hInstance, //应用程序的实例句柄
LPVOID lpParam //创建的参数,一般为NULL
);
1.5 显示窗口
ShowWindow 显示窗口
BOOL ShowWindow(
HWND hWnd, //显示的窗口句柄
int nCmdShow //显示的方式
);
UpdateWindow 刷新窗口
1.6 消息处理
GetMessage 获取消息
DispatchMessage 派发消息
1.7 程序退出
窗口销毁时,退出程序。在WndProc中实现。
WM_DESTROY: 当窗口销毁时,会调用WndProc
传递给使用者。
直接在窗口过程函数中使用,显示osg
定义一些变量:
sg::ref_ptr::Viewer> viewer;
osg::observer_ptr::GraphicsWindow> window;
osg::ref_ptr::Group> root;
osg::ref_ptr::Node> loadedModel;
osgUtil::Optimizer optimizer;
osg::ref_ptr::GraphicsContext::Traits> traits;
osg::ref_ptr::Referenced> windata;
osg::GraphicsContext* gc;
osg::ref_ptr::Camera> camera;
bool renderok;
在WM_CREATE消息中添加代码:
root = new osg::Group;
loadedModel = osgDB::readNodeFile("cessna.osg");
if (!loadedModel)
return 1;
optimizer.optimize(loadedModel.get());
optimizer.reset();
root->addChild(loadedModel.get());
traits = new osg::GraphicsContext::Traits;
windata = new osgViewer::GraphicsWindowWin32::WindowData(hwnd);
traits->x = 0;
traits->y = 0;
traits->width = 800;
traits->height = 600;
traits->windowDecoration = false;
traits->doubleBuffer = true;
traits->sharedContext = 0;
traits->inheritedWindowData = windata;
traits->setInheritedWindowPixelFormat = true;
gc = osg::GraphicsContext::createGraphicsContext(traits.get());
camera = new osg::Camera;
camera->setGraphicsContext(gc);
camera->setViewport(new osg::Viewport(traits->x, traits->y, traits->width, traits->height));
viewer = new osgViewer::Viewer;
viewer->addSlave(camera.get());
viewer->setSceneData(root.get());
viewer->setCameraManipulator(new osgGA::TrackballManipulator);
viewer->addEventHandler(new osgViewer::StatsHandler);
viewer->setThreadingModel(osgViewer::Viewer::SingleThreaded);
viewer->realize();
renderok = false;
_beginthread(render, 0, NULL);
=============================================================
全部代码:
#include
#include
#include
#include
#include
#include
#include
#include
osg::ref_ptr::Viewer> viewer;
osg::observer_ptr::GraphicsWindow> window;
osg::ref_ptr::Group> root;
osg::ref_ptr::Node> loadedModel;
osgUtil::Optimizer optimizer;
osg::ref_ptr::GraphicsContext::Traits> traits;
osg::ref_ptr::Referenced> windata;
osg::GraphicsContext* gc;
osg::ref_ptr::Camera> camera;
bool renderok;
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT("HelloOSG Win32 Project");
HWND hwnd;
MSG msg;
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))
{
MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR);
return 0;
}
hwnd = CreateWindow(szAppName, // window class name
TEXT("The Hello Program"), // window caption
WS_OVERLAPPEDWINDOW, // window style
100, // initial x position
100, // initial y position
800, // initial x size
600, // initial y size
NULL, // parent window handle
NULL, // window menu handle
hInstance, // program instance handle
NULL); // creation parameters
ShowWindow(hwnd, iCmdShow);
UpdateWindow(hwnd);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
void render(void* ptr)
{
while (!viewer->done())
{
viewer->frame();
}
renderok = true;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
root = new osg::Group;
loadedModel = osgDB::readNodeFile("cessna.osg");
if (!loadedModel)
return 1;
optimizer.optimize(loadedModel.get());
optimizer.reset();
root->addChild(loadedModel.get());
traits = new osg::GraphicsContext::Traits;
windata = new osgViewer::GraphicsWindowWin32::WindowData(hwnd);
traits->x = 0;
traits->y = 0;
traits->width = 800;
traits->height = 600;
traits->windowDecoration = false;
traits->doubleBuffer = true;
traits->sharedContext = 0;
traits->inheritedWindowData = windata;
traits->setInheritedWindowPixelFormat = true;
gc = osg::GraphicsContext::createGraphicsContext(traits.get());
camera = new osg::Camera;
camera->setGraphicsContext(gc);
camera->setViewport(new osg::Viewport(traits->x, traits->y, traits->width, traits->height));
viewer = new osgViewer::Viewer;
viewer->addSlave(camera.get());
viewer->setSceneData(root.get());
viewer->setCameraManipulator(new osgGA::TrackballManipulator);
viewer->addEventHandler(new osgViewer::StatsHandler);
viewer->setThreadingModel(osgViewer::Viewer::SingleThreaded);
viewer->realize();
renderok = false;
_beginthread(render, 0, NULL);
return 0;
case WM_PAINT:
return 0;
case WM_DESTROY:
viewer->setDone(true);
while (!renderok)
{
Sleep(10);
}
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}