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