Le format .MAP

Écrit le 05/07/2003 par Kurim
Dernière mise à jour : 01/02/2006

Introduction

Ce format est un format intermédiaire, utilisé généralement par votre soft de mapping pour convertir une map enregistrée dans son format (par ex, rmf, qrk...), en un format disons générique pouvant être lu par les outils de compilations qui eux opèrent des calculs complexe pour transcrire la map en bsp (compilation...) ou au format utilisé par le jeu.
Le format MAP n'est pas toujours 100% identique d'un jeu a l'autre, mais son fonctionnement reste grossièrement le même. On le retrouve généralement dans tous les jeux héritant d'un Quake Engine (qw, q2 ou q3a), comme par exemple Half-Life, Return To Castle Wolfenstein...

Structure générale

Le format MAP est un format texte, c'est a dire que vous pouvez ouvrir un fichier .map avec le notepad et lire et comprendre son contenu. D'une manière générale, il regroupe une liste d'entités contenu dans des blocs (séparé par des accolades { et } ). Ces entités sont constituées de clés (key) et accessoirement d'une liste de brushes pour le cas d'une entité solide.
Une entité se distingue des autres : c'est celle qui s'appelle worldspawn, et qui est en fait le corps solide de la map. On peut dire que tout bloc ne faisant pas partie d'une entité particulière fait partie de l'entité worldspawn. D'ailleurs pour cette raison le terme entité ne doit pas être utilisé pour le worldspawn, on dira qu'un bloc appartient soit a une entité soit au world.
La syntaxe général d'un .map est :

{
  "classname" "worldspawn"
  "key2" "value2"
  "key3" "value3"
  ...
  {
    [corps solide]
  }
}
{
  "classname" "entité_non_solide"
  "origin"  "X Y Z" // Position de l'entité (l'entité est assimilée à un point)
  "angle"  "#"      // Angle de l'entité
  "key2" "value2"
  "key3" "value3"

}
{
  "classname" "entité_solide"
  "key2" "value2"
  "key3" "value3"
  ...
  {
    [corps solide]
  }
}

Cette exemple nous fait déjà faire des distinctions entre les entités solides et non-solides (qu'on va appeler ponctuelle). En effet une entité ponctuelle est assimilée à un point dans l'espace, c'est à dire son origine, ainsi qu'un angle. (les solides peuvent aussi avoir un angle, mais il ne servira que de repère pour une action de l'entité). L'angle indique la direction vers laquelle l'entité ponctuelle fait face. Généralement si l'angle est une valeur comprise entre 0 et 360, cette entité sera à l'horizontal et sera tournée en direction de l'angle, sachant que 0 est généralement coté est. Les valeurs -1 et -2 correspondent aux directions haut et bas. Par ce système, il y a un certain nombre d'angle que l'on ne peut pas utiliser, vu que l'entité est soit horizontal, soit strictement perpendiculaire au sol. Les autres clés définissent divers paramètre de l'entité utilisée pour le jeu.
Je n'inciterai pas plus sur cet aspect du .map qui est très simple a comprendre (c'est à dire l'organisation du fichier, les clés et valeurs. On va s'intéresser d'avantage au repérage des solides dans l'espace.

Les solides

C'est la que ça devient intéressant. Le format .map a une façon particulière d'enregistrer les solides. La question, c'est comment conserver la forme exacte d'un solide et sa position dans l'espace, avec un minimum de données et en se débrouillant pour que toutes les faces soient forcement plane. La première idée aurait été d'enregistrer la position des points du solide, puis d'enregistrer chaque face comme un groupement de point. Mais c'est relativement lourd et peu fiable, ça augmente les possibilités d'erreur.
En fait le .map va assimiler un solide a une intersection de plan dans l'espace. Il définit chaque plan par deux vecteurs, qui correspondent généralement à deux arrêtes de ce plan. Une chose qui est importante à prendre en compte, c'est qu'en 3D, une face n'est dessinée que d'un coté, et si on la regarde de derrière, on ne la voit pas. C'est pareil dans notre cas, il faut donc un moyen de déterminer dans quelle direction notre face est visible. Pour cela, on va prendre les vecteurs dans leur sens horaire par rapport au plan qu'ils déterminent. Enfin, on se sert de 3 points pour déterminer nos deux vecteurs : une origine, et les deux points d'arrivée de chaque vecteur. Voici un schéma qui illustre comment doivent être repérés ces 3 points (pour la surface du haut du cube) :

http://www.game-lab.com/images/tuts/map_format/vec1.jpg
http://www.game-lab.com/images/tuts/map_format/vec2.jpg

Voici les coordonnés associé a ce plan, le cube étant placé de tel façon que le point 1 soit a l'origine du repère :

( 0 0 0 ) ( 0 0 -384 ) ( 448 0 -384 )

Le cube complet, intersection de 6 plans, aurait donc ce groupe de coordonnées :

( 0 0 0 ) ( 0 0 -384 ) ( 448 0 -384 ) // vers le haut
( 0 -256 -384 ) ( 0 -256 0 ) ( 448 -256 0 ) // vers le bas
( 0 -256 0 ) ( 0 -256 -384 ) ( 0 0 -384 ) // vers nous, face de gauche
( 448 0 0 ) ( 448 -256 0 ) ( 0 -256 0 ) // vers nous, face de droite
( 448 -256 -384 ) ( 448 0 -384 ) ( 0 0 -384 ) // vers le fond, face de gauche
( 448 -256 -384 ) ( 448 -256 0 ) ( 448 0 0 ) // vers le fond, face de droite

A chaque ligne représentant une surface s'ajoute les paramètres de la textures, généralement il y a le nom de la texture et les paramètres de transformation, a savoir rotation, translation et homothétie (scale). La position d'origine de la texture est généralement liée au repère du soft, et les transformations s'y ajoutent pour obtenir le placement désiré de la texture. Je ne détaillerais pas le placement de la texture dans ce tutorial car cela dépend surtout du soft utilisé et des outils de compilation utilisés.

Voilà, si ce tutorial vous a intéressé faites le savoir par le forum, je pourrais à l'occasion y ajouter plus de détails sur ce format.