My Goal was to seperate the Irrlicht related code as far as possible into a sperate class (or classes).
However there is still a bug present. I dunno if this is a Irrlicht related bug. It seems that OnResize in IrrCoreRenderer::resizeIrrWidget isn't working properly if a software renderer is used. (BTW: The other approach as linked above, has the same issue with software renderer)
Hint:
Its still not possible to run multiple instances of Irrlicht in one software where all instances are using OpenGL! One instance can use OpenGL, but other instances have to use the Burningsvideo renderer for example.
First steps:
- Create a new QtWidget Project in Qt Creator.
- Place two Widgets into MainWindow in Qt Designer.
- Make sure that the two widgets are children of centralWidget.
- Name one Widget "irrRenderWidget0" and one Widget "irrRenderWidget1"
Paste the following Code into your newly created Project.
Code: Select all
//mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "irrcorerenderer.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
IrrCoreRenderer* irr0;
IrrCoreRenderer* irr1;
private:
Ui::MainWindow *ui;
void initIrrInstance0(QWidget *irrRenderTarget);
void initIrrInstance1(QWidget *irrRenderTarget);
protected:
virtual void resizeEvent(QResizeEvent *event);
};
#endif // MAINWINDOW_H
Code: Select all
//irrcorerenderer.h
#ifndef IRRCORERENDER_H
#define IRRCORERENDER_H
#include <QObject>
#include <QWidget>
#include <irrlicht.h>
using namespace irr;
class IrrCoreRenderer : public QWidget
{
Q_OBJECT
public:
IrrCoreRenderer(QWidget *irrRenderTarget, bool softwareRenderer);
~IrrCoreRenderer();
void init();
void resizeIrrWidget(int x, int y, int newWidth, int newHeight);
private:
QWidget *irrRenderTarget;
video::E_DRIVER_TYPE rendererType;
protected:
SIrrlichtCreationParameters params;
IrrlichtDevice* device;
virtual void timerEvent(QTimerEvent* event);
};
#endif // IRRCORERENDER_H
Code: Select all
//main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
Code: Select all
//mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
//Init an Irrlicht instance and give it a target widget into where Irrlicht should show its output - here I named it "irrRenderWidget0" and "irrRenderWidget1".
this->initIrrInstance0(ui->centralWidget->findChild<QWidget *>("irrRenderWidget0"));
this->initIrrInstance1(ui->centralWidget->findChild<QWidget *>("irrRenderWidget1"));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::initIrrInstance0(QWidget *irrRenderTarget)
{
this->irr0 = new IrrCoreRenderer(irrRenderTarget, false);
this->irr0->init();
}
void MainWindow::initIrrInstance1(QWidget *irrRenderTarget)
{
this->irr1 = new IrrCoreRenderer(irrRenderTarget, true);
this->irr1->init();
}
void MainWindow::resizeEvent(QResizeEvent *event)
{
this->irr0->resizeIrrWidget(0, 0, this->size().width()/2, this->size().height());
this->irr1->resizeIrrWidget(this->size().width()/2, 0, this->size().width()/2, this->size().height());
}
Code: Select all
//irrcorerenderer.cpp
#include "irrcorerenderer.h"
IrrCoreRenderer::IrrCoreRenderer(QWidget *irrRenderTarget, bool softwareRenderer)
{
this->irrRenderTarget = irrRenderTarget;
if(softwareRenderer)
{
this->rendererType = video::EDT_BURNINGSVIDEO;
} else
{
this->rendererType = video::EDT_OPENGL;
}
//Set Parameters. Most important part here is: params.WindowId. This value sets the output destination of this Irrlicht instance.
this->params.AntiAlias = 0;
this->params.Bits = 32;
this->params.DeviceType = EIDT_X11;
this->params.Doublebuffer = true;
this->params.DriverType = rendererType;
this->params.EventReceiver = 0;
this->params.Fullscreen = false;
this->params.HighPrecisionFPU = false;
this->params.IgnoreInput = false;
this->params.LoggingLevel = ELL_INFORMATION;
this->params.Stencilbuffer = true;
this->params.Stereobuffer = false;
this->params.Vsync = false;
this->params.WindowId = reinterpret_cast<void*>(this->irrRenderTarget->winId());
this->params.WindowSize.Width = this->irrRenderTarget->size().width();
this->params.WindowSize.Height = this->irrRenderTarget->size().height();
this->params.WithAlphaChannel = false;
this->params.ZBufferBits = 16;
this->device = createDeviceEx(this->params);
}
IrrCoreRenderer::~IrrCoreRenderer()
{
this->device->drop();
}
void IrrCoreRenderer::init()
{
if (this->device != 0)
{
scene::ISceneManager* smgr = this->device->getSceneManager();
this->device->getFileSystem()->addFileArchive("media/map-20kdm2.pk3");
scene::IAnimatedMesh* mesh = smgr->getMesh("20kdm2.bsp");
scene::ISceneNode* node = 0;
if (mesh)
{
node = smgr->addOctreeSceneNode(mesh->getMesh(0), 0, -1, 1024);
}
if (node)
{
node->setPosition(core::vector3df(-1300, -144, -1299));
}
smgr->addCameraSceneNode();
startTimer(0);
}
}
void IrrCoreRenderer::timerEvent(QTimerEvent* event)
{
if(this->device != 0)
{
this->device->getTimer()->tick();
video::SColor color (255, 100, 100, 140);
this->device->getVideoDriver()->beginScene(true, true, color);
this->device->getSceneManager()->drawAll();
this->device->getVideoDriver()->endScene();
}
}
void IrrCoreRenderer::resizeIrrWidget(int x, int y, int newWidth, int newHeight)
{
//Resize the render target widget which shows the Irrlicht output.
this->irrRenderTarget->setGeometry(x, y, newWidth, newHeight);
//Resize Irrlicht render output itself
if(this->device != 0)
{
core::dimension2d<u32> widgetSize;
widgetSize.Width = newWidth;
widgetSize.Height = newHeight;
this->device->getVideoDriver()->OnResize(widgetSize);
scene::ICameraSceneNode *cam = this->device->getSceneManager()->getActiveCamera();
if (cam != 0)
{
cam->setAspectRatio((f32)widgetSize.Width / (f32)widgetSize.Height);
}
}
}