119
Moteur 3D en XNA pour un simulateur de vol Atachiants Roman Haute Ecole Rennequin Sualem page 1 MOTEUR 3D EN XNA POUR UN SIMULATEUR DE VOL Atachiants Roman Année académique : 2006-2007 Travail de Fin d’Études en vue de l’obtention du grade de Bachelier en Informatique de Gestion

B.Sc Thesis: Moteur 3D en XNA pour un simulateur de vol

Embed Size (px)

Citation preview

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 1

MOTEUR 3D EN XNA POUR UN

SIMULATEUR DE VOL

Atachiants Roman

Année académique : 2006-2007

Travail de Fin d’Études en vue de l’obtention du grade de Bachelier en Informatique de Gestion

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 2

SOMMAIRE

1. Remerciements............................................................................................................................... 5

2. Introduction.................................................................................................................................... 6

2.1 Architecture du document..................................................................................................... 6 2.2 Choix du stage........................................................................................................................ 6

3. Contexte général ............................................................................................................................ 7

3.1 L’entreprise ............................................................................................................................ 7 3.2 Les objectifs de travail ........................................................................................................... 9

3.2.1 Objectifs généraux............................................................................................................. 9

3.2.2 Objectifs à court terme...................................................................................................... 9

3.2.3 Objectifs à long terme ..................................................................................................... 10

3.3 L’environnement technique et les outils ............................................................................. 12 3.3.1 Environnement de travail : L’équipe ............................................................................... 12

3.3.2 Outils et librairies utilisés ................................................................................................ 13

3.3.3 Standards de codage ....................................................................................................... 15

4. Considérations théoriques, études préalables............................................................................. 16

4.1 Développement d’une application orientée objet .............................................................. 16 4.1.1 Expérience personnelle ................................................................................................... 16

4.1.2 Analyse et conception d’une architecture repondant aux besoins................................. 17

4.1.3 Implémentation & sécurité ............................................................................................. 17

4.1.4 Optimisation .................................................................................................................... 17

4.1.5 Tests & débogage ............................................................................................................ 18

4.2 Au plan logiciel ..................................................................................................................... 19 4.2.1 Choix de l’application ...................................................................................................... 19

4.2.2 OpenGL ou DirectX ?........................................................................................................ 19

4.2.3 Choix de Framework........................................................................................................ 20

4.3 Au plan matériel................................................................................................................... 22 4.3.1 Unité de calcul et mémoire ............................................................................................. 22

4.3.2 Choix de carte graphique................................................................................................. 22

5. Framework XNA............................................................................................................................ 24

5.1 Introduction ......................................................................................................................... 24 5.1.1 Généralités....................................................................................................................... 24

5.1.2 Prérequis.......................................................................................................................... 24

5.2 Architecture ......................................................................................................................... 26 5.2.1 Généralités....................................................................................................................... 26

5.2.2 La couche plate-forme..................................................................................................... 27

5.2.3 La couche framework de base......................................................................................... 27

5.2.4 La couche framework étendu.......................................................................................... 29

6. Notions de 3D ............................................................................................................................... 30

6.1 Introduction ......................................................................................................................... 30

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 3

6.2 Repères 3D........................................................................................................................... 30 6.3 Un vertex, des vertices......................................................................................................... 31 6.4 Les meshes........................................................................................................................... 35 6.5 Déplacement 3D : les matrices ............................................................................................ 35

7. Notions d’aviation ........................................................................................................................ 38

7.1 Introduction ......................................................................................................................... 38 7.2 Rotations.............................................................................................................................. 39

Rotations....................................................................................................................................... 39

Le rotor ......................................................................................................................................... 40

8. Le projet........................................................................................................................................ 42

8.1 vision du produit fini ............................................................................................................ 42 8.2 Objet principal...................................................................................................................... 45 8.3 Objets secondaires............................................................................................................... 46 8.4 Interfaces utilisateur............................................................................................................ 47 8.5 En conclusion ....................................................................................................................... 47

9. L’architecture globale de l’application ......................................................................................... 49

9.1 L’architecture modulaire de l’application............................................................................ 49 9.1.1 Simulation........................................................................................................................ 50

9.1.2 Affichage.......................................................................................................................... 52

9.1.3 Entrées............................................................................................................................. 53

9.2 L’architecture en couches de l’application .......................................................................... 54 9.2.1 Couche native .................................................................................................................. 55

9.2.2 Couche managée ............................................................................................................. 55

9.2.3 Couche abstraite.............................................................................................................. 56

9.2.4 Couche spécifique à l’application.................................................................................... 56

10. Simulation..................................................................................................................................... 58

10.1 Introduction ......................................................................................................................... 58 10.2 Wrapper pour MOSCA ......................................................................................................... 59

11. Moteur de rendu graphique......................................................................................................... 64

11.1 Framework objets ................................................................................................................ 64 11.1.1 Pourquoi un framework d’objets ? ............................................................................. 64

11.1.2 L’objet de base ............................................................................................................ 66

11.1.3 Les interfaces............................................................................................................... 67

11.1.4 L’utilisation.................................................................................................................. 68

11.2 Caméra................................................................................................................................. 69 11.2.1 Introduction ................................................................................................................ 69

11.2.2 Notions d’une caméra................................................................................................. 69

11.2.3 Méthodes principales.................................................................................................. 72

11.2.4 Déplacement ............................................................................................................... 73

11.3 Octree d’optimisation de rendu .......................................................................................... 75 11.3.1 Définition..................................................................................................................... 75

11.3.2 View Frustum .............................................................................................................. 75

11.3.3 Représentation graphique .......................................................................................... 76

11.3.4 Implémentation........................................................................................................... 77

11.3.5 Annexe......................................................................................................................... 80

11.4 Zones d’affichage ................................................................................................................. 81 11.4.1 Généralités .................................................................................................................. 81

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 4

11.4.2 Résultat final ............................................................................................................... 82

11.4.3 Exemple d’utilisation « pas à pas » ............................................................................. 84

11.4.4 Interaction entre le rendu et le framework objets ..................................................... 88

11.4.5 l’architecture Direct 3D ............................................................................................... 89

11.4.6 L’architecture .............................................................................................................. 92

11.4.7 L’implémentation ........................................................................................................ 98

11.5 Shaders et le post-processing ............................................................................................ 103 11.5.1 Introduction .............................................................................................................. 103

11.5.2 HLSL ........................................................................................................................... 105

11.5.3 Shader-model Framework......................................................................................... 107

11.6 Graphe de scène ................................................................................................................ 110 11.6.1 Généralités ................................................................................................................ 110

11.6.2 Utilité......................................................................................................................... 111

11.6.3 Implémentation......................................................................................................... 112

12. Perspectives et conclusions........................................................................................................ 113

12.1 Perspectives et développements ultérieurs ...................................................................... 113 12.2 Conclusions personnelles................................................................................................... 114

13. Bibliographie............................................................................................................................... 115

14. Lexique........................................................................................................................................ 116

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 5

1. REMERCIEMENTS

De nombreuses personnes ont apporté leur aide et leur soutien pendant tout le projet. Aussi, je

tiens à remercier tout particulièrement les personnes suivantes :

Monsieur Quentin Charlier qui fut un inoubliable coéquipier.

Monsieur Emmanuel Previnaire, Fondateur et administrateur délégué de Flying-Cam, pour avoir

permis, soutenu la réalisation de ce stage et également pour les idées novatrices apportées à ce

projet.

Monsieur Marco La Civita pour ses conseils tout au long du développement.

Monsieur Bernard Tollet pour ses conseils et son suivi pendant le travail de fin d’études.

Monsieur Jan Sperling, Directeur Technique, pour les explications sur l’hélicoptère.

Madame Sarah Krins, Executive Assistant Manager, pour l’aide apportée à la rédaction de ce

document et ses conseils sur l’activité de Flying-Cam.

Monsieur Christophe Schaaf, Office Manager pour son implication dans le développement du

moteur 3D en tant que personne de contact officielle.

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 6

2. INTRODUCTION

2.1 ARCHITECTURE DU DOCUMENT

Ce document a été écrit, en partie, à deux. Il contient donc deux types de chapitres :

Les chapitres écrits en commun qui sont d’ordre général. Par exemple, ce chapitre-ci ou le chapitre 3

« Contexte général » à la page 7.

Les chapitres écrits seul sont ceux où nous avons le plus travaillé par rapport au deuxième étudiant.

Ces deux types de chapitres sont reconnaissables par leurs icones : [ ] pour la partie

commune et [ ] pour la partie personnelle. Si l’icône se situe en dessous du titre principal

du chapitre, cela signifie que tout le chapitre est commun ou personnel.

Nous vous renverrons vers le deuxième document lorsque nous introduirons un concept développé

plus en détail dans le deuxième document.

2.2 CHOIX DU STAGE

Pendant tout mon cycle d’études, j’ai été confronté à de nombreux défis : que cela soit dans le

domaine de l’informatique, de la culture ou le simple fait de réussir un examen et être capable

d’assimiler une quantité importante de matière.

Mon but premier dans le choix du stage était de choisir un domaine qui me plaisait : travailler dans

un domaine et avec une technologie moderne.

Mon second souhait dans le choix du stage était d’apprendre de nouvelles technologies et m’enrichir

intellectuellement pendant ce stage.

Etant quelqu’un de passionné par les jeux vidéo, les domaines multimédia et cinématographique ; j’ai

été directement séduit par la société Flying-Cam et le projet de création d’un moteur 3D. Le fait

d’apprendre la programmation 3D m’a vraiment plu car c’était quelque chose que je souhaitais

apprendre depuis plusieurs années.

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 7

3. CONTEXTE GÉNÉRAL

3.1 L’ENTREPRISE

La société Flying-Cam, créée à Liège, en 1988, propose des services professionnels de prise de vues

aériennes par hélicoptère sans pilote. Elle fut la première société au monde à proposer ce service. La

société a réalisé des projets dans plus de 50 pays à ce jour et pour plus de 800 clients.

Figure 1 - Un hélicoptère Flying-Cam

Depuis sa création à Liège, la société a créé deux filiales, la première à Santa-Monica aux Etats-Unis

en 1994 et la seconde à Hong-Kong créée en 2005.

La société Flying-Cam maîtrise la conception et la fabrication de ses propres hélicoptères et du

système gyrostabilisé de prise de vues. Elle travaille donc aussi bien du coté matériel que logiciel. Le

système Flying-Cam a démontré une fiabilité irréprochable grâce au respect de normes

aéronautiques dans la conception et la fabrication.

La société développe pour le moment le 3ième prototype de ses hélicoptères et réalise ainsi la

transition vers l’industrialisation ainsi que le passage du pilotage manuel au pilotage automatique. Ce

projet appelé « Flying-Cam III Diamant » sera un hélicoptère autonome, taillé sur mesure pour le plus

grand nombre d’applications possibles dans le marché des UAVs (Unmanned Air Vehicles) à voilure

tournante. Le concept fait appel à des avancées dans trois technologies : la visionique, l’aéronautique

et l’aérobotique.

En plus du marché du cinéma et de l’audiovisuel, Flying-Cam vendra, sous licence, un système

complet dénommé SARAH (Special Aerial Response Autonomous Helicopter). L’actuelle Flying-Cam II

et la future Flying-Cam III Diamant seront les plates-formes porteuses du système. Ce

développement fera évoluer la société Flying-Cam de l’activité de prestation de services vers la

licence de systèmes fabriqués sur mesure pour les besoins des clients les plus variés.

Il permettra aussi la pénétration de nouveaux marchés comme la sécurité, la protection civile, le

militaire, et les productions télévisées d’événements.

La société Flying-Cam travaille également pour des annonceurs publicitaires, des séries télévisées,

des événements sportifs, des bureaux de tourisme, des universités ou encore des parcs d’attractions.

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 8

En outre, Flying-Cam participe à des programmes d’intérêt civil comme ceux de la NASA.

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 9

3.2 LES OBJECTIFS DE TRAVAIL

3.2.1 OBJECTIFS GÉNÉRAUX

L’objectif du travail est la conception d’un moteur 3D. Ce travail s’exécute dans le cadre du projet

« Flying-Cam III Diamant » et permettra à long terme d’améliorer, entre autres, la communication

avec les clients.

Plus précisément, l’objectif est de créer une application graphique 3D qui interagira avec un

simulateur de vol, fournit par la société sous forme de librairie dynamique (DLL).

Figure 2 - Photo prise lors du film "Curse of the Golden Flower"

3.2.2 OBJECTIFS À COURT TERME

A court terme, l’objectif de ce travail est de créer un moteur 3D. La société Flying-Cam souhaite que

le moteur 3D dispose de:

• La possibilité de contrôler l’hélicoptère Flying-Cam avec les radios utilisées réellement ;

• La possibilité d’avoir plusieurs vues : vue de l’hélicoptère, vue de la caméra, vue fixe, … ;

• Hélicoptère animé ;

• Décors ;

• Une interface graphique simple et claire ;

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 10

Le simulateur pourra servir d’entraînement pour les futurs pilotes. Comme dit dans le chapitre 3.1 ci-

dessus, le projet Flying-Cam III Diamant permettra à n’importe qui de piloter un hélicoptère Flying-

Cam. Cependant, tout n’est pas si simple, même avec un pilote automatique, il faut savoir comment

donner de l’altitude ou réaliser un virage avec l’hélicoptère : le simulateur permettra donc à ces

utilisateurs de s’entraîner au préalable dans un environnement virtuel sans risque.

3.2.3 OBJECTIFS À LONG TERME

A long terme, le simulateur pourrait être transformé et utilisé dans plusieurs domaines. Par exemple,

dans le cadre du tournage d’un film, un réalisateur crée un story-board pour montrer au pilote ce

qu’il attend comme plan. Souvent, le problème est que le réalisateur ne pense pas à certaines

contraintes comme la vitesse. Sachant que l’hélicoptère Flying-Cam vole à une vitesse maximale de

120 Km/h, certains plans ne peuvent pas être réalisés, surtout si des virages doivent être exécutés.

Avec le simulateur, le réalisateur verra ce qu’il est possible de faire.

Un autre exemple de développement à long terme serait de permettre de réaliser à l’écran un plan

de vol avec un modèle 3D du lieu à filmer en capturant les coordonnées des endroits où l’hélicoptère

doit passer, en sauvegardant ces coordonnées, en envoyant ensuite ces coordonnées (et d’autres

informations nécessaires à ce plan de vol, comme la vitesse ou les commandes à réaliser) au vrai

hélicoptère afin de permettre à l’hélicoptère de réaliser cette trajectoire sans l’aide d’un pilote.

Evidemment, cet objectif est à très long terme et demandera beaucoup de travail et de temps.

De notre coté, pour le temps donné, nous nous sommes fixés comme objectif de créer un moteur 3D

avec les fonctions demandées comme le changement de caméra.

Ci-dessous, un exemple de story-board utilisé pour représenter une scène réalisée à l’aide de la

Flying-Cam dans le cadre du film « Mission : Impossible 2 » :

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 11

Figure 3 - Story-board pour le film Mission Impossible 2

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 12

3.3 L’ENVIRONNEMENT TECHNIQUE ET LES OUTILS

3.3.1 ENVIRONNEMENT DE TRAVAIL : L’ÉQUIPE

L’équipe de Flying-Cam est assez petite, mais en même temps fortement motivée et déterminée.

Les personnes constituant l’équipe :

Emmanuel Prévinaire: Fondateur de la société et administrateur délégué

Sarah Krins : Executive Assistant Manager

Marco La Civita: Responsable Innovation Technologie

Jan Sperling : Directeur Technique

Alexandre Philippart de Foy : Technicien de Maintenance

Nicolas Wetzels: Apprenti

Pierre Steenput: Apprenti

Christophe Schaaf: Office Manager EU

Marc Asmode: Operations Manager US

Angel Kwok Wing Yee : Office Manager Asia

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 13

3.3.2 OUTILS ET LIBRAIRIES UTILISÉS

Nom du logiciel/SDK Description et justification du choix

Microsoft Visual Studio 2005

Microsoft Visual Studio est un environnement de

développement intégré permettant d’écrire/compiler du

code .Net (C # dans notre cas). Cet outil est de loin le plus

populaire et le plus permissif et extensible parmi des

outils similaires.

XNA Game Studio Express

Microsoft XNA est une série d'outils fournis gratuitement

par Microsoft qui facilitent les développements de jeux

pour les plates-formes Windows et Xbox 360 en

réunissant un maximum d'outils en provenance de

Microsoft et de ses partenaires (DirectX, Visual Studio,

PIX, XACT).

Voir § 4.2.2 ci-dessouspour plus d’informations concernant

notre choix.

Nvidia SDK

Nvidia SDK (Software Developement Kit) est une série

d’outils fournis gratuitement par Nvidia qui contiennent

de la documentation, des exemples et des divers logiciels

facilitant le développement 3D pour les cartes graphiques

Nvidia, ainsi les exploitant au maximum.

Voir § 4.3.2 ci-dessouspour plus d’informations concernant

notre choix.

DirectX 9 SDK

Microsoft DirectX est une suite d’APIs multimédia

intégrées au système d'exploitation Windows permettant

d'exploiter les capacités matérielles d'un ordinateur.

Voir § 4.2.2 ci-dessous pour plus d’informations concernant

notre choix.

Okino PolyTrans

Okino PolyTrans est un logiciel de conversion des divers

formats des modèles/scènes/animations 3D, ce logiciel a

été choisi parmi d’autres à cause de sa puissance de

conversion et support de multiples formats

d’import/export.

Google SketchUp est un logiciel de modélisation 3d, à la

base utilisé pour Google Earth. Nous avons choisi ce

produit pour sa facilité et pour son gain de productivité.

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 14

Google SketchUp 6 Pro

Autodesk 3D studio Max 9.0

3D Studio Max est un logiciel de modélisation et

d'animation 3D sous licence propriétaire payante,

développé par la société Autodesk. Il est l'un des logiciels

de référence dans le domaine de l'infographie 3D. Ce

logiciel a été retenu dans le projet pour sa puissance et

support des animations intégrées.

Autodesk Inventor 11

Autodesk Inventor est un logiciel de modélisation 3D

développé par la société Autodesk. Celui-ci permet

d'exploiter le concept de conception paramétrique. C'est

un logiciel de dessin technique à vocation mécanique. Le

choix de ce produit a été fait par la société Flying-Cam à

des fins professionnelles. Pour notre part, nous devons

l’utiliser afin d’avoir la possibilité d’exportation des

modèles d’hélicoptère dans le simulateur de vol.

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 15

3.3.3 STANDARDS DE CODAGE

Il n’existe pas vraiment de département informatique chez Flying-Cam et donc aucun standard de

codage n’était imposé. Nous avons donc établi nos propres règles de codage. Ceci pour plusieurs

raisons :

▪ Premièrement, nous sommes deux à travailler sur le projet et il est fort probable que

d’autres personnes continuent son développement ;

▪ Deuxièmement, pour faciliter la relecture et la lisibilité du code.

Organisation

▪ Utilisation de l’anglais pour le code (noms de classe, variables, …) ;

▪ Regroupement des fichiers en répertoires et namespace respectifs en fonction de leurs

utilités ;

Choix des noms

Voici les conventions que nous avons respectées pour nommer les éléments :

▪ Un nom de variable facile à lire, à retenir et sans ambiguïté ;

▪ Une variable membre sera toujours précédé par m_, par exemple : m_MaVariable ;

▪ Une classe sera toujours précédée par C, par exemple : CMaClasse ;

▪ Une énumération sera toujours précédée par E, par exemple : EMonEnumeration ;

▪ Une interface sera toujours précédée par I, par exemple : IMonInterface.

Documentation

▪ Utilisation à bon escient des commentaires. Ils ne doivent être ni trop nombreux, ni absents;

ils se doivent d'expliquer clairement la partie de code qui suit ;

▪ L'utilisation des /// permettant la création automatique de documentation est

recommandée ;

Nous avons décidé de ne pas commenter systématiquement toutes les méthodes mais de

commenter uniquement les méthodes quand cela s’avère utile.

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 16

4. CONSIDÉRATIONS THÉORIQUES, ÉTUDES PRÉALABLES

4.1 DÉVELOPPEMENT D’UNE APPLICATION ORIENTÉE OBJET

4.1.1 EXPÉRIENCE PERSONNELLE

Ces trois dernières années de mon activité dans le développement d’applications très diverses m’ont

amené à construire mon point de vue sur plusieurs questions. L’une d’elles, qui semble évidente mais

pas toujours bien comprise, est le cycle de développement. Comment doit-on s’y prendre afin de

concevoir une application qui à la fois :

• réponde aux besoins des utilisateurs ;

• soit facilement modifiable ;

• soit rapidement conçue ;

• soit sécurisée ;

• possède un code lisible ;

• soit optimisée ;

• et finalement soit avec le moins de bugs possibles ;

Le développement d’une telle application ne doit jamais être pris à la légère. Il nous amène à

penser : comment doit-on concevoir l’application et avec quelles techniques ? Comment faire pour

économiser le plus de temps possible sans négliger des étapes importantes ? Voici comment

j’interprète ce processus itératif : le cycle de vie d’une application:

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 17

Figure 4 - Cycle de vie d'une application orientée objet

Ce cycle de vie ne s’applique pas spécialement à l’application dans son entièreté, mais le plus

souvent à des parties de l’application.

4.1.2 ANALYSE ET CONCEPTION D’UNE ARCHITECTURE REPONDANT AUX BESOINS

A cette étape du développement, nous devons établir une architecture qui répond ou plutôt essaye

de répondre à tous les besoins des utilisateurs, et qui possède une architecture la plus souple

possible. La souplesse de l’architecture est très importante, car non seulement les besoins des

utilisateurs vont forcément changer mais en plus nous devrons probablement repenser beaucoup de

choses pendant le cycle de vie et tout est susceptible de subir les changements. On pensera aussi à

toutes les technologies nécessaires à utiliser : les langages de programmation, frameworks, etc. C’est

aussi à cette étape qu’on élabore une première liste des logiciels et composants qu’on utilisera

pendant le développement. On essayera de choisir les composants les plus adaptés à nos besoins et

faire une analyse de coûts afin d’optimiser la durée de développement.

4.1.3 IMPLÉMENTATION & SÉCURITÉ

Une fois l’architecture établie, on va procéder à son implémentation. C’est pendant l’implémentation

que l’on est le plus susceptible de revenir à l’étape précédente et de changer l’architecture, d’y

ajouter quelque chose de nouveau ou même de complètement tout repenser. Tout en effectuant

l’implémentation, nous devons intégrer les diverses techniques de sécurité et ne jamais les perdre de

vue. Les techniques de sécurité utilisées dépendront du contexte de l’application.

4.1.4 OPTIMISATION

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 18

Cette étape nous amène à revoir tout le code de l’application afin de l’optimiser. Nous utiliserons

divers outils, le plus souvent des profilers qui nous permettent d’optimiser le temps d’exécution de

l’application. Cette étape est malheureusement trop souvent oubliée ou négligée ce qui a pour

conséquence la production d’une application dont les performances ne sont pas optimales.

4.1.5 TESTS & DÉBOGAGE

Une fois l’écriture du code terminée, nous passons à l’étape des tests effectués par nous-mêmes ou

par les testeurs. Le plus souvent dans cette étape on effectuera des tests unitaires et leur débogage.

On veillera à ce que tous les besoins soient respectés et que les calculs soient effectués dans un délai

raisonnable. Pendant cette étape on testera également la sécurité de l’application.

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 19

4.2 AU PLAN LOGICIEL

4.2.1 CHOIX DE L’APPLICATION

Nous avons dû prendre plusieurs décisions importantes dès le début de la conception de l’application

sur le plan logiciel.

Tout d’abord, nous avions le choix entre deux applications à développer : une application basée sur

le motion builder, technique qui, en gros, consiste à « capturer » une scène réelle et à reproduire

celle-ci sur l’ordinateur ou un moteur 3D basé sur un simulateur de vol temps-réel.

Nous avons choisi de faire le moteur 3D car la première application devait être faite dans un langage

de programmation totalement inconnu pour nous : le « python ». De plus, le programme de

développement nécessitait l’achat d’une licence et donc le programme était assez dépendant du

logiciel. Enfin, il nous était impossible d’obtenir le code source. Remarque : le développement d’une

application en python nous offrait peu d’apports personnels pour notre avenir professionnel.

4.2.2 OPENGL OU DIRECTX ?

Après ce premier choix, nous devions choisir quelle technologie nous allions utiliser pour réaliser le

moteur 3D. Nous avions le choix entre une programmation en DirectX (Managed ou non) ou OpenGL

ou XNA.

Tableau basique comparant DirectX et OpenGL:

DirectX OpenGL

Avantages - Une seule API pour toutes les fonctions du simulateur ;

- plus puissant.

- Multiplateforme ; - plus simple.

Inconvénients - Non portable. - Nécessite des librairies additionnelles (notamment pour le fenêtrage et la gestion des entrées).

Point de vue personnel

- Proche du C# : bonnes connaissances personnelles ;

- nous travaillons sous Windows XP : DirectX se prête mieux.

- Moins de connaissances.

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 20

4.2.3 CHOIX DE FRAMEWORK

MANAGED DIRECTX OU XNA FRAMEWORK ?

Le choix de DirectX ayant été fait, il nous restait à savoir quelle version de DirectX nous allions

utiliser, le managé ou non. Après certaines recherches, nous avons découvert un nouveau

framework développé par Microsoft appelé XNA.

Nous avions donc 3 possibilités car nous voulions utiliser les produits Microsoft afin d’avoir le plus de

support et de documentation possibles :

• utilisation de l’API DirectX native en C++ ;

• utilisation du framework « Managed DirectX » en code managé;

• utilisation du framework XNA en code managé.

Le Framework XNA est complètement différent du Managed DirectX (MDX), ce framework basé sur le

framework .NET 2.0 a été créé spécialement pour les développeurs de jeux 2D et 3D sous Windows

et pour la console de jeux Xbox.

Le Framework XNA partage bien entendu des similitudes avec Managed DirectX car ces deux

technologies sont basées sur DirectX. En plus de ces points communs, d’autres technologies comme

XACT (librairies de programmation audio) ou X/Input (une API qui permet la gestion des entrées à

partir du contrôleur de la console XBOX 360 sur un PC Windows) ont été intégrées au framework

XNA. Le Framework XNA implémente également une large partie des fonctionnalités de Direct3D X.

Ce framework est destiné à remplacer Managed DirectX. Ainsi, les libraires de Managed DirectX 2.0

beta ont été déclarées obsolètes (deprecated) en Avril 2006 et ont expiré le 5 octobre 2006 ; il n’y a

donc plus de développement en cours pour le Managed DirectX 2.0. De plus, XNA reprend la plupart

des fonctionnalités qui ont précédemment existé dans le MDX 2.0 beta. Il n’y aura donc pas de

nouvelles fonctionnalités pour Managed DirectX 1.1 et il est possible de faire migrer du code MDX

1.1 en code pour le framework XNA. Le framework XNA peut donc être utilisé par tout le monde : les

anciens développeurs sous MDX et les nouveaux sous XNA.

Nous avons donc choisi d’utiliser ce framework pour des choix de simplicité et de perspective

d’avenir car XNA est le futur pour le développement de jeux vidéo, notre simulateur pouvant être

considéré comme un jeu. De plus, il tend à remplacer le DirectX Managed, ce qui renforce notre

décision pour ce type de programmation. Finalement, nous avons appris qu’un projet appelé

« Mono.XNA » était en développement, celui-ci permettant un portage de XNA sous Linux et Mac.

Ainsi, en utilisant XNA, notre projet sera également portable.

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 21

Voici un résumé de l’analyse que nous avons fait afin de comparer les 3 possibilités et faire ce choix :

API en mode natif

Avantages - Meilleures performances.

Inconvénients - Productivité moindre.

Point de vue

personnel

- Création d’un projet sous cette API en 3 mois nous semblait impossible ;

- beaucoup de débogages et de problèmes dus à trop de liberté de l’API.

Framework Managed DirectX

Avantages - Code managé ;

- Bien documenté.

Inconvénients - Productivité moyenne ;

- Pas de support XBox ;

- N’utilise pas les patterns de programmation .Net.

Point de vue

personnel

- A long terme, MDX ne sera plus supporté et son utilisation va diminuer de

plus en plus, nous ne souhaitons pas apprendre une technologie destinée à

disparaître à moyen terme.

Framework XNA

Avantages - Code managé ;

- support XBox 360 ;

- utilise les patterns de programmation .Net

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 22

Inconvénients - Peu documenté car trop nouveau

Point de vue

personnel

- A long terme, XNA va devenir le framework « principal » de Microsoft

permettant l’utilisation DirectX en code managé. Une opportunité pour

nous.

4.3 AU PLAN MATÉRIEL

4.3.1 UNITÉ DE CALCUL ET MÉMOIRE

Un simulateur de vol, même en étant optimisé, effectue les calculs à la fois de simulation et de rendu

graphique qui sont très complexes. Nous avions besoin d’acheter une machine capable de faire

tourner le simulateur. Pour ceci on a choisi d’avoir quelque chose de fiable et stable :

• Processeur Intel Core 2 Duo ;

• Mémoire vive Corsair (2 giga de DDR2).

4.3.2 CHOIX DE CARTE GRAPHIQUE

L’étape suivante était de choisir une carte graphique correspondant aux besoins du simulateur. En ce

qui concerne les cartes graphiques, après avoir fait diverses recherches, nous avons constaté que ce

choix avait un impact direct sur le développement de l’application. Cet impact est directement lié à

la manipulation des shaders, car chaque constructeur de chipset avait des petites différences dans ce

langage. Nous reviendrons plus en détail sur cette notion de shaders dans le chapitre §11.5 ci-

dessous. La 2ième différence consistait dans la version de ce fameux shader langage, après une petite

recherche nous avons établi une liste des versions existantes, introduites dans des versions de

DirectX correspondantes :

Version de DirectX Shader Model Pixel Shader Vertex Shader

8.0 1.0, 1.1 1.0, 1.1 1.0

8.1 1.2, 1.3, 1.4 1.2, 1.3, 1.4

9.0 2.0 2.0 2.0

9.0a 2_x 2_A, 2_B 2_x

9.0c 3.0 3.0 3.0

10 4.0 4.0 4.0

Nous avons opté pour la version du Shader Model 3.0, la plus répandue et la plus accessible au

moment du développement. La version 4.0 étant encore prématurée et peu documentée a été

recalée lors de notre choix.

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 23

Une fois le choix du Shader Model fait, le choix du constructeur et le modèle de la carte graphique

nécessaire fut assez simple. Nous avons opté pour le constructeur le plus répandu/vendu dans le

milieu professionnel : Nvidia. Pour ce qui est du modèle de la carte graphique, nous avons opté pour

une GeForce de série 7 car c’est la seule à supporter le Shader Model 3.0.

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 24

5. FRAMEWORK XNA

5.1 INTRODUCTION

5.1.1 GÉNÉRALITÉS

Le framework XNA permet aux développeurs de créer des jeux modernes en utilisant le langage C# et

un ensemble complet de bibliothèques de développements. Il utilise son propre pipeline de contenu

rendant l'accès simple et rapide aux contenus 3D, 2D, sonores, etc. Il fournit une API de haut niveau

indépendante des plates-formes Windows et 360, éliminant par ce fait le coût et l'effort à fournir

pour porter les jeux entre ces deux plates-formes.

Le Framework .Net est la principale API de développement pour réaliser des applications Windows.

Le framework XNA a été conçu pour profiter de ce framework en ajoutant un ensemble de

fonctionnalités propre au développement de jeux.

XNA Game Studio Express est une nouvelle solution de développement de jeu destinée

principalement aux étudiants, passionnés et développeurs de jeux indépendants. XNA Game Studio

Express fonctionne avec Visual C# Express 2005 et permet aux développeurs de créer des jeux à la

fois pour Windows et pour la XBOX 360. XNA Game Studio Express inclus :

• le framework XNA est un ensemble de bibliothèques de développement qui permet aux

développeurs d'être plus productifs dans la création de jeux pour Windows et Xbox 360 ;

• le framework XNA Framework Content Pipeline est un ensemble d'outils qui permet aux

développeurs d’incorporer facilement des contenus 3D à l'intérieur de leurs jeux ;

• XNA Game Studio Express contient une documentation complète, des cas pratiques et des

starters kits qui mettent en évidence les bonnes pratiques (patterns) de développement

.Net ;

• XNA Game Studio Express cohabite sans problème avec les autres versions de Visual Studio ;

• XNA Game Studio Express supporte à la fois le développement Windows et Xbox 360.

En résumé, dans XNA Game Studio Express, on peut distinguer deux choses :

• XNA Game Studio Express : un ensemble d'outils basés sur Visual C# Express 2005 ;

• le framework XNA : un ensemble de bibliothèques managées (.NET).

5.1.2 PRÉREQUIS

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 25

Pour pouvoir utiliser le framework XNA, il est nécessaire de télécharger et installer Visual C#

Express et les dernières mises à jour des librairies DirectX (le SDK complet n'est pas obligatoire). De

même, il est nécessaire d’avoir une carte vidéo compatible Direct3D 9.0 supportant le modèle Shader

1.1.

Microsoft recommande une carte supportant le modèle 2.0 sachant qu'une partie du

starter kits l'utilise.

Pour plus d’informations sur Visual C# Express, rendez vous sur le site :

http://msdn.microsoft.com/vstudio/express/visualcsharp/

Pour plus d’informations sur le DirectX Software Development Kit (SDK), vous pouvez le télécharger à

cette adresse : http://www.microsoft.com/downloads/details.aspx?FamilyID=86CF7FA2-E953-475C-

ABDE-F016E4F7B61A&displaylang=en

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 26

5.2 ARCHITECTURE

5.2.1 GÉNÉRALITÉS

Afin d’expliquer l’architecture XNA, voici un schéma officiel de Microsoft décrivant cette

architecture :

Sur ce schéma, nous pouvons voir que le développement a été effectué couche par couche afin de

rendre le framework le plus souple et extensible possible.

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 27

5.2.2 LA COUCHE PLATE-FORME

XNA Game Studio Express réunit un maximum d'outils en provenance de Microsoft et de ses

partenaires :

• API Direct3D pour le rendu graphique ;

• XACT fournissant les outils et fonctionnalités du support sonore ;

• XINPUT offrant des fonctionnalités de base pour le stockage d’informations ;

• XCONTENT offrant une gestion de contenu et des formats de fichiers portables et souples.

5.2.3 LA COUCHE FRAMEWORK DE BASE

XNA inclut un certain nombre de librairies spécifiques pour le développement de jeux afin de

promouvoir un maximum de réutilisations du code entre les deux plates-formes ciblées. On trouve

entre autres des librairies pour les graphiques, l’audio, les inputs, les mathématiques et la

sauvegarde de données.

La librairie « graphique » fournit des capacités pour le rendu de bas niveau ; elle est construite sur

Direct3D 9 et fournit des ressources comme les modèles, les textures, les effets, etc.

La librairie « audio » est basée sur XACT, ce qui permet aux ingénieurs du son et aux programmeurs

de travailler plus naturellement. De plus, elle permet une intégration plus facile pour les

développeurs, par exemple :

- l’accès via des noms logiques,

- les boucles, le streaming et la gestion de la mémoire,

- et ne nécessite aucune gestion du buffer bas niveau1.

La librairie « input » permet une capture des entrées extrêmement facile. La programmation est

immédiate, il n’y a pas d’initialisation, ni de gestion d’état. La gestion du clavier, de la souris et de la

manette XBOX 360 sont fournies.

La librairie « mathématique » fournit toutes sortes de notions mathématiques utiles en 3D comme

les vecteurs, les matrices, les quaternions, la notion de plan, les sphères, le rayon, le frustrum, la

courbe, etc. 2 Un repère main droite est défini par défaut alors qu’un repère main gauche était utilisé

dans DirectX Managed, nous y reviendrons plus tard. Cette librairie fournit également une aide sur

les intersections et les mouvements.

1 Ces notions sont décrites dans le lexique

2 Ces notions sont décrites dans le lexique

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 28

La librairie « sauvegarde » fournit un moyen simple pour écrire et lire les données du jeu et les écrire

sur le disque. Ces données seront toujours sauvegardées dans un répertoire correct pour chaque

plate-forme.

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 29

5.2.4 LA COUCHE FRAMEWORK ÉTENDU

La couche du framework étendu est une couche supplémentaire et une des différences majeures

entre XNA et le Managed DirectX ; elle est divisée en deux parties :

• application model ;

• et content pipeline.

La dite « application model » est une librairie contenant le squelette d’un moteur 3D basé sur les

composants, offrant ainsi un modèle de base pour permettre aux programmeurs de concevoir les

composants des jeux, se les échanger, voire les vendre. Ce concept est issu du modèle classique des

formulaires Windows (WindowsForms), où il existe beaucoup de sociétés privées qui vendent des

composants offrant de nombreuses fonctionnalités supplémentaires.

Dans toute application XNA, il est nécessaire de gérer différentes ressources de type graphique, son,

modèles 3D, etc. Le « Content Pipeline » de XNA permet de charger ces ressources et de les utiliser

simplement.

A partir d'un fichier "traditionnel" comme une image .png, un son .wav ou un modèle 3D .x (ou .fbx),

une classe de type « Content Importer » charge le fichier et son « Content Processor » le transforme

en ressource utilisable par le jeu (.xnb). Il est également possible de créer votre propre

Importer/Processor mais XNA Game Express en fournit déjà plusieurs qui suffisent dans un premier

temps pour la plupart des assets (contenu artistique). De plus, l'IDE de C# Express supporte

nativement ces Importers/Processors ce qui fait qu'importer une image (son, modèle) revient

simplement à ajouter dans le projet la dite image (son, modèle).

Il existe aussi un Importer/Processor pour les effets (shaders), effets stockés dans des fichiers .fx

pour des effets de type Vertex, Pixels Shader en HLSL (High Level Shader Language).

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 30

6. NOTIONS DE 3D

6.1 INTRODUCTION

Beaucoup de nouvelles notions en 3D ont dû être acquises lors de la conception du simulateur. XNA

fournit des aides pour ces notions, mathématiques ou autres.

Tout d’abord, il faut savoir se positionner dans un repère orthonormé 3D. Ensuite, on doit créer des

points et les relier pour former des formes géométriques. Une fois que nous avons notre objet en 3D,

il faut pouvoir le faire bouger.

Tout développeur 3D doit faire face à ces notions et ne pas les comprendre rendrait le

développement plus compliqué qu’il ne l’est déjà. Ces notions sont donc primordiales.

6.2 REPÈRES 3D

Pour positionner un point en 2D, on dispose de deux axes orthonormés : X est l’axe horizontal et Y

l’axe vertical. La 3D nécessite un troisième axe : l’axe Z.

Le monde où l’hélicoptère va évoluer est donc un espace 3D orthonormé. Tout point est donc situé

par l’intermédiaire de trois composantes:

- sa position par rapport à la côte X,

- sa position par rapport à la hauteur Y,

- sa position par rapport à la profondeur Z.

En 3D "XNA", on se situe par rapport à un repère dit de

"main droite". La figure ci-contre montre un repère main

droite.

Ce nom vient du fait que vous pouvez reproduire ce

repère à l'aide de votre main droite. Le pouce représente

l'axe X, l'index l'axe Z et le majeur l'axe Y. Nous

positionnerons donc nos objets en utilisant ces

coordonnées 3D. Z croît avec la distance, Y croît avec la

hauteur et X permet de se déplacer sur l'horizontale.

Figure 5 - Repère 3D dit "main droite"

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 31

6.3 UN VERTEX, DES VERTICES

En 2D, afficher un objet consiste à « plaquer » une image à l’écran. En 3D, c’est différent. Les objets

ne sont pas dessinés à partir d'une image mais plutôt à partir de différents points. C’est ce qu’on

appelle un vertex ou les vertices au pluriel.

Un vertex est donc un point dans l'espace auquel on associe des propriétés (couleur, position, ...).

C’est le pipeline 3D qui va relier ces points pour former un objet ; concrètement c’est toute

l’architecture de l’ordinateur qui s’en occupe (à l’aide de la carte graphique par exemple). Le

développeur a pour tâche de bien placer ces points et d'indiquer au device l’objet permettant

l’interfaçage avec la carte graphique ainsi que la façon de relier les vertices. Il existe différentes

méthodes pour relier ces vertices, nous y reviendrons rapidement.

La figure ci-dessous illustre bien la notion de vertex. Nous voyons un cube et un tube en trois

dimensions. On remarque qu'ils sont tout simplement formés à partir de points (nos vertices) qui

sont reliés entre eux.

Figure 6 - Un cube et un tube en 3D

Nous remarquons que notre cube et notre cylindre ci-dessus sont formés uniquement de triangles.

Le triangle est la forme géométrique la plus simple en 3D. Trois vertices sont nécessaires pour la

former. Toute forme géométrique en 3D est formée de triangles, c’est à dire d’une multitude de

vertices qui, reliés, permettent de donner une apparence à certains objets.

Voici deux exemples de code où nous utilisons les vertices :

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 32

• Le premier provient de la classe CGrid qui représente une grille sur le sol. On y utilise un

VertexPositionColor ; comme son nom l’indique on peut paramétrer sa position et sa couleur.

• Le second provient de la classe CTexturedQuad qui permet de créer un carré en 3D avec pour

surface une texture. On y utilise VertexPositionTexture, celui-ci aura comme second

paramètre les coordonnées des points dans la texture.

namespace Diamond.World { public partial class CGrid : CObject, ILoadable, IRenderable { #region Members private Color m_color = Color.White; private VertexDeclaration m_vDec; private VertexPositionColor[] m_verts; private VertexBuffer m_vBuffer; private void FillBufferForXZPlane(VertexPositionColor[] data, int gridSize) { int index = 0; float zPos = (CMeasure.PointsPerMeter * m_MeterPerSquare ); float xPos = (CMeasure.PointsPerMeter * m_MeterPerSquare ); int gridSizeHalfed = gridSize / 2; float yPos = 0; // Draw x zero line data[index++] = new VertexPositionColor( new Vector3(gridSizeHalfed * (CMeasure.PointsPerMeter * m_MeterPerSquare), yPos, 0), m_color); data[index++] = new VertexPositionColor( new Vector3(-gridSizeHalfed * (CMeasure.PointsPerMeter * m_Meter PerSquare), yPos, 0), m_color); ( … ) } #endregion } }

namespace Diamond.Render { public class CTexturedQuad : CObject, IRenderable, ILoadable { private string m_Asset; private Texture2D m_Texture; private VertexBuffer m_Vertices; #region ILoadable Membres public void LoadGraphicsContent(GraphicsDevice _Device, ContentManager _Loader) { m_Texture = _Loader.Load<Texture2D>(m_A sset) as Texture2D; VertexPositionTexture[] verts = { new VertexPositionTexture( new Vector3(-0.5f, 0.5f, 0), new Vector2(0, 0)),

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 33

new VertexPositionTexture( new Vector3(0.5f, 0.5f, 0), new Vector2(1, 0)), new VertexPositionTexture( new Vector3(-0.5f, -0.5f, 0), new Vector2(0, 1)), new VertexPositionTexture( new Vector3(0.5f, -0.5f, 0), new Vector2(1, 1)) }; ( … ) } } }

Remarque : nous utiliserons le type Vector3 pour définir une position dans l’espace. Un Vector3 est

un vecteur possédant trois composants x, y et z : nos trois coordonnées.

Comme signalé plus haut, il existe plusieurs solutions pour relier les vertices entre eux afin de former

des objets 3D. Chaque solution possède ses propres avantages en fonction de la forme de l’objet.

C'est pourquoi il convient d’utiliser celle qui s'avère la plus adaptée dans un seul but : réduire au

maximum le nombre de vertices. L’association de plusieurs vertices entre eux permet à XNA de

former des triangles (assimilables à des surfaces). L’association de ces surfaces permet alors de

former des objets dans l’espace. XNA raisonne en ternaire ; Il lui faut trois point pour former la plus

petit figure géométrique possible : le triangle.

Triangle List

Le mode de liaison de vertex le plus simple : les points sont liés trois

par trois afin de former les triangles à afficher. Avec ce mode de

liaison, il est donc nécessaire de créer un nombre de vertices multiple

de trois. Les trois premiers vertices représenteront le premier

triangle, les trois suivant le second triangle et ainsi de suite... C’est le

mode de définition le plus simple mais aussi le plus coûteux. Il n’est

jamais utilisé sur des formes géométriques complexes car il impose

de créer et de placer un nombre très important de vertices...

Pour dessiner 3 triangles : Vertices (0, 1, 2) puis Vertices (3, 4, 5), puis Vertices (6 7, 8) : 9 vertices

pour afficher 3 triangles.

Triangle Fan

Ce mode est plus intelligent ; il réutilise des vertices déjà utilisé pour

les liaisons. On gagne ainsi de précieux octets en mémoire libérant

ainsi le pipeline 3D. Dans ce mode, le premier vertex est relié à tous

les autres. Là aussi, les possibilités sont limitées ; on ne peut faire que

des formes rectangulaires et/ou cylindriques comme le montre le

schéma ci-contre.

Pour dessiner 3 triangles : Vertices (0, 1, 2) puis Vertices (0, 2, 3), puis

Vertices (0, 3, 4) : 5 vertices pour afficher 3 triangles.

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 34

Triangle Strip

Ce troisième mode est un peu plus compliqué. On relie ici

aussi les vertices par trois. Mais en considérant que le dernier

vertex créé doit être relié aux deux précédents. Le gain de

place en mémoire est très important, mais la difficulté pour

créer des formes complexes est multipliée.

Pour dessiner 6 triangles : Vertices (0, 1, 2), Vertices (1, 2, 3),

Vertices (2, 3, 4), Vertices (3, 4, 5), Vertices (4, 5, 6), Vertices

(5, 6, 7) : 8 vertices pour afficher 6 triangles.

Au niveau du code, c'est l'énumération PrimitiveType qui contient les différents types d'énumérations possibles. D'autres types de liaisons plus simples sont possibles :

▪ Point qui ne fait aucune liaison et laisse les points tels quels, ▪ LineList qui relie les points deux à deux, ▪ LineStrip qui relie un point à son prédécesseur.

Dans nos classes CGrid et CTexturedQuad nous relions respectivement nos vertices avec les modes

PrimitiveType.LineList et PrimitiveType.TriangleList.

Dans le cas de CGrid, nous utilisons le mode LineList car nous ne faisons que de relier chaque fois

deux points pour former une ligne. Nous créons donc notre grille en créant une succession de lignes

formées de deux points.

Dans le cas de CTexturedQuad, nous utilisons le mode TriangleList car notre forme géométrique est

très basique, il n’y a que deux triangles, utilisé un mode compliqué n’aurait pas apporté un gain

significatif.

Pour dessiner un triangle, il faudra donc créer 3 vertices, leur donner une position et, au moment de

l'affichage, spécifier la méthode de liaison.

Un modèle 3D est donc constitué de vertices ; plus il y en a et plus le modèle est complexe. Pour

donner un exemple, le modèle de l’hélicoptère Flying-Cam possède environ 13000 vertices.

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 35

6.4 LES MESHES

Un Mesh est littéralement un treillis ou un maillage. C’est un objet tridimensionnel constitué de

polygones sous forme de fil de fer. Cet ensemble structuré contient la géométrie, les matrices, les

caractéristiques de couleurs et les textures d’un modèle 3D.

Figure 7 – Le modèle de l'hélicoptère Flying-Cam en mode "fil de fer"

6.5 DÉPLACEMENT 3D : LES MATRICES

Pour déplacer nos objets dans un monde 3D, nous devons utiliser les matrices. Ces matrices vont

effectuer des transformations sur nos objets.

Ainsi, si l’on multiplie une position dans l’espace (un Vecteur3 est une matrice ligne3) par une

matrice, on obtient en retour une position transformée.

Nous pouvons paramétrer nos matrices afin d’effectuer plusieurs sortes de transformations : une

translation (déplacement), une homothétie (redimensionnement) et/ou une rotation.

Grâce à XNA, nos matrices peuvent aussi représenter un ensemble de calculs mathématiques comme

une série de transformations ou encore les propriétés d'une caméra (position, direction, angle de

vision, distance de vision ...).

Par exemple, nous utiliserons souvent des matrices nommées View et Projection.

3 Une matrice ligne est une matrice qui ne possède qu’une seule ligne.

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 36

La première matrice est utilisée pour reproduire la vue de la caméra, elle contient des informations à propos de la position de la caméra, le point vers lequel elle regarde et l’axe vertical. XNA fournit des méthodes permettant de créer cette matrice. Par exemple, la méthode CreateLookAt de la classe Matrix. Exemple de création d’une matrice vue m_View dans la classe CCamera : m_View = Matrix .CreateLookAt(m_Position, m_Target, m_UpVector);

La seconde matrice nous permet de paramétrer la caméra. XNA fournit encore une fois une méthode

pour créer cette matrice, c’est la méthode CreatePerspectiveFieldOfView de la classe Matrix. Les

paramètres de cette méthode sont l’angle d’ouverture de la caméra, l’aspect ratio, la position la plus

proche visible et la position la plus éloignée visible. Nous reviendrons sur ces notions propres à la

caméra dans le chapitre § 11.2 ci-dessous qui lui est consacré.

m_Projection = Matrix .CreatePerspectiveFieldOfView(fieldOfView, aspectRa tio, m_Viewport.MinDepth, m_Viewport.MaxDepth);

Comme indiqué plus haut, les matrices sont utilisées aussi pour effectuer des transformations sur les

objets. Par exemple, toujours dans la classe Matrix, nous avons des méthodes comme

CreateTranslation, CreateRotationX, CreateRotationY, CreateRotationZ, CreateScale, …

Voici un exemple venant de la classe CCubeLogo où nous créons une matrice d’étirement, le

« scale », une matrice de translation et une matrice de rotation. Ces matrices sont ensuite utilisées

pour calculer la matrice World qui est la représentation de la géométrie 3D :

public void SetSize( Vector3 size) {

this .m_Width = size.X; this .m_Height = size.Z; this .m_Depth = size.Y; this .m_ScaleMatrix = Matrix .CreateScale(size.X, size.Y, size.Z);

this .UpdateTransformation(); } public void SetPosition( Vector3 location) {

this .m_X = location.X; this .m_Y = location.Y; this .m_Z = location.Z; this .m_TranslationMatrix = Matrix .CreateTranslation(location.X,

location.Y, location.Z); this .UpdateTransformation();

}

public void SetRotation( float rotationX, float rotationY, float rotationZ) {

this .m_RotationX = rotationX; this .m_RotationY = rotationY; this .m_RotationZ = rotationZ;

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 37

this .m_RotationMatrix = Matrix .CreateRotationX(rotationX) * Matrix .CreateRotationY(rotationY) * Matrix .CreateRotationZ(rotationZ); this .UpdateTransformation(); } private void UpdateTransformation() {

this .m_TransformationMatrix = this .m_ScaleMatrix * this .m_RotationMatrix * this .m_TranslationMatrix;

this .m_Effect.World = this .m_TransformationMatrix;

}

XNA fournit donc une aide précieuse dans l’utilisation des matrices. Tout est fait automatiquement,

la programmation n’en est que plus simple. Les opérateurs sont surchargés pour les matrices et

d’autres fonctions comme Invert ou Transposed également. Le programmeur n’a donc plus besoin de

faire toutes sortes de calculs pour programmer en 3D.

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 38

7. NOTIONS D’AVIATION

7.1 INTRODUCTION

Avant de nous lancer dans la conception même du moteur 3D, même si la simulation a été conçue

par un ingénieur spécialisé, nous devions comprendre le fonctionnement d’un hélicoptère et avoir

des notions de base d’aviation.

Dans un hélicoptère, comme pour un avion, la vitesse relative de l'air et de la voilure génère une

action mécanique qui permet à l'engin de voler. On distingue deux composantes de cette action

aérodynamique:

• la traînée qui est la résistance à l'avancement. De son action sur le rotor de l'hélicoptère, il résulte un couple tendant à faire tourner l'appareil autour de son axe, d'où la nécessité d'un dispositif anti-couple. La trainée a également un effet sur le fuselage dès que la vitesse de l’hélicoptère augmente ;

• la portance qui soulève l'appareil.

Le contrôle d'un appareil repose alors sur la gestion de cette portance. Alors que sur les avions, des

volets permettent de modifier la portance moyenne des ailes pour virer et monter, sur l'hélicoptère

on modifie le pas qui modifie l'inclinaison des pales.

Tout déplacement et stabilisation d’un hélicoptère est effectué grâce à l’inclinaison des pales.

Equilibre en vol stationnaire

Déséquilibre

Déplacement stabilisé

Vol stationnaire.

Le rotor de l'hélicoptère étant entraîné à vitesse constante, les déplacements verticaux de

l'hélicoptère sont obtenus par la seule modification du pas des pales. À ce stade du vol, la portance

des pales reste identique sur un tour du rotor. Il existe une position où la portance globale s'oppose

exactement au poids de l'appareil : l'hélicoptère peut rester immobile. Si elle lui est inférieure,

l'appareil descend. Si elle est supérieure, il monte.

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 39

7.2 ROTATIONS

ROTATIONS

Afin d’effectuer correctement les rotations de l’hélicoptère dans l’espace, ces rotations doivent être

effectuées dans un certain ordre.

Il existe une convention de nommage des angles de rotations. Voici ces 3 angles :

: Angle “Phi” : Rotation autours de l’axe X;

: Angle “The” : Rotation autours de l’axe Y;

: Angle “Psi” : Rotation autours de l’axe Z.

Pour faciliter la compréhension, illustrons ces rotations.

La rotation sur l’axe Z :

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 40

La rotation sur l’axe X :

La rotation sur l’axe Y :

LE ROTOR

Toute rotation du rotor principal entraîne un

couple de réaction qui a tendance à faire tourner

la cellule autour de lui et en sens inverse (3e loi

de Newton). Pour contrer cet effet indésirable,

on place (pour les hélicoptères à un seul rotor

principal) à l'extrémité de la poutre de queue, un

rotor secondaire plus petit et tournant dans un

plan sensiblement vertical appelé rotor anti-

couple.

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 41

Pour ce qui concerne le sens des rotations du rotor principal, ça n’a pas vraiment d’importante. Une

petite anecdote est que tous les hélicoptères américains utilisent la rotation contraire au sens

inverse des aiguilles d’une montre et les hélicoptères russes utilisent la rotation dans le sens des

aiguilles d’une montre. Les européens n’ont pas de normes.

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 42

8. LE PROJET

8.1 VISION DU PRODUIT FINI

Notre projet est donc la réalisation d’un moteur 3D pour un simulateur. Mais qu’est-ce qu’un

simulateur ?

Un simulateur est un outil permettant notamment à l'apprenant de simuler les expériences en vue

de retrouver lui-même les lois qui les sous-tendent ou d'en voir le résultat.

Dans notre cas, nous devons donc permettre à un pilote ou à un futur pilote d’obtenir les mêmes

sensations que s’il pilotait un vrai hélicoptère. Afin de faciliter la compréhension du projet et de ce

document, voici plusieurs captures d’écran du moteur 3D fini :

Nous voyons à l’écran plusieurs choses :

• deux vues ;

• un menu ;

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 43

• un hélicoptère au centre de l’écran ;

• deux bateaux dont l’un (le voilier) est affiché dans deux vues différentes;

• de l’eau et le ciel.

Sur cette capture d’écran on peut remarquer la complexité de la scène :

• l’hélicoptère est penché en arrière (à cause du mouvement effectué) mais la vue de la

caméra reste fixe par rapport à l’horizon ;

• l’affichage de l’hélicoptère est assez complexe, contenant des parties transparentes afin de

donner une impression de flou ;

• la deuxième vue a été déplacée sur l’écran.

On peut donc déduire qu’il y a plusieurs choses bien distinctes dans cette scène :

• les interfaces utilisateurs afin de configurer la scène ;

• un espace de travail (ou monde) dans lequel nous avons nos objets ;

• une interface homme /machine définie par des contrôleurs de l’hélicoptère ;

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 44

• plusieurs zones d’affichage permettant d’afficher les espaces de travail sous différents

angles ;

• des objets quelconques pouvant être affichés ;

• un hélicoptère pouvant être contrôlé et déplacé.

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 45

8.2 OBJET PRINCIPAL

Notre objet principal est donc notre hélicoptère. En 3D, on parle de modèle 3D. Cet objet possède

une géométrie et différentes propriétés par rapport au monde :

• il peut se déplacer ;

• il peut être affiché ;

• il peut être contrôlé par différents contrôleurs (joystick par exemple);

• en fonction des angles de la caméra, une vue spécifique est affichée ;

Figure 8 - Modèle 3D de l'hélicoptère Flying-Cam

Cet hélicoptère qu’on voit à l’écran est, en réalité, un modèle 3D composé de meshes ( Voir § 6.4

above pour plus d’informations concernant les meshes et la 3D). Il possède des propriétés et des méthodes et

peut interagir avec le matériel. Il peut être donc considéré comme un objet dans le sens orienté

objet.

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 46

8.3 OBJETS SECONDAIRES

Les objets secondaires (bateaux, ciel, eau, …) que nous avons vu sur l’écran, ont la même structure

que l’objet principal (hélicoptère) excepté qu’ils ne peuvent pas être contrôlés et que la complexité

d’affichage est moindre :

• pas de transparence des parties de l’objet ;

• pas d’animations à l’intérieur.

Figure 9 - Objet secondaire (bateau)

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 47

8.4 INTERFACES UTILISATEUR

Voyons maintenant un peu plus en détail le menu de contrôle rapide :

Nous pouvons voir que ce menu permet :

(1) De créer une nouvelle scène de simulation.

(2) Une fois la scène créée, nous pouvons démarrer ou arrêter la simulation.

(3) Nous pouvons afficher la console de simulation, avec les données de cette dernière (les

angles, positions ou autre).

(4) Nous pouvons choisir un contrôleur actif (il existe deux types d’interfaçages de contrôleurs

utilisés chez Flying-Cam : USB et Série.

(5) Plusieurs modes de simulation (un mode de simulation normal et un mode de test).

(6) Nous pouvons afficher ou pas les diverses composantes d’environnement (l’eau, grille).

Nous pouvons donc déduire qu’il y a :

• une scène et une gestion de scène ;

• démarrage et arrêt de la simulation (qui n’est pas spécialement attachée à la scène) ;

• deux types d’interfaçages de contrôleurs à gérer : USB et Série.

8.5 EN CONCLUSION

Pour conclure, nous pouvons donc déduire de tout ceci que nous avons plusieurs parties plus

globales :

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 48

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 49

9. L’ARCHITECTURE GLOBALE DE L’APPLICATION

9.1 L’ARCHITECTURE MODULAIRE DE L’APPLICATION

L’architecture globale de l’application a été pensée et conçue par modules, une division logique a été

faite. Le schéma ci-dessous montre les divers modules logiques :

Figure 10 - Architecture globale (Modules)

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 50

9.1.1 SIMULATION

Le processus de simulation est effectué grâce à un modèle non linéaire dans l’hélicoptère obtenu par

une technique appelée MOdelling for Flight Simulation and Control Analysis (MOSCA) [9].

MOSCA est le fruit des recherches de Marco La Civita réalisé pour son mémoire « Integrated

Modeling and Robust Control for Full-Envelope Flight of Robotic Helicopters ». Il est responsable de

la recherche et développement chez Flying-Cam.

C’est une technique de modélisation de vol automatisé en combinant 2 techniques différentes :

• First-principles modeling, permettant d’obtenir les modèles de vol à la fois en temps réel et

non temps réel. Ces modèles possèdent les dynamiques non-linéaires.

• System Identification, permettant d’obtenir les modèles de vol en temps réel (donc très

haute fréquence). Ces modèles possèdent les dynamiques linéaires.

De notre côté, en utilisant cette librairie on peut assez facilement échanger les données et effectuer

l’affichage de l’hélicoptère en 3D sur l’écran. Pour assurer l’exécution fluide de la simulation, nous

devons nous assurer d’une exécution à 125 hertz de la librairie MOSCA. Nous devons également

gérer les différentes scènes du simulateur, l’échange des données (axes, contrôleurs) entre la

librairie et notre code C#.

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 51

Figure 11 - Suivi d'une voiture de Formule 1 par la Flying-Cam

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 52

9.1.2 AFFICHAGE

Le module d’affichage est le plus gros module que nous devions développer. Ce module est composé

de plusieurs parties :

• moteur de rendu graphique ;

• objets de scènes;

• interfaces utilisateur.

Le moteur de rendu graphique est en même temps le moteur d’optimisation d’affichage. Il possède

une notion des objets 3D permettant de développer simplement et rapidement diverses scènes. Ce

moteur lui-même intègre plusieurs parties, dont 3 principales :

• framework de rendu « objets », simplifiant le processus de développement grâce à une

couche plus abstraite. Ceci permet de développer les classes standards et flexibles afin de ne

plus vraiment se soucier des vertices en tant que tels et travailler par objets. Par exemple,

l’hélicoptère est un objet 3D en lui-même qui contient un modèle 3d, une fonction de mise à

jour et de rendu. Il peut être tourné en modifiant sa propriété de rotation et déplacé en

modifiant sa propriété de position ;

• gestion d’optimisation de rendu qui permet ne pas dessiner ce qui n’est pas visible, rendant

ainsi le temps d’affichage de la scène plus court. Cette partie de moteur de rendu utilise des

techniques avancées utilisées dans le domaine des jeux vidéos (où la performance est

importante) ;

• gestion des zones d’affichage et des vues de caméra qui permettent de définir une zone

d’affichage et de n’afficher que dans cette zone. Cette partie remplace une partie du

framework XNA qui, lui, a été conçu pour les jeux vidéo et ne possède pas cette notion de

zone. Nous avions besoin de cette technique afin d’afficher plusieurs vues simultanément

(dont une de la caméra qui se trouve dans l’hélico).

Divers objets de scène ont été créés pour l’environnement 3D de la simulation : l’hélicoptère, skybox,

skydome, bateaux, maisons, océan...

Les interfaces utilisateurs ont également été créées afin d’assurer l’interaction la plus simple possible

entre l’utilisateur et la simulation. Ces interfaces comprennent la configuration des contrôleurs et

divers composants personnalisés.

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 53

9.1.3 ENTRÉES

Le module des entrées est un module très important car il permet de configurer et d’utiliser divers

types de radios. Ce module a été conçu en 2 parties :

• module USB, permettant de brancher et de gérer n’importe quel contrôleur USB. Ce module

a été conçu pour être le plus flexible possible, vu la diversité des radios existantes sur le

marché ;

• module Série, permettant de gérer les données qui arrivent par le port série d’un contrôleur

spécifique. Nous nous sommes basés sur un protocole de ce contrôleur afin d’extraire les

données dans le bon ordre.

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 54

9.2 L’ARCHITECTURE EN COUCHES DE L’APPLICATION

L’architecture globale de l’application a été pensée en plusieurs couches en se basant sur DirectX

pour l’affichage graphique et l’interaction avec le matériel de l’ordinateur et sur la librairie de

simulation MOSCA pour la simulation en elle-même.

Figure 12 - Architecture en couches

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 55

9.2.1 COUCHE NATIVE

La première couche native comprend 2 parties

principales : DirectX API et Mosca. Chacune de ces

librairies est écrite en mode natif Win32.

Microsoft DirectX est une suite d'API multimédia

intégrée au système d'exploitation Windows

permettant d'exploiter les capacités matérielles

d'un ordinateur. DirectX fournit un ensemble de

bibliothèques de fonctions essentiellement

dédiées aux traitements audio / vidéo (carte vidéo, carte son, etc.) et aux périphériques d'entrée /

sortie (joystick, carte réseau, souris, etc.).

L'avantage des fonctions de DirectX pour les programmeurs est que celles-ci utilisent un algorithme

alternatif (confié au processeur) quand le matériel installé ne gère pas ce type de traitement. Il

fonctionne comme une surcouche de Windows, évitant théoriquement aux programmeurs de devoir

s'occuper des différences matérielles qui existent entre les différents PC. Par exemple, si une carte

vidéo n'a pas de fonctions dédiées à la 3D, DirectX demandera au processeur principal de s'occuper

du rendu d'une image de synthèse ou du rendu 3D en temps réel.

Pour plus d’information sur le fonctionnement global de la librairie MOSCA, voir § 9.1.1 ci-dessus.

9.2.2 COUCHE MANAGÉE

La deuxième couche était nécessaire afin de

donner une interface managée à la couche

native. Cette couche amène à la fois la portabilité

des couches du dessus et l’amélioration de la

productivité et de la sécurité.

La librairie Diamond.Mosca que nous avons

conçu permet l’interfaçage avec la librairie

MOSCA. Cette librairie assure également

l’exécution de la librairie à une fréquence de 125 hertz et permet l’échange des données entre les

deux. Elle utilise des fonctionnalités non portables.

La première couche de XNA Framework et la librairie DirectInput du Managed DirectX servent à faire

le même interfaçage mais au niveau de la carte graphique et des entrées USB.

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 56

9.2.3 COUCHE ABSTRAITE

La troisième couche est une couche à la fois

abstraite et générique. Le but de cette dernière

est de fournir les fonctionnalités simplifiant la

programmation et améliorant la productivité. Sur

cette couche il existe 2 parties principales : une

pour le rendu (c’est en fait le moteur de rendu

graphique) et une autre pour les entrées des

contrôleurs.

Diamond.Input.Usb et Diamond.Input.Serial sont des librairies qui permettent d’utiliser facilement

les contrôleurs USB et Série et qui fournissent les fonctionnalités afin de configurer ces contrôleurs.

Diamond.Render est une des librairies les plus développées de notre application. C’est à la fois le

moteur de rendu graphique et le remplacement de la deuxième couche XNA nécessaire pour

l’affichage par zone et non plus par fenêtre Windows. Cette librairie se compose principalement de :

• framework de gestion objets ;

• gestion de multiples caméras (de rendu) ;

• gestion de terrain et les optimisations de ce dernier ;

• graphe de scène ;

• octree d’optimisation de rendu ;

• zones d’affichage et leur gestion ;

• gestion des shaders et du post-processing ;

• gestion des exceptions du moteur.

Chacune de ses parties sera expliquée dans le chapitre consacré au moteur de rendu graphique et

ses composants. Voir § 11 below pour plus d’informations sur le moteur de rendu graphique.

9.2.4 COUCHE SPÉCIFIQUE À L’APPLICATION

La dernière couche est une couche spécifique à

l’application. Elle intègre les fonctionnalités

demandées (logique métier en quelque sorte), les

interfaces graphiques et d’autres fonctionnalités

accessoires comme l’enregistrement des

paramètres ou le logging. Cette couche intègre

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 57

également une couche plus abstraite des entrées utilisées dans le simulateur.

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 58

10. SIMULATION

10.1 INTRODUCTION

Une simulation de vol est un système dans lequel un pilote réel est aux commandes d'un hélicoptère

virtuel dont le comportement est obtenu par simulation.

Notre moteur 3D est un outil professionnel conçu pour remplir plusieurs besoins de l’entreprise :

• la formation continue des pilotes;

• simulation des scènes réelles (sur un tournage par exemple) ;

• permettre le pilotage en aveugle (sans voir l’hélicoptère réel, en regardant uniquement l’écran).

En plus simple, MOSCA prend en charge tout ce qui concerne le modèle des vols et nous permet de

l’utiliser de cette manière :

MOSCA est implémenté chez Flying-Cam sous forme d’une librairie écrite en langage C. Etant donné

que nous devions pouvoir l’utiliser en langage C#, le développement du module « Wrapper » fut

nécessaire pour permettre l’interaction.

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 59

10.2 WRAPPER POUR MOSCA

Dans le cadre de simulation, afin d’assurer une

exécution fluide de la simulation, nous devons

nous assurer d’une exécution à 125 hertz de la

librairie MOSCA.

Le module de simulation interne à notre

simulateur est représenté sous forme d’une

classe statique CMoscaWrapper. Cette classe

permet de :

• démarrer/arrêter la

simulation ;

• assurer l’exécution à

125 hertz ;

• offrir des accès

rapides à des valeurs d’entrée/sortie

de la librairie MOSCA ;

• effectuer la

transition entre le code C et le code

managé.

L’exécution de la librairie MOSCA se résume à un appel itératif d’une fonction. Cette fonction est

prototypée d’une manière à avoir les valeurs d’entrées (double InputValues[]) et les valeurs de sortie

(double OutputValues[]). Ces valeurs sont mémorisées sous forme des variables statiques dans la

classe CMoscaWrapper.

Examinons maintenant les principales fonctions de cette classe en commençant par la fonction de

démarrage de la simulation, la fonction Start(). Dans cette fonction l’appel itératif à la fonction

MOSCA est implémenté. Cette dernière n’est pas conçue en temps réel et la durée d’exécution peut

varier. Nous devions donc nous assurer d’attendre le temps restant, calculé suivant la formule :

Où : est le temps d’attente à trouver.

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 60

est le temps d’exécution de la fonction MOSCA.

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 61

public static void Start() { if ( CInputController .Instance.ControllerType == EInputController .SerialController) { CInputController .Instance.SerialController.SerialReadMessageEvent + = new CSerialReadEventHandler (SerialController_SerialReadMessageEvent); SerialAsyncThread = CInputController .Instance.SerialController.ReadLoopThread(); } //(1) GetPosition( true , Microsoft.Xna.Framework.Input. Keys .D9, ref InputValues, ref OutputValues); //(2) Started = true ; timeBeginPeriod(1); //(3) while (Started) //(4) { PerfTimer2.Stop(); PerfTimer1.Start(); GetPosition( false , KeyPressed, ref .InputValues, ref OutputValues); //(5) PerfTimer1.Stop(); int diff=8-( int )((PerfTimer1.Duration+PerfTimer2.Duration)*1000); //(6) if (diff > 0) Thread .Sleep(diff); //(7) PerfTimer2.Start(); } }

(1) Tout d’abord, nous initialisons l’événement de la lecture du contrôleur

série ( Voir le TFE de Quentin Charlier pour plus d’informations sur la gestion des contrôleurs).

(2) Un premier appel à la fonction MOSCA est effectué, réinitialisant ainsi la

simulation.

(3) La période de temps (la résolution du timer) est mise à 1 milliseconde,

assurant ainsi que la fonction Thread.Sleep() effectue une attente avec la bonne précision

(Thread.Sleep(7) sans avoir forcé une période peut attendre 15ms suivant l’horloge).

(4) On démarre la boucle principale, la simulation en elle-même.

(5) On effectue l’appel à la fonction MOSCA, en passant par référence les

valeurs d’entrée et en récupérant les valeurs de sortie.

(6) On effectue le calcul à l’aide des chronomètres.

(7) Finalement, on effectue un Thread.Sleep( ) et on attend le temps

nécessaire.

Examinons maintenant la fonction MOSCA et son prototype C :

int wrapper_fc_gui__(integer *first_call__, integer * mode_key__, doublereal *input_futaba__, doublereal *all_state__)

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 62

Cette fonction contient 4 paramètres dont 2 vecteurs (doublereal*). Afin de pouvoir l’utiliser en C#, il

est nécessaire de créer une liaison sous forme d’une fonction « static extern » et dotée d’un attribut

DllImport, disant au compilateur que c’est une fonction externe se trouvant dans une librairie.

[ DllImport ( "mosca_FC.dll" , EntryPoint = "wrapper_fc_gui__" , CallingConvention = CallingConvention .Cdecl)] unsafe static extern int UnsafeCallFcGui( int * first_call__, int * mode_key__, double * input_futaba__, double * all_state__);

Pour mieux expliquer la fonction, voici un tableau des 4 paramètres de la fonction et les valeurs

possibles :

Paramètre Description Valeurs possibles

int* first_call__

Permet de dire à la librairie MOSCA si

les valeurs doivent être réinitialisées

dans un état de situation initiale ou pas.

0 : non

1 : oui

int* mode_key__

Permet de transférer à la librairie

MOSCA des informations sur le mode

de la simulation.

0 : Pilotage manuel

9 : Pilotage automatique

8 : Pilotage automatique avec caméra

gyrostabilisé

double* input_futaba__

Vecteur de 8 entrées des valeurs des La valeur de pulsion est comprise entre

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 63

axes des contrôleurs. -0.5 et 0.5

double* all_state__

Vecteur de 35 entrées avec des diverses

informations de sortie. all_state__[6] : angle de

l’hélicoptère

all_state__[7] : angle de l’hélicoptère

all_state__[8] : angle 4de

l’hélicoptère

all_state__[11] : angle du rotor

all_state__[12] : angle du rotor

all_state__[30] : position x de

l’hélicoptère

all_state__[31] : position y de

l’hélicoptère

all_state__[32] : position z de

l’hélicoptère

all_state__[33] : angle de la caméra

all_state__[34] : angle de la caméra

4 : “Psi”

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 64

11. MOTEUR DE RENDU GRAPHIQUE

11.1 FRAMEWORK OBJETS

11.1.1 POURQUOI UN FRAMEWORK D’OBJETS ?

Le framework d’objets a été conçu dans le but de simplifier et d’uniformiser l’affichage des objets 3D

et également de rendre possible l’optimisation de rendu de scène. Ce framework définit:

• une classe de base représentant une entité 3D ;

• des interfaces représentant les capacités d’une entité 3D.

Grâce à une représentation de ce genre, nous pouvons afficher un objet 3D, définir ses propriétés,

charger/décharger le contenu graphique ou le mettre à jour. Tout cela se fait très rapidement et est

pris en charge par le moteur de rendu. Voir § 11.4 below pour plus d’information sur cette prise en charge.

Voici un schéma des interfaces et d’objets de base avec les propriétés et méthodes contenues :

Figure 13 - Framework d'objets, schéma global

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 65

11.1.2 L’OBJET DE BASE

L’objet de base (la classe CObject) représentant une entité 3D possède 4 propriétés principales:

Propriété Description

Vector3 Position Une position en 3D (un point) permettant de positionner l’objet

simplement en définissant ses coordonnées.

Vector3 Scaling L’étirement de cet objet permettant de l’agrandir ou diminuer.

Représenté par une coordonnée de proportions sur chaque axe.

Quaternion Rotation Un quaternion de rotation définissant les rotations sur les axes X, Y

et Z de l’objet.

bool Visible Une propriété permettant de voir si l’objet est visible ou pas, donc

doit ou pas être affiché.

Cet objet de base implémente une fonction Draw() unique, qui analyse les interfaces implémentées

et exécute les méthodes nécessaires pour effectuer le rendu avec la prise en charge du framework

des shaders objet intégré.

public void Draw( CRenderContext _RenderContext) { if ( this is IChildRenderer ) (( IChildRenderer ) this ).RenderChildren(_RenderContext); if ( this is IRenderable ) { CShader objShader = CShaderManager .Instance.GetShader(m_Shader); if (objShader != null ) { objShader.SetParameters( this ,_RenderContext); objShader.Effect.Begin(); foreach ( EffectPass pass in objShader.Effect.CurrentTechnique.Passes) { pass.Begin(); (( IRenderable ) this ).Render(_RenderContext); pass.End(); } objShader.Effect.End(); } } }

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 66

11.1.3 LES INTERFACES

Notre framework définit plusieurs interfaces que l’objet peut ou pas implémenter. Chacune de ses

interfaces est également un « flag logique » permettant de créer les différents objets. On peut créer

un objet qui n’a pas de contenu graphique ou même un objet qui ne sera pas affiché du tout (objet

de mise à jour).

• IRenderable, une interface qui définit une méthode Render(). Cette interface permet au

moteur de rendu graphique de comprendre que l’objet est « Affichable » et l’afficher en

exécutant la méthode implémentée ;

• IUpdateable, une interface qui définit une méthode Update(). Cette interface permet au

moteur de rendu graphique de comprendre que l’objet peut être mis à jour par sa méthode

implémentée ;

• IChildRenderer, une interface définissant une méthode RenderChildren(), l’exécution de

cette méthode ressemble à celle de IRenderable, mais le shader d’objet n’est pas pris en

compte. Il est sous-entendu que l’objet implémentant l’interface est un container d’objets

graphiques ;

• ILoadable, une interface définissant deux méthodes : LoadGraphicsContent() et

UnloadGraphicsContent(). Cette interface permet au moteur de rendu de charger/décharger

le contenu graphique de l’objet. Ex : le chargement des textures, modèles 3D, etc.

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 67

11.1.4 L’UTILISATION

Le framework objet a été largement utilisé pendant le projet pour créer une variété d’objets utilisés

dans le simulateur, dont les plus importants sont :

• la classe CMobile, représentant une entité 3D avec la possibilité de se déplacer dans le

monde ;

• la classe CHelicopter, dérivée de CMobile. Elle est la représentation de l’hélicoptère et prend

en charge des contrôleurs et d’autres propriétés spécifiques à l’hélicoptère ;

• la classe CGrid, représentant une grille. Elle permet de s’orienter dans l’espace.

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 68

11.2 CAMÉRA

11.2.1 INTRODUCTION

Le composant caméra est en réalité la vue de l’utilisateur dans le monde 3D. Plusieurs caméras ou

vues sont possibles. Par exemple, il y a la vue en mode FirstPerson ou en mode ThirdPerson. La

première est en réalité la vue à l’intérieur de l’hélicoptère, c’est-à-dire ce qu’il filme. La deuxième est

une vue extérieure où l’on suit l’hélicoptère, on est à la place du pilote.

11.2.2 NOTIONS D’UNE CAMÉRA

Pour bien comprendre la notion de caméra, nous devons connaitres les propriétés de celle-ci. Dans le

schéma ci-dessous les principales propriétés d’une caméra ont été reprises et dans le tableau qui suit

une explication plus détaillée est fournie.

Figure 14 - Caméra

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 69

Nous avons implémenté la notion de caméra sous forme d’un objet CCamera, facilement configurable grâce à ses propriétés, les voici :

Propriétés Descriptions

Vector3 Position Position de la caméra définie dans l’espace 3D

par trois coordonnées x, y et z.

BoundingFrustum Frustum Le frustum est l’espace 3D visible par la caméra,

il est compris entre le plan visible le plus proche

et le plan visible le plus lointain.

Vector3 UpVector L’axe pour la hauteur de la caméra

Vector3 Target Le point que la caméra va fixer.

float NearVision La vision minimale de la caméra en terme de

distance.

float FarVision La vision maximale de la caméra en terme de

distance.

int ScreenHeight La hauteur de l’écran en pixel (h sur le schéma).

int ScreenWidth La largeur de l’écran en pixel (w sur le schéma).

float AspectRatio Proportion de la largeur sur la hauteur de

l’écran. Cela permet d'éviter de voir les objets

affinés ou grossis si la taille de la zone

d'affichage n'est pas carrée.

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 70

Autres propriétés de la caméra :

Propriétés Description

ECameraState Mode Mode de la caméra : FirstPerson, ThirdPerson,

FreeFloating, …

Quaternion Rotation Quaternion utilisé pour effectuer une rotation

de la caméra. Un quaternion contient un axe et

un angle. On effectue donc une rotation d’un

certain angle sur un axe.

Viewport Viewport Définit les dimensions de la fenêtre de notre

écran (2D) sur laquelle notre monde virtuel (3D)

va être dessiné.

float FieldOfView Angle d’ouverture de la caméra.

Matrix View Matrice de vue de la caméra. Elle permet de

calculer les points qui sont visibles par la

caméra.

Matrix Projection Matrice de projection de la caméra. C’est la

projection de l’image sur l’écran, on passe bien

d’un monde 3D (View) à un monde 2D

(projection).

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 71

11.2.3 MÉTHODES PRINCIPALES

Notre caméra doit pouvoir changer de position et être tournée, comme une caméra réelle. Elle peut

donc bouger sur les axes x, y et z et être tournée sur ces mêmes axes d’un angle donné.

Tout d’abord, notre caméra doit pouvoir bouger dans l’espace. On parle de translation.

public void Translate( Vector3 distance) {

m_Position += Vector3 .Transform(distance, Matrix .CreateFromQuaternion(m_Rotation)); }

Ensuite, la caméra doit être tournée. On parle d’une rotation de caméra. Cette rotation est

représentée par un quaternion, une notion mathématique souvent utilisée dans les moteur 3D.

public void Rotate( Vector3 axis, float angle) { axis = Vector3 .Transform(axis, Matrix .CreateFromQuaternion(m_Rotation)); m_Rotation = Quaternion .Normalize( Quaternion .CreateFromAxisAngle(axis, angle) * m_Rotation); }

Et finalement, une caméra doit pouvoir « orbiter » autour d’une cible. Cette fonctionnalité est

représentée par la méthode Revolve(). La caméra tourne sur un axe donné suivant un angle donné et

la cible (représentée par la propriété Target).

public void Revolve( Vector3 axis, float angle) { Vector3 revolveAxis = Vector3 .Transform(axis, Matrix .CreateFromQuaternion(m_Rotation)); Quaternion rotate = Quaternion .CreateFromAxisAngle(revolveAxis, angle); m_Position = Vector3 .Transform(m_Target - m_Position, Matrix .CreateFromQuaternion(rotate)) + m_Target; Rotate(axis, angle); }

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 72

11.2.4 DÉPLACEMENT

Une caméra doit pouvoir être déplacée dans notre monde 3D. Cette caméra est donc mise à jour à

chaque frame. La position de la caméra et donc ce qu’elle voit (les matrices View et Projection) est

mis à jour tout le temps.

La fonction qui effectue cette mise à jour :

public virtual void Update() { if (mode == ECameraState .FreeFloating) //(1) { //Translate the camera with the target if (!m_Target.Equals(m_OldTarget)) { m_Position.X += (m_Target.X - m_OldTarge t.X); m_Position.Y += (m_Target.Y - m_OldTarge t.Y); m_Position.Z += (m_Target.Z - m_OldTarge t.Z); //(2) m_OldTarget = m_Target; } m_View = Matrix .Invert( Matrix .CreateFromQuaternion(m_Rotation) * Matrix .CreateTranslation(m_Position)); //(3) } else if (mode == ECameraState .FirstPerson) { m_View = Matrix .CreateLookAt(m_Position, m_Target, m_UpVector); m_Rotation = Quaternion .CreateFromRotationMatrix( Matrix .Invert(m_View)); } else if (mode == ECameraState .FixedFollow) { m_View = Matrix .CreateLookAt(m_Position, m_Target, Vector3 .Up); m_Rotation = Quaternion .CreateFromRotationMatrix( Matrix .Invert(m_View)); } else { m_View = Matrix .Invert( Matrix .CreateFromQuaternion(m_Rotation) * Matrix .CreateTranslation(m_Position)); } m_Projection = Matrix .CreatePerspectiveFieldOfView( m_FieldOfView, m_AspectRatio, m_Vie wport.MinDepth, m_Viewport.MaxDepth); //(4) m_Frustum = new BoundingFrustum ( Matrix .Multiply(m_View, m_Projection)); }

(1) On fait une vérification sur le mode de la caméra (le plus utilisé est le mode FreeFloating,

permettant à la caméra de suivre une cible tout en permettant d’orbiter autour).

(2) Pour chaque mode diffèrent, on effectue la mise à jour différemment. Dans le cas de

FreeFloating, on fait suivre la cible par la caméra en modifiant la position de la caméra.

(3) Ensuite, il est possible pour chaque mode de créer la matrice de vue.

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 73

(4) Finalement, la matrice de projection et le frustum de la caméra sont créés.

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 74

11.3 OCTREE D’OPTIMISATION DE RENDU

11.3.1 DÉFINITION

Un octree est une structure de données de type arbre dans laquelle chaque nœud peut compter

jusqu'à huit enfants. Les octrees sont le plus souvent utilisés pour partitionner un espace

tridimensionnel en le subdivisant récursivement en huit octants.

Quelques utilisations courantes des octrees:

• L'indexation spatiale

• La détection efficace de collision dans le cadre de la 3D

• Le view frustum culling

Les octrees sont l'analogie tridimensionnelle des quadtrees. Le nom est formé à partir d'oct et de tree

(arbre, en anglais). Chaque nœud d'un octree subdivise l'espace qu'il représente en huit sous-espaces

(les octants).

Dans le cas d'un octree de type point region (PR), le nœud

mémorise explicitement un point tridimensionnel qui est le

"centre" de la subdivision pour ce nœud, le point défini

alors l'un des coins de chacun des huit enfants. Le nœud

racine d'un octree de type PR peut représenter un espace

infini.

Dans un octree de type MX, le point de subdivision est

implicitement le centre de l'espace que le nœud représente.

Le nœud racine d'un octree de type MX doit représenter un

espace fini de manière à ce que les centres implicites des

nœuds soient bien définis.

11.3.2 VIEW FRUSTUM

Le viewing frustum est la représentation du

volume visible par la camera. Naturellement, les

objets en dehors de ce volume ne seront pas

visibles, donc pas affichés. Les objets étant à cheval

sur ce volume seront découpés en morceaux plus

petits dans un processus appelé clipping, et les

morceaux en dehors du volume ne seront pas

Figure 15 - Octree, présentation en 3D

Figure 16 - View Frustum

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 75

affichés. Le clipping n’est pas implémenté dans notre octree pour cause de manque de temps, mais

son développement est prévu pour les versions futures du moteur de rendu.

11.3.3 REPRÉSENTATION GRAPHIQUE

Dans le « monde de la programmation 3D » il n’est pas toujours évident d’imaginer les formes et les

techniques utilisées et leur utilité. Donc avant de parler de l’implémentation d’un octree, pour mieux

comprendre le principe, c’est toujours très utile de se faire une idée d’une représentation graphique.

Voici donc une représentation graphique dans laquelle nous avons 10 objets dans une scène, dont 6

sont assez rapprochés les uns des autres :

Figure 17 - Octree, représentation graphique

Sur cette dernière figure, on peut voir que la Racine contient 10 objets et la division d’un cube n’est

effectuée qu’à partir de 5 objets. Nous avons donc un total de 17 cubes (nœuds). On peut également

voir que si le cube A n’est pas visible, en une opération assez simple on élimine 60% de temps

d’affichage de la scène, ce qui n’est pas négligeable.

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 76

11.3.4 IMPLÉMENTATION

Notre octree implémente une interface IOctree, qui définit plusieurs méthodes principales afin de

manipuler un Octree quelconque :

Méthode Description

void AddObject(CObject _Object); Cette fonction permet d’ajouter un objet dans

l’octree et gère également la division de cette

dernière dans le cas de dépassement de

capacité d’un des nœuds.

void RemoveObject(CObject _Object, Vector3 _OldPosition);

Cette fonction permet de supprimer un objet de

l’octree. Une position est nécessaire pour

retrouver l’objet plus rapidement

void UpdateObject(CObject _Object, Vector3 _OldPosition);

Cette fonction permet de faire la mise à jour de

l’octree en fonction d’un objet qui a été mis à

jour. Elle vérifie la position, ceci permet de

replacer l’objet dans un autre nœud (dans le cas

des objets en mouvement).

void Draw(CRenderContext _RenderContext);

Cette fonction permet d’afficher les lignes

d’octree dans le cas de débogage et mettre à

jour la propriété « Visible » des objets contenus

dans l’octree.

void Update(BoundingFrustum _CameraFrustum);

Cette fonction effectue une mise à jour des

nœuds. Elle permet de déterminer si le nœud

d’octree est visible ou pas.

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 77

Notre implémentation de l’octree contient des objets, il nous fallait une fonction de placement

automatique d’un objet dans l’octree, cette fonction c’est la fonction AddObject.

/// <summary> /// Add an object in a node /// </summary> /// <param name="newObject"></param> public void AddObject( CObject _Object) { if (m_Nodes.Count != 0) { // S’il y a des enfants, leur passer l’objet foreach ( COctreeNode node in m_Nodes) { if (node.Contains(_Object.Position)) { node.AddObject(_Object); } } } else if (m_Objects.Count >= COctreeManager .Instance.MaxObjectsPerNode) { // S’il n’y a pas d’enfants, vérifier la capacité // et s’il y a dépassement de capacité, diviser le cube en 8 // et redistribuer les objets aux enfants. m_Objects.Add(_Object); Split(); } else { // sinon tout simplement ajouter l’objet m_Objects.Add(_Object); } }

Examinons la fonction Update() qui permet d’effectuer la mise à jour de la visibilité des nœuds.

Chaque nœud possède une propriété IsCulled permettant de dire si le nœud est visible (false) ou

invisible (true).

/// <summary> /// Updates nodes if culled /// </summary> public void Update( BoundingFrustum _CameraFrustum) { m_IsCulled = _CameraFrustum.Contains(m_Bounds)== ContainmentType .Disjoint; if (!m_IsCulled) { foreach ( COctreeNode node in m_Nodes) { node.Update(_CameraFrustum); } } }

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 78

Dans cette architecture, nous avons développé une autre classe : COCtreeManager. Elle permet de

configurer l’ensemble des octrees (une classe de configuration globale). Elle permet de définir entre

autres :

• si les lignes de visualisation d’octrees doivent être affichées ou pas ;

• la couleur et la taille de ces lignes ;

• le nombre d’objets maximum par nœud (une fois arrivé à ce nombre d’objet, un nœud va se

diviser automatiquement en plusieurs autres et leur redistribuer les objets).

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 79

11.3.5 ANNEXE

En annexe, voici la représentation graphique de notre octree dans le cadre des premiers essais du

moteur 3D. Les lignes rouges représentent les cubes de l’octree, qui, elle, est divisée suivant les

modèles contenues à l’intérieur (les nombreux vaisseaux spatiales) :

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 80

11.4 ZONES D’AFFICHAGE

11.4.1 GÉNÉRALITÉS

Le framework XNA est un framework qui était conçu principalement pour les jeux vidéo. Dans notre

cas, l’application était une application professionnelle et les critères pour une telle application ne

sont pas forcement les mêmes que ceux d’un jeu vidéo. Un des points principaux était le fait de

pouvoir afficher dans plusieurs zones simultanément. Vu que le framework XNA ne prévoyait pas la

possibilité d’affichage simultané dans deux zones bien distinctes, nous avons été obligés de réécrire

une partie de ce dernier afin d’implémenter cette fonctionnalité.

Cette fonctionnalité a été pensée en s’intégrant complètement au moteur de rendu graphique afin

de pouvoir gérer plus facilement plusieurs choses :

• gestion des scènes (affichage, mise à jour, optimisation) ;

• chargement/déchargement de contenu graphique (dynamiquement ou pas) ;

• placement de ces zones d’affichage dans WindowsForms.

Comme nous avons pu voir dans le chapitre 5.2.4 above, le framework XNA est composé de plusieurs

couches (framework étendu et framework de base). La couche du framework étendu effectuait

l’instanciation et la gestion de l’infrastructure Direct 3D et se chargeait d’instancier la fenêtre

d’affichage et d’autres choses connexes. Cette couche implémentait également un « Application

Model » que nous avons déjà remplacé par notre framework objets. De tout ceci, on peut déduire

que pour créer les zones d’affichage, nous devions réécrire complètement l’architecture du

framework étendu (et non pas uniquement l’ « Application Model »).

Afin de rester semblable au framework XNA de base, notre couche des zones d’affichage est liée à

notre framework objets pour effectuer l’affichage et rendre le développement plus simple.

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 81

11.4.2 RÉSULTAT FINAL

Pour mieux comprendre nos buts, voici une image de résultat final des zones d’affichage avec

quelques explications :

Figure 18 - Zones d'affichage

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 82

(1) Possibilité d’utiliser des composants Windows Forms (des menus, boutons, …).

(2) Des multiples zones d’affichage peuvent être placées n’importe où, redimensionnées,

déplacées. On a donc une notion de surface de rendu (IRenderingSurface).

(3) Les zones d’affichage peuvent être visibles/non visibles sans pour autant arrêter l’affichage

ou la mise à jour des données logiques de l’application.

(4) Le rendu peut être démarré ou arrêté à n’importe quel moment de l’application, les objets

peuvent être ajoutés dynamiquement pendant l’affichage.

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 83

11.4.3 EXEMPLE D’UTILISATION « PAS À PAS »

Avant d’entrer dans les détails de l’architecture et de son implémentation, nous allons voir

l’utilisation concrète de cette architecture dans le cadre du moteur 3D.

Cet exemple est basé sur la fonction utilisée pour la création de la scène présentée lors de

l’exposition NAB à Las Vegas :

public void Initialize_MainScene() { CWorkspace m_MainScene = new CWorkspace (); this .AddWorkspace( "MainScene" , m_MainScene); //(1) m_Helicopter = new CHelicopter (); m_Grid.VisibleState = EVisibleState .AlwaysInvisible; m_Water.VisibleState = EVisibleState .AlwaysInvisible; CMobile Bay = new CMobile ( @"Content\Models\Bay" ); Bay.Position = new Vector3 (2210, 60, 9999); Bay.Scaling = new Vector3 (2, 2, 2); CMobile Ketch = new CMobile ( @"Content\Models\Ketch" ); Ketch.Position = new Vector3 (-8340, 800, 8120); Ketch.Scaling = new Vector3 (1, 1, 1); //(2) m_MainScene.ObjectManager.AddObject( "Grid" , m_Grid); //(3) m_MainScene.ObjectManager.AddObject( "Water" , m_Water); m_MainScene.ObjectManager.AddObject( "Bay" , Bay); m_MainScene.ObjectManager.AddObject( "Ketch" , Ketch); m_MainScene.ObjectManager.AddObject( "SkyDome" , new CSkyDome()); m_MainScene.ObjectManager.AddObject( "Helicopter" , m_Helicopter); }

(1) On commence par créer un espace de travail qui servira de container aux objets de scène.

Ensuite, on ajoute cet espace de travail à un gestionnaire des espaces de travail.

(2) On continue par instancier les objets de scène et à modifier leurs propriétés.

(3) On finit par ajouter tous ces objets de scène (dans un ordre de préférence) à l’espace de

travail.

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 84

Nous commençons notre scène avec une zone d’affichage remplie d’une couleur bleue, utilisée par

défaut. Cette opération est effectuée à chaque début de la boucle de rendu.

La ligne suivante ajoute la grille nommée « Grid » sur la zone d’affichage :

m_MainScene.ObjectManager.AddObject( "Grid" , m_Grid);

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 85

La ligne suivante ajoute un modèle 3D (une bouée) nommée « Bay » sur la zone d’affichage :

m_MainScene.ObjectManager.AddObject( "Bay" , Bay);

La ligne suivante ajoute un modèle 3D (un voilier) nommé « Ketch » sur la zone d’affichage :

m_MainScene.ObjectManager.AddObject( "Ketch" , Ketch);

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 86

La ligne suivante ajoute un SkyDome (ciel) sur la zone d’affichage :

m_MainScene.ObjectManager.AddObject( "SkyDome" , new CSkyDome());

Et finalement, nous ajoutons un hélicoptère et nous pouvons commencer à utiliser la scène.

m_MainScene.ObjectManager.AddObject( "Helicopter" , m_Helicopter);

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 87

11.4.4 INTERACTION ENTRE LE RENDU ET LE FRAMEWORK OBJETS

Afin de concevoir les zones d’affichage en interaction avec le framework objets, nous avons analysé

et établi plusieurs notions bien distinctes :

• notion d’un contexte de rendu : un contexte général comprenant toutes les informations

nécessaires pour l’affichage et la mise à jour;

• notion de surface de rendu : est en quelque sorte une «toile» de dessin afin de permettre de

définir des zones à deux dimensions dans lesquelles l’affichage est permis;

• notion d’un gestionnaire d’objets : permet de gérer et afficher une collection d’objets (basés

sur le framework d’objets);

• notion d’un espace de travail : contient divers gestionnaires dont un gestionnaire d’objets et

un gestionnaire de contenus ; permet d’effectuer des opérations globales à l’affichage;

• notion d’un gestionnaire des espaces de travail : un simple gestionnaire permettant de gérer

de multiples espaces de travail.

Afin d’effectuer l’affichage final, il est nécessaire de définir une surface de rendu sur laquelle un

espace de travail va effectuer le dessin.

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 88

11.4.5 L’ARCHITECTURE DIRECT 3D

Avant de parler d’implémentation d’infrastructure Direct 3D, nous devions comprendre les bases du

fonctionnement de l’API.

Il existe 2 types de modifications de rendu final :

• programmable pipeline : permet au développeur de modifier presque tous les algorithmes

pour le rendu final. Il existe deux possibilités d’interférer avec le pipeline de base :

o vertex shader : permet la modification des vertices avant qu’ils ne soient utilisés dans

la surface de rendu

o pixel shader : permet la modification de chaque pixel avant le rendu final

• fixed function pipeline (FFP) : permet la modification de rendu final en se basant sur

l’utilisation des algorithmes. Avec FFP le développeur peut choisir un des algorithmes

prédéfinis et le paramétrer. Les nouveaux algorithmes ne peuvent pas être ajoutés (d’où le

nom). Cette technique d’affichage est considérée de plus en plus comme obsolète et n’existe

d’ailleurs plus dans DirectX 10.

Le processus d’affichage (dit graphics pipeline) fournit la puissance nécessaire afin de procéder à

l’affichage des scènes Direct3D sur un écran, en utilisant le plus possible les ressources matérielles.

Cette figure illustre conceptuellement ce processus:

Figure 19 - Graphics pipeline

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 89

Nom du composant Description

Vertex data Les vertices du modèle non transformés stockés dans la mémoire tampon

des vertices (vertex memory buffers).

Primitive data Les primitives géométriques, y compris les points, lignes, triangles et

polygones, sont référenciées dans les données vertices grâce à index

buffers.

Tessellation Le tesselator est une unité de conversion des primitives de haut niveau

(mesh parts et autres) en vertices et permet de les stocker dans les vertex

buffers.

Vertex processing Les transformations Direct3D sont appliquées aux vertices stockés dans le

vertex buffer.

Geometry processing Le clipping, back face culling, évaluation des attributs sont appliqués aux

vertices transformés.

Texture surface Les coordonnées des textures Direct3D sont fournies par le biais d’une

interface IDirect3DTexture.

Texture sampler Le niveau de détail (filtres) est appliqué aux textures.

Pixel processing Les opérations du pixel shader utilisent les données de la géométrie afin

de modifier les entrées vertex et textures.

Pixel rendering Les processus du rendu final modifient les couleurs des pixels grâce à

l’alpha (transparence), profondeur ou autres techniques afin de finaliser

le rendu qui sera affiché à l’écran.

Nous n’allons pas rentrer dans les détails de chaque élément, ceci sortant largement du cadre de ce

travail.

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 90

Le composant central du Direct3D est le Device 3D, il encapsule et stocke l’état de rendu (rendering

state).

Il existe deux types principaux des Direct 3D device :

• un device HAL (hardware-accelerated), se basant sur le matériel afin d’effectuer et accélérer

le processus de rendu ;

• un reference device, sur lequel tout le processus de rendu est effectué par le CPU.

On peut imaginer ces deux types de devices comme des pilotes séparés. Un pilote spécifique pour les

reference devices et un pour les HAL devices. Dans le cadre de ce travail nous allons nous intéresser

aux HAL devices, car ils offrent un gain de performance considérable. Les HAL devices sont

disponibles sur toutes les cartes graphiques supportant Direct3D.

Voici comment on procède à la création d’un device en XNA : GraphicsDevice device = new GraphicsDevice ( GraphicsAdapter .DefaultAdapter, // (1) DeviceType .Hardware, // (2) base .Handle, // (3) CreateOptions .HardwareVertexProcessing, // (4) presentationParameters // (5) ); device.RenderState.CullMode = CullMode .CullCounterClockwiseFace; // (6) device.RenderState.DepthBufferEnable = true ; // (7)

Plus en détail :

(1) Ce paramètre permet de choisir l’adaptateur graphique (la carte graphique à utiliser).

(2) Permet de définir le type de device à créer, HAL ou Reference.

(3) Le handle (pointeur) de la fenêtre Win32 dans laquelle l’affichage est effectué.

(4) Le type de Vertex processing à utiliser, indique comment Direct3D doit traiter les

transformations des vertices (hardware, software, threadé…).

(5) Les paramètres de présentations, les différents buffers et autres paramètres encapsulés dans

une seule classe. Il en existe des dizaines donc nous n’entrerons pas dans les détails de cette

classe.

(6) Ce paramètre permet de définir un état (temporaire et modifiable) d’ordre d’affichage des

vertices.

(7) Ce paramètre permet d’activer le DepthBuffer (dit aussi Z-Buffer). Z-buffer est une méthode

employée dans le cadre de l'affichage d'une scène 3D. Le Z-Buffer permet de gérer le

problème de la visibilité qui consiste à déterminer quels éléments de la scène doivent être

rendus, lesquels sont cachés par d'autres et dans quel ordre l'affichage des primitives doit se

faire.

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 91

11.4.6 L’ARCHITECTURE

CONTEXTE DE RENDU

Le contexte de rendu est l’élément principal d’affichage,

permettant d’avoir un objet commun contenant tout ce qui est

nécessaire pour effectuer un affichage ou une mise à jour

quelconque. Ce contexte est également utilisé dans le

framework objet (passé en paramètre à la fonction Render() ou

RenderChildren() ). Cet objet permet de fournir plusieurs

paramètres et fonctionnalités (sous forme de propriétés

dynamiques). Les principales fonctionnalités sont :

• les paramètres de la caméra suivant lesquels on doit

faire l’affichage. Voir § 11.2 above pour plus d’informations

sur les paramètres de la caméra;

• récupération d’états de clavier et souris ;

• le temps interne (combien de millisecondes se sont

écoulées depuis le début ou depuis le dernier frame) ;

• récupération du Device Direct 3D chargé de faire

l’affichage ;

• des propriétés dynamiques fournissant les diverses

multiplications des matrices ;

• des événements permettant de signaler la

création/destruction/réinitialisation du Device Direct

3D ;

• des méthodes de mise à jour du contexte de rendu,

permettant ainsi de mettre à jour les données de la

caméra et des entrées clavier/souris à chaque frame.

Sur la figure à droite vous pouvez voir le schéma fortement simplifié de cette classe.

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 92

SURFACE DE RENDU

Une interface IRenderingSurface définit une notion de

surface de rendu, qui nous est nécéssaire afin de définir

la zone d’affichage. Cette interface définit les méthodes

nécessaires pour effectuer l’affichage et la création de

Device Direct3D.

Méthode Description

CRenderContext CreateDevice(); Cette méthode permet de créer un Device Direct 3D

au début de l’initialisation de l’affichage; elle crée et

définit également un contexte de rendu

correspondant.

void Attach(IWorkspace _Workspace);

Cette méthode permet d’attacher un « espace de

travail » (IWorkspace) à la zone d’affichage pour

qu’elle sache ce qu’elle doit afficher. Le Worskpace va

être expliqué plus loin en détail.

void Run(); Cette méthode permet de démarrer l’affichage.

void Stop(); Cette méthode permet d’arrêter l’affichage.

void LoadGraphicsContent(bool AllContent);

Cette méthode permet de charger le contenu

graphique (à la demande).

void UnloadGraphicsContent(bool AllContent);

Cette méthode permet de décharger le contenu

graphique (à la demande).

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 93

ESPACE DE TRAVAIL

Comme signalé précédemment, nous voulions définir

plusieurs « notions » (interfaces) et faire une division

claire entre plusieurs choses :

• une zone d’affichage ;

• un espace de travail.

La notion d’espace de travail est représentée par une

interface IWorkspace, permettant de gérer plusieurs

fonctionnalités :

• gestion de divers services (objets permettant l’extensibilité de l’espace de travail)

• accès direct au Direct 3D Device qui effectue l’affichage de l’espace de travail ;

• accès au ContentManager : un objet du framework XNA permettant le

chargement/déchargement des ressources artistiques (modèles 3D, sons, textures,

images…) ;

• accès au ObjectManager (cette notion sera expliquée après le tableau suivant).

Méthode Description

object GetService(Type serviceType);

Cette méthode obtient l’objet service du type spécifié.

Un service est un objet qui assure la prise en charge

personnalisée d'autres objets.

void RegisterService(Type type, object provider);

Cette méthode permet d’enregistrer le service dans

l’espace de travail en l’intégrant dans son

environnement.

void RevokeService(Type _ServiceType);

Cette méthode permet de retirer un service de

l’environnement de l’espace de travail.

GraphicsDevice GraphicsDevice { get;}

Cette propriété permet d’accéder au Device Direct 3D

lié.

ContentManager ContentManager{ get; }

Cette propriété permet d’accéder au gestionnaire de

contenu lié.

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 94

IObjectManager ObjectManager { get; }

Cette propriété permet d’accéder au gestionnaire

d’objets 3D lié.

Une notion de « gestionnaire d’objets » a été également

définie au moyen de l’interface IObjectManager. Ce

gestionnaire d’objets effectue toute la gestion des divers

mécanismes implémentant les optimisations d’affichage, le

chargement des ressources nécessaires et en simplifiant

tout le processus.

Sans entrer dans les détails, elle permet de :

• gérer une collection d’objets ;

• afficher cette collection ;

• effectuer la mise à jour de cette collection ;

• charger/décharger les ressources utilisées par les objets.

Voici les méthodes principales qui ont été définies :

Méthode Description

void AddObject(string _Asset, CObject _Object);

Cette méthode permet d’ajouter un objet à la

collection d’objets qui sera gérée par le

gestionnaire.

void RemoveObject(string _Asset); Cette méthode permet d’enlever (et décharger)

l’objet de la collection.

Obj GetTypedObject<Obj>(string _Asset) where Obj : class;

Cette méthode permet de récupérer un objet

typé de la collection.

void UpdateObjects( CRenderContext _RenderContext);

Cette méthode permet d’effectuer une mise à

jour (appel des fonctions Update

correspondantes) de chaque objet dans la

collection.

void DrawObjects( CRenderContext _RenderContext);

Cette méthode permet d’effectuer l’affichage

des objets de la collection.

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 95

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 96

GESTIONNAIRE DES ESPACES DE TRAVAIL

Dans une application comprenant plusieurs zones

d’affichage il est nécessaire de pouvoir gérer toutes les

zones d’affichage d’un seul et unique endroit. Pour

permettre ceci, nous avons défini une notion de

gestionnaire des espaces de travail, permettant la gestion

de cette collection et éventuellement de la partie

«métier » de l’application. Cette notion est représentée

sous forme de l’interface IWorkspaceManager. Vous

pouvez voir ses méthodes principales sur le schéma ci-contre. Cette notion est assez simple en soi,

donc nous n’allons pas entrer dans les détails.

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 97

11.4.7 L’IMPLÉMENTATION

IMPLÉMENTATION DE LA SURFACE DE RENDU

Nous avons conçu une première implémentation de la notion de

surface de rendu. Nous voulions l’utiliser dans WindowsForms nous

avons donc créé une classe dérivée de UserControl (contrôle

d’utilisateur) et implémentant l’interface IRenderingSurface. Ceci

permet l’utilisation (placement et modification de propriétés)

simple dans le designer de Visual Studio.

Sur le schéma ci-contre vous pouvez voir les méthodes principales

de cette classe. Son fonctionnement comprend :

• Lancement/arrêt de la boucle d’affichage. Cette boucle est

gérée par un timer (chronomètre) permettant d’appeler la

méthode Tick à une cadence spécifiée ;

• Création d’un Device Direct 3D et gestion de ses

événements

Voici la fonction Tick, qui est appelée en boucle et représente tout ce qui se passe pendant

l’affichage d’un frame :

private void Tick( object sender, EventArgs e) { UpdateScene(); //(1) if (!m_SuspendRendering) {

GraphicsDevice.Clear(m_ClearColor); //(2) DrawScene(); //(3) GraphicsDevice.Present(); //(4)

} }

(1) Une fonction de mise à jour de scènes est appelée (aucun affichage ne peut être effectué

dans cette fonction) ;

(2) La surface de rendu est « nettoyée » pour effectuer un nouvel affichage ;

(3) La scène est dessinée dans la zone d’affichage ;

(4) Tout ce qui a été dessiné est présenté à l’écran.

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 98

Regardons maintenant plus en détails les deux fonctions privées appelées dans la fonction Tick. La

première est la fonction de mise à jour de scène attachée à la surface de rendu.

protected virtual void UpdateScene() { //Mettre à jour le contexte de rendu this .RenderContext.ElapsedTime = 0.01666667f; this .RenderContext.LastTime = this .RenderContext.Time; this .RenderContext.Time += this .RenderContext.ElapsedTime; this .StopWatch.Reset(); this .StopWatch.Start(); this .RenderContext.HasFocus = base .Focused; RenderContext.Update(); //(1) if (Focused) { RenderContext.GetCamera().UpdateInput(); //(2) } else { RenderContext.GetCamera().ResetInput(); } Workspace.ObjectManager.UpdateObjects(RenderCont ext); //(3) }

(1) Le contexte de rendu est mis à jour : les matrices de projection, vue, les temps et autres

propriétés qui doivent être mises à jour à chaque frame ;

(2) Les entrées (clavier, souris) sont mises à jour. Grâce à ceci tous les objets peuvent accéder à

l’état des touches du clavier ou à la position en cours de la souris ;

(3) Les objets de l’espace de travail gérés par le gestionnaire d’objets associé sont mis à jour.

Et pour l’affichage de la scène :

protected virtual void DrawScene() { Workspace.ObjectManager.DrawObjects(RenderContex t); //(1) }

(1) Les objets de l’espace de travail gérés par le gestionnaire d’objets associé sont affichés.

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 99

IMPLÉMENTATION DU GESTIONNAIRE D’OBJETS ET DE

L’ESPACE DE TRAVAIL

Les notions d’un gestionnaire d’objets et d’un espace de

travail ont été implémentées dans le même objet.

Cet objet se charge donc à la fois de la gestion des objets,

services et du contenu graphique. Il implémente également

une technique d’optimisation de rendu qui a été expliquée

précédemment : l’Octree. Il instancie et utilise également un

graphe de scène afin de gérer la scène hiérarchiquement.

L’objet implémente donc les deux interfaces IWorkspace et

IObjectManager (éventuellement IDisposable pour avoir plus

de contrôle sur ce qui se passe pendant le nettoyage par le

Garbage Collector).

Nous allons examiner maintenant ces implémentations. Un

objet doit être ajouté dans l’espace de travail, cela ce fait au

moyen de la fonction d’ajout d’objet, la voici :

public void AddObject( string _Asset, CObject _Object, string _ParentAsset) { if (_Object == null ) throw new ArgumentNullException ( "_Object" ); if (_Asset == null || _Asset.Length == 0) throw new ArgumentNullException ( "_Asset" ); if (m_Objects.ContainsKey(_Asset)) throw new ArgumentException ( "Object with the name {0} is already present" , "_Asset" ); //Load graphics content if already loaded if (m_GraphicsContentLoaded && _Object is ILoadable ) //(1) (( ILoadable )_Object).LoadGraphicsContent(GraphicsDevice, m_ContentManager); m_Objects.Add(_Asset, _Object); //(2) m_ObjectPositions.Add(_Object, _Object.Position) ; _Object.Attach( this ); //(3) m_Octree.AddObject(_Object); if (_ParentAsset.Length > 0) m_SceneGraph.AddObject(_Asset, _Object, _Pare ntAsset); else m_SceneGraph.AddObject(_Asset, _Object); //(4)

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 100

}

(1) Tout d’abord, nous devons nous assurer que le contenu graphique nécessaire à l’objet est

chargé. Si l’affichage de l’espace de travail est déjà en cours, nous devons charger le contenu

directement, dans le cas contraire nous ne devons rien faire et l’espace de travail effectuera

le chargement de tous les objets au démarrage.

(2) On ajoute l’objet à une hashtable permettant d’y accéder très rapidement lorsque cela est

nécessaire.

(3) L’objet est « attaché » au gestionnaire d’objets, permettant au développeur d’objets 3D

d’avoir accès à la référence vers le gestionnaire.

public void Attach( IObjectManager _ObjectManager) { m_ObjectManager = _ObjectManager; }

(4) Finalement, l’objet est ajouté au graphe de scène expliqué précédemment.

Au démarrage de l’affichage, la fonction Start() de la surface de rendu fait appel au chargement de

contenu graphique de l’espace de travail attaché. La fonction LoadGraphicsContent() est donc

exécutée. Elle effectue le chargement du contenu graphique pour chaque objet contenu dans

l’espace de travail.

public void LoadGraphicsContent( GraphicsDevice _Device, ContentManager _Loader) { lock ( this ) { if (!m_GraphicsContentLoaded) { CShaderManager .Instance.LoadGraphicsContent(_Device, _Loader); COctreeManager .Instance.LoadGraphicsContent(_Device); //Load all graphics content here foreach ( CObject _Object in m_Objects.Values) { if (_Object is ILoadable ) (( ILoadable )_Object).LoadGraphicsContent(_Device, _Loader); } m_GraphicsContentLoaded = true ; } } }

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 101

Pendant la boucle d’affichage, les fonctions UpdateObjects() et DrawObjects() sont appelées par la

surface de rendu. Les voici :

public void UpdateObjects( CRenderContext _RenderContext) { m_Octree.Update(_RenderContext.Frustum); //(1) foreach ( CObject Obj in m_Objects.Values) { if (Obj is IUpdateable ) (( IUpdateable )Obj).Update(_RenderContext); //(2) if (m_ObjectPositions[Obj] != Obj.Position) { //Same code in UpdateByObject, but without useless function call m_Octree.UpdateObject(Obj, m_ObjectPositions[ Obj]); //(3) m_ObjectPositions[Obj] = Obj.Position; } } }

(1) L’octree est mise à jour suivant le Frustum de la caméra, ceci permet de mettre à jour la propriété Visible des objets. Nous savons donc à cette étape si l’objet doit être affiché ou pas.

(2) Tous les objets implémentant l’interface IUpdatable sont mis à jour (les positions, logique métier…).

(3) Si l’objet est déplacé, l’octree est mise à jour. Ensuite, la fonction DrawObjects() dessine tout simplement tous les objets du graphe de scène en appelant la fonction Draw() correspondante. public void DrawObjects( CRenderContext _RenderContext) { m_Octree.Draw(_RenderContext); m_SceneGraph.SceneRoot.Draw(_RenderContext); }

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 102

11.5 SHADERS ET LE POST-PROCESSING

11.5.1 INTRODUCTION

Un shader est un programme utilisé en image de synthèses pour paramétrer une partie du processus

de rendu réalisé par une carte graphique. Pour la facilité de compréhension, voici un exemple de

résultat final qui peut être obtenu grâce aux shaders :

Sur cette figure, vous pouvez voir 7 sphères ayant la même géométrie et sur chaque sphère un

shader est appliqué.

Les shaders permettent de décrire l'absorption et la diffusion de la lumière, la texture à utiliser, les

réflexions et réfractions, l'ombrage, le déplacement de primitives et des effets post-traitement.

Par la conception même du processus de rendu, les shaders sont les candidats idéaux pour une

exécution parallèle par les processeurs graphiques multiples, situés dans une carte vidéo. Ceci

permet un traitement vectorisé soulageant l'unité centrale pour obtenir un résultat plus rapidement.

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 103

Les shaders sont flexibles et efficaces. Des surfaces apparemment compliquées peuvent être rendues

à partir de géométries simples. Par exemple, un shader peut être utilisé pour générer un océan à

partir d’un simple plan et une texture :

Un autre exemple d’utilisation des shaders dans l’animation est un effet appliqué sur un modèle 3D

afin de donner une impression de dessin. Voici un exemple (à gauche le modèle 3D tel quel, à droite

un shader de BD a été appliqué) :

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 104

11.5.2 HLSL

HLSL (High Level Shading Language) est un langage développé par Microsoft, permettant aux

développeurs d’écrire des programmes (shaders) qui seront ensuite exécutés par la carte graphique.

Grâce à ce langage standard de haut niveau, les développeurs de shaders peuvent se consacrer aux

algorithmes lorsqu'ils implémentent des shaders, plutôt que de se préoccuper des détails matériels

complexes, tels que l'allocation de registres, etc. Outre l'avantage de détacher le développeur des

contingences matérielles, le langage HLSL présente tous les avantages habituels d'un langage de haut

niveau, tels que la réutilisation facile du code, une lisibilité améliorée et la présence d'un compilateur

d'optimisation.

Au lieu de faire une description exhaustive du langage HLSL, nous allons examiner un simple shader,

tiré d'une application de Microsoft qui effectue le rendu de l'aspect bois simple. L'exemple ci-dessous

décrit un vertex shader simple :

float4x4 ViewProj; float4x4 texture_matrix0; //(1) struct VS_OUTPUT { float4 Pos : POSITION; float3 Pshade : TEXCOORD0; }; //(2) VS_OUTPUT main (float4 vPosition : POSITION) //(3) { VS_OUTPUT Out = (VS_OUTPUT) 0; //(4) // Transform position to clip space Out.Pos = mul (ViewProj, vPosition); //(5) // Transform Pshade Out.Pshade = mul (texture_matrix0, vPosition); //(6) return Out; }

(1) Les deux premières lignes déclarent une paire de matrices 4 × 4 appelées ViewProj et

texture_matrix0.

(2) Suite à la déclaration de ces matrices au niveau de la portée globale, une structure est

déclarée. Cette structure, VS_OUTPUT, comporte deux membres : un membre float4, appelé

Pos, et un membre float3, appelé Pshade.

(3) La fonction principale de ce shader prend un paramètre d'entrée unique float4 et renvoie

une structure VS_OUTPUT. L'entrée float4, vPosition, constitue la seule entrée vers le shader,

alors que la structure renvoyée, VS_OUTPUT, définit la sortie de ce nuanceur vertex. Pour le

moment, laissons de côté les mots clés POSITION et TEXCOORD0 qui suivent ces paramètres

et ces membres de structure. Ces mots sont appelés sémantiques et nous expliquerons leur

signification dans la suite de ce chapitre.

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 105

(4) Ensuite une variable Out de type VS_OUTPUT est déclarée et initialisée à 0.

(5) Dans le corps même du code de la fonction principale, on peut voir une fonction appelée mul

qui est utilisée pour multiplier le vecteur d'entrée vPosition par la matrice ViewProj. Cette

fonction est très souvent utilisée dans les vertex shader pour effectuer la multiplication du

vecteur par la matrice. Dans ce cas, le vecteur vPosition est traité comme un vecteur de

colonne, étant donné qu'il s'agit du second paramètre de mul. Si le vecteur vPosition était le

premier paramètre de mul, il serait traité comme un vecteur de ligne.

(6) Suite à la transformation de la position d'entrée vPosition en « clip-space », le vecteur

vPosition est multiplié par une autre matrice appelée texture_matrix0 pour générer une

coordonnée de texture 3D. Les résultats de ces deux transformations sont ensuite écrits vers

les membres d'une structure VS_OUTPUT, qui est renvoyée.

Nous n’allons pas entrer dans les détails ni faire une description exhaustive du langage HLSL car ce

n’est pas le but principal de ce document.

Revenons maintenant à ces 2 lignes :

float4x4 ViewProj; float4x4 texture_matrix0;

Ces 2 matrices sont appelées « paramètres », car elles sont déclarées en quelque sorte comme des

variables globales du shader et permettent de configurer le shader depuis le code C# via la classe

Effect de XNA.

Voici comment on procède pour effectuer une assignation d’un paramètre (la classe Effect doit être

précédemment instanciée avec le shader demandé) :

if (m_Effect.Parameters[ "ViewProj" ] != null ) m_Effect.Parameters[ "ViewProj" ].SetValue(_RenderContext.ViewProjection);

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 106

11.5.3 SHADER-MODEL FRAMEWORK

Bien que le framework XNA possède déjà une classe encapsulant un shader (la classe Effect), nous

avons pensé un mini framework permettant de gérer facilement les collections des shaders et

d’assigner les paramètres automatiquement.

Ce framework devait permettre :

• d’effectuer l’instanciation des shaders au démarrage de l’application ;

• de permettre au développeur d’utiliser n’importe quel shader à n’importe quel moment ;

• de permettre la compilation just-in-time d’un shader à partir d’un fichier source ;

• de faciliter l’utilisation grâce à une fonction SetShader() dans la classe CObject.

Pour le faire, deux classes CShader et CShaderManager ont été conçues. La classe CShader

encapsulant un shader (la classe Effect de XNA).

Voici un schéma de classes de cette architecture:

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 107

La classe CShader implémente les fonctionnalités suivantes :

• chargement et instanciation automatique d’un shader

• compilation just-in-time ;

• assignation des paramètres issus d’un contexte de rendu.

Examinons les implémentations correspondantes : public virtual void LoadGraphicsContent( GraphicsDevice _Device, ContentManager _Loader) { if (m_Asset == "BasicEffect" ) { m_Effect = new BasicEffect (_Device, null ); //(1) } else { if (m_Filename.Length == 0) m_Effect = _Loader.Load<Effect>(m_Asset) ; //(2) else { CompileCode(m_Filename, _Device); //(3) } } }

(1) Dans le cas où le shader instancié est un BasicEffect (l’effet de base dans XNA pour

simplifier l’affichage), on instancie cette classe.

(2) Dans le cas contraire et si on ne veut pas faire de compilation just-in-time, on utilise un

gestionnaire de contenu pour charger le fichier .xnb contenant le shader compilé pour

XNA.

(3) Dans le cas où on veut compiler le shader à partir d’un fichier, on rappelle une fonction

dont voici l’implémentation :

private void CompileCode( string _SourceFilename, GraphicsDevice _Device, TargetPlatform _TargetPlatform, bool _IsDebug) { CompilerOptions debug; if (_IsDebug) debug = CompilerOptions .Debug; else debug = CompilerOptions .None; CompiledEffect effect = Effect .CompileEffectFromSource(_SourceFilename, null , null , debug, _TargetPlatform); if (effect.Success) { m_Effect = new Effect (_Device, effect.GetEffectCode(), debug, null ); } }

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 108

Finalement, la classe CShader contient une fonction SetParameters permettant l’assignation des paramètres issus d’un contexte de rendu. Voici son code : public virtual void SetParameters( CObject _Object, CRenderContext _RenderContext) //(1) { Matrix World = Matrix .CreateScale(_Object.Scaling) * Matrix .CreateFromQuaternion(_Object.Rotation) * Matrix .CreateTranslation(_Object.Position); //(2) if (m_Effect.Parameters[ "WorldViewProject" ] != null ) { m_Effect.Parameters[ "WorldViewProject" ].SetValue( World * _RenderContext.View * _RenderContext.Projection); //(3) } if (m_Effect.Parameters[ "World" ] != null ) m_Effect.Parameters[ "World" ].SetValue(World); if (m_Effect.Parameters[ "View" ] != null ) m_Effect.Parameters[ "View" ].SetValue(_RenderContext.View); if (m_Effect.Parameters[ "Projection" ] != null ) m_Effect.Parameters[ "Projection" ].SetValue(_RenderContext.Projection); if (m_Effect.Parameters[ "EyePosition" ] != null ) m_Effect.Parameters[ "EyePosition" ].SetValue(_RenderContext.CameraPosition); (…) }

(1) Vu que la fonction SetParameters() est appelée par un CObject, elle contient en paramètre

l’objet sur lequel le shader doit être appliqué.

(2) Première ligne de ce code crée la matrice World à partir de l’objet, sa position et ses

rotations.

(3) Les lignes suivantes assignent automatiquement les paramètres dont les noms sont définis à

l’avance. Dans nos shaders nous avons imposé les noms sémantiques des paramètres (donc

une matrice World doit être appelée « World » et non pas « _World » ou autre dans le code

du shader en question).

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 109

11.6 GRAPHE DE SCÈNE

11.6.1 GÉNÉRALITÉS

Un graphe de scène est une structure générale de donnée utilisée communément par les outils de

modélisation 3D et les jeux vidéo actuels. Le graphe de scène est une structure orientée objet qui

structure de manière logique la représentation spatiale d'une scène graphique. La définition d'un

graphe de scène est floue, puisque les programmeurs qui implémentent les graphes de scènes dans

les applications, plus particulièrement dans les moteurs 3D, reprennent les principes généraux et les

adaptent à leurs besoins particuliers.

D'une manière générale, un graphe de scène est une collection de nœuds renfermée dans un graphe

ou une structure d'arbre. Ceci signifie qu'un nœud peut avoir plusieurs enfants mais seulement un

parent. Ainsi, un effet appliqué sur un nœud se répercute sur ses descendants, ce qui permet de

propager l'opération à un groupe de nœuds. Dans de nombreux programmes, l'utilisation typique est

pour appliquer une transformation géométrique à un groupe d'objet. A vrai dire, le terme de

"graphe" est un peu vague car il s'agit en fait d'un arbre descendant (ou graphe acyclique orienté)

que l'on manipule en général à partir de sa racine.

Pour mieux comprendre, voici un exemple d’un graphe de scène implémenté dans un autre moteur

3D:

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 110

11.6.2 UTILITÉ

Lorsque l'on écrit un programme dont l'une des fonctionnalités est d'afficher une scène 3D, on est en

général amené à créer des classes qui vont servir d'enveloppes à nos objets et à les stocker dans une

liste, avant de parcourir séquentiellement cette liste au moment de les afficher.

Dès que les scènes deviennent un peu complexes, on va chercher à organiser les objets entre eux:

d'abord simplement en les triant. Pour, par exemple, regrouper dans la liste tous ceux qui utilisent

une même texture, puis en les connectant entre eux si besoin est. Par exemple, pour modéliser un

système solaire, la position d'une planète va dépendre de celle de l'étoile centrale, de même que les

transformations appliquées à la planète doivent être répercutées sur d'éventuels satellites. Cet

héritage de positions/transformations sous-entend une relation hiérarchique entre les objets et donc

sans le savoir on est déjà en train de construire un graphe de scène.

Pour afficher une scène, on parcourt cet arbre de la racine aux feuilles en affichant le contenu des

nœuds au fur et à mesure. Les avantages d'un graphe de scène peuvent donc se répartir en deux

types:

• Par rapport à l’affichage :

o L'ordre d'affichage: les parents sont affichés avant les enfants et les enfants sont

parcourus de manière séquentielle; chaque nœud est traité comme la racine de

son propre sous-graphe.

o La transmission des transformations: les enfants héritent de toutes les

transformations appliquées aux parents (position, couleur, etc.)

• Par rapport à l’organisation :

o Un graphe de scène permet de regrouper des éléments de manière intelligente

dans votre programme; par exemple, tous les objets qui ont une certaine

propriété en commun peuvent se trouver dans un même sous-graphe que l'on

peut ensuite choisir d'afficher ou non. Chaque sous-graphe est entièrement

contrôlé à partir de sa racine

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 111

11.6.3 IMPLÉMENTATION

L’implémentation d’un tel graphe est assez simple. Pour ce faire, nous avons créé une classe CNode,

qui représente le nœud du graphe qui encapsule une collection de nœuds adjacents. La classe CNode

comprendra aussi une fonction Draw() afin d’effectuer l’affichage du contenu des nœuds et de ses

nœuds adjacents. Comme dans chaque arbre, nous avons besoin d’un nœud de base (dit nœud

racine) pour commencer nos itérations (dans ce cas-ci cela servira de nœud de départ pour afficher

la scène).

Parfois, nous avons besoin de savoir si le nœud qu’on affiche est un nœud d’un type précis et le

traiter différemment. Par exemple, on doit pouvoir afficher un nœud d’un objet 3D contenant un

modèle 3D, qui ne sera pas affiché de la même façon qu’un nœud contenant une scène entière. Pour

ce faire nous avons donc permis de dériver la classe CNode et de créer 2 filles (les plus utilisées) :

• CObjectNode qui représentera un CObject encapsulé qu’on doit afficher ;

• CSceneNode qui représentera une scène quelconque (une ville, une chambre, etc.).

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 112

12. PERSPECTIVES ET CONCLUSIONS

12.1 PERSPECTIVES ET DÉVELOPPEMENTS ULTÉRIEURS

Comme on l’a souvent répété dans les différents chapitres, le moteur 3D peut être amélioré et

complété dans beaucoup de domaines. Nous avons tout au long du stage travaillé avec une « todo

list ». Voici, ce que comportait la dernière en date :

- Réalisation du « motion blur » complet, c’est-à-dire l’effet de transparence sur les pales ;

- Création de l’ombre des différents objets de scène ;

- Détection des collisions ;

- Amélioration de la trajectoire en utilisant un ruban ;

- Editeur de trajectoire permettant la pré-programmation d’un vol à l’aide de trajectoires

enregistrées et réalisables par l’hélicoptère ;

- Capture des données par port série lors d’un vol réel et affichage sur notre logiciel en direct ;

- Possibilité d’agrandir ou de réduire la taille de la fenêtre secondaire ;

- Utilisation de deux écrans pour les deux vues ;

- Création d’un éditeur de carte permettant le chargement de modèles dans le simulateur ;

- Création d’un second décor de base avec la gare des Guillemins située à Liège sur base du

modèle 3D réalisé par Santiago Calatrava, l’architecte qui s’occupe de la conception de la

nouvelle gare ;

- Contrôle de la caméra par une deuxième radio.

Il reste donc de nombreux points sur lesquels le simulateur peut être amélioré. Cette liste n’est pas

exhaustive loin de là.

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 113

12.2 CONCLUSIONS PERSONNELLES

Comme prévu, ce stage fut un défi dès le départ jusqu’à la fin des quinze semaines. Au début, le

travail à effectuer me semblait long et complexe, mais au fil de temps et avec de l’expérience ce défi

me paraissait de plus en plus réalisable.

Le stage fut intéressant et enrichissant sur le plan culturel et social : j’ai pu découvrir le monde

cinématographique et connaître l’équipe de Flying-Cam qui est motivée et déterminée. Sur le plan

technique le stage a dépassé mes attentes : j’ai pu apprendre la 3D ainsi que les bases du langage

shader des cartes graphiques, j’ai participé au développement de l’infrastructure IT de la société en

elle-même, apprendre les notions du développement temps-réel et d’aviation.

La plus grande récompense était tout de même le fait que notre moteur 3D a été exposé sur le stand

de Flying-Cam à la NAB à Las Vegas. Ce grand rassemblement annuel des professionnels des médias

électroniques permet de découvrir les dernières nouveautés dans le domaine de la création, de la

gestion, de la diffusion et des tendances en télévision, radio, cinéma, audio, vidéo, streaming,

satellite et télécommunication.

Je tiens à remercier encore une fois tout l’équipe de Flying-Cam pour leur soutien tout au long du

projet.

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 114

13. BIBLIOGRAPHIE

[1] CodeProject – C# Articles. http://www.codeproject.com .

[2] Ziggyware XNA Tutorials. http://www.ziggyware.com .

[3] Riemers XNA. http://www.riemers.net .

[4] Games Creators Network. http://www.games-creators.org .

[5] Microsoft MSDN DirectX developer center. http://msdn.microsoft.com/directx

[6] Nvidia Developer website. http://developer.nvidia.com

[7] Graphic Stream. http://msmvps.com/blogs/valentin/

[8] Miller, T. 2003. Managed DirectX 9: Kick Start : Graphics and Game Programming.

[9] La Civita, M. Integrated Modeling and Robust Control for Full-Envelope Flight of Robotic

Helicopters. http://www.cs.cmu.edu/~marcol/papers/papers.html

[10] Reflex Simulator. http://www.reflex-sim.de

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 115

14. LEXIQUE

Alpha blending :

Désigne un processus de mélange et combinaison des couleurs selon leurs valeurs de transparence. Cette valeur de transparence est souvent appelée « Alpha ».

Backbuffer :

Tampon de mémoire contenant le brouillon de la scène graphique, avant d'être présenté au frontbuffer.

Backface culling:

Elimination des faces (triangles) en arrière.

Blur :

Mot anglais pour flou. On parle souvent de motion blur, c'est l'effet de trainée que crée un sujet se

déplaçant trop rapidement sur une photo, prise dans un laps de temps ne permettant pas de le fixer.

Clipping :

Provient du verbe anglais « to clip » signifiant tailler, couper, tondre. Le clipping est un terme utilisé

en graphisme et qui représente l'action de borner un affichage. En 3D le clipping suit la même idée,

une forme peut ne pas être affichée au delà d'une certaine limite (souvent plane) comme la near

clipping plane ou la far clipping plane ou tout autre plan qui pourrait être utilisé comme tel

délimiteur.

Double buffering :

Technique générale consistant à calculer quelque chose dans un tampon de mémoire pendant que

quelque chose d’autre est visualisé dans un autre tampon de mémoire. Au cycle suivant on bascule

les tampons de mémoire.

Frontbuffer :

Tampon de mémoire contenant un tableau de pixels représentant l'image actuellement affichée à

l'écran. Cette mémoire est physiquement située sur la carte graphique.

Mapping :

Le mapping est l'action d'appliquer des coordonnées de texture à une face ou plus généralement à

un objet (coordonnées UV).

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 116

Mesh :

Ensemble structuré contenant la géométrie, les matrices, définitions de couleurs et de textures d’un

modèle 3D.

Moteur 3D :

Un moteur 3D est un middlware qui se présente sous forme de bibliothèque dynamiquement liable,

statiquement ou simplement par intégration des modules de codes au projet. Le but est d'encapsuler

les méthodes d'affichage et d'initialisation des modes graphiques pour faciliter au client la

programmation d'un logiciel graphique.

Pixel shader :

Programme exécuté par la carte graphique d'un PC ou d'une console, et qui permet de créer des

effets spéciaux en 2D (Halo lumineux, trainée lumineuse, ...) sans avoir à passer par un programme

d'où gain de temps.

Quaterion :

Une notion mathématique permettant de décrire une rotation suivant une structure {x,y,z,w}.

Temps réel :

L'expression temps réel en informatique s'applique à des programmes et/ou du matériel permettant

d'avoir une réponse dans les délais demandés.

Vertex shader :

Les vertex shaders travaillent sur la géométrie des objets. Physiquement dans le processeur

graphique, les unités de calculs du vertex shader se situent avant celles des pixels shaders. Ce qui

signifie qu'on effectue les calculs de géométrie avant les calculs de rendu d'image.

Wireframe :

Littéralement fil de fer, aussi appelé mode filaire. Désigne un mode de visualisation 3D où les objets

sont uniquement représentés par leurs arêtes et non pas par des volumes (texturés ou non). Cela

rend ce mode plus rapide à afficher vu qu'il n'y a pas de calcul de remplissage et d'interpolation.

Z-buffer :

Le Z-buffer est un terme devenu générique désignant la technique permettant l'affichage organisé

par ordre de profondeur des éléments d'une scène 3D.

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 117

15. INDEX

1. Remerciements............................................................................................................................... 5

2. Introduction.................................................................................................................................... 6

2.1 Architecture du document..................................................................................................... 6 2.2 Choix du stage........................................................................................................................ 6

3. Contexte général ............................................................................................................................ 7

3.1 L’entreprise ............................................................................................................................ 7 3.2 Les objectifs de travail ........................................................................................................... 9

3.2.1 Objectifs généraux............................................................................................................. 9

3.2.2 Objectifs à court terme...................................................................................................... 9

3.2.3 Objectifs à long terme ..................................................................................................... 10

3.3 L’environnement technique et les outils ............................................................................. 12 3.3.1 Environnement de travail : L’équipe ............................................................................... 12

3.3.2 Outils et librairies utilisés ................................................................................................ 13

3.3.3 Standards de codage ....................................................................................................... 15

4. Considérations théoriques, études préalables............................................................................. 16

4.1 Développement d’une application orientée objet .............................................................. 16 4.1.1 Expérience personnelle ................................................................................................... 16

4.1.2 Analyse et conception d’une architecture repondant aux besoins................................. 17

4.1.3 Implémentation & sécurité ............................................................................................. 17

4.1.4 Optimisation .................................................................................................................... 17

4.1.5 Tests & débogage ............................................................................................................ 18

4.2 Au plan logiciel ..................................................................................................................... 19 4.2.1 Choix de l’application ...................................................................................................... 19

4.2.2 OpenGL ou DirectX ?........................................................................................................ 19

4.2.3 Choix de Framework........................................................................................................ 20

4.3 Au plan matériel................................................................................................................... 22 4.3.1 Unité de calcul et mémoire ............................................................................................. 22

4.3.2 Choix de carte graphique................................................................................................. 22

5. Framework XNA............................................................................................................................ 24

5.1 Introduction ......................................................................................................................... 24 5.1.1 Généralités....................................................................................................................... 24

5.1.2 Prérequis.......................................................................................................................... 24

5.2 Architecture ......................................................................................................................... 26 5.2.1 Généralités....................................................................................................................... 26

5.2.2 La couche plate-forme..................................................................................................... 27

5.2.3 La couche framework de base......................................................................................... 27

5.2.4 La couche framework étendu.......................................................................................... 29

6. Notions de 3D ............................................................................................................................... 30

6.1 Introduction ......................................................................................................................... 30 6.2 Repères 3D........................................................................................................................... 30 6.3 Un vertex, des vertices......................................................................................................... 31 6.4 Les meshes........................................................................................................................... 35 6.5 Déplacement 3D : les matrices ............................................................................................ 35

7. Notions d’aviation ........................................................................................................................ 38

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 118

7.1 Introduction ......................................................................................................................... 38 7.2 Rotations.............................................................................................................................. 39

Rotations....................................................................................................................................... 39

Le rotor ......................................................................................................................................... 40

8. Le projet........................................................................................................................................ 42

8.1 vision du produit fini ............................................................................................................ 42 8.2 Objet principal...................................................................................................................... 45 8.3 Objets secondaires............................................................................................................... 46 8.4 Interfaces utilisateur............................................................................................................ 47 8.5 En conclusion ....................................................................................................................... 47

9. L’architecture globale de l’application ......................................................................................... 49

9.1 L’architecture modulaire de l’application............................................................................ 49 9.1.1 Simulation........................................................................................................................ 50

9.1.2 Affichage.......................................................................................................................... 52

9.1.3 Entrées............................................................................................................................. 53

9.2 L’architecture en couches de l’application .......................................................................... 54 9.2.1 Couche native .................................................................................................................. 55

9.2.2 Couche managée ............................................................................................................. 55

9.2.3 Couche abstraite.............................................................................................................. 56

9.2.4 Couche spécifique à l’application.................................................................................... 56

10. Simulation..................................................................................................................................... 58

10.1 Introduction ......................................................................................................................... 58 10.2 Wrapper pour MOSCA ......................................................................................................... 59

11. Moteur de rendu graphique......................................................................................................... 64

11.1 Framework objets ................................................................................................................ 64 11.1.1 Pourquoi un framework d’objets ? ............................................................................. 64

11.1.2 L’objet de base ............................................................................................................ 66

11.1.3 Les interfaces............................................................................................................... 67

11.1.4 L’utilisation.................................................................................................................. 68

11.2 Caméra................................................................................................................................. 69 11.2.1 Introduction ................................................................................................................ 69

11.2.2 Notions d’une caméra................................................................................................. 69

11.2.3 Méthodes principales.................................................................................................. 72

11.2.4 Déplacement ............................................................................................................... 73

11.3 Octree d’optimisation de rendu .......................................................................................... 75 11.3.1 Définition..................................................................................................................... 75

11.3.2 View Frustum .............................................................................................................. 75

11.3.3 Représentation graphique .......................................................................................... 76

11.3.4 Implémentation........................................................................................................... 77

11.3.5 Annexe......................................................................................................................... 80

11.4 Zones d’affichage ................................................................................................................. 81 11.4.1 Généralités .................................................................................................................. 81

11.4.2 Résultat final ............................................................................................................... 82

11.4.3 Exemple d’utilisation « pas à pas » ............................................................................. 84

11.4.4 Interaction entre le rendu et le framework objets ..................................................... 88

11.4.5 l’architecture Direct 3D ............................................................................................... 89

11.4.6 L’architecture .............................................................................................................. 92

Moteur 3D en XNA pour un simulateur de vol

Atachiants Roman Haute Ecole Rennequin Sualem page 119

11.4.7 L’implémentation ........................................................................................................ 98

11.5 Shaders et le post-processing ............................................................................................ 103 11.5.1 Introduction .............................................................................................................. 103

11.5.2 HLSL ........................................................................................................................... 105

11.5.3 Shader-model Framework......................................................................................... 107

11.6 Graphe de scène ................................................................................................................ 110 11.6.1 Généralités ................................................................................................................ 110

11.6.2 Utilité......................................................................................................................... 111

11.6.3 Implémentation......................................................................................................... 112

12. Perspectives et conclusions........................................................................................................ 113

12.1 Perspectives et développements ultérieurs ...................................................................... 113 12.2 Conclusions personnelles................................................................................................... 114

13. Bibliographie............................................................................................................................... 115

14. Lexique........................................................................................................................................ 116