嵌入效果
源码下载
http://download.csdn.net/download/oXingShuJun/12591792
- 流程
1.首先,建立一个C++ CLR工程 OSGCLRDLL。
2.建立一个OSGWrapper用来封装基本的osgEarth的C++代码。
OSGWrapper.h 文件
#pragma once
#include <windows.h>
#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>
#include <osgViewer/api/win32/GraphicsWindowWin32>
#include <osgGA/TrackballManipulator>
#include <osgGA/KeySwitchMatrixManipulator>
#include <osgDB/DatabasePager>
#include <osgDB/Registry>
#include <osgDB/ReadFile>
#include <osgUtil/Optimizer>
#include <string>
#include <osgGA/StateSetManipulator>
#include <osgEarthUtil/EarthManipulator>
#include <osgEarth/Map>
#include <osgEarth/MapNode>
#include <osgEarthDrivers/tms/TMSOptions>
#include <osgEarthDrivers/model_feature_geom/FeatureGeomModelOptions>
#include <osgEarthDrivers/feature_ogr/OGRFeatureOptions>
#include <osgEarthDrivers/cache_filesystem/FileSystemCache>
#include <osgEarthUtil/EarthManipulator>
#include <osgEarthUtil/GeodeticGraticule>
#include <osgEarthUtil/LatLongFormatter>
#include <osgEarthUtil/Controls>
#include <osgEarthUtil/MouseCoordsTool>
#include <osgEarthUtil/AutoClipPlaneHandler>
#include <osg/PositionAttitudeTransform>
#include <osg/Group>
#include <osg/Node>
#include <osgDB/ReadFile>
#include <osgEarth/ImageLayer>
#include <osgEarth/Notify>
#include <osgEarthUtil/EarthManipulator>
#include <osgEarthUtil/ExampleResources>
#include <osgEarth/MapNode>
#include <osgEarth/ThreadingUtils>
#include <osgEarth/Metrics>
using namespace osgEarth::Util;
class OSGWrapper
{
public:
OSGWrapper(HWND hWnd);
~OSGWrapper();
void InitOSG(std::string filename);
void InitManipulators(void);
void InitSceneGraph(void);
void InitCameraConfig(void);
void PreFrameUpdate(void);
void PostFrameUpdate(void);
void Done(bool value) { mDone = value; }
bool Done(void) { return mDone; }
osg::ref_ptr<osgViewer::Viewer> getViewer() { return viewer; }
osg::ref_ptr<EarthManipulator> getEm() { return manip; }
osg::ref_ptr<osg::Group> getRoot() { return mRoot; }
osg::ref_ptr<osgEarth::Map> getMap() { return mMap; }
osg::ref_ptr<osgEarth::MapNode> getMapNode() { return mMapNode; }
private:
bool mDone;
std::string m_ModelName;
HWND m_hWnd;
osg::ref_ptr<osgViewer::Viewer> viewer;
osg::ref_ptr<osg::Group> mRoot;
osg::ref_ptr<osg::Node> mModel;
osg::ref_ptr<osgEarth::Map> mMap;
osg::ref_ptr<osgEarth::MapNode> mMapNode;
osg::ref_ptr < EarthManipulator> manip;
};
class CRenderingThread : public OpenThreads::Thread
{
public:
CRenderingThread(OSGWrapper* ptr);
CRenderingThread(OSGWrapper * ptr, bool is3dThread);
virtual ~CRenderingThread();
void Done(bool);
bool isEnd();
void setOsgRuningFlag(bool);
bool getOsgRuningState();
virtual void run();
protected:
OSGWrapper* _ptr;
bool _done;
bool _is3Dthread;
bool _osgRuningFlag;
bool _osgRuningState;
};
OSGWrapper.cpp文件
#include "pch.h"
#include "OSGWrapper.h"
OSGWrapper::OSGWrapper(HWND hWnd) :
m_hWnd(hWnd)
{
}
OSGWrapper::~OSGWrapper()
{
viewer->setDone(true);
Sleep(100);
viewer->stopThreading();
viewer.~ref_ptr();
delete viewer;
}
void OSGWrapper::InitOSG(std::string modelname)
{
// Store the name of the model to load
m_ModelName = modelname;
// Init different parts of OSG
InitManipulators();
InitSceneGraph();
InitCameraConfig();
}
void OSGWrapper::InitManipulators(void)
{
}
void OSGWrapper::InitSceneGraph(void)
{
// Init the main Root Node/Group
mRoot = new osg::Group;
int argc = 2;
char* argv[2];
argv[0] = _pgmptr;
argv[1] = (char*)m_ModelName.c_str();
osg::ArgumentParser arguments(&argc, argv);
// Create the viewer for this window
viewer = new osgViewer::Viewer();
// Load the Model from the model name
mModel = MapNodeHelper().load(arguments, viewer);
if (!mModel) return;
// Optimize the model
osgUtil::Optimizer optimizer;
optimizer.optimize(mModel);
optimizer.reset();
// Add the model to the scene
mRoot->addChild(mModel);
}
void OSGWrapper::InitCameraConfig(void)
{
// Local Variable to hold window size data
RECT rect;
// Add a Stats Handler to the viewer
viewer->addEventHandler(new osgViewer::StatsHandler);
// Get the current window size
::GetWindowRect(m_hWnd, &rect);
// Init the GraphicsContext Traits
osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
// Init the Windata Variable that holds the handle for the Window to display OSG in.
osg::ref_ptr<osg::Referenced> windata = new osgViewer::GraphicsWindowWin32::WindowData(m_hWnd);
// Setup the traits parameters
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;
// Create the Graphics Context
osg::GraphicsContext* gc = osg::GraphicsContext::createGraphicsContext(traits.get());
// Init Master Camera for this View
osg::ref_ptr<osg::Camera> camera = viewer->getCamera();
// Assign Graphics Context to the Camera
camera->setGraphicsContext(gc);
// Set the viewport for the Camera
camera->setViewport(new osg::Viewport(0, 0, traits->width, traits->height));
// set the draw and read buffers up for a double buffered window with rendering going to back buffer
camera->setDrawBuffer(GL_BACK);
camera->setReadBuffer(GL_BACK);
// Set projection matrix and camera attribtues
camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
camera->setClearColor(osg::Vec4f(0.0f, 0.0f, 0.0f, 1.0f));
camera->setProjectionMatrixAsPerspective(
30.0f, static_cast<double>(traits->width) / static_cast<double>(traits->height), 1.0, 1000.0);
viewer->setCamera(camera.get());
osgEarth::MapNode* mapNode = osgEarth::MapNode::findMapNode(mRoot);
mMapNode = mapNode;
osgEarth::Map* map = mapNode->getMap();
mMap = map;
double equatorRadius = map->getSRS()->getEllipsoid()->getRadiusEquator();
viewer->getCamera()->addCullCallback(new osgEarth::Util::AutoClipPlaneCullCallback(mapNode));
manip = new EarthManipulator();
manip->setHomeViewpoint(osgEarth::Util::Viewpoint("北京", 116.3, 39.9, 0, 0, -90, equatorRadius * 4));
viewer->setCameraManipulator(manip);
// Set the Scene Data
viewer->setSceneData(mRoot);
viewer->setThreadingModel(osgViewer::ViewerBase::ThreadingModel::SingleThreaded);
viewer->addEventHandler(new osgViewer::StatsHandler);
viewer->addEventHandler(new osgGA::StateSetManipulator(viewer->getCamera()->getOrCreateStateSet()));
viewer->addEventHandler(new osgViewer::ThreadingHandler);
viewer->addEventHandler(new osgViewer::RecordCameraPathHandler);
viewer->addEventHandler(new osgViewer::LODScaleHandler);
viewer->addEventHandler(new osgViewer::ScreenCaptureHandler);
viewer->realize();
}
void OSGWrapper::PreFrameUpdate()
{
// Due any preframe updates in this routine
}
void OSGWrapper::PostFrameUpdate()
{
// Due any postframe updates in this routine
}
CRenderingThread::CRenderingThread(OSGWrapper* ptr)
: OpenThreads::Thread(), _ptr(ptr), _done(false)
{
_osgRuningFlag = true;
_osgRuningState = true;
}
CRenderingThread::CRenderingThread(OSGWrapper* ptr, bool is3dThread)
: OpenThreads::Thread(), _ptr(ptr), _done(false)
{
_is3Dthread = is3dThread;
_osgRuningFlag = true;
_osgRuningState = true;
}
CRenderingThread::~CRenderingThread()
{
_done = true;
if (isRunning())
{
cancel();
join();
}
}
void CRenderingThread::Done(bool flag)
{
_done = flag;
}
void CRenderingThread::setOsgRuningFlag(bool b)
{
_osgRuningFlag = b;
}
bool CRenderingThread::getOsgRuningState()
{
return _osgRuningState;
}
bool CRenderingThread::isEnd()
{
osgViewer::Viewer* viewer = _ptr->getViewer();
if (!testCancel() && !viewer->done() && !_done)
return false;
else
return true;
}
void CRenderingThread::run()
{
if (!_ptr)
{
_done = true;
return;
}
osgViewer::Viewer* viewer = _ptr->getViewer();
do
{
if (_osgRuningFlag)
{
_ptr->PreFrameUpdate();
viewer->frame();
_ptr->PostFrameUpdate();
_osgRuningState = true;
}
else
{
_osgRuningState = false;
Sleep(5);
}
} while (!testCancel() && !viewer->done() && !_done);
}
3.封装C#调用接口
osgclr.h文件
#pragma once
#include "OSGWrapper.h"
using namespace System;
using namespace System::Runtime::InteropServices;
namespace OSGCLR {
public ref class OSGCLRDLL
{
// TODO: 在此处为此类添加方法。
private:
static OSGCLRDLL m_instance;
public:
static property OSGCLRDLL^ Instance { OSGCLRDLL^ get() { return %m_instance; } }
int InitDLL(IntPtr _hwnd2, bool is3D);
};
}
osgclr.cpp文件
#include "pch.h"
#include "OSGCLR.h"
namespace OSGCLR
{
OSGWrapper* mOSG3D = nullptr; //三维地图osg
OSGWrapper* mOSG2D = nullptr; //二维地图osg
CRenderingThread* m3DThreadHandle = nullptr; //三维地图线程
CRenderingThread* m2DThreadHandle = nullptr; //二维地图线程
}
int OSGCLR::OSGCLRDLL::InitDLL(IntPtr _hwnd2, bool is3D)
{
HWND _hwnd = (HWND)_hwnd2.ToPointer();
if (is3D)
{
//通过传入的句柄初始化cOSG对象
mOSG3D = new OSGWrapper(_hwnd);
mOSG3D->InitOSG("Earth3D.earth");
//创建渲染线程并开始渲染
m3DThreadHandle = new CRenderingThread(mOSG3D, false);
m3DThreadHandle->start();
}
else
{
//通过传入的句柄初始化cOSG对象
mOSG2D = new OSGWrapper(_hwnd);
mOSG2D->InitOSG("Map2D.earth");
double fov, ratio, near1, far1;
mOSG2D->getViewer()->getCamera()->getProjectionMatrixAsPerspective(fov, ratio, near1, far1);
mOSG2D->getViewer()->getCamera()->setProjectionMatrixAsPerspective(7.5, ratio, near1, far1);
//创建渲染线程并开始渲染
m2DThreadHandle = new CRenderingThread(mOSG2D, true);
m2DThreadHandle->start();
}
return 0;
}
4.新建一个winfrom程序,调用clr接口,调用前请先引用osgclr.dll
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace OSGWinForm
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
OSGCLR.OSGCLRDLL oSGCLRDLL = OSGCLR.OSGCLRDLL.Instance;
oSGCLRDLL.InitDLL(this.Handle, true);
}
}
}