Horde3D

Next-Generation Graphics Engine
It is currently 19.03.2024, 04:10

All times are UTC + 1 hour




Post new topic Reply to topic  [ 3 posts ] 
Author Message
PostPosted: 05.03.2015, 15:47 
Offline

Joined: 04.03.2015, 20:14
Posts: 2
Hi everyone,

first off - congratulations on this engine. I was kinda skepictal when I decided to switch from Ogre3d a few days ago and was surprised how easy and accessible Horde3D is. I really want to use it which makes this problem a very frustrating one.

I have an existing Qt Application with lots of code and other dependencies that make it impossible for me to switch to any other framework. Following the Qt "OpenGL Window Example" (http://doc.qt.io/qt-5/qtgui-openglwindow-example.html), integrating the Knight-example from the Horde3D source was straightforward and painless. But then an I realized, that the offical example binary (using glfw) looked a lot better than what was displayed in the QWindow :shock: Most visibly, the particles emitted from the tip of the sword are missing. So is the glow of the armor and the soft specular on the ground.

Here is a comparison:

Original Display (source example using glfw)

Image

QWindow Display

Image

There is an existing thread on Stackoverflow reporting the same problem 3 years ago, but it is still unresolved: http://stackoverflow.com/questions/8594805/horde3d-particle-system-not-rendering-in-qt-opengl

I have attached the complete source at the bottom - just like in the SO post above, it is the exact same code used in the Knight example but with a bit of Qt framework around. My machine is running Ubuntu 14.10, I am using the current NVIDIA driver version 311.11, Qt 5.4 and the latest Horde3D, freshly built from the Github repo.

Here are some things I tried out already, but didn't work:

  1. Made sure that the particles exist. If you turn on the debug view, their bounding box is clearly visible and updated.
  2. Define the default QSurfaceFormat to use OpenGL version 4.3 (compatibility profile). The correct context is created, but
    the change has no visible effect.
  3. Copied all values I found in the glfw initializing code to the QSurfaceFormat with no effect.
  4. Set the Qt::AA_UseDesktopOpenGL attribute in order to force the application NOT to use OpenGL ES - no effect (as expected with the correct OpenGL context in place).
  5. Tried using the QOpenGLWidget instead of QWindow as the base class for integrating Horde3D - no effect.
  6. Replaced the new-style QOpenGLWidget with an old-style QGLWidget - no effect.
  7. Downloaded the official Horde Editor (since the newest version also uses Qt) and looked at its code, but found no significant functionality that I was missing.
  8. Rebuild Qt from source specifying "-opengl desktop", which I think does nothing under Linux but just in case
  9. Tried to use GLEW for OpenGL function resolving, not sure that it actually worked as it (again) did not change anything...

So right now, I am ready to give up :cry:
Does anybody here have a working Qt-integration of Horde3D that looks as it should? Any help would be greatly appreciated.

Cheers and thank you,
- Clemens

For reference, here is the complete code of the Qt Knight example application:

KnightExample.pro
Code:
QT      += core gui widgets
CONFIG  += c++11

TARGET = KnightExample
TEMPLATE = app

SOURCES += main.cpp \
    hordewindow.cpp

HEADERS  += \
    hordewindow.h

INCLUDEPATH += >>>HARDCODED PATH TO:/Horde3D/Horde3D/Bindings/C++/
LIBS += -L>>>HARDCODED PATH TO:/Horde3D/libs -lHorde3D -lHorde3DUtils # I created the libs folder for convenience
LIBS += -L/usr/lib/nvidia-331-updates/ # fixes a linker bug in Ubuntu 14.10


main.cpp

Code:
#include "horde3dwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    // doesn't change anything...
    QApplication::setAttribute(Qt::AA_UseDesktopOpenGL);

    // changes the context version, but nothing visually...
    QSurfaceFormat format;
    format.setVersion(4,3);
    format.setProfile(QSurfaceFormat::CompatibilityProfile);
    QSurfaceFormat::setDefaultFormat(format);

    QApplication a(argc, argv);
    Horde3DWindow w;
    w.setAnimating(true);
    w.show();
    w.resize(1024, 576); // same as the example

    return a.exec();
}


horde3dwindow.h

Code:
#ifndef HORDE3DWINDOW_H
#define HORDE3DWINDOW_H

#include <sstream>
#include <string>

#include <QWindow>

#include "Horde3D.h"

class QOpenGLContext;

class Horde3DWindow : public QWindow
{
    Q_OBJECT

public:

    explicit Horde3DWindow(QWindow *parent = nullptr);
    ~Horde3DWindow();
    void initialize();
    void render();
    void setAnimating(bool animating);

public slots:

    void renderNow();
    void renderLater();

protected:

    bool event(QEvent *event) override;
    void exposeEvent(QExposeEvent *event) override;

private:

    QOpenGLContext *m_context;
    bool m_isUpdateRequested;
    bool m_isAnimated;

private: // knight example members

    float              _x, _y, _z, _rx, _ry;  // Viewer position and orientation
    float              _velocity;  // Velocity for movement
    float              _curFPS;
    std::stringstream  _text;

    int                _statMode;
    int                _freezeMode;
    bool               _debugViewMode, _wireframeMode;
    float              _animTime, _weight;

    // Engine objects
    H3DRes             _fontMatRes, _panelMatRes;
    H3DRes             _pipeRes, _logoMatRes, _hdrPipeRes, _forwardPipeRes;
    H3DNode            _cam, _knight, _particleSys;

    std::string        _contentDir;
};

#endif // HORDE3DWINDOW_H


horde3dwindow.cpp

Code:
#include "horde3dwindow.h"

#include <math.h>
#include <iomanip>

#include <QCoreApplication>
#include <QDebug>
#include <QOpenGLContext>
#include <QSurfaceFormat>

#include <Horde3DUtils.h>

Horde3DWindow::Horde3DWindow(QWindow *parent)
    : QWindow(parent)
    , m_context(nullptr)
    , m_isUpdateRequested(false)
    , m_isAnimated(false)
{
    // indicate that the window is to be used for OpenGL rendering
    setSurfaceType(QWindow::OpenGLSurface);

    // knight example initializations
    _x = 5; _y = 3; _z = 19; _rx = 7; _ry = 15; _velocity = 10.0f;
    _curFPS = 30;

    _statMode = 1;
    _freezeMode = 0; _debugViewMode = false; _wireframeMode = false;
    _animTime = 0; _weight = 1.0f;
    _cam = 0;

    _contentDir = >>>HARDCODED PATH TO:"/Horde3D/Horde3D/Binaries/Content";
}

Horde3DWindow::~Horde3DWindow()
{
    // Release engine
    h3dutDumpMessages();
    h3dRelease();
}

// This is an exact copy of the original example's source
void Horde3DWindow::initialize()
{
    h3dInit();

    // Set options
    h3dSetOption( H3DOptions::LoadTextures, 1 );
    h3dSetOption( H3DOptions::TexCompression, 0 );
    h3dSetOption( H3DOptions::FastAnimation, 0 );
    h3dSetOption( H3DOptions::MaxAnisotropy, 4 );
    h3dSetOption( H3DOptions::ShadowMapSize, 2048 );

    // Add resources
    // Pipelines
    _hdrPipeRes = h3dAddResource( H3DResTypes::Pipeline, "pipelines/hdr.pipeline.xml", 0 );
    _forwardPipeRes = h3dAddResource( H3DResTypes::Pipeline, "pipelines/forward.pipeline.xml", 0 );
    // Overlays
    _fontMatRes = h3dAddResource( H3DResTypes::Material, "overlays/font.material.xml", 0 );
    _panelMatRes = h3dAddResource( H3DResTypes::Material, "overlays/panel.material.xml", 0 );
    _logoMatRes = h3dAddResource( H3DResTypes::Material, "overlays/logo.material.xml", 0 );
    // Environment
    H3DRes envRes = h3dAddResource( H3DResTypes::SceneGraph, "models/sphere/sphere.scene.xml", 0 );
    // Knight
    H3DRes knightRes = h3dAddResource( H3DResTypes::SceneGraph, "models/knight/knight.scene.xml", 0 );
    H3DRes knightAnim1Res = h3dAddResource( H3DResTypes::Animation, "animations/knight_order.anim", 0 );
    H3DRes knightAnim2Res = h3dAddResource( H3DResTypes::Animation, "animations/knight_attack.anim", 0 );
    // Particle system
    H3DRes particleSysRes = h3dAddResource( H3DResTypes::SceneGraph, "particles/particleSys1/particleSys1.scene.xml", 0 );

    // Load resources
    h3dutLoadResourcesFromDisk( _contentDir.c_str() );

    // Add scene nodes
    // Add camera
    _cam = h3dAddCameraNode( H3DRootNode, "Camera", _hdrPipeRes );
    //h3dSetNodeParamI( _cam, H3DCamera::OccCullingI, 1 );
    // Add environment
    H3DNode env = h3dAddNodes( H3DRootNode, envRes );
    h3dSetNodeTransform( env, 0, -20, 0, 0, 0, 0, 20, 20, 20 );
    // Add knight
    _knight = h3dAddNodes( H3DRootNode, knightRes );
    h3dSetNodeTransform( _knight, 0, 0, 0, 0, 180, 0, 0.1f, 0.1f, 0.1f );
    h3dSetupModelAnimStage( _knight, 0, knightAnim1Res, 0, "", false );
    h3dSetupModelAnimStage( _knight, 1, knightAnim2Res, 0, "", false );
    // Attach particle system to hand joint
    h3dFindNodes( _knight, "Bip01_R_Hand", H3DNodeTypes::Joint );
    H3DNode hand = h3dGetNodeFindResult( 0 );
    _particleSys = h3dAddNodes( hand, particleSysRes );
    h3dSetNodeTransform( _particleSys, 0, 40, 0, 90, 0, 0, 1, 1, 1 );

    // Add light source
    H3DNode light = h3dAddLightNode( H3DRootNode, "Light1", 0, "LIGHTING", "SHADOWMAP" );
    h3dSetNodeTransform( light, 0, 15, 10, -60, 0, 0, 1, 1, 1 );
    h3dSetNodeParamF( light, H3DLight::RadiusF, 0, 30 );
    h3dSetNodeParamF( light, H3DLight::FovF, 0, 90 );
    h3dSetNodeParamI( light, H3DLight::ShadowMapCountI, 1 );
    h3dSetNodeParamF( light, H3DLight::ShadowMapBiasF, 0, 0.01f );
    h3dSetNodeParamF( light, H3DLight::ColorF3, 0, 1.0f );
    h3dSetNodeParamF( light, H3DLight::ColorF3, 1, 0.8f );
    h3dSetNodeParamF( light, H3DLight::ColorF3, 2, 0.7f );
    h3dSetNodeParamF( light, H3DLight::ColorMultiplierF, 0, 1.0f );

    // Customize post processing effects
    H3DNode matRes = h3dFindResource( H3DResTypes::Material, "pipelines/postHDR.material.xml" );
    h3dSetMaterialUniform( matRes, "hdrExposure", 2.5f, 0, 0, 0 );
    h3dSetMaterialUniform( matRes, "hdrBrightThres", 0.5f, 0, 0, 0 );
    h3dSetMaterialUniform( matRes, "hdrBrightOffset", 0.08f, 0, 0, 0 );
}

// This is an (almost) exact copy of the original example's source
void Horde3DWindow::render()
{
    _curFPS = 30; // just hardcode the fps for now

    h3dSetOption( H3DOptions::DebugViewMode, _debugViewMode ? 1.0f : 0.0f );
    h3dSetOption( H3DOptions::WireframeMode, _wireframeMode ? 1.0f : 0.0f );

    if( !_freezeMode )
    {
        _animTime += 1.0f / _curFPS;

        // Do animation blending
        h3dSetModelAnimParams( _knight, 0, _animTime * 24.0f, _weight );
        h3dSetModelAnimParams( _knight, 1, _animTime * 24.0f, 1.0f - _weight );
        h3dUpdateModel( _knight, H3DModelUpdateFlags::Animation | H3DModelUpdateFlags::Geometry );

        // Animate particle systems (several emitters in a group node)
        unsigned int cnt = h3dFindNodes( _particleSys, "", H3DNodeTypes::Emitter );
        for( unsigned int i = 0; i < cnt; ++i )
            h3dUpdateEmitter( h3dGetNodeFindResult( i ), 1.0f / _curFPS );
    }

    // Set camera parameters
    h3dSetNodeTransform( _cam, _x, _y, _z, _rx ,_ry, 0, 1, 1, 1 );

    // Show stats
    h3dutShowFrameStats( _fontMatRes, _panelMatRes, _statMode );
    if( _statMode > 0 )
    {
        // Display weight
        _text.str( "" );
        _text << std::fixed << std::setprecision( 2 ) << "Weight: " << _weight;
        h3dutShowText( _text.str().c_str(), 0.03f, 0.24f, 0.026f, 1, 1, 1, _fontMatRes );
    }

    // Show logo
    const float ww = (float)h3dGetNodeParamI( _cam, H3DCamera::ViewportWidthI ) /
                     (float)h3dGetNodeParamI( _cam, H3DCamera::ViewportHeightI );
    const float ovLogo[] = { ww-0.4f, 0.8f, 0, 1,  ww-0.4f, 1, 0, 0,  ww, 1, 1, 0,  ww, 0.8f, 1, 1 };
    h3dShowOverlays( ovLogo, 4, 1.f, 1.f, 1.f, 1.f, _logoMatRes, 0 );

    // Render scene
    h3dRender( _cam );

    // Finish rendering of frame
    h3dFinalizeFrame();

    // Remove all overlays
    h3dClearOverlays();

    // Write all messages to log file
    h3dutDumpMessages();
}

void Horde3DWindow::setAnimating(bool animating)
{
    m_isAnimated = animating;
    if (m_isAnimated) {
        renderLater();
    }
}

void Horde3DWindow::renderNow()
{
    // return early if the Window is not visible on the screen
    if (!isExposed()){
        return;
    }

    // create a new context, if there is none yet...
    if (!m_context) {

        //  create the Context with the same QSurfaceFormat as the Horde3DWindow
        m_context = new QOpenGLContext(this);
        m_context->setFormat(requestedFormat());
        qDebug() << m_context->format(); // print out the context format .. I think this is were the problem is?
        m_context->create();
        m_context->makeCurrent(this);

        initialize();

    // ...otherwise just make it current
    } else {
        m_context->makeCurrent(this);
    }

    // render the Window and make its contents visible
    render();
    m_context->swapBuffers(this);

    // if the window is animated, automatically trigger an update on the next vertical refresh
    if (m_isAnimated) {
        renderLater();
    }
}

void Horde3DWindow::renderLater()
{
    // only post one request at a time
    if (!m_isUpdateRequested) {
        m_isUpdateRequested = true;
        QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest));
    }
}

bool Horde3DWindow::event(QEvent *event)
{
    // handle update requests by rendering...
    if(event->type() == QEvent::UpdateRequest){
        m_isUpdateRequested = false;
        renderNow();
        return true;
    }

    // ... and pass everything else up to QWindow
    return QWindow::event(event);
}

void Horde3DWindow::exposeEvent(QExposeEvent *event)
{
    Q_UNUSED(event);
    if (isExposed()){
        renderNow();
    }
}


Top
 Profile  
Reply with quote  
PostPosted: 05.03.2015, 21:47 
Offline
Tool Developer

Joined: 13.11.2007, 11:07
Posts: 1150
Location: Germany
Maybe Qt modifies the OpenGL states. See also this thread viewtopic.php?f=1&t=1734&p=9104


Top
 Profile  
Reply with quote  
PostPosted: 05.03.2015, 23:32 
Offline

Joined: 04.03.2015, 20:14
Posts: 2
Hi Volker, thanks for the quick answer! I took a look at the link, but sadly it didn't help.
I also dug a little further and found your old post and example of the Knight in Qt here: http://www.horde3d.org/forums/viewtopic.php?p=6355#p6355 but it produces the same result as what I have been getting so far.

I am pretty convinced that the problem lies not with the code but with some internal Qt strangeness. Perhaps the library-loading issue that is discussed the the above thread?
Anyway, for now the quality of the output is sufficient as I am mainly interested in displaying animation and not visual fidelity. Let's hope that whatever is going wrong does not manifest itself in other, more destructive ways :)


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 3 posts ] 

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 7 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron
Powered by phpBB® Forum Software © phpBB Group