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

Reply via email to