注意工程类型应与下载的OSG库类型一样,我这里是Release版OSG库,生成Release版程序没问题,但是Debug版有错误,如需要生成Debug版程序,需要下载Debug版OSGbinary。
OSGbinary版库(OpenSceneGraph3.0.1forVS2010-X86-32bi)下载OSGbinary版下载 (已经编译好的lib,不用自己编译,直接使用即可)
需要自己增加两个环境变量,OSG_FILE_PATH 指定OSG 程序读取图形和模型文件时的搜索路径。如果环境变量为空或者没有设置,OSG 在读取图形和
模型文件时只搜索当前的目录。
1、项目名称3DVision
选择字符集为多字符集
2、第一步:修改doc类
public: //从属性面板上把建立新文档操作删除掉,因为不需要建立新文档,什么时候都不会需要这个功能 //virtual BOOL OnNewDocument();
protected: //定义一个文件名称,用来存放用来读取的模型文件 CString m_csFileName;
public: //类向导重载OnOpenDocument函数,
virtual BOOL OnOpenDocument(LPCTSTR lpszPathName);添加函数GetFileName专门用来获得文件名
CString GetFileName() const{ return m_csFileName;};
// CMy3DVisionDoc 构造/析构 CMy3DVisionDoc::CMy3DVisionDoc() { // 定义一个默认打开文件 m_csFileName="cow.osg"; }
删除掉重载的新建文档函数
//BOOL CMy3DVisionDoc::OnNewDocument() //{ // // if (!CDocument::OnNewDocument()) // return FALSE; // // // TODO: 在此添加重新初始化代码 // // (SDI 文档将重用该文档) // // return TRUE; //}新加的打开文档映射
BOOL CMy3DVisionDoc::OnOpenDocument(LPCTSTR lpszPathName) { //打开时,把文件名传入m_csFileName. m_csFileName=lpszPathName; if (!CDocument::OnOpenDocument(lpszPathName)) return FALSE; return TRUE; }
#pragma once #include <osgViewer/Viewer> #include <osgViewer/ViewerEventHandlers> #include <osgViewer/api/Win32/GraphicsWindowWin32> /*********osgGA =osg GUI ACTION 图形界面交互库*****************/ #include <osgGA/TrackballManipulator> #include <osgGA/KeySwitchMatrixManipulator> #include <osgDB/DatabasePager> #include <osgDB/Registry> #include <osgDB/ReadFile> #include <osgDB/WriteFile> #include <osgUtil/Optimizer> #include <string> /************************************************************************/ /* OSG核心类,在这里执行MFC对OSG的大部分的管理功能 */ /************************************************************************/ class CCoreOSG { public: // CCoreOSG(void); ~CCoreOSG(void); // 构造函数获取上一级窗口句柄 CCoreOSG(HWND hWnd); // 初始化OSG,参数filename为需要加入的模型 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); // SetDone void Done(bool value) { mDone=value; } // getDone bool Done(void) { return mDone; } // 渲染,注意这里是静态的,可启用为全局线程 static void Render(void* ptr); // 使用一个名称为filename的模型代替当前场景中的所有模型 void ReplaceSceneData(std::string filename); // osgViewer::Viewer* GetViewer(void); private: bool mDone; std::string m_ModelName; HWND m_hWnd; osgViewer::Viewer* mViewer; osg::ref_ptr<osg::Group> mRoot; // osg::ref_ptr<osg::Node> m_Node; public: osg::ref_ptr<osg::Node> mModel; private: osg::ref_ptr<osgGA::TrackballManipulator> trackball; osg::ref_ptr<osgGA::KeySwitchMatrixManipulator> keyswitchManipulator; public: osgViewer::Viewer* GetViewer(void) { return mViewer; } };
#include "StdAfx.h" #include "CoreOSG.h" // 构造函数获取上一级窗口句柄 CCoreOSG::CCoreOSG(HWND hWnd):m_hWnd(hWnd) { } CCoreOSG::~CCoreOSG() { mViewer->setDone(true); Sleep(1000); mViewer->stopThreading(); delete mViewer; } void CCoreOSG::InitOSG(std::string modelname) { //存储取到的模型文件名称 m_ModelName = modelname; // 初始化OSG的不同部分 InitManipulators(); InitSceneGraph(); InitCameraConfig(); } void CCoreOSG::InitManipulators(void) { /* //创建一个trackball操作器 trackball = new osgGA::TrackballManipulator(); //创建一个KEY切换 keyswitchManipulator = new osgGA::KeySwitchMatrixManipulator; // 加入KEY切换 keyswitchManipulator->addMatrixManipulator( '1', "Trackball", trackball.get()); //选择一个 keyswitchManipulator->selectMatrixManipulator(0);// 0是索引值*/ //创建一个trackball操作器 trackball = new osgGA::TrackballManipulator(); //创建一个KEY切换 keyswitchManipulator = new osgGA::KeySwitchMatrixManipulator; // 加入KEY切换 keyswitchManipulator->addMatrixManipulator( '1', "Trackball", trackball.get()); //选择一个 keyswitchManipulator->selectMatrixManipulator(0);// 0是索引值 } void CCoreOSG::InitSceneGraph(void) { //初始化组 mRoot = new osg::Group; //读取模型 mModel = osgDB::readNodeFile(m_ModelName); // 优化模型 osgUtil::Optimizer optimizer; optimizer.optimize(mModel.get()); optimizer.reset(); //把模型加入到场景中 mRoot->addChild(mModel.get()); } void CCoreOSG::InitCameraConfig(void) { // 局部变量存放窗口矩形 RECT rect; // 创建一个viewer mViewer = new osgViewer::Viewer(); // 加入一个statshandler mViewer->addEventHandler(new osgViewer::StatsHandler); // 得到当前窗口矩形 ::GetWindowRect(m_hWnd, &rect); // 初始化图形描述 osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits; // 初始化窗口变量,为OSG所用 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 mViewer->addSlave(camera.get()); // 添加操作器到VIEWER mViewer->setCameraManipulator(keyswitchManipulator.get()); //设置数据 mViewer->setSceneData(mRoot.get()); // 实现VIEWER mViewer->realize(); } // 建立窗口 void CCoreOSG::SetupWindow(void) { } // 建立相机 void CCoreOSG::SetupCamera(void) { } void CCoreOSG::PreFrameUpdate(void) { // 帧前操作可在这里做一下 } void CCoreOSG::PostFrameUpdate(void) { // 帧后操作可在这里做一下 } // 渲染,注意这里是静态的,可启用为全局线程 void CCoreOSG::Render(void* ptr) { CCoreOSG* osg=(CCoreOSG*)ptr; osgViewer::Viewer* viewer=osg->GetViewer(); //可以这样 // view->run() or // while(!viewer->done()){viewer->frame();} // viewer->run(); //也可以这样,建议这样 while (!viewer->done()) { osg->PreFrameUpdate(); viewer->frame(); osg->PostFrameUpdate(); //Sleep(10);//让其他程序也占用CPU,放出MS } //退出了程序,弹出个对话框说一下 AfxMessageBox("线程退出"); _endthread(); } void CCoreOSG::ReplaceSceneData(std::string filename) { //移掉mRoot中所有的数据,这些数据将会被自动释放掉,不用手动处理 mRoot->removeChildren(0, mRoot->getNumChildren()); //加入要置换的模型 mModel = osgDB::readNodeFile(filename); //优化 osgUtil::Optimizer optimizer; optimizer.optimize(mModel.get()); optimizer.reset(); //添加孩子 mRoot->addChild(mModel.get()); }
// 3DVisionView.h : CMy3DVisionView 类的接口 // #pragma once #include "CoreOSG.h"
protected: // 添加类CCoreOSG CCoreOSG* mOSG; // 线程句柄 HANDLE mThreadHandle; // 用于文件计数 int iFileNum;
public: // 重写以下类型函数 virtual void OnInitialUpdate(); afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); afx_msg void OnDestroy(); afx_msg BOOL OnEraseBkgnd(CDC* pDC); afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
构造函数
// CMy3DVisionView 构造/析构 CMy3DVisionView::CMy3DVisionView() : mOSG(NULL) , iFileNum(0) { // TODO: 在此处添加构造代码 iFileNum=1; }
如果多字符集
void CMy3DVisionView::OnInitialUpdate() { //在这里控制一下打开文件的操作 CView::OnInitialUpdate(); if(iFileNum ==1) { //第一次打开默认飞机文件 iFileNum ++ ; CString csFileName = GetDocument() ->GetFileName() ; mOSG ->InitOSG(csFileName.GetString()) ; mThreadHandle = (HANDLE)_beginthread(&CCoreOSG::Render, 0, mOSG) ; } else { //后续打开,直接替掉模型就可以了 iFileNum ++ ; CString csFileName = GetDocument() ->GetFileName() ; mOSG ->ReplaceSceneData(csFileName.GetString()) ; } }
int CMy3DVisionView::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CView::OnCreate(lpCreateStruct) == -1) return -1; // TODO: 在此添加您专用的创建代码 mOSG=new CCoreOSG(m_hWnd); //return 0; return 1; }
void CMy3DVisionView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) { // TODO: 在此添加消息处理程序代码和/或调用默认值 mOSG->GetViewer()->getEventQueue()->keyPress(nChar); if (nChar==VK_ESCAPE) { GetParent()->SendMessage(WM_CLOSE); } // CView::OnKeyDown(nChar, nRepCnt, nFlags); }
void CMy3DVisionView::OnDestroy() { if (mOSG!=0) { delete mOSG; } WaitForSingleObject(mThreadHandle,1000); CView::OnDestroy(); }