Annexe : Winform et Xna

Il est tout à fait possible d’interconnecter un affichage “Xna” à un affichage Winform. Deux choix s’offrent au développeur : soit amener les fonctionnalités Winform dans un programme Xna, soit intégrer du Xna dans une application Winform. Cette annexe aborda ces deux cas au travers d’exemples simples.

Fonctionnalités Winform dans un programme Xna

La fenêtre dans laquelle s’exécute un programme Xna correspond à un objet de type GameWindow.L’équipe Xna ne s’est pas amusé à “redévellopper la roue” ; chaque fenêtre sous Windows est identifié par un handle qui l’identifie de manière unique parmi toutes les fenêtres affichées par le système d’exploitation. L’astuce consiste donc ici à charger un objet Form (Winform) à partir du handle de l’objet GameWindow.


A ce stade l’accès aux fonctionnalités Winforms est un jeu d’enfant. Nous allons créer une application affichant un carré. Elle donnera à l’utilisateur la possibilité de modifier la couleur du cube par l’intermédiaire d’une combobox et sa taille via un slider. Un bouton permettra de tout réinitialiser.








Fonctionnalités Xna dans un programme Winform



Conclusion

L’association Winform Xna est un cas exceptionnel qui répond à un ensemble de problématiques particulières : besoin de profiter de la maturité ou de rapidité d’implémentation de Winform

Livre Blanc Terminé

Livre blanc sur le Content Pipeline terminé (80 pages word ouf).


 http://msmvps.com/blogs/valentin/archive/2007/03/21/livre-blanc-le-xna-framework-content-pipeline.aspx


Je vous invite à decouvrir l’api associée qui est vraiment très très utile quand on est pointilleux sur la qualité de ses projets et la gestion de ses ressources.


 


(sommaire des cours Xna : http://msmvps.com/blogs/valentin/archive/2007/03/30/tutoriaux-xna-sommaire-g-n-ral.aspx)


 


[soon]


 Valentin Billotte


 [Help]

De nouveau MVP :)

Ca vient de tomber je suis à nouveau nommé MVP pour la 4ème année consécutive.


Jusque là c’était mes cours sur le C# et le MDX ainsi que ma communauté qui me donnaient ce titre, je m’oriente maintenant plus vers le Xna (qui en doutait :) ).


A moi d’essayer de fédérer en aidant à la création d’une communauté Française sur le sujet avec sans doute quelques uns des lecteurs qui suivent ce blog (que je remercie par ailleur).


[Soon]


Valentin Billotte


(plus d’infos sur le programme MVP)

Mise a jour du XNA Game Studio Express prévue ce mois !

Dans le courant du mois devrait sortie une mise à jour du XNA Game Studio Express. Elle prendra en compte la plupart des requetes utilisateurs reçue par Microsoft et bien entendu la correction de divers bugs et lacunes du framework. Elle incluera ainsi un grand nombre de nouveautés. Au programme :


  • XNA Game Studio Express
    • Windows Vista est completement supporté.
    • Ajout d’icones aux jeux XNA Game Studio Express possible..
    • Gestion des déploiement projet améliorée.
  • XNA Framework
    • Support des bitmap de font (texte)
    • Support de XACT 3D.
    • Ajouts et améliorations des fonctionnalités mathématiques du framework. 
    • Le BasicEffect supporte le per-pixel lighting
  • XNA Framework Content Pipeline
    • Support des Volume Textures (Texture3D)
    • Le build de contenu peut être annulé
    • Support du nettoyage des précédent build
    • Possibilité de lire les vertices et indices à partir des modèles.
  • XNA Game Launcher (Xbox 360)
    • Un thumbnails affiché pour vos jeux
    • Amélioration de l’interface de connexion entre pc et console. 
    • Test et diagnostique possible pour une connexion entre la Xbox 360 et le PC
  • Packaged XNA Game Studio Express Games
    • Les utilisateurs peuvent créer un package de leurs données binaires en un seul fichier pour aider au partage d’applications avec les autres utilisateurs du XNA Game Studio Express.
    • Ces fichiers peuvent être “emailés” ou uploadés sur un serveur comme n’importe quel fichier.
    • Pour lancer un jeu, vous n’aurez qu’a double cliquer sur ce fichier et celui si sera dézippé et installé sur votre pc ou votre console Xbox 360 console (ca va faire l’objet d’un tuto ça :)

Reste plus qu’à attendre :)


 


[soon]


Valentin Billotte

Annexe : Progressive Mesh en Xna

Retourner au sommaire des cours 


 


Avant toutes choses je tiens à remercier Stan Melax qui m’a gentiment aidé à passer son algorithme en DirectX et Xna et m’a laissé la possibilité d’utiliser pour ce cours quelque schémas qu’il avait réalisé. 


 


 


L’utilisation de MRM est une véritable merveille pour accroître de manière significative les performances de ses applications. Le principe est simple : transformer un model 3D détaillé et formé de très nombreux polygones en une version allégée utilisant moins de faces mais aillant un aspect aussi similaire que possible.


Cette technique est la plupart du temps couplée avec la camera pour réduire proportionnellement la qualité du modèle 3D en fonction de la distance à laquelle il se trouve de la camera.


Au final, nous pouvons ainsi grappiller des FPS et libérer le GPU en lui évitant d’afficher des modèles détaillés au loin, là ou une version grandement allégée donne le même résultat à l’écran.


L’image suivante explicite cela :


 


La porche a 25% donne le même affichage a grande distance que le modèle a 100%.

 On y voir l’affichage d’une voiture sous différentes résolutions (le poucentage indiqué au dessus de chaque modèle correspond au nombre de vertices utilisé par rapport à l’original). Le modèle à 10% reste tout à fait acceptable et similaire à l’original. Il est donc tout à fait imaginable de l’utiliser à grande distance à la place d’un modèle plus “complet” et plus lourd à manipuler.

 

Les MRM  (multi resolution mesh) occupent une place prépondérante dans les moteurs 3D : Utilisés pricipalement pour libérer du traitement GPU sur l’affichage des objets lointains il est aussi employé dans l’occlusion culling (l’occlusion consiste à supprimer de l’affichage les objets qui sont cachés par d’autres objets nous y reviendrons dans un autre post).   Nous allons donc dans ce cours chercher un moyen pour créer et utiliser des MRM dans nos applications. Ce moyen, c’est bien evidemment un algorithme qui va etre en mesure de calculer la réduction du nombre de vertices dans une forme 3D en sauvegardant au maximum son aspect général lors de cette transformation.    L’algorithme  

 


 


Une complexité qui rebute 


 


Si on se tourne vers les moteurs de recherche sur le net (live.com, google.fr) à l’aide des mots clés “MRM algorithme” on trouve un grand nombre de travaux de chercheurs et de passionnés sur ce sujet. Pourtant la plupart des algorithmes qu’on y trouve sont inexploitables : soit ils sont trop gourmants en calculs et donc inexploitable en temps réel, soit le resultat change l’aspect de la forme 3D ou bien encore la complexité est telle qu’il est tout bonnement incompréhensible. Quelques pasionnés ont toutefois trouvé un moyen de réaliser des réductions de résolutions relativement simplement. Nous retiendrons ainsi la méthode utilisé par Stan Melax parce qu’à priori la meilleure et, cerise sur le gâteau, l’une des plus simples.


 


Réduction par Fusion de Meshs 


 


Melax se base lui-même sur les travaux de H.Hoppes, un développer de MSR (Microsoft Research) dont est issue vraisemblablement l’algorithme se trouvant derrière la classe ProgressiveMesh de Direct3D. Cet algorithme vise a réduire la complexité d’un model 3D par l’intermédiaire de fusions de vertices. Le principe est trivial : à chaque réduction de résolution on fusionne deux vertices (que nous nommerons ici u et v).S’ensuit :


  • La suppression des triangles qui possèdent à la fois les vertices u et v.
  • La mise à jour des triangles qui utilisaient u sur l’un de leurs trois points afin qu’ils utilisent v à la place.
  • La suppression du vertex u.
  A chaque réduction de complexité, deux vertices u et v sont sélectionnés et l'un deux est "fusionné" avec l'autre (ici respectivement u et v).   Le schéma ci-dessus explicite tout cela. La figure A montre l’état du modèle avant la baisse de résolution. La figure B montre le même modèle après la fusion de deux de ces vertices. Le modèle garde son aspect mais en utilisant un vertex et deux faces en moins.

 


Ce processus est répété jusqu’à atteindre le nombre de vertices ou de faces voulu.

 Choix de u et v 

Cette méthode est relativement simple sur le papier et réduit effectivement sans grandes difficultés un model 3D. Il ne faut pourtant pas crier victoire trop vite : comme dit précédemment, il est primodial que le model “réduit” garde une apparence similaire au model complexe originel. Il convient donc de choisir avec intelligence les sommets u et v à fusionner afin de provoquer la plus fine modification visuelle à l’écran. L’image suivante illustre celà :


 


 


 Le choix du vertex est important !


Le choix du sommet à supprimer est important pour garder une apparence aussi similaire que possible à l’original (image extraite de l’article de Stan Melax avec l’aimable autorisation de l’auteur). 


 


 


C’est là ou le bat blesse : la plupart des algorithmes propose pour ce choix des calculs lourds et inutilisables en temps réel. Sur ce point, Stan Melax a montré son savoir faire. Il part d’un principe élémentaire : les surfaces coplanaires ne demandent pas autant de vertices pour être rendue à l’écran que les surfaces avec un relief prononcé (comme les courbes). Il est plus facile de réduire la complexité des premières, que celle des secondes. Le coût pour la disparition d’un sommet pourrait se traduire ainsi : c’est le résultat de la multiplication de la taille du sommet par l’importance dans la courbe sur laquelle il se trouve.


 


Pour la fusion uv, visant à déplacer u vers v nous avons l’algorithme :


 


  • Calculer la taille du sommet (distance u à v).
  • Déterminer l’ensemble des triangles qui possède à la fois u et v.
  • Pour chacun des triangles connectés à u :
    • Calculer le produit orthonormé de la normal du triangle courant avec chacun des triangles qui possèdent à la fois u et v. En extraire le plus petit produit.
  • Calculer le plus gros des plus petits produits : C’est la coùt de la fusion.

La formule mathématique pour calculer ce cout est la suivante est la suivante :


 


where Tu is the set of triangles that contain u and Tuv is the set of triangles that contain both u and v.
où Tu
est l’ensemble des triangles qui possèdent u and Tuv l’ensemble des triangles qui contiennent à la fois u et v (image extraite de l’article de Stan Melax avec l’aimable autorisation de l’auteur). 


 


 


Le principe peut se résumer ainsi : on parcourt tous les triangles connectés à u. Il est nécessaire, pour chacun de ces triangles, d’analyser le cout de la fusion avec v. On calcul celà en analysant l’impacte de la transformation des triangles afin de déterminer l’ampleur de la modification. Il y’a deux types de modifications : Soit les triangles sont connectés uniquement à u, et, dans ce cas ils sont modifiés pour être reliés à v, soit les triangles sont liés à u et v à la fois et doivent etre supprimés du modèle. La figure A et B au début de cette annexe illustre celà parfaitement.


 


 


Passons aux choses sérieuses


 


 


Pour l’heure la classe ProgressiveMesh que vous pouvez reprendre est industrialisable mais est encore améliorable :


 


  • Il reste à associer un poid à chaque vertex pour la transformation.
  • A réaliser un tris sur la liste de vertices pour classer par ordre de coût de transformation.
  • A réaliser des méthodes d’optimisation comme dans la classe Mesh de Direct3DX (fusionner les vertices qui sont assez proches pour ne faire qu’un).

Passons maintenant au code.


 


Celui-ci se trouve à l’intérieur d’une DLL nommée ArcaneEngine.Objects. Deux types de données nous interesse :


 


  1. ProgressiveMesh<T>
  2. Resolution

La création d’un mesh progressif et son affichage se fait en trois étapes.


 


Tout d’abord la création de l’objet (étape pouvant être asynchrone) en passant au constructeur la liste des vertices qui composent le mesh, la liste des indices pour relier les vertices et enfin les poids associés aux vertices (un tableau de booléens pour l’heure) :

ProgressiveMesh<VertexPositionNormalTexture> mesh = new ProgressiveMesh<VertexPositionNormalTexture>(vertices, ints, null);


Puis le chargement des buffers 3D lorsque le device a été créé

mesh.Load(this._device);


Enfin l’affichage du mesh

this.mesh.Render();


La gestion des MRM est beaucoup plus simple qu’avec la classe de Direct3DX.


Revenons sur la généricité de la classe. Le développeur doit indiquer un argument de spécificité a la classe générique ProgressiveMesh (ici VertexPositionNormalTexture). Il s’agit en fait de la classe utilisée pour le type de vertices.


A partir de cet argument, la classe pourra extraire les positions de chaque vertices et, avec les indices, calculer les différentes résolutions. Elle pourra en outre extraire le format des vertices pour l’affichage, elle pourra aussi renvoyer à l’utilisateur pour chaque resolution les buffers et array de vertices actuellement affichés.


Pour changer la résolution deux choix. Soit vous utilisez la propriété NumberOfVertices pour indiquer directement le nombre de vertices a afficher. Soit vous utilisez la property Resolution en donnant un membre de l’énumération :


 

    public enum Resolution
    {
        /// <summary>
        /// <para>No resolution : no mesh rendered.</para>
        /// </summary>
        None = 0,
        /// <summary>
        /// <para>No resolution : no mesh rendered.</para>
        /// </summary>
        Dynamic = -1,
        /// <summary>
        /// <para>Ten percents of the mesh’s vertices used to render it.</para>
        /// </summary>
        Lowest = 10,
        /// <summary>
        /// <para>Twenty five percents of the mesh’s vertices used to render it.</para>
        /// </summary>
        Low = 25,
        /// <summary>
        /// <para>Fivety percents of the mesh’s vertices used to render it.</para>
        /// </summary>
        Medium = 50,
        /// <summary>
        /// <para>Seventy five percents of the mesh’s vertices used to render it.</para>
        /// </summary>
        High = 75,
        /// <summary>
        /// <para>One hundred percents of the mesh’s vertices used to render it.</para>
        /// <remarks>Full vertices are used.</remarks>
        /// </summary>
        Full = 100 

    }


 


Le changement de la résolutiond’un mesh demande un leger temps de calcul à priori invisible à l’écran.


 


Nous n’analyserons pas ici le code qui reste assez simple. A l’intérieur de la classe ProgressiveMesh se trouve la region “Multi resolution computing”  qui contient les méthodes liées au calcul de la resolution. La méthode ComputeEdgeCostAtVertex détermine le cout de la fusion d’un vertex, la méthode Collapse réalise cette fusion et MinimumCostEdge permet de trouver le vertex ayant le coût le plus bas pour une fusion. A noter que la classe ProgressiveMesh possède deux types internes : Vertex et Triangle qui permettent d’opérer sur les vertices et les faces plus facilement.


Une analyse du code par vos propres moyens devrait eclaircir tous les points encore obscurs à vos yeux.  N’hesitez pas a poster des commentaires pour toutes questions.


 


A l’intérieur de la classe Game1 se trouve le code qui montre comment utiliser notre classe ProgressiveMesh. L’application principale contient en outre un ensemble de classes statiques qui contiennent des ensembles de vertices et d’indices permettant de charger un MRM. Elles héritent toutes de l’interface IData qui permet une utilisation générique de ces dernières.


 


 


Les liens


 


 


Evidemment en première place le site de Stan Melax 


http://www.melax.com/polychop/


 


Ensuite le site de Hugues Hoppes


http://research.microsoft.com/~hoppe/


(déprimant parcequ’on voit qu’il fait des trucs super, mais on comprend rien)


 


Sample 

telecharger Vous pouvez télécharger les trois samples ici.   


 


Conclusion


 


 


L’application au final se présente ainsi :


 



 


L’interface graphique est rudimentaire mais nous l’améliorerons avec l’arrivée de l’annexe portant sur l’UI. Les touches Page Haut et Page Bas permettent de passer d’une résolution à une autre. Les touches + et – permettent de modifier la resolution plus finnement en changeant le nombre de vertices affichés. La souris permet de déplacer la camera autour du mesh affiché. Enfin la touche espace permet de changer de modèle. L’application affiche 6 modèles :


 


  • Beethoven
  • Fourmi
  • Un terrain
  • Porsche
  • Vache
  • Lapin

 


A noter que le modèle terrain sert à voir l’utilité du tableau de poids passé au constructeur. Sans ce poid, la portion de terrain “s’arrondit” au fil de la réduction de résolution en perdant ainsi tout son aspect. Notez de même que le modèle fourmi montre les limites de notre système sur les formes 3D disposant de peu de vertices …


 


 


[Soon]


 


Valentin Billotte


 


[Help]


 


telecharger Vous pouvez télécharger les trois samples ici.   


Retourner au sommaire des cours 

Fenêtre de création de projets vide sous Visual Studio 2005

Je ne sais pas si ca vous est déjà arrivé mais moi oui. En gros après l’installation d’un produit qui ajoute des extensions à Visual Studio 2005 on se retrouve avec la fenêtre de création de projets complètement vide : plus aucun template (exit Application Windows, Class Library, Web Site etc.). Souvent, il ne reste d’ailleur que les templates liés à l’extension qu’on vient de mettre (supppeeeer).


On se retrouve donc complètement bloqué. J’ai eu ce problème plusieurs fois, notamment avec WWF, Ajax et VSTO. C’est peut être moi qui opère mal,en tout cas, je me souviens que je n’étais pas le seul sur le net lorsque le problème s’est présenté la première fois.


Je viens d’aider deux personnes qui ont eu cette merde et je me suis dis qu’il serait cool de placer une solution en Francais sur le net, la voici :


Il suffit tout simplement d’aller dans Tools/Options/Environmet/International Settings/Language. A priori par défaut vous avez en langage celui de Windows. Changez ce langage pour English. Fermez Visual Studio et reouvrez le. Normalement tout est rétabli.


A l’époque de 2003 je me souviens d’un deven.exe /installvstemplates mais si cette option ne plante pas, elle ne change rien à ce problème.


 Pas la peine de me demander le pourquoi du comment : je ne sais pas pourquoi ca rétabli tout :)


 [Soon]