DirectX9 et C#

Utiliser Irrlicht 3D en C#

Introduction

Irrlicht est un moteur 3D Open Source créé par Nikolaus Gebhardt. Développé en C++, il tourne sous Windows et Linux et supporte actuellement OpenGL, DirectX 8 et 9.
Si comme moi vous avez été frustré par l'abandon de Managed DirectX et la lourdeur de déploiement de XNA, IrrLich est fait pour vous, d'autant plus qu'il existe un wrapper pour Java (Jirr) et pour .NET (IrrlichtNetCP).



Pour plus d'informations sur ce moteur, je vous invite à visiter le site officiel du projet sur SourceForge : http://Irrlicht.sourceforge.net

Comme premier exemple, plutôt que d'afficher un modèle 3D, j'ai préféré vous montrer comment réaliser un effet de boule de feu à l'aide du moteur de particules.



Création du projet

Pour utiliser le wrapper .NET, créez une nouvelle application de type console dans Visual Studio ou SharpDevelop et ajoutez une référence à la librairie "Irrlicht.NET.dll". Copiez ensuite les fichiers "Irrlicht.dll" et "IrrlichtW.dll" dans le répertoire bin/debug|release de votre application.

Classes principales

Avant d'aborder le code de la démonstration, quelques explications s'imposent sur les principales classes utilisées :

  • Device : il s'agit de la classe la plus importante d'Irrlicht. Vous pouvez accéder à toutes les fonctionnalités du moteur 3D si vous avez une référence vers cette classe.
  • Driver : permet d'accéder à toutes les fonctions graphiques 2D et 3D. L'interface IVideoDriver est une des interfaces les plus importantes de Irrlicht; Toutes les opérations de rendu et de manipulation de textures sont faites à travers elle.
  • Billboard : un sprite 2D qui fait toujours face à la caméra. Habituellement utilisé pour réaliser des explosions, des feux, des reflets de soleil ou des particules.
  • SceneManager : gères les noeuds d'une scène (nodes), les objets 3D (mesh), les terrains ou encore les caméras. Chaque noeud d'une scène peut avoir une hiérarchie de noeuds fils. Ces enfants bougent de manière relative par rapport à leur parents.
  • GUIEnvironment : permet de créer et gérer des éléments d'interface graphique (listes déroulantes, labels, menus...)
Un peu de code...

Chacune des lignes de code est commentée pour vous aider à bien comprendre cet exemple.

using System;
using System.IO;
using System.Xml;
using System.Collections.Generic;
using System.Text;
using IrrlichtNETCP;
using IrrlichtNETCP.Inheritable;

namespace Particule
{
class Demo
{
static IrrlichtDevice device;
static string StartUpModelFile = string.Empty;
static string MessageText = string.Empty;
static string Caption = string.Empty;
static VideoDriver driver=null;
static SceneManager smgr=null;

static void Main(string[] args)
{
// choisit le driver directx9
DriverType driverType = DriverType.Direct3D9;

// crée un nouveau device (mode fenêtre de 400x320 en
// 32 bits)
device = new IrrlichtDevice(driverType,
new Dimension2D(400, 320), 32,
false, false, true, true);

// définit le répertoire par défaut pour les images
device.FileSystem.WorkingDirectory = "../../../media";

driver = device.VideoDriver;
smgr = device.SceneManager;

// définit le format des textures
driver.SetTextureFlag(TextureCreationFlag.Always32Bit, true);

// ajoute une caméra pilotée par la souris
CameraSceneNode camera = smgr.AddCameraSceneNodeFPS(null,
100, 300, false);
camera.Position = new Vector3D(-200, 200, -200);

// désactive l'affichage du curseur de la souris
device.CursorControl.Visible = false;

// ajoute un peu de brouillard
driver.SetFog(new Color(0, 138, 125, 81), true, 250, 1000,
0, true, false);

// ajoute une lumière
SceneNode light =
smgr.AddLightSceneNode(null, new Vector3D(0, 0, 0),
new Colorf(1.0f, 0.2f, 0.2f, 0.0f), 200.0f, 0);

// crée une animation circulaire pour la lumière
Animator anim = smgr.CreateFlyCircleAnimator(
new Vector3D(0, 150, 0), 200.0f, 0.0005f);
light.AddAnimator(anim);

// attache un sprite 2d à la lumière pour les reflets
SceneNode bill = smgr.AddBillboardSceneNode(light,
new Dimension2Df(120, 120), 0);
bill.SetMaterialFlag(MaterialFlag.Lighting, false);
bill.SetMaterialType(MaterialType.TransparentAddColor);
bill.SetMaterialTexture(0,
driver.GetTexture("particlewhite.bmp"));

// définit un nouveau moteur de particules
ParticleSystemSceneNode ps =
smgr.AddParticleSystemSceneNode(false, light, 0);

ps.ParticleSize = new Dimension2Df(30.0f, 40.0f);

// crée un émetteur de particules
ParticleEmitter em = ps.CreateBoxEmitter(
new Box3D(-3, 0, -3, 3, 1, 3),
new Vector3D(0.0f, 0.03f, 0.0f),
80, 100,
new Color(0, 255, 255, 255),
new Color(0, 255, 255, 255),
400, 1100, 0);
ps.SetEmitter(em);

// associe un effet fade-out au moteur de particules
ParticleAffector paf = ps.CreateFadeOutParticleAffector(
new Color(), 1000);
ps.AddAffector(paf);

// définit la texture de l'émetteur de particule
ps.SetMaterialFlag(MaterialFlag.Lighting, false);
ps.SetMaterialTexture(0,
driver.GetTexture("fireball.bmp"));
ps.SetMaterialType(
MaterialType.TransparentVertexAlpha);

/*
La scéne est maintenant configurée; il ne reste plus
qu'à la dessiner dans la boucle d'affichage principale.
Nous affichons également le nombre d'images par seconde.
*/

int lastFPS = -1;

while (device.Run())
{
if (device.WindowActive)
{
// on définit ici la couleur de fond
driver.BeginScene(true, true,
new Color(0, 0, 0, 0));
smgr.DrawAll();
driver.EndScene();

int fps = device.VideoDriver.FPS;
if (lastFPS != fps)
{
device.WindowCaption = "Irrlicht Demo " +
"FPS:" + fps.ToString();
lastFPS = fps;
}
}
}

device.Dispose();
}
}
}

Configuration de l'émetteur de particules

La méthode CreateBoxEmitter() utilisée ci-dessus mérite quelques explications complémentaires :
  • Box : boîte définissant les limites de l'émetteur.
  • Direction : direction et vitesse des particules émises.
  • MinParticlesPerSecond : nombre minimal de particules émises par seconde.
  • MaxParticlesPerSecond : nombremaxnimal de particules émises par seconde.
  • MinStartColor : couleur de départ. La couleur d'une particule est déterminée par une interpolation aléatoire entre la couleur de départ et la couleur de fin.
  • MaxStartColor : couleur de fin.
  • LifeTimeMin : durée de vie minimale d'une particule, en millisecondes.
  • LifeTimeMax : durée de vie maximale d'une particule, en millisecondes.
  • MaxAngleDegrees : angle maximal de déviation (en degrés) par rapport à la trajectoire par défaut des particules.
Les deux images ci-dessous peuvent être utilisées pour tester cet exemple :





Vous trouverez d'autres exemples de code C# sur le Wiki de IrrlichNetCP. Bon amusement...

Commentaires