Tutoriel Irrlicht 14

Fenêtres Win32

| Nikolaus Gebhart | Laurent Alexandre |

Traducteur

Neckara

Ce tutoriel est une traduction de l'anglais des tutoriels officiels d'Irrlicht.

Cet exemple ne s'exécute que sur Windows MS et montre qu'Irrlicht est capable de dessiner à l'intérieur d'une fenêtre win32. Ceci est aussi possible avec les fenêtres MFC, .NET et Windows.Form.

Commentez

- Titre : Tutoriel Irrlicht 14

- Auteurs : Nikolaus Gebhart, Laurent Alexandre

- Traducteur : Neckara

- Parution : 31 mai 2013

- Mise à jour : 31 mai 2013

- Public visé :

- Licence : Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright ® 2013 Neckara. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. Création de la fenêtre Windows

- II. Création du moteur Irrlicht

- III. Boucle de rendu

- IV. Conclusion

- V. Remerciements

I - Création de la fenêtre Windows

Pour commencer, nous créons une fenêtre Windows en utilisant l'API Windows. Je n'expliquerai pas ce code puisqu'il est spécifique à Windows. Regardez la documentation MSDN ou un livre sur Windows pour plus de détails.

#include <irrlicht.h>
#ifndef _IRR_WINDOWS_
#error Windows only example
#else
#include <windows.h> // Cet exemple s'exécute uniquement sous Windows.
#include <iostream>
#include "driverChoice.h"

using namespace irr;

#pragma comment(lib, "irrlicht.lib")

HWND hOKButton;
HWND hWnd;

static LRESULT CALLBACK CustomWndProc(HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_COMMAND:
{
HWND hwndCtl = (HWND)lParam;
int code = HIWORD(wParam);

if (hwndCtl == hOKButton)
{
DestroyWindow(hWnd);
PostQuitMessage(0);
return 0;
}
}
break;
case WM_DESTROY:
PostQuitMessage(0);
return 0;

}

return DefWindowProc(hWnd, message, wParam, lParam);
}

Maintenant, demandons un pilote et créons une fenêtre spécifique à Windows.

int main()
{
// Demande à l'utilisateur un pilote.
video::E_DRIVER_TYPE driverType=driverChoiceConsole();
if (driverType==video::EDT_COUNT)
return 1;

printf("Select the render window (some dead window may exist too):\n"\
" (a) Window with button (via CreationParam)\n"\
" (b) Window with button (via beginScene)\n"\
" (c) Own Irrlicht window (default behavior)\n"\
" (otherKey) exit\n\n");

char key;
std::cin >> key;
if (key != 'a' && key != 'b' && key != 'c')
return 1;

HINSTANCE hInstance = 0;
// Crée une boîte de dialogue.

const char* Win32ClassName = "CIrrlichtWindowsTestDialog";

WNDCLASSEX wcex;
wcex.cbSize         = sizeof(WNDCLASSEX);
wcex.style          = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc    = (WNDPROC)CustomWndProc;
wcex.cbClsExtra     = 0;
wcex.cbWndExtra     = DLGWINDOWEXTRA;
wcex.hInstance      = hInstance;
wcex.hIcon          = NULL;
wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW);
wcex.lpszMenuName   = 0;
wcex.lpszClassName  = Win32ClassName;
wcex.hIconSm        = 0;

RegisterClassEx(&wcex);

DWORD style = WS_SYSMENU | WS_BORDER | WS_CAPTION |
WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_SIZEBOX;

int windowWidth = 440;
int windowHeight = 380;

hWnd = CreateWindow( Win32ClassName, "Irrlicht Win32 window example",
style, 100, 100, windowWidth, windowHeight,
NULL, NULL, hInstance, NULL);

RECT clientRect;
GetClientRect(hWnd, &clientRect);
windowWidth = clientRect.right;
windowHeight = clientRect.bottom;

// Crée un bouton 'OK'.

hOKButton = CreateWindow("BUTTON", "OK - Close", WS_CHILD | WS_VISIBLE | BS_TEXT,
windowWidth - 160, windowHeight - 40, 150, 30, hWnd, NULL, hInstance, NULL);

// Crée du texte.

CreateWindow("STATIC", "This is Irrlicht running inside a standard Win32 window.\n"\
"Also mixing with MFC and .NET Windows.Forms is possible.",
WS_CHILD | WS_VISIBLE, 20, 20, 400, 40, hWnd, NULL, hInstance, NULL);

// Crée une fenêtre pour mettre Irrlicht dedans.

HWND hIrrlichtWindow = CreateWindow("BUTTON", "",
WS_CHILD | WS_VISIBLE | BS_OWNERDRAW,
50, 80, 320, 220, hWnd, NULL, hInstance, NULL);
video::SExposedVideoData videodata((key=='b')?hIrrlichtWindow:0);

II - Création du moteur Irrlicht

Ainsi, maintenant que nous avons une fenêtre, nous pouvons créer un moteur Irrlicht à l'intérieur. Nous utilisons pour cela la fonction createEx() d'Irrlicht. Nous avons uniquement besoin du gestionnaire (HWND) de cette fenêtre, de le mettre en tant que paramètre windowID et de démarrer le moteur comme d'habitude. Voilà, c'est tout.

// Crée le moteur Irrlicht dans le bouton de la fenêtre.

irr::SIrrlichtCreationParameters param;
param.DriverType = driverType;
if (key=='a')
param.WindowId = reinterpret_cast<void*>(hIrrlichtWindow);

irr::IrrlichtDevice* device = irr::createDeviceEx(param);
if (!device)
return 1;

// Met en place une scène 3D simple.

irr::scene::ISceneManager* smgr = device->getSceneManager();
video::IVideoDriver* driver = device->getVideoDriver();

if (driverType==video::EDT_OPENGL)
{
HDC HDc=GetDC(hIrrlichtWindow);
PIXELFORMATDESCRIPTOR pfd={0};
pfd.nSize=sizeof(PIXELFORMATDESCRIPTOR);
int pf = GetPixelFormat(HDc);
DescribePixelFormat(HDc, pf, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
pfd.dwFlags |= PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;
pfd.cDepthBits=16;
pf = ChoosePixelFormat(HDc, &pfd);
SetPixelFormat(HDc, pf, &pfd);
videodata.OpenGLWin32.HDc = HDc;
videodata.OpenGLWin32.HRc=wglCreateContext(HDc);
wglShareLists((HGLRC)driver->getExposedVideoData().OpenGLWin32.HRc, (HGLRC)videodata.OpenGLWin32.HRc);
}
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->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"));

// Montre et exécute la boîte de dialogue.

ShowWindow(hWnd , SW_SHOW);
UpdateWindow(hWnd);

// Crée une queue de messages.

III - Boucle de rendu

Maintenant, la seule chose manquante est la boucle de rendu avec IrrlichtDevice::run(). Nous le faisons comme d'habitude. Mais au lieu de cela, il y a une autre possibilité : vous pouvez aussi utiliser votre propre boucle de messages en utilisant GetMessage, DispatchMessage ou n'importe quoi d'autre. Appeler Device->run(), fera qu'Irrlicht enverra aussi ses messages internes. Vous ne devez pas appeler Device->run() si vous voulez faire votre propre boucle d'envoi de messages, mais Irrlicht ne sera alors pas capable de rapporter les événements de l'utilisateur. Vous devez donc le faire vous-même en utilisant les messages de la fenêtre, DirectInput ou n'importe quoi d'autre.

while (device->run())
{
driver->beginScene(true, true, 0, videodata);
smgr->drawAll();
driver->endScene();
}

L'alternative avec votre propre boucle d'envoi de message sans Device->run() devrait ressembler à cela :

MSG msg;
while (true) {
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg); DispatchMessage(&msg);
if (msg.message == WM_QUIT) break;
}
advance virtual time device->getTimer()->tick();
draw engine picture driver->beginScene(true, true, 0, (key=='c') ? hIrrlichtWindow:0);
smgr->drawAll();
driver->endScene();
}
device->closeDevice();
device->drop();

return 0;
}
#endif // si Windows

Voilà, Irrlicht tourne maintenant dans votre propre fenêtre Windows.

IV - Conclusion

Vous pouvez désormais utiliser Irrlicht dans une fenêtre Windows.

Dans le prochain tutoriel Charger des scènes à partir de fichiers .irr, nous verrons comment sauvegarder et charger des scènes entières dans un fichier .irr.

V - Remerciements

Merci à Nikolaus Gebhardt de nous permettre de traduire ce tutoriel.

Merci à LittleWhite pour sa relecture technique ainsi qu'à ClaudeLELOUP pour sa relecture orthographique.