Dear Nick,
As I didn’t check email recently , I’m sorry to reply you so late. Thank
you very much, Nick. You explained clearly how to wrap OSG into C# application.
Now I know the direction to follow up. When I go further in this way, I think I
will have more detailed problem and bother you to answer.
Thanks a lot in advance.
Glen
发件人: osg-users [mailto:[email protected]] 代表 Trajce
Nikolov NICK
发送时间: 2014年6月19日 20:31
收件人: OpenSceneGraph Users
主题: Re: [osg-users] C# language invoke OSG function
Hi Glen,
I just did this like a week ago, was facing the same challenge. There are few
options: One is to make C# wrappers with SWIG, I spent good time on this
supported somewhat from the community, but at the end did not succeeded.
The other is to wrap some functions into unmanaged dll, where you initialize
the viewer by a given handle (HWND). Then in C# you call this function and
provide the HWND. Some snippets here, not going to provide the whole source
code since it is rather complicated:
This is the function that is exported from a dll, creates the Viewer based on a
given handle (HWND) and start the rendering thread:
extern "C" __declspec(dllexport) int __stdcall InitControl(HWND window)
{
// Lookup for this control, it might be already in use
MapViewersIterator itr = g_Viewers.find(window);
if (itr != g_Viewers.end())
{
return -1;
}
// Local Variable to hold window size data
RECT rect;
// Create the viewer for this window
g_Viewers[window] = new osgViewer::Viewer();
// Get the current window size
::GetWindowRect(window, &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(window);
// 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 a new Camera (Master for this View)
osg::ref_ptr<osg::Camera> camera = new osg::Camera;
// Assign Graphics Context to the Camera
camera->setGraphicsContext(gc);
// Set the viewport for the Camera
camera->setViewport(new osg::Viewport(traits->x, traits->y, traits->width,
traits->height));
// Set projection matrix and camera attribtues
camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
camera->setClearColor(osg::Vec4f(0.2f, 0.2f, 0.4f, 1.0f));
camera->setProjectionMatrixAsPerspective(30.0f,
static_cast<double>(traits->width)/static_cast<double>(traits->height), 1.0,
1000.0);
// Add the Camera to the Viewer
g_Viewers[window]->setCamera(camera.get());
// Setup the geometry for this control
g_Viewers[window]->setSceneData( createHUD(osg::Vec2(0,traits->height/2.f),
osg::Vec2(traits->width,traits->height), window) );
// Realize the Viewer
g_Viewers[window]->realize();
// Start the rendring thread and save it as user data for later clearance
osg::ref_ptr< RenderingThread > renderer = new RenderingThread(
g_Viewers[window] );
renderer->startThread();
g_Viewers[window]->getCamera()->setUserData( renderer.get() );
return 0;
}
This is the rendering thread class. Only do frames in a loop. Other option is
to have it on your C# side, to have another exported function like DoFrame(),
and use timer or C# thread to do the rendering loop:
class RenderingThread : public OpenThreads::Thread, public osg::Referenced
{
public:
RenderingThread(osgViewer::Viewer* viewer)
: m_Viewer(viewer)
, m_Running(false)
{
}
virtual void run()
{
m_Running = true;
while (m_Running)
{
m_Viewer->frame();
}
cancel();
}
void setIsRunning( bool running )
{
m_Running = running;
}
protected:
osg::ref_ptr<osgViewer::Viewer> m_Viewer;
bool m_Running;
};
And finaly the C# side. You create control ot get the HWND of the .NET Form. In
my case I have a picture control and I have the viewer running it it's client's
area:
[DllImport("MyOSG.dll")]
static extern int InitControl(Int32 hwnd);
.....
this.pictureBox1.Location = new System.Drawing.Point(30, 71);
this.pictureBox1.Name = "pictureBox1";
this.pictureBox1.Size = new System.Drawing.Size(225, 105);
this.pictureBox1.TabIndex = 0;
this.pictureBox1.TabStop = false;
InitControl(hdl = this.pictureBox1.Handle.ToInt32());
It is tricky but doable. Took some time to figured it out. If you got stuck
ping me, I might be able to give more hints
Cheers,
Nick
On Thu, Jun 19, 2014 at 8:11 AM, 龚来恩 <[email protected]> wrote:
Hi Everyone,
I want to develop an 3D application based on OSG. Is it possible that I use C#
language to develop UI, and OSG presentation function is invoke by C#. If it
is feasible, please give me an source code example.
Glen
_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
--
trajce nikolov nick
_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org