#include "QtHorde3D.h"
#include <QQuickWindow>
#include <QOpenGLContext>
#include <QSGSimpleTextureNode>
#include <Horde3DUtils.h>
QtHorde3D::QtHorde3D(QQuickItem* parent)
: QQuickItem(parent),
m_timerID(0),
m_fbo(0),
m_cam(0)
{
this->setFlag(QQuickItem::ItemHasContents);
}
QtHorde3D::~QtHorde3D()
{
this->cleanup();
}
void QtHorde3D::timerEvent(QTimerEvent* evt)
{
if (evt && evt->timerId() == m_timerID)
this->update();
}
QSGNode* QtHorde3D::updatePaintNode(QSGNode* node, UpdatePaintNodeData* data)
{
QSGSimpleTextureNode* textureNode = static_cast<QSGSimpleTextureNode*>(node);
if (!textureNode)
textureNode = new QSGSimpleTextureNode();
// Push Qt state.
glPushClientAttrib(GL_CLIENT_ALL_ATTRIB_BITS);
glPushAttrib(GL_ALL_ATTRIB_BITS);
glMatrixMode(GL_TEXTURE);
glPushMatrix();
glLoadIdentity();
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glShadeModel(GL_FLAT);
glDisable(GL_CULL_FACE);
glDisable(GL_LIGHTING);
glDisable(GL_STENCIL_TEST);
glDisable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
// Render Horde3D.
int x = this->x();
int y = this->y();
int width = this->width();
int height = this->height();
delete m_fbo;
m_fbo = 0;
if (width && height)
{
m_fbo = new QOpenGLFramebufferObject(width, height);
textureNode->setTexture(this->window()->createTextureFromId(m_fbo->texture(), m_fbo->size()));
}
else
{
textureNode->setTexture(this->window()->createTextureFromId(0, QSize(0,0)));
}
textureNode->setRect(this->boundingRect());
// Flip Y-axis between Horde3D and GLSL.
QMatrix4x4 flipY;
flipY.translate(width*0.5, height*0.5);
flipY.scale(1.0, -1.0);
flipY.translate(-width*0.5, -height*0.5);
data->transformNode->setMatrix(flipY);
if (m_fbo)
{
m_fbo->bind();
if (!m_cam)
{
// Initialize engine.
h3dInit();
h3dSetOption(H3DOptions::LoadTextures, 1);
h3dSetOption(H3DOptions::TexCompression, 0);
h3dSetOption(H3DOptions::FastAnimation, 0);
h3dSetOption(H3DOptions::MaxAnisotropy, 4);
h3dSetOption(H3DOptions::ShadowMapSize, 2048);
// Add resources.
H3DRes pipelineRes = h3dAddResource(H3DResTypes::Pipeline, "pipelines/forward.pipeline.xml", 0);
H3DRes envRes = h3dAddResource(H3DResTypes::SceneGraph, "models/platform/platform.scene.xml", 0);
H3DRes modelRes = h3dAddResource(H3DResTypes::SceneGraph, "models/knight/knight.scene.xml", 0);
// Load added resources.
h3dutLoadResourcesFromDisk("Content");
// Add an environment.
H3DNode env = h3dAddNodes(H3DRootNode, envRes);
h3dSetNodeTransform(env, 0, 0, 0, 0, 0, 0, 20, 20, 20 );
// Add a model.
H3DNode model = h3dAddNodes(H3DRootNode, modelRes);
h3dSetNodeTransform(model, 0, 0, 0, 0, 180, 0, 1, 1, 1 );
// Add a light source.
H3DNode light = h3dAddLightNode( H3DRootNode, "Light1", 0, "LIGHTING", "SHADOWMAP" );
h3dSetNodeTransform( light, 0, 15, 40, 0, 0, 0, 100, 100, 100 );
h3dSetNodeParamF( light, H3DLight::RadiusF, 0, 1000 );
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 );
// Add a camera.
m_cam = h3dAddCameraNode(H3DRootNode, "Camera", pipelineRes);
h3dSetNodeTransform(m_cam, 0, 30, 100, 0, 0, 0, 1, 1, 1 );
QObject::connect(QOpenGLContext::currentContext(), SIGNAL(aboutToBeDestroyed()), this, SLOT(cleanup()), Qt::DirectConnection);
}
// Setup viewport and render target sizes.
h3dSetNodeParamI(m_cam, H3DCamera::ViewportXI, 0);
h3dSetNodeParamI(m_cam, H3DCamera::ViewportYI, 0);
h3dSetNodeParamI(m_cam, H3DCamera::ViewportWidthI, width);
h3dSetNodeParamI(m_cam, H3DCamera::ViewportHeightI, height);
h3dSetupCameraView(m_cam, 45.0f, (float)width / height, 0.1f, 1000.0f);
h3dResizePipelineBuffers(h3dGetNodeParamI(m_cam, H3DCamera::PipeResI), width, height);
// Render scene.
h3dRender(m_cam);
// Finish rendering of frame.
h3dFinalizeFrame();
m_fbo->release();
// Restore (pop) Qt state.
glMatrixMode(GL_TEXTURE);
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
glPopAttrib();
glPopClientAttrib();
}
if (!m_timerID)
m_timerID = this->startTimer(16);
return textureNode;
}
void QtHorde3D::cleanup()
{
this->killTimer(m_timerID);
m_timerID = 0;
if (m_cam)
{
h3dRelease();
m_cam = 0;
delete m_fbo;
m_fbo = 0;
}
}