B.Sc Thesis: Moteur 3D en XNA pour un simulateur de vol
Upcoming SlideShare
Loading in...5
×
 

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

on

  • 693 views

We created a real-time 3D rendering engine and a simulation environment for an existing flight simulator algorithm.

We created a real-time 3D rendering engine and a simulation environment for an existing flight simulator algorithm.

Statistics

Views

Total Views
693
Slideshare-icon Views on SlideShare
690
Embed Views
3

Actions

Likes
0
Downloads
7
Comments
0

2 Embeds 3

https://www.linkedin.com 2
http://www.linkedin.com 1

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

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

    • 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_MeterPerSquare), 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_Asset) 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, aspectRatio, m_Viewport.MinDepth, m_Viewport.MaxDepth); Comme indiqué plus haut, les matrices sont utilisées aussi pour effectuer des transformations sur les objets. Par exemple, toujours dans la classe Matrix, nous avons des méthodes comme CreateTranslation, CreateRotationX, CreateRotationY, CreateRotationZ, CreateScale, … Voici un exemple venant de la classe CCubeLogo où nous créons une matrice d’étirement, le « scale », une matrice de translation et une matrice de rotation. Ces matrices sont ensuite utilisées pour calculer la matrice World qui est la représentation de la géométrie 3D : public void SetSize(Vector3 size) { this.m_Width = size.X; this.m_Height = size.Z; this.m_Depth = size.Y; this.m_ScaleMatrix = Matrix.CreateScale(size.X, size.Y, size.Z); this.UpdateTransformation(); } public void SetPosition(Vector3 location) { this.m_X = location.X; this.m_Y = location.Y; this.m_Z = location.Z; this.m_TranslationMatrix = Matrix.CreateTranslation(location.X, location.Y, location.Z); this.UpdateTransformation(); } public void SetRotation(float rotationX, float rotationY, float rotationZ) { this.m_RotationX = rotationX; this.m_RotationY = rotationY; this.m_RotationZ = rotationZ;
    • Moteur 3D en XNA pour un simulateur de vol Atachiants Roman Haute Ecole Rennequin Sualem page 37 this.m_RotationMatrix = Matrix.CreateRotationX(rotationX) * Matrix.CreateRotationY(rotationY) * Matrix.CreateRotationZ(rotationZ); this.UpdateTransformation(); } private void UpdateTransformation() { this.m_TransformationMatrix = this.m_ScaleMatrix * this.m_RotationMatrix * this.m_TranslationMatrix; this.m_Effect.World = this.m_TransformationMatrix; } XNA fournit donc une aide précieuse dans l’utilisation des matrices. Tout est fait automatiquement, la programmation n’en est que plus simple. Les opérateurs sont surchargés pour les matrices et d’autres fonctions comme Invert ou Transposed également. Le programmeur n’a donc plus besoin de faire toutes sortes de calculs pour programmer en 3D.
    • Moteur 3D en XNA pour un simulateur de vol Atachiants Roman Haute Ecole Rennequin Sualem page 38 7. NOTIONS D’AVIATION 7.1 INTRODUCTION Avant de nous lancer dans la conception même du moteur 3D, même si la simulation a été conçue par un ingénieur spécialisé, nous devions comprendre le fonctionnement d’un hélicoptère et avoir des notions de base d’aviation. Dans un hélicoptère, comme pour un avion, la vitesse relative de l'air et de la voilure génère une action mécanique qui permet à l'engin de voler. On distingue deux composantes de cette action aérodynamique: • la traînée qui est la résistance à l'avancement. De son action sur le rotor de l'hélicoptère, il résulte un couple tendant à faire tourner l'appareil autour de son axe, d'où la nécessité d'un dispositif anti-couple. La trainée a également un effet sur le fuselage dès que la vitesse de l’hélicoptère augmente ; • la portance qui soulève l'appareil. Le contrôle d'un appareil repose alors sur la gestion de cette portance. Alors que sur les avions, des volets permettent de modifier la portance moyenne des ailes pour virer et monter, sur l'hélicoptère on modifie le pas qui modifie l'inclinaison des pales. Tout déplacement et stabilisation d’un hélicoptère est effectué grâce à l’inclinaison des pales. Equilibre en vol stationnaire Déséquilibre Déplacement stabilisé Vol stationnaire. Le rotor de l'hélicoptère étant entraîné à vitesse constante, les déplacements verticaux de l'hélicoptère sont obtenus par la seule modification du pas des pales. À ce stade du vol, la portance des pales reste identique sur un tour du rotor. Il existe une position où la portance globale s'oppose exactement au poids de l'appareil : l'hélicoptère peut rester immobile. Si elle lui est inférieure, l'appareil descend. Si elle est supérieure, il monte.
    • Moteur 3D en XNA pour un simulateur de vol Atachiants Roman Haute Ecole Rennequin Sualem page 39 7.2 ROTATIONS ROTATIONS Afin d’effectuer correctement les rotations de l’hélicoptère dans l’espace, ces rotations doivent être effectuées dans un certain ordre. Il existe une convention de nommage des angles de rotations. Voici ces 3 angles : : Angle “Phi” : Rotation autours de l’axe X; : Angle “The” : Rotation autours de l’axe Y; : Angle “Psi” : Rotation autours de l’axe Z. Pour faciliter la compréhension, illustrons ces rotations. La rotation sur l’axe Z :
    • Moteur 3D en XNA pour un simulateur de vol Atachiants Roman Haute Ecole Rennequin Sualem page 40 La rotation sur l’axe X : La rotation sur l’axe Y : LE ROTOR Toute rotation du rotor principal entraîne un couple de réaction qui a tendance à faire tourner la cellule autour de lui et en sens inverse (3e loi de Newton). Pour contrer cet effet indésirable, on place (pour les hélicoptères à un seul rotor principal) à l'extrémité de la poutre de queue, un rotor secondaire plus petit et tournant dans un plan sensiblement vertical appelé rotor anti- couple.
    • Moteur 3D en XNA pour un simulateur de vol Atachiants Roman Haute Ecole Rennequin Sualem page 41 Pour ce qui concerne le sens des rotations du rotor principal, ça n’a pas vraiment d’importante. Une petite anecdote est que tous les hélicoptères américains utilisent la rotation contraire au sens inverse des aiguilles d’une montre et les hélicoptères russes utilisent la rotation dans le sens des aiguilles d’une montre. Les européens n’ont pas de normes.
    • Moteur 3D en XNA pour un simulateur de vol Atachiants Roman Haute Ecole Rennequin Sualem page 42 8. LE PROJET 8.1 VISION DU PRODUIT FINI Notre projet est donc la réalisation d’un moteur 3D pour un simulateur. Mais qu’est-ce qu’un simulateur ? Un simulateur est un outil permettant notamment à l'apprenant de simuler les expériences en vue de retrouver lui-même les lois qui les sous-tendent ou d'en voir le résultat. Dans notre cas, nous devons donc permettre à un pilote ou à un futur pilote d’obtenir les mêmes sensations que s’il pilotait un vrai hélicoptère. Afin de faciliter la compréhension du projet et de ce document, voici plusieurs captures d’écran du moteur 3D fini : Nous voyons à l’écran plusieurs choses : • deux vues ; • un menu ;
    • Moteur 3D en XNA pour un simulateur de vol Atachiants Roman Haute Ecole Rennequin Sualem page 43 • un hélicoptère au centre de l’écran ; • deux bateaux dont l’un (le voilier) est affiché dans deux vues différentes; • de l’eau et le ciel. Sur cette capture d’écran on peut remarquer la complexité de la scène : • l’hélicoptère est penché en arrière (à cause du mouvement effectué) mais la vue de la caméra reste fixe par rapport à l’horizon ; • l’affichage de l’hélicoptère est assez complexe, contenant des parties transparentes afin de donner une impression de flou ; • la deuxième vue a été déplacée sur l’écran. On peut donc déduire qu’il y a plusieurs choses bien distinctes dans cette scène : • les interfaces utilisateurs afin de configurer la scène ; • un espace de travail (ou monde) dans lequel nous avons nos objets ; • une interface homme /machine définie par des contrôleurs de l’hélicoptère ;
    • Moteur 3D en XNA pour un simulateur de vol Atachiants Roman Haute Ecole Rennequin Sualem page 44 • plusieurs zones d’affichage permettant d’afficher les espaces de travail sous différents angles ; • des objets quelconques pouvant être affichés ; • un hélicoptère pouvant être contrôlé et déplacé.
    • Moteur 3D en XNA pour un simulateur de vol Atachiants Roman Haute Ecole Rennequin Sualem page 45 8.2 OBJET PRINCIPAL Notre objet principal est donc notre hélicoptère. En 3D, on parle de modèle 3D. Cet objet possède une géométrie et différentes propriétés par rapport au monde : • il peut se déplacer ; • il peut être affiché ; • il peut être contrôlé par différents contrôleurs (joystick par exemple); • en fonction des angles de la caméra, une vue spécifique est affichée ; Figure 8 - Modèle 3D de l'hélicoptère Flying-Cam Cet hélicoptère qu’on voit à l’écran est, en réalité, un modèle 3D composé de meshes ( Voir § 6.4 above pour plus d’informations concernant les meshes et la 3D). Il possède des propriétés et des méthodes et peut interagir avec le matériel. Il peut être donc considéré comme un objet dans le sens orienté objet.
    • Moteur 3D en XNA pour un simulateur de vol Atachiants Roman Haute Ecole Rennequin Sualem page 46 8.3 OBJETS SECONDAIRES Les objets secondaires (bateaux, ciel, eau, …) que nous avons vu sur l’écran, ont la même structure que l’objet principal (hélicoptère) excepté qu’ils ne peuvent pas être contrôlés et que la complexité d’affichage est moindre : • pas de transparence des parties de l’objet ; • pas d’animations à l’intérieur. Figure 9 - Objet secondaire (bateau)
    • Moteur 3D en XNA pour un simulateur de vol Atachiants Roman Haute Ecole Rennequin Sualem page 47 8.4 INTERFACES UTILISATEUR Voyons maintenant un peu plus en détail le menu de contrôle rapide : Nous pouvons voir que ce menu permet : (1) De créer une nouvelle scène de simulation. (2) Une fois la scène créée, nous pouvons démarrer ou arrêter la simulation. (3) Nous pouvons afficher la console de simulation, avec les données de cette dernière (les angles, positions ou autre). (4) Nous pouvons choisir un contrôleur actif (il existe deux types d’interfaçages de contrôleurs utilisés chez Flying-Cam : USB et Série. (5) Plusieurs modes de simulation (un mode de simulation normal et un mode de test). (6) Nous pouvons afficher ou pas les diverses composantes d’environnement (l’eau, grille). Nous pouvons donc déduire qu’il y a : • une scène et une gestion de scène ; • démarrage et arrêt de la simulation (qui n’est pas spécialement attachée à la scène) ; • deux types d’interfaçages de contrôleurs à gérer : USB et Série. 8.5 EN CONCLUSION Pour conclure, nous pouvons donc déduire de tout ceci que nous avons plusieurs parties plus globales :
    • Moteur 3D en XNA pour un simulateur de vol Atachiants Roman Haute Ecole Rennequin Sualem page 48
    • Moteur 3D en XNA pour un simulateur de vol Atachiants Roman Haute Ecole Rennequin Sualem page 49 9. L’ARCHITECTURE GLOBALE DE L’APPLICATION 9.1 L’ARCHITECTURE MODULAIRE DE L’APPLICATION L’architecture globale de l’application a été pensée et conçue par modules, une division logique a été faite. Le schéma ci-dessous montre les divers modules logiques : Figure 10 - Architecture globale (Modules)
    • Moteur 3D en XNA pour un simulateur de vol Atachiants Roman Haute Ecole Rennequin Sualem page 50 9.1.1 SIMULATION Le processus de simulation est effectué grâce à un modèle non linéaire dans l’hélicoptère obtenu par une technique appelée MOdelling for Flight Simulation and Control Analysis (MOSCA) [9]. MOSCA est le fruit des recherches de Marco La Civita réalisé pour son mémoire « Integrated Modeling and Robust Control for Full-Envelope Flight of Robotic Helicopters ». Il est responsable de la recherche et développement chez Flying-Cam. C’est une technique de modélisation de vol automatisé en combinant 2 techniques différentes : • First-principles modeling, permettant d’obtenir les modèles de vol à la fois en temps réel et non temps réel. Ces modèles possèdent les dynamiques non-linéaires. • System Identification, permettant d’obtenir les modèles de vol en temps réel (donc très haute fréquence). Ces modèles possèdent les dynamiques linéaires. De notre côté, en utilisant cette librairie on peut assez facilement échanger les données et effectuer l’affichage de l’hélicoptère en 3D sur l’écran. Pour assurer l’exécution fluide de la simulation, nous devons nous assurer d’une exécution à 125 hertz de la librairie MOSCA. Nous devons également gérer les différentes scènes du simulateur, l’échange des données (axes, contrôleurs) entre la librairie et notre code C#.
    • Moteur 3D en XNA pour un simulateur de vol Atachiants Roman Haute Ecole Rennequin Sualem page 51 Figure 11 - Suivi d'une voiture de Formule 1 par la Flying-Cam
    • Moteur 3D en XNA pour un simulateur de vol Atachiants Roman Haute Ecole Rennequin Sualem page 52 9.1.2 AFFICHAGE Le module d’affichage est le plus gros module que nous devions développer. Ce module est composé de plusieurs parties : • moteur de rendu graphique ; • objets de scènes; • interfaces utilisateur. Le moteur de rendu graphique est en même temps le moteur d’optimisation d’affichage. Il possède une notion des objets 3D permettant de développer simplement et rapidement diverses scènes. Ce moteur lui-même intègre plusieurs parties, dont 3 principales : • framework de rendu « objets », simplifiant le processus de développement grâce à une couche plus abstraite. Ceci permet de développer les classes standards et flexibles afin de ne plus vraiment se soucier des vertices en tant que tels et travailler par objets. Par exemple, l’hélicoptère est un objet 3D en lui-même qui contient un modèle 3d, une fonction de mise à jour et de rendu. Il peut être tourné en modifiant sa propriété de rotation et déplacé en modifiant sa propriété de position ; • gestion d’optimisation de rendu qui permet ne pas dessiner ce qui n’est pas visible, rendant ainsi le temps d’affichage de la scène plus court. Cette partie de moteur de rendu utilise des techniques avancées utilisées dans le domaine des jeux vidéos (où la performance est importante) ; • gestion des zones d’affichage et des vues de caméra qui permettent de définir une zone d’affichage et de n’afficher que dans cette zone. Cette partie remplace une partie du framework XNA qui, lui, a été conçu pour les jeux vidéo et ne possède pas cette notion de zone. Nous avions besoin de cette technique afin d’afficher plusieurs vues simultanément (dont une de la caméra qui se trouve dans l’hélico). Divers objets de scène ont été créés pour l’environnement 3D de la simulation : l’hélicoptère, skybox, skydome, bateaux, maisons, océan... Les interfaces utilisateurs ont également été créées afin d’assurer l’interaction la plus simple possible entre l’utilisateur et la simulation. Ces interfaces comprennent la configuration des contrôleurs et divers composants personnalisés.
    • Moteur 3D en XNA pour un simulateur de vol Atachiants Roman Haute Ecole Rennequin Sualem page 53 9.1.3 ENTRÉES Le module des entrées est un module très important car il permet de configurer et d’utiliser divers types de radios. Ce module a été conçu en 2 parties : • module USB, permettant de brancher et de gérer n’importe quel contrôleur USB. Ce module a été conçu pour être le plus flexible possible, vu la diversité des radios existantes sur le marché ; • module Série, permettant de gérer les données qui arrivent par le port série d’un contrôleur spécifique. Nous nous sommes basés sur un protocole de ce contrôleur afin d’extraire les données dans le bon ordre.
    • Moteur 3D en XNA pour un simulateur de vol Atachiants Roman Haute Ecole Rennequin Sualem page 54 9.2 L’ARCHITECTURE EN COUCHES DE L’APPLICATION L’architecture globale de l’application a été pensée en plusieurs couches en se basant sur DirectX pour l’affichage graphique et l’interaction avec le matériel de l’ordinateur et sur la librairie de simulation MOSCA pour la simulation en elle-même. Figure 12 - Architecture en couches
    • Moteur 3D en XNA pour un simulateur de vol Atachiants Roman Haute Ecole Rennequin Sualem page 55 9.2.1 COUCHE NATIVE La première couche native comprend 2 parties principales : DirectX API et Mosca. Chacune de ces librairies est écrite en mode natif Win32. Microsoft DirectX est une suite d'API multimédia intégrée au système d'exploitation Windows permettant d'exploiter les capacités matérielles d'un ordinateur. DirectX fournit un ensemble de bibliothèques de fonctions essentiellement dédiées aux traitements audio / vidéo (carte vidéo, carte son, etc.) et aux périphériques d'entrée / sortie (joystick, carte réseau, souris, etc.). L'avantage des fonctions de DirectX pour les programmeurs est que celles-ci utilisent un algorithme alternatif (confié au processeur) quand le matériel installé ne gère pas ce type de traitement. Il fonctionne comme une surcouche de Windows, évitant théoriquement aux programmeurs de devoir s'occuper des différences matérielles qui existent entre les différents PC. Par exemple, si une carte vidéo n'a pas de fonctions dédiées à la 3D, DirectX demandera au processeur principal de s'occuper du rendu d'une image de synthèse ou du rendu 3D en temps réel. Pour plus d’information sur le fonctionnement global de la librairie MOSCA, voir § 9.1.1 ci-dessus. 9.2.2 COUCHE MANAGÉE La deuxième couche était nécessaire afin de donner une interface managée à la couche native. Cette couche amène à la fois la portabilité des couches du dessus et l’amélioration de la productivité et de la sécurité. La librairie Diamond.Mosca que nous avons conçu permet l’interfaçage avec la librairie MOSCA. Cette librairie assure également l’exécution de la librairie à une fréquence de 125 hertz et permet l’échange des données entre les deux. Elle utilise des fonctionnalités non portables. La première couche de XNA Framework et la librairie DirectInput du Managed DirectX servent à faire le même interfaçage mais au niveau de la carte graphique et des entrées USB.
    • Moteur 3D en XNA pour un simulateur de vol Atachiants Roman Haute Ecole Rennequin Sualem page 56 9.2.3 COUCHE ABSTRAITE La troisième couche est une couche à la fois abstraite et générique. Le but de cette dernière est de fournir les fonctionnalités simplifiant la programmation et améliorant la productivité. Sur cette couche il existe 2 parties principales : une pour le rendu (c’est en fait le moteur de rendu graphique) et une autre pour les entrées des contrôleurs. Diamond.Input.Usb et Diamond.Input.Serial sont des librairies qui permettent d’utiliser facilement les contrôleurs USB et Série et qui fournissent les fonctionnalités afin de configurer ces contrôleurs. Diamond.Render est une des librairies les plus développées de notre application. C’est à la fois le moteur de rendu graphique et le remplacement de la deuxième couche XNA nécessaire pour l’affichage par zone et non plus par fenêtre Windows. Cette librairie se compose principalement de : • framework de gestion objets ; • gestion de multiples caméras (de rendu) ; • gestion de terrain et les optimisations de ce dernier ; • graphe de scène ; • octree d’optimisation de rendu ; • zones d’affichage et leur gestion ; • gestion des shaders et du post-processing ; • gestion des exceptions du moteur. Chacune de ses parties sera expliquée dans le chapitre consacré au moteur de rendu graphique et ses composants. Voir § 11 below pour plus d’informations sur le moteur de rendu graphique. 9.2.4 COUCHE SPÉCIFIQUE À L’APPLICATION La dernière couche est une couche spécifique à l’application. Elle intègre les fonctionnalités demandées (logique métier en quelque sorte), les interfaces graphiques et d’autres fonctionnalités accessoires comme l’enregistrement des paramètres ou le logging. Cette couche intègre
    • Moteur 3D en XNA pour un simulateur de vol Atachiants Roman Haute Ecole Rennequin Sualem page 57 également une couche plus abstraite des entrées utilisées dans le simulateur.
    • Moteur 3D en XNA pour un simulateur de vol Atachiants Roman Haute Ecole Rennequin Sualem page 58 10. SIMULATION 10.1 INTRODUCTION Une simulation de vol est un système dans lequel un pilote réel est aux commandes d'un hélicoptère virtuel dont le comportement est obtenu par simulation. Notre moteur 3D est un outil professionnel conçu pour remplir plusieurs besoins de l’entreprise : • la formation continue des pilotes; • simulation des scènes réelles (sur un tournage par exemple) ; • permettre le pilotage en aveugle (sans voir l’hélicoptère réel, en regardant uniquement l’écran). En plus simple, MOSCA prend en charge tout ce qui concerne le modèle des vols et nous permet de l’utiliser de cette manière : MOSCA est implémenté chez Flying-Cam sous forme d’une librairie écrite en langage C. Etant donné que nous devions pouvoir l’utiliser en langage C#, le développement du module « Wrapper » fut nécessaire pour permettre l’interaction.
    • Moteur 3D en XNA pour un simulateur de vol Atachiants Roman Haute Ecole Rennequin Sualem page 59 10.2 WRAPPER POUR MOSCA Dans le cadre de simulation, afin d’assurer une exécution fluide de la simulation, nous devons nous assurer d’une exécution à 125 hertz de la librairie MOSCA. Le module de simulation interne à notre simulateur est représenté sous forme d’une classe statique CMoscaWrapper. Cette classe permet de : • démarrer/arrêter la simulation ; • assurer l’exécution à 125 hertz ; • offrir des accès rapides à des valeurs d’entrée/sortie de la librairie MOSCA ; • effectuer la transition entre le code C et le code managé. L’exécution de la librairie MOSCA se résume à un appel itératif d’une fonction. Cette fonction est prototypée d’une manière à avoir les valeurs d’entrées (double InputValues[]) et les valeurs de sortie (double OutputValues[]). Ces valeurs sont mémorisées sous forme des variables statiques dans la classe CMoscaWrapper. Examinons maintenant les principales fonctions de cette classe en commençant par la fonction de démarrage de la simulation, la fonction Start(). Dans cette fonction l’appel itératif à la fonction MOSCA est implémenté. Cette dernière n’est pas conçue en temps réel et la durée d’exécution peut varier. Nous devions donc nous assurer d’attendre le temps restant, calculé suivant la formule : Où : est le temps d’attente à trouver.
    • Moteur 3D en XNA pour un simulateur de vol Atachiants Roman Haute Ecole Rennequin Sualem page 60 est le temps d’exécution de la fonction MOSCA.
    • Moteur 3D en XNA pour un simulateur de vol Atachiants Roman Haute Ecole Rennequin Sualem page 61 public static void Start() { if(CInputController.Instance.ControllerType == EInputController.SerialController) { CInputController.Instance.SerialController.SerialReadMessageEvent += new CSerialReadEventHandler(SerialController_SerialReadMessageEvent); SerialAsyncThread = CInputController.Instance.SerialController.ReadLoopThread(); } //(1) GetPosition(true, Microsoft.Xna.Framework.Input.Keys.D9, ref InputValues, ref OutputValues); //(2) Started = true; timeBeginPeriod(1); //(3) while (Started) //(4) { PerfTimer2.Stop(); PerfTimer1.Start(); GetPosition(false, KeyPressed, ref.InputValues, ref OutputValues);//(5) PerfTimer1.Stop(); int diff=8-(int)((PerfTimer1.Duration+PerfTimer2.Duration)*1000); //(6) if (diff > 0) Thread.Sleep(diff); //(7) PerfTimer2.Start(); } } (1) Tout d’abord, nous initialisons l’événement de la lecture du contrôleur série ( Voir le TFE de Quentin Charlier pour plus d’informations sur la gestion des contrôleurs). (2) Un premier appel à la fonction MOSCA est effectué, réinitialisant ainsi la simulation. (3) La période de temps (la résolution du timer) est mise à 1 milliseconde, assurant ainsi que la fonction Thread.Sleep() effectue une attente avec la bonne précision (Thread.Sleep(7) sans avoir forcé une période peut attendre 15ms suivant l’horloge). (4) On démarre la boucle principale, la simulation en elle-même. (5) On effectue l’appel à la fonction MOSCA, en passant par référence les valeurs d’entrée et en récupérant les valeurs de sortie. (6) On effectue le calcul à l’aide des chronomètres. (7) Finalement, on effectue un Thread.Sleep( ) et on attend le temps nécessaire. Examinons maintenant la fonction MOSCA et son prototype C : int wrapper_fc_gui__(integer *first_call__, integer * mode_key__, doublereal *input_futaba__, doublereal *all_state__)
    • Moteur 3D en XNA pour un simulateur de vol Atachiants Roman Haute Ecole Rennequin Sualem page 62 Cette fonction contient 4 paramètres dont 2 vecteurs (doublereal*). Afin de pouvoir l’utiliser en C#, il est nécessaire de créer une liaison sous forme d’une fonction « static extern » et dotée d’un attribut DllImport, disant au compilateur que c’est une fonction externe se trouvant dans une librairie. [DllImport("mosca_FC.dll", EntryPoint = "wrapper_fc_gui__", CallingConvention = CallingConvention.Cdecl)] unsafe static extern int UnsafeCallFcGui(int* first_call__, int* mode_key__, double* input_futaba__, double* all_state__); Pour mieux expliquer la fonction, voici un tableau des 4 paramètres de la fonction et les valeurs possibles : Paramètre Description Valeurs possibles int* first_call__ Permet de dire à la librairie MOSCA si les valeurs doivent être réinitialisées dans un état de situation initiale ou pas. 0 : non 1 : oui int* mode_key__ Permet de transférer à la librairie MOSCA des informations sur le mode de la simulation. 0 : Pilotage manuel 9 : Pilotage automatique 8 : Pilotage automatique avec caméra gyrostabilisé double* input_futaba__ Vecteur de 8 entrées des valeurs des La valeur de pulsion est comprise entre
    • Moteur 3D en XNA pour un simulateur de vol Atachiants Roman Haute Ecole Rennequin Sualem page 63 axes des contrôleurs. -0.5 et 0.5 double* all_state__ Vecteur de 35 entrées avec des diverses informations de sortie. all_state__[6] : angle de l’hélicoptère all_state__[7] : angle de l’hélicoptère all_state__[8] : angle 4 de 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_OldTarget.X); m_Position.Y += (m_Target.Y - m_OldTarget.Y); m_Position.Z += (m_Target.Z - m_OldTarget.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_Viewport.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(@"ContentModelsBay"); Bay.Position = new Vector3(2210, 60, 9999); Bay.Scaling = new Vector3(2, 2, 2); CMobile Ketch = new CMobile(@"ContentModelsKetch"); Ketch.Position = new Vector3(-8340, 800, 8120); Ketch.Scaling = new Vector3(1, 1, 1); //(2) m_MainScene.ObjectManager.AddObject("Grid", m_Grid); //(3) m_MainScene.ObjectManager.AddObject("Water", m_Water); m_MainScene.ObjectManager.AddObject("Bay", Bay); m_MainScene.ObjectManager.AddObject("Ketch", Ketch); m_MainScene.ObjectManager.AddObject("SkyDome", new CSkyDome()); m_MainScene.ObjectManager.AddObject("Helicopter", m_Helicopter); } (1) On commence par créer un espace de travail qui servira de container aux objets de scène. Ensuite, on ajoute cet espace de travail à un gestionnaire des espaces de travail. (2) On continue par instancier les objets de scène et à modifier leurs propriétés. (3) On finit par ajouter tous ces objets de scène (dans un ordre de préférence) à l’espace de travail.
    • Moteur 3D en XNA pour un simulateur de vol Atachiants Roman Haute Ecole Rennequin Sualem page 84 Nous commençons notre scène avec une zone d’affichage remplie d’une couleur bleue, utilisée par défaut. Cette opération est effectuée à chaque début de la boucle de rendu. La ligne suivante ajoute la grille nommée « Grid » sur la zone d’affichage : m_MainScene.ObjectManager.AddObject("Grid", m_Grid);
    • Moteur 3D en XNA pour un simulateur de vol Atachiants Roman Haute Ecole Rennequin Sualem page 85 La ligne suivante ajoute un modèle 3D (une bouée) nommée « Bay » sur la zone d’affichage : m_MainScene.ObjectManager.AddObject("Bay", Bay); La ligne suivante ajoute un modèle 3D (un voilier) nommé « Ketch » sur la zone d’affichage : m_MainScene.ObjectManager.AddObject("Ketch", Ketch);
    • Moteur 3D en XNA pour un simulateur de vol Atachiants Roman Haute Ecole Rennequin Sualem page 86 La ligne suivante ajoute un SkyDome (ciel) sur la zone d’affichage : m_MainScene.ObjectManager.AddObject("SkyDome", new CSkyDome()); Et finalement, nous ajoutons un hélicoptère et nous pouvons commencer à utiliser la scène. m_MainScene.ObjectManager.AddObject("Helicopter", m_Helicopter);
    • Moteur 3D en XNA pour un simulateur de vol Atachiants Roman Haute Ecole Rennequin Sualem page 87 11.4.4 INTERACTION ENTRE LE RENDU ET LE FRAMEWORK OBJETS Afin de concevoir les zones d’affichage en interaction avec le framework objets, nous avons analysé et établi plusieurs notions bien distinctes : • notion d’un contexte de rendu : un contexte général comprenant toutes les informations nécessaires pour l’affichage et la mise à jour; • notion de surface de rendu : est en quelque sorte une «toile» de dessin afin de permettre de définir des zones à deux dimensions dans lesquelles l’affichage est permis; • notion d’un gestionnaire d’objets : permet de gérer et afficher une collection d’objets (basés sur le framework d’objets); • notion d’un espace de travail : contient divers gestionnaires dont un gestionnaire d’objets et un gestionnaire de contenus ; permet d’effectuer des opérations globales à l’affichage; • notion d’un gestionnaire des espaces de travail : un simple gestionnaire permettant de gérer de multiples espaces de travail. Afin d’effectuer l’affichage final, il est nécessaire de définir une surface de rendu sur laquelle un espace de travail va effectuer le dessin.
    • Moteur 3D en XNA pour un simulateur de vol Atachiants Roman Haute Ecole Rennequin Sualem page 88 11.4.5 L’ARCHITECTURE DIRECT 3D Avant de parler d’implémentation d’infrastructure Direct 3D, nous devions comprendre les bases du fonctionnement de l’API. Il existe 2 types de modifications de rendu final : • programmable pipeline : permet au développeur de modifier presque tous les algorithmes pour le rendu final. Il existe deux possibilités d’interférer avec le pipeline de base : o vertex shader : permet la modification des vertices avant qu’ils ne soient utilisés dans la surface de rendu o pixel shader : permet la modification de chaque pixel avant le rendu final • fixed function pipeline (FFP) : permet la modification de rendu final en se basant sur l’utilisation des algorithmes. Avec FFP le développeur peut choisir un des algorithmes prédéfinis et le paramétrer. Les nouveaux algorithmes ne peuvent pas être ajoutés (d’où le nom). Cette technique d’affichage est considérée de plus en plus comme obsolète et n’existe d’ailleurs plus dans DirectX 10. Le processus d’affichage (dit graphics pipeline) fournit la puissance nécessaire afin de procéder à l’affichage des scènes Direct3D sur un écran, en utilisant le plus possible les ressources matérielles. Cette figure illustre conceptuellement ce processus: Figure 19 - Graphics pipeline
    • Moteur 3D en XNA pour un simulateur de vol Atachiants Roman Haute Ecole Rennequin Sualem page 89 Nom du composant Description Vertex data Les vertices du modèle non transformés stockés dans la mémoire tampon des vertices (vertex memory buffers). Primitive data Les primitives géométriques, y compris les points, lignes, triangles et polygones, sont référenciées dans les données vertices grâce à index buffers. Tessellation Le tesselator est une unité de conversion des primitives de haut niveau (mesh parts et autres) en vertices et permet de les stocker dans les vertex buffers. Vertex processing Les transformations Direct3D sont appliquées aux vertices stockés dans le vertex buffer. Geometry processing Le clipping, back face culling, évaluation des attributs sont appliqués aux vertices transformés. Texture surface Les coordonnées des textures Direct3D sont fournies par le biais d’une interface IDirect3DTexture. Texture sampler Le niveau de détail (filtres) est appliqué aux textures. Pixel processing Les opérations du pixel shader utilisent les données de la géométrie afin de modifier les entrées vertex et textures. Pixel rendering Les processus du rendu final modifient les couleurs des pixels grâce à l’alpha (transparence), profondeur ou autres techniques afin de finaliser le rendu qui sera affiché à l’écran. Nous n’allons pas rentrer dans les détails de chaque élément, ceci sortant largement du cadre de ce travail.
    • Moteur 3D en XNA pour un simulateur de vol Atachiants Roman Haute Ecole Rennequin Sualem page 90 Le composant central du Direct3D est le Device 3D, il encapsule et stocke l’état de rendu (rendering state). Il existe deux types principaux des Direct 3D device : • un device HAL (hardware-accelerated), se basant sur le matériel afin d’effectuer et accélérer le processus de rendu ; • un reference device, sur lequel tout le processus de rendu est effectué par le CPU. On peut imaginer ces deux types de devices comme des pilotes séparés. Un pilote spécifique pour les reference devices et un pour les HAL devices. Dans le cadre de ce travail nous allons nous intéresser aux HAL devices, car ils offrent un gain de performance considérable. Les HAL devices sont disponibles sur toutes les cartes graphiques supportant Direct3D. Voici comment on procède à la création d’un device en XNA : GraphicsDevice device = new GraphicsDevice( GraphicsAdapter.DefaultAdapter, // (1) DeviceType.Hardware, // (2) base.Handle, // (3) CreateOptions.HardwareVertexProcessing, // (4) presentationParameters // (5) ); device.RenderState.CullMode = CullMode.CullCounterClockwiseFace; // (6) device.RenderState.DepthBufferEnable = true; // (7) Plus en détail : (1) Ce paramètre permet de choisir l’adaptateur graphique (la carte graphique à utiliser). (2) Permet de définir le type de device à créer, HAL ou Reference. (3) Le handle (pointeur) de la fenêtre Win32 dans laquelle l’affichage est effectué. (4) Le type de Vertex processing à utiliser, indique comment Direct3D doit traiter les transformations des vertices (hardware, software, threadé…). (5) Les paramètres de présentations, les différents buffers et autres paramètres encapsulés dans une seule classe. Il en existe des dizaines donc nous n’entrerons pas dans les détails de cette classe. (6) Ce paramètre permet de définir un état (temporaire et modifiable) d’ordre d’affichage des vertices. (7) Ce paramètre permet d’activer le DepthBuffer (dit aussi Z-Buffer). Z-buffer est une méthode employée dans le cadre de l'affichage d'une scène 3D. Le Z-Buffer permet de gérer le problème de la visibilité qui consiste à déterminer quels éléments de la scène doivent être rendus, lesquels sont cachés par d'autres et dans quel ordre l'affichage des primitives doit se faire.
    • Moteur 3D en XNA pour un simulateur de vol Atachiants Roman Haute Ecole Rennequin Sualem page 91 11.4.6 L’ARCHITECTURE CONTEXTE DE RENDU Le contexte de rendu est l’élément principal d’affichage, permettant d’avoir un objet commun contenant tout ce qui est nécessaire pour effectuer un affichage ou une mise à jour quelconque. Ce contexte est également utilisé dans le framework objet (passé en paramètre à la fonction Render() ou RenderChildren() ). Cet objet permet de fournir plusieurs paramètres et fonctionnalités (sous forme de propriétés dynamiques). Les principales fonctionnalités sont : • les paramètres de la caméra suivant lesquels on doit faire l’affichage. Voir § 11.2 above pour plus d’informations sur les paramètres de la caméra; • récupération d’états de clavier et souris ; • le temps interne (combien de millisecondes se sont écoulées depuis le début ou depuis le dernier frame) ; • récupération du Device Direct 3D chargé de faire l’affichage ; • des propriétés dynamiques fournissant les diverses multiplications des matrices ; • des événements permettant de signaler la création/destruction/réinitialisation du Device Direct 3D ; • des méthodes de mise à jour du contexte de rendu, permettant ainsi de mettre à jour les données de la caméra et des entrées clavier/souris à chaque frame. Sur la figure à droite vous pouvez voir le schéma fortement simplifié de cette classe.
    • Moteur 3D en XNA pour un simulateur de vol Atachiants Roman Haute Ecole Rennequin Sualem page 92 SURFACE DE RENDU Une interface IRenderingSurface définit une notion de surface de rendu, qui nous est nécéssaire afin de définir la zone d’affichage. Cette interface définit les méthodes nécessaires pour effectuer l’affichage et la création de Device Direct3D. Méthode Description CRenderContext CreateDevice(); Cette méthode permet de créer un Device Direct 3D au début de l’initialisation de l’affichage; elle crée et définit également un contexte de rendu correspondant. void Attach(IWorkspace _Workspace); Cette méthode permet d’attacher un « espace de travail » (IWorkspace) à la zone d’affichage pour qu’elle sache ce qu’elle doit afficher. Le Worskpace va être expliqué plus loin en détail. void Run(); Cette méthode permet de démarrer l’affichage. void Stop(); Cette méthode permet d’arrêter l’affichage. void LoadGraphicsContent(bool AllContent); Cette méthode permet de charger le contenu graphique (à la demande). void UnloadGraphicsContent(bool AllContent); Cette méthode permet de décharger le contenu graphique (à la demande).
    • Moteur 3D en XNA pour un simulateur de vol Atachiants Roman Haute Ecole Rennequin Sualem page 93 ESPACE DE TRAVAIL Comme signalé précédemment, nous voulions définir plusieurs « notions » (interfaces) et faire une division claire entre plusieurs choses : • une zone d’affichage ; • un espace de travail. La notion d’espace de travail est représentée par une interface IWorkspace, permettant de gérer plusieurs fonctionnalités : • gestion de divers services (objets permettant l’extensibilité de l’espace de travail) • accès direct au Direct 3D Device qui effectue l’affichage de l’espace de travail ; • accès au ContentManager : un objet du framework XNA permettant le chargement/déchargement des ressources artistiques (modèles 3D, sons, textures, images…) ; • accès au ObjectManager (cette notion sera expliquée après le tableau suivant). Méthode Description object GetService(Type serviceType); Cette méthode obtient l’objet service du type spécifié. Un service est un objet qui assure la prise en charge personnalisée d'autres objets. void RegisterService(Type type, object provider); Cette méthode permet d’enregistrer le service dans l’espace de travail en l’intégrant dans son environnement. void RevokeService(Type _ServiceType); Cette méthode permet de retirer un service de l’environnement de l’espace de travail. GraphicsDevice GraphicsDevice { get;} Cette propriété permet d’accéder au Device Direct 3D lié. ContentManager ContentManager{ get; } Cette propriété permet d’accéder au gestionnaire de contenu lié.
    • Moteur 3D en XNA pour un simulateur de vol Atachiants Roman Haute Ecole Rennequin Sualem page 94 IObjectManager ObjectManager { get; } Cette propriété permet d’accéder au gestionnaire d’objets 3D lié. Une notion de « gestionnaire d’objets » a été également définie au moyen de l’interface IObjectManager. Ce gestionnaire d’objets effectue toute la gestion des divers mécanismes implémentant les optimisations d’affichage, le chargement des ressources nécessaires et en simplifiant tout le processus. Sans entrer dans les détails, elle permet de : • gérer une collection d’objets ; • afficher cette collection ; • effectuer la mise à jour de cette collection ; • charger/décharger les ressources utilisées par les objets. Voici les méthodes principales qui ont été définies : Méthode Description void AddObject(string _Asset, CObject _Object); Cette méthode permet d’ajouter un objet à la collection d’objets qui sera gérée par le gestionnaire. void RemoveObject(string _Asset); Cette méthode permet d’enlever (et décharger) l’objet de la collection. Obj GetTypedObject<Obj>(string _Asset) where Obj : class; Cette méthode permet de récupérer un objet typé de la collection. void UpdateObjects( CRenderContext _RenderContext); Cette méthode permet d’effectuer une mise à jour (appel des fonctions Update correspondantes) de chaque objet dans la collection. void DrawObjects( CRenderContext _RenderContext); Cette méthode permet d’effectuer l’affichage des objets de la collection.
    • Moteur 3D en XNA pour un simulateur de vol Atachiants Roman Haute Ecole Rennequin Sualem page 95
    • Moteur 3D en XNA pour un simulateur de vol Atachiants Roman Haute Ecole Rennequin Sualem page 96 GESTIONNAIRE DES ESPACES DE TRAVAIL Dans une application comprenant plusieurs zones d’affichage il est nécessaire de pouvoir gérer toutes les zones d’affichage d’un seul et unique endroit. Pour permettre ceci, nous avons défini une notion de gestionnaire des espaces de travail, permettant la gestion de cette collection et éventuellement de la partie «métier » de l’application. Cette notion est représentée sous forme de l’interface IWorkspaceManager. Vous pouvez voir ses méthodes principales sur le schéma ci-contre. Cette notion est assez simple en soi, donc nous n’allons pas entrer dans les détails.
    • Moteur 3D en XNA pour un simulateur de vol Atachiants Roman Haute Ecole Rennequin Sualem page 97 11.4.7 L’IMPLÉMENTATION IMPLÉMENTATION DE LA SURFACE DE RENDU Nous avons conçu une première implémentation de la notion de surface de rendu. Nous voulions l’utiliser dans WindowsForms nous avons donc créé une classe dérivée de UserControl (contrôle d’utilisateur) et implémentant l’interface IRenderingSurface. Ceci permet l’utilisation (placement et modification de propriétés) simple dans le designer de Visual Studio. Sur le schéma ci-contre vous pouvez voir les méthodes principales de cette classe. Son fonctionnement comprend : • Lancement/arrêt de la boucle d’affichage. Cette boucle est gérée par un timer (chronomètre) permettant d’appeler la méthode Tick à une cadence spécifiée ; • Création d’un Device Direct 3D et gestion de ses événements Voici la fonction Tick, qui est appelée en boucle et représente tout ce qui se passe pendant l’affichage d’un frame : private void Tick(object sender, EventArgs e) { UpdateScene(); //(1) if (!m_SuspendRendering) { GraphicsDevice.Clear(m_ClearColor); //(2) DrawScene(); //(3) GraphicsDevice.Present(); //(4) } } (1) Une fonction de mise à jour de scènes est appelée (aucun affichage ne peut être effectué dans cette fonction) ; (2) La surface de rendu est « nettoyée » pour effectuer un nouvel affichage ; (3) La scène est dessinée dans la zone d’affichage ; (4) Tout ce qui a été dessiné est présenté à l’écran.
    • Moteur 3D en XNA pour un simulateur de vol Atachiants Roman Haute Ecole Rennequin Sualem page 98 Regardons maintenant plus en détails les deux fonctions privées appelées dans la fonction Tick. La première est la fonction de mise à jour de scène attachée à la surface de rendu. protected virtual void UpdateScene() { //Mettre à jour le contexte de rendu this.RenderContext.ElapsedTime = 0.01666667f; this.RenderContext.LastTime = this.RenderContext.Time; this.RenderContext.Time += this.RenderContext.ElapsedTime; this.StopWatch.Reset(); this.StopWatch.Start(); this.RenderContext.HasFocus = base.Focused; RenderContext.Update(); //(1) if (Focused) { RenderContext.GetCamera().UpdateInput(); //(2) } else { RenderContext.GetCamera().ResetInput(); } Workspace.ObjectManager.UpdateObjects(RenderContext); //(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(RenderContext); //(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, _ParentAsset); 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