Upload
roman-atachiants
View
631
Download
3
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 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 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