Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: SFML2 & OpenSceneGraph Examples  (Read 5426 times)

0 Members and 1 Guest are viewing this topic.

kloffy

  • Newbie
  • *
  • Posts: 21
    • View Profile
SFML2 & OpenSceneGraph Examples
« on: March 08, 2013, 10:35:31 pm »
The old thread on this topic has not been updated in a while. Towards the end, it sounds like the original author had a couple of problems. Lately, I have decided to give this a try myself. So far, everything is working well, but there are a few things to look out for. I have decided to post a couple of examples that will hopefully make it easier for others to get started.

The examples are written and tested on Windows using Visual Studio 2012. However, the only platform specific feature are some of the preprocessor directives, which are used to conveniently configure project settings and link libraries.

There are no dependencies apart from SFML 2 and OpenSceneGraph 3.

kloffy

  • Newbie
  • *
  • Posts: 21
    • View Profile
Re: SFML2 & OpenSceneGraph Examples
« Reply #1 on: March 08, 2013, 10:39:26 pm »
Example 1: Setup Viewer

Setting up an osgViewer in a SFML window is very easy. Here is how I do it:

#if defined(_DEBUG)
#pragma comment(linker, "/SUBSYSTEM:\"console\"")
#else
#pragma comment(linker, "/SUBSYSTEM:\"windows\" /ENTRY:\"mainCRTStartup\"")
#endif

#if defined(_DEBUG)
#pragma comment(lib, "sfml-graphics-d.lib")
#pragma comment(lib, "sfml-window-d.lib")
#pragma comment(lib, "sfml-system-d.lib")
#else
#pragma comment(lib, "sfml-graphics.lib")
#pragma comment(lib, "sfml-window.lib")
#pragma comment(lib, "sfml-system.lib")
#endif

#if defined(_DEBUG)
#pragma comment(lib, "osgd.lib")
#pragma comment(lib, "osgViewerd.lib")
#else
#pragma comment(lib, "osg.lib")
#pragma comment(lib, "osgViewer.lib")
#endif

#include <SFML/Graphics.hpp>

#pragma warning(push)
#pragma warning(disable: 4250)

#include <osgViewer/Viewer>

#pragma warning(pop)

int main(int argc, char** argv)
{
        //osg::setNotifyLevel(osg::DEBUG_INFO);

        sf::RenderWindow window;
        window.setVerticalSyncEnabled(true);

        sf::VideoMode mode = sf::VideoMode::getDesktopMode();
        mode.width = 800;
        mode.height = 600;

        window.create(mode, "SFML+OSG Example");

        sf::Vector2u size = window.getSize();

        osgViewer::Viewer viewer;
        osg::ref_ptr<osgViewer::GraphicsWindowEmbedded> gw = viewer.setUpViewerAsEmbeddedInWindow(0, 0, size.x, size.y);
        viewer.realize();

        while (window.isOpen())
        {
                sf::Event event;
                while (window.pollEvent(event))
                {
                        switch(event.type)
                        {
                        case sf::Event::Closed:
                                window.close();
                                break;
                        case sf::Event::KeyPressed:
                                if (event.key.code == sf::Keyboard::Escape)
                                {
                                        window.close();
                                }
                                break;
                        case sf::Event::Resized:
                                gw->resized(0, 0, event.size.width, event.size.height);
                                break;
                        }
                }

                window.setActive();
               
                viewer.frame();

                window.display();
        }

        return 0;
}

The only thing to keep in mind is letting the viewer know whenever the window changes size.
« Last Edit: March 08, 2013, 10:55:02 pm by kloffy »

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 10815
    • View Profile
    • development blog
    • Email
Re: SFML2 & OpenSceneGraph Examples
« Reply #2 on: March 08, 2013, 10:53:24 pm »
I strongly advise against the use of #pragma comment or similar, since it's not the source codes job to tell the linker how to work.
Besides that it's not really complicated to state, that one has to link against the SFML and OpenSceneGraph. With such a statement and a cleaned up code, your source code will automatically become cross-platform.

Nice example though. ;)

Btw. you should never use a framerate limit and vsync together, this can lead to strange and bad behavior. Also if you're using a sf::RenderWindow you need to clear it each frame iteration.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

kloffy

  • Newbie
  • *
  • Posts: 21
    • View Profile
Re: SFML2 & OpenSceneGraph Examples
« Reply #3 on: March 08, 2013, 11:03:57 pm »
Thank you for your comments! Yes, you are absolutely right about the pragmas. I suppose I can just remove them in the next examples. Basically, I just wanted to make it explicit which libraries are being linked.

Thanks for the heads up about potential problems with framerate limit and vsync. I have opted to use only vsync for now. However, is clear really necessary? (OpenGL buffers are cleared by osgViewer.)

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 10815
    • View Profile
    • development blog
    • Email
Re: SFML2 & OpenSceneGraph Examples
« Reply #4 on: March 08, 2013, 11:22:40 pm »
However, is clear really necessary? (OpenGL buffers are cleared by osgViewer.)
Ah well if they get cleared by osgViewer then it's okay. ;D
If you don't draw anything with SFML directly you might want to only use a sf::Window instead.
If you plan on drawing stuff with SFML, I think you'll also have to adjust the sf::View of the RenderWindow.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

kloffy

  • Newbie
  • *
  • Posts: 21
    • View Profile
Re: SFML2 & OpenSceneGraph Examples
« Reply #5 on: March 08, 2013, 11:23:33 pm »
Example 2: Inject Events

Since SFML is in charge of the window, it is necessary to forward events to OSG. This requires conversion functions, which are essentially huge switch statements. In order to keep the main application code simple, I threw them in a separate header.

#if defined(_DEBUG)
#pragma comment(linker, "/SUBSYSTEM:\"console\"")
#else
#pragma comment(linker, "/SUBSYSTEM:\"windows\" /ENTRY:\"mainCRTStartup\"")
#endif

#if defined(_DEBUG)
#pragma comment(lib, "sfml-graphics-d.lib")
#pragma comment(lib, "sfml-window-d.lib")
#pragma comment(lib, "sfml-system-d.lib")
#else
#pragma comment(lib, "sfml-graphics.lib")
#pragma comment(lib, "sfml-window.lib")
#pragma comment(lib, "sfml-system.lib")
#endif

#if defined(_DEBUG)
#pragma comment(lib, "osgd.lib")
#pragma comment(lib, "osgGAd.lib")
#pragma comment(lib, "osgViewerd.lib")
#else
#pragma comment(lib, "osg.lib")
#pragma comment(lib, "osgGA.lib")
#pragma comment(lib, "osgViewer.lib")
#endif

#include <SFML/Graphics.hpp>

#pragma warning(push)
#pragma warning(disable: 4250)

#include <osgViewer/Viewer>

#pragma warning(pop)

#include "sf2osg.h"

int main(int argc, char** argv)
{
        //osg::setNotifyLevel(osg::DEBUG_INFO);

        sf::RenderWindow window;
        window.setVerticalSyncEnabled(true);

        sf::VideoMode mode = sf::VideoMode::getDesktopMode();
        mode.width = 800;
        mode.height = 600;

        window.create(mode, "SFML+OSG Example");

        sf::Vector2u size = window.getSize();

        osgViewer::Viewer viewer;
        osg::ref_ptr<osgViewer::GraphicsWindowEmbedded> gw = viewer.setUpViewerAsEmbeddedInWindow(0, 0, size.x, size.y);
        viewer.realize();

        while (window.isOpen())
        {
                sf::Event event;
                while (window.pollEvent(event))
                {
                        sf2osg::processEvent(*(gw->getEventQueue()), event);

                        switch(event.type)
                        {
                        case sf::Event::Closed:
                                window.close();
                                break;
                        case sf::Event::KeyPressed:
                                if (event.key.code == sf::Keyboard::Escape)
                                {
                                        window.close();
                                }
                                break;
                        case sf::Event::Resized:
                                gw->resized(0, 0, event.size.width, event.size.height);
                                break;
                        }
                }

                if (!window.isOpen()) break;

                window.setActive();
               
                viewer.frame();

                window.display();
        }

        return 0;
}

I have attached the header file, since it is a bit long. It is not an exhaustive implementation, but it should cover the most common uses.

[attachment deleted by admin]
« Last Edit: March 09, 2013, 01:17:38 am by kloffy »

kloffy

  • Newbie
  • *
  • Posts: 21
    • View Profile
Re: SFML2 & OpenSceneGraph Examples
« Reply #6 on: March 08, 2013, 11:39:19 pm »
Example 3: Render Something

With the preparations out of the way, let us use the osgViewer to render a model.

#if defined(_DEBUG)
#pragma comment(linker, "/SUBSYSTEM:\"console\"")
#else
#pragma comment(linker, "/SUBSYSTEM:\"windows\" /ENTRY:\"mainCRTStartup\"")
#endif

#if defined(_DEBUG)
#pragma comment(lib, "sfml-graphics-d.lib")
#pragma comment(lib, "sfml-window-d.lib")
#pragma comment(lib, "sfml-system-d.lib")
#else
#pragma comment(lib, "sfml-graphics.lib")
#pragma comment(lib, "sfml-window.lib")
#pragma comment(lib, "sfml-system.lib")
#endif

#if defined(_DEBUG)
#pragma comment(lib, "osgd.lib")
#pragma comment(lib, "osgDBd.lib")
#pragma comment(lib, "osgGAd.lib")
#pragma comment(lib, "osgViewerd.lib")
#else
#pragma comment(lib, "osg.lib")
#pragma comment(lib, "osgDB.lib")
#pragma comment(lib, "osgGA.lib")
#pragma comment(lib, "osgViewer.lib")
#endif

#include <SFML/Graphics.hpp>

#pragma warning(push)
#pragma warning(disable: 4250)

#include <osgDB/ReadFile>
#include <osgDB/WriteFile>
#include <osgGA/TrackballManipulator>
#include <osgViewer/Viewer>

#pragma warning(pop)

#include "sf2osg.h"

int main(int argc, char** argv)
{
        //osg::setNotifyLevel(osg::DEBUG_INFO);

        sf::RenderWindow window;
        window.setVerticalSyncEnabled(true);

        sf::VideoMode mode = sf::VideoMode::getDesktopMode();
        mode.width = 800;
        mode.height = 600;

        window.create(mode, "SFML+OSG Example");

        osg::ref_ptr<osg::Node> root = osgDB::readNodeFile("cow.osg");
       
        if (!root)
        {
                std::cerr << "Failed to load model." << std::endl;
                return 1;
        }
       
        sf::Vector2u size = window.getSize();

        osgViewer::Viewer viewer;
        osg::ref_ptr<osgViewer::GraphicsWindowEmbedded> gw = viewer.setUpViewerAsEmbeddedInWindow(0, 0, size.x, size.y);
        viewer.setCameraManipulator(new osgGA::TrackballManipulator);
        viewer.setSceneData(root.get());
        viewer.realize();

        while (window.isOpen())
        {
                sf::Event event;
                while (window.pollEvent(event))
                {
                        sf2osg::processEvent(*(gw->getEventQueue()), event);

                        switch(event.type)
                        {
                        case sf::Event::Closed:
                                window.close();
                                break;
                        case sf::Event::KeyPressed:
                                if (event.key.code == sf::Keyboard::Escape)
                                {
                                        window.close();
                                }
                                break;
                        case sf::Event::Resized:
                                gw->resized(0, 0, event.size.width, event.size.height);
                                break;
                        }
                }

                if (!window.isOpen()) break;

                window.setActive();
               
                viewer.frame();

                window.display();
        }

        return 0;
}

In order for this to work, you can either configure the OSG_FILE_PATH environment variable to point to the OSG example data directory or copy the model (and associated data) into the working directory.
« Last Edit: March 09, 2013, 12:23:10 am by kloffy »

kloffy

  • Newbie
  • *
  • Posts: 21
    • View Profile
Re: SFML2 & OpenSceneGraph Examples
« Reply #7 on: March 09, 2013, 12:59:07 am »
Example 4: Mixed OSG/SFML Rendering

This is what eXpl0it3r already hinted at: Drawing from both APIs. This can be somewhat tricky due to the shared OpenGL state. Nevertheless, it is possible and here is one way to go about it:

#if defined(_DEBUG)
#pragma comment(linker, "/SUBSYSTEM:\"console\"")
#else
#pragma comment(linker, "/SUBSYSTEM:\"windows\" /ENTRY:\"mainCRTStartup\"")
#endif

#if defined(_DEBUG)
#pragma comment(lib, "sfml-graphics-d.lib")
#pragma comment(lib, "sfml-window-d.lib")
#pragma comment(lib, "sfml-system-d.lib")
#else
#pragma comment(lib, "sfml-graphics.lib")
#pragma comment(lib, "sfml-window.lib")
#pragma comment(lib, "sfml-system.lib")
#endif

#if defined(_DEBUG)
#pragma comment(lib, "osgd.lib")
#pragma comment(lib, "osgDBd.lib")
#pragma comment(lib, "osgGAd.lib")
#pragma comment(lib, "osgViewerd.lib")
#else
#pragma comment(lib, "osg.lib")
#pragma comment(lib, "osgDB.lib")
#pragma comment(lib, "osgGA.lib")
#pragma comment(lib, "osgViewer.lib")
#endif

#include <SFML/Graphics.hpp>

#pragma warning(push)
#pragma warning(disable: 4250)

#include <osgDB/ReadFile>
#include <osgDB/WriteFile>
#include <osgGA/TrackballManipulator>
#include <osgViewer/Viewer>

#pragma warning(pop)

#include "sf2osg.h"

int main(int argc, char** argv)
{
        //osg::setNotifyLevel(osg::DEBUG_INFO);

        sf::RenderWindow window;
        window.setVerticalSyncEnabled(true);

        sf::VideoMode mode = sf::VideoMode::getDesktopMode();
        mode.width = 800;
        mode.height = 600;

        window.create(mode, "SFML+OSG Example");

        osg::ref_ptr<osg::Node> root = osgDB::readNodeFile("cow.osg");

        if (!root)
        {
                std::cerr << "Failed to load model." << std::endl;
                return 1;
        }

        sf::Vector2u size = window.getSize();

        sf::Font font;
        if (!font.loadFromFile("verdana.ttf"))
        {
                std::cerr << "Failed to load font." << std::endl;
                return 1;
        }

        sf::Text text("Hello SFML+OSG!", font, 24);
        sf::FloatRect bounds = text.getLocalBounds();
        text.setPosition((size.x-bounds.width)/2.0f, (size.y-bounds.height)/2.0f);

        osgViewer::Viewer viewer;
        osg::ref_ptr<osgViewer::GraphicsWindowEmbedded> gw = viewer.setUpViewerAsEmbeddedInWindow(0, 0, size.x, size.y);
        viewer.setCameraManipulator(new osgGA::TrackballManipulator);
        viewer.setSceneData(root.get());
        viewer.realize();

        while (window.isOpen())
        {
                sf::Event event;
                while (window.pollEvent(event))
                {
                        sf2osg::processEvent(*(gw->getEventQueue()), event);

                        switch(event.type)
                        {
                        case sf::Event::Closed:
                                window.close();
                                break;
                        case sf::Event::KeyPressed:
                                if (event.key.code == sf::Keyboard::Escape)
                                {
                                        window.close();
                                }
                                break;
                        case sf::Event::Resized:
                                window.setView(sf::View(sf::FloatRect(0.0f, 0.0f, float(event.size.width), float(event.size.height))));
                                gw->resized(0, 0, event.size.width, event.size.height);
                                break;
                        }
                }

                if (!window.isOpen()) break;

                window.setActive();

                viewer.frame();

                window.pushGLStates();

                window.draw(text);

                window.popGLStates();

                window.display();
        }

        return 0;
}

While it can be done, I am not convinced that it is actually a good idea. It may be better to just stick with one rendering API. If you're already using OSG, you might as well use it for all your drawing code.
« Last Edit: March 09, 2013, 01:59:49 pm by kloffy »