Imagine this as a supplement to Tutorial 14, which explained how to use Irrlicht in a win32 window. However, using it in WinForms takes a bit of a different approach, using Threading.
Note: I am not sure if this is the ideal way to do this (I'm a bit new to threads myself); let me know if you spot any bad design choices!
---------------
The final product will be a window that has Irrlicht running visuals inside of it.
1) Create a new Windows Forms Application in Visual Studio.
2) Create a new class: I called it IrrlichtManager. This is the main interface to all your Irrlicht operations.
3) Here is the implementation of the class:
- Code: Select all
#pragma
once
#include "stdafx.h"
using namespace irr;
public ref class IrrlichtManager
{
private:
IrrlichtDevice* _device;
scene::ISceneManager* _smgr;
video::IVideoDriver* _driver;
bool _isRunning;
public:
IrrlichtManager(IrrlichtDevice* device);
void Init();
void Close();
void SetCubeVisiblity(bool isVisible);
private:
void run();
};
#include "stdafx.h"
#include "IrrlichtManager.h"
// constructor
IrrlichtManager::IrrlichtManager(IrrlichtDevice* device)
: _device (device)
, _smgr (_device->getSceneManager())
, _driver (_device->getVideoDriver())
, _isRunning (true)
{
}
// Set up some visuals, and begin running the device.
// This method will be the function pointer for the Irrlicht thread.
void IrrlichtManager::Init()
{
scene::ICameraSceneNode* cam = _smgr->addCameraSceneNode();
cam->setTarget(core::vector3df(0,0,0));
scene::ISceneNodeAnimator* anim = _smgr->createFlyCircleAnimator(core::vector3df(0,15,0), 30.0f);
cam->addAnimator(anim);
anim->drop();
scene::ISceneNode* cube = _smgr->addCubeSceneNode(20);
cube->setID(10);
cube->setMaterialTexture(0, _driver->getTexture("../media/wall.bmp"));
cube->setMaterialTexture(1, _driver->getTexture("../media/water.jpg"));
cube->setMaterialFlag( video::EMF_LIGHTING, false );
cube->setMaterialType( video::EMT_REFLECTION_2_LAYER );
_smgr->addSkyBoxSceneNode(
_driver->getTexture("../media/irrlicht2_up.jpg"),
_driver->getTexture("../media/irrlicht2_dn.jpg"),
_driver->getTexture("../media/irrlicht2_lf.jpg"),
_driver->getTexture("../media/irrlicht2_rt.jpg"),
_driver->getTexture("../media/irrlicht2_ft.jpg"),
_driver->getTexture("../media/irrlicht2_bk.jpg"));
run();
}
// Stop running and dispose of the device
void IrrlichtManager::Close()
{
_device->closeDevice();
_isRunning = false;
}
// This method is to demonstrate how to interact with the device
void IrrlichtManager::SetCubeVisiblity(bool isVisible)
{
scene::ISceneNode* node = _smgr->getSceneNodeFromId(10);
node->setVisible(isVisible);
}
// The main Irrlicht loop
void IrrlichtManager::run()
{
while (_device->run() && _isRunning == true)
{
_driver->beginScene(true, true, 0);
_smgr->drawAll();
_driver->endScene();
}
_device->drop();
}
4) Next, open the Form Designer for your main form, probably called "Form1.h [Design]". Open the Toolbox on the left side of the screen, and select PictureBox. Draw a picture box inside the main form. Also, add a Button, and set the text to "Toggle Cube Visibility." Do this with the Property window.
5) Now you need to add the Irrlicht window to the form. Open up "Form1.h". Add "using namespace irr;" and "using namespace System::Threading;" to the file. Now, Locate the constructor. Add the following code so that the code around the constructor looks like this:
- Code: Select all
public:
Thread^ irrThread;
IrrlichtManager^ irrMgr;
IrrlichtDevice* device;
Form1()
{
InitializeComponent();
SIrrlichtCreationParameters param;
param.WindowId = reinterpret_cast<void*>(this->pictureBox1->Handle.ToPointer());
device = createDeviceEx(param);
irrMgr = gcnew IrrlichtManager(device);
irrThread = gcnew Thread(gcnew ThreadStart (irrMgr, &IrrlichtManager::Init));
irrThread->Start();
}
What's going on here is that you are creating a new thread where the Irrlicht device main rendering loop will be running. You are using the picture box you added earlier as the Irrlicht window. Those funny caret things are basically pointers to a managed class. "gcnew" is also the managed version of "new". These are weird .NET things that you can read up about later.
6) Now we will add code for the button. Clicking on this button will toggle the visibility of the cube node. This is just to show one way of interacting with the Irrlicht device. Go back to the Form1.h Designer and double click on button1. It should take you have to Form1.h with a method generated for you.
Make it look like this:
- Code: Select all
void button1_Click(System::Object^ sender, EventArgs^ e)
{
static bool visible = true;
visible = !visible;
irrMgr->SetCubeVisiblity(visible);
}
7) Almost done! We just need to add some code to properly close the Irrlicht device when the window is closed. Go back to the Form1.h Designer again. Select Form1. In the Properties window, click on the Events button. It's represented by a lightning bolt symbol. Find the event "Form Closing" and double click on the empty field on the right. Just like before, it should take you to Form1.h with a new method stub. Just add these two lines so it looks like this:
- Code: Select all
void Form1_FormClosing (System::Object^ sender, FormClosingEventArgs^ e)
{
irrMgr->Close();
irrThread->Join();
}
The Join method will wait for the Irrlicht thread to finish before continuing.
8) Now we just add the right references. My stdafx.h file looks like this:
- Code: Select all
#pragma once
#pragma comment( lib, "irrlicht.lib" )
#pragma unmanaged
#include <irrlicht.h>
#pragma managed
#include "IrrlichtManager.h"
The #pragma unmanged and managed lines are important. Make sure you #include the stdafx.h where you need it, like your main() file. Also, this is a good time to set the following option. Go to your property settings. In the general Configuration Properties, change the "Common Language Runtime support" field to the /clr one. You can't use /clr:pure or /clr:safe.
9) You're done! Compile it and hopefully it will work. This is what it should look like:
The camera should be rotating around the cube. When you click the button, the cube should disappear or appear.
For further information, it's a good idea to read up on Threading and the Windows Form Designer.
I hope this helps you get started on your project!



