在wpf工程中使用osg技術

我主要想說的是使用的後臺的c#代碼來添加osg場景。
需要實現:新建一個窗口Window1.xaml,然後在窗口中顯示osg場景。
這裏比較困難的地方是wpf中使用的是c#,是一種託管代碼;而osg的代碼是使用c++編寫,是一種非託管代碼。如何將二者結合起來使用就是最關鍵的步驟。
看網上說的可以使用C++/CLI可以實現c#和c++的混合編程,但由於一開始我就是寫的wpf程序,不想再新建工程,於是想到可以將c++的osg代碼寫成dll文件,然後在wpf程序中引用便可。

WPF中除主窗口外再新建一個窗口Window1.xaml;再在MainWindow頁面上隨便畫一個按鈕
代碼如下:
public partial class MainWindow : Window
    {
//注意把ConsoleApplication1.dll文件放到wpf的debug文件夾下
        [DllImport(@"ConsoleApplication1.dll",
            EntryPoint = "osgRunCow", CallingConvention = CallingConvention.Cdecl)]
        public static extern void osgRunCow(IntPtr m_hWnd);

        IntPtr handle;//c#中用IntPtr來保存窗口句柄,對應c++中的HWND
        Thread th;
        public MainWindow()
        {
            InitializeComponent();
        }
        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            Window win = new Window1();//Window1是新建的Window
            win.Show();
            handle = new WindowInteropHelper(win).Handle;//獲取窗口句柄,提供給osgRunCow使用
            th = new Thread(new ThreadStart(func));//多開一個線程防止界面假死
            th.Start();
        }

        public void func()
        {
            osgRunCow(handle);
        }
    }

dll文件中新建一個module-definition file文件Source.def(add new item->visual c++ ->code->module definition file)
其代碼如下(注意沒有任何分號):
LIBRARY ConsoleApplication1.dll  
EXPORTS  
osgRunCow  

主文件ConsoleApplication1.cpp的代碼如下:
// ConsoleApplication1.cpp : Defines the exported functions for the DLL application.
//

#include "stdafx.h"
#include <osg/Group>

#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>
#include <osgViewer/api/win32/GraphicsWindowWin32>

#include <osgDB/ReadFile>

#include <osgGA/OrbitManipulator>
#include <osgGA/StateSetManipulator>
#include <osgGA/CameraManipulator>
#include <osgGA/KeySwitchMatrixManipulator>
#include <osgGA/GUIEventHandler>

#include <osgUtil/Optimizer>
osg::ref_ptr m_Viewer;
osg::ref_ptr m_Root; // 場景根節點

void initSG()
{
// 創建場景分類樹樹
m_Root = new osg::Group;
m_Root->addChild(osgDB::readNodeFile("cow.osg"));
// 優化場景數據
//osgUtil::Optimizer optimizer;
//optimizer.optimize(m_Root);
}

void initCameraCfg(HWND m_hWnd)
{
// 本地窗口Size
RECT rect;
// 爲窗口創建Viewer
m_Viewer = new osgViewer::Viewer();
// 取消Esc鍵的事件響應
m_Viewer->setKeyEventSetsDone(0);
// 獲得當前窗口大小
::GetWindowRect(m_hWnd, &rect);
// 初始化圖形環境GraphicsContext Traits
osg::ref_ptr traits = new osg::GraphicsContext::Traits;
// Init the Windata Variable that holds the handle for the Window to display OSG in.
osg::ref_ptr windata = new osgViewer::GraphicsWindowWin32::WindowData(m_hWnd);
// 設置traits 參數
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;
// 創建圖形環境Graphics Context
osg::ref_ptr gc = osg::GraphicsContext::createGraphicsContext(traits.get());
{
// 根據分辨率確定合適的投影來保證顯示的圖形不變形
double fovy =0.0; 
double aspectRatio =0.0;
double zNear =0.0;
double zFar= 0.0;
m_Viewer->getCamera()->getProjectionMatrixAsPerspective(fovy,aspectRatio,zNear,zFar);
double newAspectRatio =double(traits->width)/double(traits->height);
double aspectRatioChange = newAspectRatio/aspectRatio;
if (aspectRatioChange != 1.0)
{
m_Viewer->getCamera()->getProjectionMatrix()  *= osg::Matrix::scale(1.0/aspectRatioChange,1.0,1.0);
}
}
// 設置相機視口
m_Viewer->getCamera()->setViewport(traits->x,traits->y,traits->width,traits->height);
// 爲相機分配圖形環境
m_Viewer->getCamera()->setGraphicsContext(gc.get());
// 爲Viewer的Camera添加操縱器
m_Viewer->setCameraManipulator(new osgGA::OrbitManipulator());
// 設置線程模型
m_Viewer->setThreadingModel(osgViewer::ViewerBase::SingleThreaded);
// 設置場景數據
m_Viewer->setSceneData(m_Root);
// 初始化並創建窗口
m_Viewer->realize();
}

void osgStartRender()
{
m_Viewer->run();
}

void osgRunCow(HWND m_hWnd)
{
initSG();
initCameraCfg(m_hWnd);
osgStartRender();
}
注意:對於託管和非託管我的理解並不深刻,所以使用的時候可能會出現線程安全性問題,但起碼我用的時候沒出什麼問題。

參考工程:ssDlgFrm(網上搜應該可以查到)

有關如何新建dll工程並在wpf中調用可以參照:http://blog.csdn.net/jarvischu/article/details/6634185

感謝每一個願意分享的人。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章