Discussion:
Using OSG Embedded in an Existing OpenGL Project
Dainon Woudstra
2012-09-08 23:24:43 UTC
Permalink
Hi,

Background:
I've written an application in C# for various reasons. SharpGL provided the OpenGL portion, C# provided the Database, and Intellisense works with it in VS 2010. I've rewritten this application in 3 different frameworks and have hit issues I could not solve for one reason or another. For example, now that my application works and I use it everyday, I'm trying to enhance some of its features, such as loading a 3D object and good text rendering.

I've come across OpenSceneGraph and have been trying to use it with the C# wrappers. I couldn't get that working and read a bunch of posts providing other solutions and mentioning it isn't supported anymore. Thus, I've learned to write a wrapper for a C++ OSG DLL to call some native OSG functions.

It works great, except that it doesn't, LOL. The code it fine, I've tested it in a sample, non C# application using the viewer and all.

The Question:
The part that I don't understand is how to use OSG to render in an existing OpenGL viewport. Is there a way to attach to the existing OpenGL instead of creating the OSG viewer as noted in every OSG example I've seen?

C# SharpGL initialization

Code:

// Initialize SharpGL
void initSharpGL() {
openGLControl = new SharpGL.OpenGLControl();
((System.ComponentModel.ISupportInitialize)(openGLControl)).BeginInit();

//
// openGLControl
//
openGLControl.BitDepth = 32;
openGLControl.Dock = System.Windows.Forms.DockStyle.Fill;
openGLControl.DrawFPS = true;
openGLControl.FrameRate = 60;
openGLControl.Location = new System.Drawing.Point(0, 0);
openGLControl.Name = "openGLControl";
openGLControl.RenderContextType = SharpGL.RenderContextType.FBO;
openGLControl.Size = new System.Drawing.Size(1680, 1060);
openGLControl.TabIndex = 0;
openGLControl.OpenGLInitialized += new System.EventHandler(openGLControl_OpenGLInitialized);
openGLControl.OpenGLDraw += new System.Windows.Forms.PaintEventHandler(openGLControl_OpenGLDraw);
openGLControl.Resized += new System.EventHandler(openGLControl_Resized);
openGLControl.Click += new System.EventHandler(OpenGL_Click);
((System.ComponentModel.ISupportInitialize)(openGLControl)).EndInit();
Controls.Add(openGLControl);

...
}




Native OSG Code:

Code:

// Create the scene root
mRoot = new osg::Group;

// The viewer
mViewer = new osgViewer::Viewer;
mWindow = mViewer->setUpViewerAsEmbeddedInWindow(0, 0, 1680, 998);
mViewer->getCamera()->setClearMask(0);
mViewer->setSceneData(mRoot);
mViewer->realize();

osg::ref_ptr<osg::Geode> geode = new osg::Geode;

std::string fontFile("arial.ttf");
font = osgText::readFontFile(fontFile);
if (font.valid()) {

osgText::Text* text = new osgText::Text;
if (text != 0) {
text->setFont(font);
text->setColor(osg::Vec4(0.0f, 1.0f, 1.0f, 1.0f));
text->setCharacterSize(40.0f);
text->setPosition(osg::Vec3(100.0f, 100.0f, 0.0f));
text->setText("SomeSome!");

text->setLayout(osgText::Text::LEFT_TO_RIGHT);

geode->addDrawable(text);
}
}

mRoot->addChild(geode);




The OSG Draw Callback function contents

Code:

mViewer->frame();




Thank you!

Cheers,
Dainon

------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=49871#49871
Sergey Polischuk
2012-09-17 07:33:45 UTC
Permalink
Hi

You could use graphics context\window created by another means (that what osg::GraphicsWindowEmbedded does), but you still should create osgviewer and stuff. You can check various osgviewer*** examples in osg source tree in examples directory.

Cheers.
Post by Dainon Woudstra
Hi,
I've written an application in C# for various reasons. SharpGL provided the OpenGL portion, C# provided the Database, and Intellisense works with it in VS 2010. I've rewritten this application in 3 different frameworks and have hit issues I could not solve for one reason or another. For example, now that my application works and I use it everyday, I'm trying to enhance some of its features, such as loading a 3D object and good text rendering.
I've come across OpenSceneGraph and have been trying to use it with the C# wrappers. I couldn't get that working and read a bunch of posts providing other solutions and mentioning it isn't supported anymore. Thus, I've learned to write a wrapper for a C++ OSG DLL to call some native OSG functions.
It works great, except that it doesn't, LOL. The code it fine, I've tested it in a sample, non C# application using the viewer and all.
The part that I don't understand is how to use OSG to render in an existing OpenGL viewport. Is there a way to attach to the existing OpenGL instead of creating the OSG viewer as noted in every OSG example I've seen?
C# SharpGL initialization
// Initialize SharpGL
void initSharpGL() {
   openGLControl = new SharpGL.OpenGLControl();
   ((System.ComponentModel.ISupportInitialize)(openGLControl)).BeginInit();
   //
   // openGLControl
   //
   openGLControl.BitDepth = 32;
   openGLControl.Dock = System.Windows.Forms.DockStyle.Fill;
   openGLControl.DrawFPS = true;
   openGLControl.FrameRate = 60;
   openGLControl.Location = new System.Drawing.Point(0, 0);
   openGLControl.Name = "openGLControl";
   openGLControl.RenderContextType = SharpGL.RenderContextType.FBO;
   openGLControl.Size = new System.Drawing.Size(1680, 1060);
   openGLControl.TabIndex = 0;
   openGLControl.OpenGLInitialized += new System.EventHandler(openGLControl_OpenGLInitialized);
   openGLControl.OpenGLDraw += new System.Windows.Forms.PaintEventHandler(openGLControl_OpenGLDraw);
   openGLControl.Resized += new System.EventHandler(openGLControl_Resized);
   openGLControl.Click += new System.EventHandler(OpenGL_Click);
   ((System.ComponentModel.ISupportInitialize)(openGLControl)).EndInit();
   Controls.Add(openGLControl);
   ...
}
// Create the scene root
mRoot = new osg::Group;
// The viewer
mViewer = new osgViewer::Viewer;
mWindow = mViewer->setUpViewerAsEmbeddedInWindow(0, 0, 1680, 998);
mViewer->getCamera()->setClearMask(0);
mViewer->setSceneData(mRoot);
mViewer->realize();
osg::ref_ptr<osg::Geode> geode = new osg::Geode;
std::string fontFile("arial.ttf");
font = osgText::readFontFile(fontFile);
if (font.valid()) {
   osgText::Text* text = new osgText::Text;
   if (text != 0) {
      text->setFont(font);
      text->setColor(osg::Vec4(0.0f, 1.0f, 1.0f, 1.0f));
      text->setCharacterSize(40.0f);
      text->setPosition(osg::Vec3(100.0f, 100.0f, 0.0f));
      text->setText("SomeSome!");
      text->setLayout(osgText::Text::LEFT_TO_RIGHT);
      geode->addDrawable(text);
   }
}
mRoot->addChild(geode);
The OSG Draw Callback function contents
mViewer->frame();
Thank you!
Cheers,
Dainon
------------------
http://forum.openscenegraph.org/viewtopic.php?p=49871#49871
_______________________________________________
osg-users mailing list
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org
Shayne Tueller
2012-09-17 16:28:46 UTC
Permalink
To render OSG in an existing OGL viewport, you still need to create an OSG viewer because that is what kicks off the OSG traversals when the frame() method is called. You also need to manage (i.e. Push and Pop) OGL state correctly since OSG and OGL share the same render context so that you don't trash your existing OGL rendering state.

Anyway, here's basically what you do to setup and render OSG stuff in an OGL viewport/window. This uses CompositeViewer so you could render multiple OSG viewports embedded inside an OGL window...:)

osgViewer::CompositeViewer *viewer = new osgViewer::CompositeViewer();
osgViewer::GraphicsWindowEmbedded *gw = new osgViewer::GraphicsWindow(ogl_x, ogl_y, ogl_w, ogl_h);

osgViewer::View *view = new osgViewer::View;
view->getCamera->setGraphicsContext(gw);
view->getCamera->setViewport(osg_x, osg_y, osg_w, osg_h); // somewhere inside OGL viewport/window that has origin in LL corner
.
.
// set rest of the view OSG camera state and matrices as usual
.
.
view->setSceneData(scenegraph);
viewer->addView(view);
viewer->realize();
.
.

// do this during rendering loop for each OGL frame...
PushOGLState();
viewer->frame(); // render OSG embedded viewport in OGL window
PopOGLState();

Hope this helps...

Shayne[/code]

------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=50153#50153
Dainon Woudstra
2012-09-18 01:30:04 UTC
Permalink
Hi,

S2LR, thanks for your help... I've tested out your suggestion and feel like I'm getting somewhere. The good/bad news, depending on your outlook, is that it does something. I had to modify some of what you provided to make it compile, but the result is that the application renders a solid color. With or without using...

gw->getCamera()->setClearMask(0);

or

view->getCamer()->setClearMask(0);

or neither

the application renders a solid color...

1) White without the clearMask
2) Black with the clearMask on view
3) Blue with the clearMask on gw

Additional Information
I have a three monitor display. The application runs on a 1680 x 1060 window, not full screen. When I run the code provided here, parts of the dartboard application renders on the first monitor for a split-second, then all three monitors are displaying the solid color.

I've played around with the OSG Cookbook Spheres example and found that calling the single screen function fixed the three screen issue.

viewer.setUpViewOnSingleScreen();

This function is not available with osgViwere::CompositeViewer.

OSG Setup

Code:

geode = new osg::Geode;

std::string fontFile("arial.ttf");
font = osgText::readFontFile(fontFile);
if (font.valid()) {

osgText::Text* text = new osgText::Text;
if (text != 0) {
text->setUseDisplayList(false);
text->setFont(font);
text->setColor(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
text->setCharacterSize(36.0f);
text->setAutoRotateToScreen(true);
text->setPosition(osg::Vec3(100.0f, 100.0f, 10.0f));
//text->setAxisAlignment(osgText::Text::XZ_PLANE);
text->setText("SomeSome!");

text->setLayout(osgText::Text::LEFT_TO_RIGHT);

geode->addDrawable(text);
}
}

viewer = new osgViewer::CompositeViewer();
osgViewer::GraphicsWindowEmbedded *gw = (osgViewer::GraphicsWindowEmbedded*) new osgViewer::GraphicsWindow();
gw->setWindowRectangle(0, 0, 1680, 1060);

osgViewer::View *view = new osgViewer::View;
view->getCamera()->setGraphicsContext(gw);
view->getCamera()->setViewport(0, 0, 1680, 1060); // somewhere inside OGL viewport/window that has origin in LL corner

view->setSceneData(geode);
viewer->addView(view);
viewer->realize();




Frame Renderer

Code:

glPushAttrib(GL_ALL_ATTRIB_BITS);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glMatrixMode(GL_TEXTURE);
glPushMatrix();
glMatrixMode(GL_MODELVIEW);
glPushMatrix();

viewer->frame();

glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glMatrixMode(GL_TEXTURE);
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glPopAttrib();
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);




Thank you!

Cheers,
Dainon

------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=50162#50162
Thomas Hogarth
2012-09-18 05:38:10 UTC
Permalink
Hi

So I've done this when working with the QCAR sdk as it seems
to insist on having ownership of the GL Context.

What you want is first setup the emmbeded viewer


Code:
osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();
osg::ref_ptr<osgViewer::GraphicsWindowEmbedded> embeddedWindow
embeddedWindow = viewer->setUpViewerAsEmbeddedInWindow(0, 0, w,h);
osg::ref_ptr<osg::StateSet> m_lastStateSet = new osg::StateSet();
viewer->getCamera()->getGraphicsContext()->getState()->captureCurrentState(*m_lastStateSet.get());




Then in your OpenGL apps render function after you have done your raw OpenGL stuff you want something like

osg::State *osgState = _viewer->getCamera()->getGraphicsContext()->getState();
osgState->reset();
osgState->apply(m_lastStateSet.get());

//render your osg frame here
viewer->frame();

//now get the state so you can restore next frame
viewer->getCamera()->getGraphicsContext()->getState()->captureCurrentState(*m_lastStateSet.get());


Hope that helps
Tom

------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=50167#50167
Dainon Woudstra
2012-09-18 23:10:22 UTC
Permalink
What I've tried from your suggestions
I hope the code here is clear enough. I haven't had any success with your suggestions to this point. I have placed them in an easy format to try them all without getting commented code mixed up with other code. I'm posting here the four relevant sections of my code, in hopes it may help get me over this hump. I've tried putting the OSG initialization before the OpenGl initialization and the three different suggestions of initialization and rendering. I've ensured the DLL wrapper works, it will retun the values I set in them and I can step through it while debugging and see legit values being assigned to the font. "DartModelDll.dll" is poorly named and will be changed in the future. Anywhere that name is in the following, assume OsgDLL.

C# Form Constructor

Code:

public partial class Form1 : Form
{
OsgWrapper osgWrapper;

// OpenGL contrrol object
private static OpenGLControl openGLControl;

public Form1()
{
// Initialze components
InitializeComponent();

// Test
osgWrapper = new OsgWrapper();
int blah = osgWrapper.Init();

// Initialize SharpGL
initSharpGL();

...




C# OSG Drawing Function

Code:

private void openGLControl_OpenGLDraw(object sender, PaintEventArgs e)
{
// Get the OpenGL object.
OpenGL gl = openGLControl.OpenGL;

// Clear the color and depth buffer.
gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT);
gl.ClearColor(0.0f, 0.0f, 0.0f, 1.0f);

// Load the identity matrix.
gl.LoadIdentity();

scoreKeeper.calculateGameScore();

// Render the textures for the dartboard and background
renderBackgroundTextures();

// render dartboard sections
renderDartboardSections();

// render scoring sections
renderScoringSection();

int blah = osgWrapper.TestText();

...




C# Wrapper Code for the Osg DLL

Code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using WMPLib;
using System.Runtime.InteropServices;

namespace DartBoardApplication.Items {
public class OsgWrapper {
[DllImport("DartModelDll.dll")]
static extern IntPtr dll_cOsgViewer();

[DllImport("DartModelDll.dll", CallingConvention = CallingConvention.Cdecl)]
static extern int dll_initViewer(IntPtr dm);

[DllImport("DartModelDll.dll", CallingConvention = CallingConvention.Cdecl)]
static extern int dll_testText(IntPtr dm);

IntPtr dartModel;

public OsgWrapper() {
dartModel = dll_cOsgViewer();
}

public int Init() {
return dll_initViewer(dartModel);
}

public int TestText() {
return dll_testText(dartModel);
}
}
}




Osg DLL

Code:

#include "Windows.h"
#include "gl/gl.h"
#include "osg/Node"
#include "osg/Geode"
#include "osg/Group"
#include "osgViewer/Viewer"
#include "osgViewer/CompositeViewer"
#include "osgViewer/GraphicsWindow"
#include "osgDB/ReadFile"
#include "osgText/Text"
#include "osg/ShapeDrawable"
#include "excpt.h"
#include "osg/StateSet"

#include "osgViewer/Viewer"
#include "osg/MatrixTransform"

using namespace osg;
using namespace osgDB;
using namespace osgText;

class COsgViewer {
public:
COsgViewer() {
};

~COsgViewer() {
}

osg::ref_ptr<osgText::Font> font;
osg::ref_ptr<osgViewer::Viewer> mViewer;
osgViewer::CompositeViewer *viewer;
osg::observer_ptr<osgViewer::GraphicsWindowEmbedded> mWindow;
osg::ref_ptr<osg::Group> mRoot;
osg::ref_ptr<osg::Geode> geode;
osg::ref_ptr<osg::StateSet> mLastStateSet;

int initViewer(void) {

//initViewer1();
//initViewer2();
initViewer3();

return 4;
}

void initViewer1() {
// Create the scene root
mRoot = new osg::Group;

geode = new osg::Geode;

std::string fontFile("arial.ttf");
font = osgText::readFontFile(fontFile);
if (font.valid()) {

osgText::Text* text = new osgText::Text;
if (text != 0) {
text->setUseDisplayList(false);
text->setFont(font);
text->setColor(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
text->setCharacterSize(36.0f);
text->setAutoRotateToScreen(true);
text->setPosition(osg::Vec3(100.0f, 100.0f, 10.0f));
//text->setAxisAlignment(osgText::Text::XZ_PLANE);
text->setText("SomeSome!");

text->setLayout(osgText::Text::LEFT_TO_RIGHT);

geode->addDrawable(text);
}
}

mRoot->addChild(geode);

// The viewer
mViewer = new osgViewer::Viewer;
mWindow = mViewer->setUpViewerAsEmbeddedInWindow(0, 0, 1680, 1060);
mViewer->getCamera()->setClearMask(0);
mViewer->getCamera()->setComputeNearFarMode(osgUtil::CullVisitor::DO_NOT_COMPUTE_NEAR_FAR);
mViewer->setSceneData(mRoot);
mViewer->realize();
}

void initViewer2() {
// Create the scene root
mRoot = new osg::Group;

geode = new osg::Geode;

std::string fontFile("arial.ttf");
font = osgText::readFontFile(fontFile);
if (font.valid()) {

osgText::Text* text = new osgText::Text;
if (text != 0) {
text->setUseDisplayList(false);
text->setFont(font);
text->setColor(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
text->setCharacterSize(36.0f);
text->setAutoRotateToScreen(true);
text->setPosition(osg::Vec3(100.0f, 100.0f, 10.0f));
//text->setAxisAlignment(osgText::Text::XZ_PLANE);
text->setText("SomeSome!");

text->setLayout(osgText::Text::LEFT_TO_RIGHT);

geode->addDrawable(text);
}
}

viewer = new osgViewer::CompositeViewer();
osgViewer::GraphicsWindowEmbedded *gw = (osgViewer::GraphicsWindowEmbedded*) new osgViewer::GraphicsWindow();
gw->setWindowRectangle(0, 0, 1680, 1060);
gw->setClearMask(0);

osgViewer::View *view = new osgViewer::View;
view->getCamera()->setGraphicsContext(gw);
view->getCamera()->setViewport(0, 0, 1680, 1060); // somewhere inside OGL viewport/window that has origin in LL corner

view->setSceneData(geode);
viewer->addView(view);
viewer->realize();
}

void initViewer3() {
// Create the scene root
mRoot = new osg::Group;

geode = new osg::Geode;

std::string fontFile("arial.ttf");
font = osgText::readFontFile(fontFile);
if (font.valid()) {

osgText::Text* text = new osgText::Text;
if (text != 0) {
text->setUseDisplayList(false);
text->setFont(font);
text->setColor(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
text->setCharacterSize(36.0f);
text->setAutoRotateToScreen(true);
text->setPosition(osg::Vec3(100.0f, 100.0f, 10.0f));
//text->setAxisAlignment(osgText::Text::XZ_PLANE);
text->setText("SomeSome!");

text->setLayout(osgText::Text::LEFT_TO_RIGHT);

geode->addDrawable(text);
}
}

mRoot->addChild(geode);

mViewer = new osgViewer::Viewer();
osg::ref_ptr<osgViewer::GraphicsWindowEmbedded> embeddedWindow;

embeddedWindow = mViewer->setUpViewerAsEmbeddedInWindow(0, 0, 1680, 1060);

osg::ref_ptr<osg::StateSet> mLastStateSet = new osg::StateSet();
mViewer->getCamera()->getGraphicsContext()->getState()->captureCurrentState(*mLastStateSet.get());

//mViewer->setSceneData(mRoot);
//mViewer->realize();
}

int testText() {
//testText1();
//testText2();
testText3();

return 1;
}

int testText1() {
// This function can be used to test rendering text.
// Is called every frame

glPushAttrib(GL_ALL_ATTRIB_BITS);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glMatrixMode(GL_TEXTURE);
glPushMatrix();
glMatrixMode(GL_MODELVIEW);
glPushMatrix();

mViewer->frame();

glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glMatrixMode(GL_TEXTURE);
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glPopAttrib();
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);

return 1;
}

int testText2() {
// This function can be used to test rendering text.
// Is called every frame

glPushAttrib(GL_ALL_ATTRIB_BITS);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glMatrixMode(GL_TEXTURE);
glPushMatrix();
glMatrixMode(GL_MODELVIEW);
glPushMatrix();

viewer->frame();

glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glMatrixMode(GL_TEXTURE);
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glPopAttrib();
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);

return 1;
}

int testText3() {
osg::State *osgState = mViewer->getCamera()->getGraphicsContext()->getState();
osgState->reset();
osgState->apply(mLastStateSet.get());

//render your osg frame here
mViewer->frame();

//now get the state so you can restore next frame
mViewer->getCamera()->getGraphicsContext()->getState()->captureCurrentState(*mLastStateSet.get());

return 1;
}
};

extern "C" {
__declspec(dllexport) COsgViewer* dll_cOsgViewer() { return new COsgViewer(); }
}

extern "C" {
__declspec(dllexport) int dll_initViewer(COsgViewer* dm) { return dm->initViewer(); }
}

extern "C" {
__declspec(dllexport) int dll_testText(COsgViewer* dm) { return dm->testText(); }
}






Thank you!

Cheers,
Dainon

------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=50179#50179

Loading...