Home - Forums - Documentation - Gallery - Bugs

Contents

Syntaxe du fichier XML World

Cet article a pour but de détailler le fichier World de Crystal Space en différentes parties pour expliquer la syntaxe et les usages habituels. Bien qu'une grande partie soit couverte par la documentation, certaines demeurent incomplètes ou non approfondies. Cet article espère réussir là ou la documentation pèche.

Tout d'abord, étant donné que le format de fichier World de Crystal Space a l'avantage d'être dans un format ASCII, nous pouvons l'ouvrir avec un éditeur de texte standard (de préférence pourvu de la coloration syntaxique sur les fichiers XML pour simplifier la compréhension). Donc créez un nouveau document ou ouvrez un fichier world existant pour l'éditer (beaucoup d'exemples sont accessibles dans le sous répertoire CS/data/, sous Ubuntu : /usr/share/crystalspace/data).

Partie initialisation

Au commencement...

Tous les fichiers World de Crystal Space commencent avec la balise <world> et se terminent avec </world>. Donc nous débuterons par un :

<world>
</world>

A noter que si vous voulez faire une bibliothèque, il suffit de remplacer world par library. Le reste de ce tutoriel est également valide pour des bibliothèques, excepté que les bibliothèques contiennent exculivement des textures, des matériaux et des fabriques de mesh, mais pas de secteurs.

Ajouter une Texture

Ensuite, nous allons initialiser quelles textures et quels matériaux nous avons l'intention d'utiliser. Pour spécifier des emplacements de fichier dans Crystal Space, nous utiliserons toujours les chemins VFS (Système de Fichier Virtuel). Les chemins VFS sont une manière de définir des chemins réels sans utiliser ceux spécifiques aux OS. Ils vous permettent aussi de lire directement des textures ou tout autre fichier à partir d'archives ZIP.

Les chemins VFS ne sont pas simplement des chemins de système de fichier ordinaires mais des chemins définis par Crystal Space pour assurer une compatibilité multi-plateforme. Les chemins réels sont habiuellement mountés dans un chemin VFS grâce au fichier de configuration vfs.cfg. Par exemple /lib/stdtex est actuellement un fichier ZIP appelé stdtex.zip dans CS/data qui a été monté dans le chemin VFS /lib/. Cela devient plus maniable si vous pouvez vous référer à des fichiers ZIP comme à des dossiers simplement en les montant.

Nous débuterons l'initialisation du fichier world en spécifiant que nous parlons de textures en utilisant la balise <textures> et nous spécifions quelle texture nous utilisons avec la balise texture. Enfin, pour chaque texture, nous spécifions son emplacement en utilisant la balise <file>.

<textures>
    <texture name="oldmetal">
        <file>/lib/stdtex/oldmetal.jpg</file>
    </texture>
</textures>

Cela chargerait une texture qui peut être référencée en tant que oldmetal dans ce chemin VFS /lib/stdtex.

D'autres spécificités en relation aux cas spéciaux dans <textures> tels que les cubemaps et les keycolours peuvent être lues à partir de la documentation officielle de Crystal Space ou vous pouvez regarder un exemple dans CS/data/flarge/world. (sous Ubuntu : /usr/share/crystalspace/data/maps/flarge)

Ajouter des Shaders

Les Shaders interviendront dans la section matériau. Mais avant que nous puissions utiliser un shader dans un matériau, nous devons charger ce shader :

<shaders>
    <shader>
        <file>/shader/std_lighting_detail.xml</file>
    </shader>
</shaders>

Ajouter des Matériaux avec des Shaders

Les matériaux définissent les attibuts d'une surface. Typiquement les matériaux sont associés aux textures, mais il existe beaucoup d'autres possibilités. Un exemple d'un matériau qui ne soit pas associé à une texture est un matériau qui définit une couleur verte :

<materials>
    <material name="green_color">
        <color red="0" green="1" blue="0" />
    </material>
</materials>

Cependant, vous voudriez spécifier une texture comme ceci :

<material name="oldmetal">
    <texture>oldmetal</texture>
</material>

Un autre exemple de ce que sont les shaders, je n'entrerais pas dans les spécificités d'un shader mais sur l'application d'un shader à un matériau comme un simple processus. Nous ferons référence au shader que nous avons utilisé plus tôt :

<material name="oldmetal">
    <texture>oldmetal</texture>
    <shader type="standard">std_lighting_detail</shader>
</material>

Ceci attachera le shader au matériau oldmetal. Mais si nous examinons le shader actuel, nous remarquerons qu'il prend 2 variables que nous pouvons spécifier ici. L'une est une texture que nous pouvons appliquer par-dessus la texture existante, et l'autre est un vecteur 2D qui réduit cette texture à son échelle. Pour utiliser ces variables, nous pouvons faire ce qui suit :

<material name="oldmetal">
    <texture>oldmetal</texture>
    <shader type="standard">std_lighting_detail</shader>
    <shadervar name="tex detail" type="texture">oldmetal</shadervar>
    <shadervar name="detail texture scale" type="vector2">10,10</shadervar>
</material>

Heureusement pour nous, ce shader est un shader standard et la boucle de rendu par défaut inclut déjà les shaders standards. Si c'était un autre type de shader, il est possible que nous aurions du changer la boucle de rendu. J'ai décidé de garder la même texture pour la texture de détail pour éviter d'avoir à spécifier un autre texture et la réduire en 10 UVs. Si vous êtes troublé par la façon dont j'ai obtenu le nom de la variable et son type, vous pouvez vérifier cs/data/shaders/std_lighting_detail.xml (sous Ubuntu : /usr/share/crystalspace/data/shader/std_lighting_detail.xml) pour connaître le type et le nom des variables de shader qu'il prend. Ce sont les mêmes pour tous les shaders.

En résumé

En résumé, nous avons spécifié une simple texture, un matériau et paramétré un shader et çà donnerait ceci :

<world>
    <textures>
        <texture name="oldmetal">
            <file>/lib/stdtex/oldmetal.jpg</file>
        </texture>
    </textures>
    <shaders>
        <shader>
            <file>/shader/std_lighting_detail.xml</file>
        </shader>
    </shaders>
    <materials>
        <material name="oldmetal">
            <texture>oldmetal</texture>
            <shader type="standard">std_lighting_detail</shader>
            <shadervar name="tex detail" type="texture">oldmetal</shadervar>
            <shadervar name="detail texture scale" type="vector2">10,10</shadervar>
        </material>
    </materials>
</world>

Ajouter un Son

Ajouter un son est, comme tout le reste dans Crystal Space, très simple. Cela devrait donner quelque chose comme çà :

<sounds>
    <sound name="tada.wav">
        <file>/lib/std/tada.wav</file>
    </sound>
</sounds>

Ajouter une Bibliothèque

Une autre manière de définir la plupart de ces choses est par l'utilisation de bibliothèques. Une bibliothèque est structurée d'une façon très proche d'un fichier World sauf qu'elle débute par <library> et se termine par </library>. Elle ne peut pas accepter d'emplacements de départ ni de secteurs. C'est une bonne manière de grouper certaine chose pour le chargement. En outre, en spécifiant des fabriques de mesh dans une bibliothèque, vous serez capable de les charger dans le Viewmesh. Pour inclure une bibliothèque dans un fichier World nous pouvons utiliser :

<library path="/lib/std" file="library" />

Ajouter des Plugins

Crystal Space est très modulaire. Ainsi le chargement d'une map est également modulaire. Ceci signifie que chaque objet de mesh possède son propre plugin qui est responsable de son chargement. Chaque plugin possède un nom spécifique. Vous pouvez spécifier ce nom complet chaque fois que nécessaire (par exemple, pour chaque objet de mesh). Mais il est souvent plus simple de spécifier des raccourcis pour chaque plugin dont vous avez besoin. Ceci peut être fait dans la section <plugins> :

<plugins>
    <plugin name="thing">crystalspace.mesh.loader.thing</plugin>
    <plugin name="thingFact">crystalspace.mesh.loader.factory.thing</plugin>
</plugins>

Les meshes de type Thing sont généralement des meshes en low-poly (peu de polygones) qui utilisent des surfaces avec des éclairages pré-calculés. Leur inconvénient est qu'ils sont moins efficaces qu'un Genmesh (mesh générique).

Modifier des Paramètres

Les paramètres sont là pour se substituer à certains paramètres par défaut du moteur tels que la lumière ambiante et la taille de la lightmap que vous pouvez lire dans la documentation.

Ajouter des Fabriques

Le scénario Fabriques/Objet de mesh est très important si vous souhaitez répéter de nombreuses fois un mesh. Mais ce n'est pas nécessaire si vous n'avez qu'une instance d'un mesh. Dans ce document, je profiterai de la configuration des Fabriques/Objet de mesh pour mieux familiariser l'utilisateur avec çà.

Dans une fabrique, nous disons au moteur quelle fabrique doit être appelée (son nom), le plugin à utiliser pour la charger, les informations de géométrie et bien sur le matériau utilisé sur le mesh. Avec un mesh Thing, nous pouvons avoir de matériaux multiples basés sur les polygones sur lesquels vous les avez assignés. Cette fabrique est issue de la petite map du tutoriel de la documentation. C'est un simple cube avec un seul matériau :

<meshfact name="walls">
    <plugin>thingFact</plugin>
    <zfill />
    <params>
        <v x="-10" y="-1" z="10"/> <v x="10" y="-1" z="10"/>
        <v x="-10" y="-1" z="-10"/> <v x="10" y="-1" z="-10"/>
        <v x="-10" y="4" z="10"/> <v x="10" y="4" z="10"/>
        <v x="-10" y="4" z="-10"/> <v x="10" y="4" z="-10"/>
        <material>old_metal</material>
        <texlen>4</texlen>
        <p name="up">
            <v>6</v> <v>7</v> <v>5</v> <v>4</v>
        </p>
        <p name="down">
            <v>3</v> <v>2</v> <v>0</v> <v>1</v>
        </p>
        <p name="back">
            <v>7</v> <v>6</v> <v>2</v> <v>3</v>
        </p>
        <p name="front">
            <v>4</v> <v>5</v> <v>1</v> <v>0</v>
        </p>
        <p name="left">
            <v>6</v> <v>4</v> <v>0</v> <v>2</v>
        </p>
        <p name="right">
            <v>5</v> <v>7</v> <v>3</v> <v>1</v>
        </p>
    </params>
</meshfact>

La première ligne initialise et nomme la fabrique de mesh. La deuxième dit au chargeur quel plugin est utilisé (dans ce cas, une fabrique de Thing parce que nous définissons la géométrie). <zfill /> est utilisé de sorte que la carte ignore le Z-buffer et trace la valeur Z des polygones Thing par dessus les anciennes valeurs Z présentes sur l'écran. Ceci est utilisé par les murs les plus éloignés parce que c'est un mode plus rapide que <zuse/> vu qu'il n'a pas besoin de lire le Z-buffer.Ce sera la première chose à afficher dans un rendu de type arrière vers avant. Chaque chose à l'intérieur du bloc <params> est spécifique au mesh Thing (manipulé par le plugin chargeur de fabrique de Thing). Les autres meshes auront d'autres instructions ici. Le prochain bloc défini actuellement la position des sommets. Cette boite est faite à partir de 8 sommets. Ensuite nous appliquons le matériau. Nous spécifions celui que nous avons créé plus tôt (oldmetal). Maintenant nous définissons <texlen> à 4 dans le sens où pour chaque 4x4 unités du monde, on carrelera la texture. C'est un raccourci pour faciliter le mappage de texture. Pour les modèles réels, vous voudrez probablement spécifier directement les coordonnées UV. C'est fait plus facilement avec un éditeur de map comme Blender. Ensuite, nous définissons des polygones en spécifiant les sommets qui le composent, mais souvenez-vous que le numéro des sommets débutent à 0. Ces polygones peuvent avoir des noms, ce qui est très utile pour débugguer.

Et cela conclut la partie initialisation du fichier World. Dans le reste du tutoriel, je vous expliquerai comment utiliser cela pour créer un secteur dans un monde qui peut être chargé par le Walktest.

Créer une Salle

Mise en route

Maintenant, il est temps d'utiliser ces ressources qui sont chargées et de créer un simple pièce utilisable par le Walktest. Normalement, la section définition devrait probablement être la plus grande partie du fichier World, heureusement nous avons une faible quantité d'objets. Pour débuter, nous avons besoin d'une position de génération que nous spécifions comme ceci :

<start>
    <sector>room</sector>
    <position x="0" y="0" z="0" />
</start>

room sera éventuellement notre nom de secteur. 0,0,0 seront les coordonnées de ce secteur dans lesquelles nous génèrerons (Crystal Space n'y fait pour l'instant pas attention, c'est une façon très spécifique de manipuler les points de départ. Vous pouvez avoir de multiple positions de départ et avoir des personnages générés à différentes emplacements). Maintenant nous allons créer et nommer nos secteurs comme ceci :

Création d'un Secteur

<sector name="room">
</sector>

Ajout de notre Objet Mesh

Nous avons maintenant un secteur appelé room, que nous pouvons remplir de ce que l'on veut. Nous commencerons par ajouter un Objet mesh appelé walls que nous allons créer à partir de la fabrique du même nom, créée plus tôt.

<sector name="room">
    <meshobj name="walls">
        <plugin>thing</plugin>
        <params>
            <factory>walls</factory>
        </params>
    </meshobj>
</sector>

La deuxième ligne se réfère encore au chargeur de plugin, ne pas le confondre avec le plugin thingFact d'une fabrique de Thing. Si vous regardez à la section plugin, nous en avons initialisés deux : le chargeur de mesh et de fabrique. Le bloc <params> n'a uniquement besoin que d'une référence à notre fabrique. Si je n'ai pas utilisé de fabrique, ce serait cette section où je placerai l'information sur les sommets et les polygones, suivi des matériaux. Au final, nous terminons notre section Objet mesh et nous en avons fini avec cette partie.

Ajouter une Lumière

A partir d'ici, si nous chargeons le fichier World comme çà dans le Walktest, cela fonctionnera mais vous pourrez rien voir. Pourquoi, me demandez-vous ? Il n'y a pas de lumières. Pour ajouter une lumière, nous ajoutons les lignes suivantes :

<sector name="room">
    <meshobj name="walls">
        <plugin>thing</plugin>
        <params>
            <factory>walls</factory>
        </params>
    </meshobj>
    <light name="light1">
        <center x="0" y="0" z="0" />
        <radius>20</radius>
        <color red="2" green="2" blue="2" />
    </light>
</sector>

Nous pourrons voir avec çà : son nom : light1 et elle sera créée où nous générons (au point 0,0,0 dans le secteur room). Nous avons défini le rayon à 20. Cela ne signifie pas que tout sera éclairé. Cela signifie seulement que la lumière ne faiblira pas dès son point d'émission. Les valeurs de luminosité fonctionne sur un pourcentage de couleurs, r1g1b1 (100% Rouge, 100% Vert, 100% Bleu) sera blanc, mais les nombres plus grands auront une intensité supérieure, signifiant que la notre sera 2x plus lumineuse qu'une lumière en r1g1b1.

Charger votre niveau dans le Walktest

Le niveau est maintenant prêt (et la syntaxe judicieuse) pour le Walktest. Pour le lancer, vous devez spécifier au Walktest le dossier où se trouve le fichier World :

walktest /repertoire_de_world -relight

Si vous avez mis le fichier World dans le dossier courant, vous pouvez également faire :

walktest /this -relight

La raison pour laquelle les deux fonctionnent, est que le Walktest accepte le chemin VFS (le /this ci-dessus) autant que le chemin standard (le /repertoire_de_world. Le chemin VFS /this est très utile pour le débuggage (mais devrait autrement être évité) et se réfère au répertoire courant.

L'option de ligne de commande -relight est uniquement nécessaire la première fois, dans le cas où vous utilisez des mesh Thing qui requiert des illuminations statiques précalculées. Il calculera donc les illuminations. La prochaine fois que vous lancerez la map, vous n'aurez pas besoin d'ajouter cette option tant que vous ne la modifierez pas (déplacer ou ajouter une lumière, ou encore modifier une géométrie).

Secteur et Portails

Il semble que les autres articles ont omis de parler des secteurs et des portails, nous décidons donc d'ajouter un autre secteur à ce tutoriel.

Dupliquer votre secteur actuel et renommez le de cette façon :

<sector name="room2">
    <meshobj name="walls">
        <plugin>thing</plugin>
        <params>
            <factory>walls</factory>
        </params>
    </meshobj>
    <light name="light1">
        <center x="0" y="0" z="0" />
        <radius>20</radius>
        <color red="2" green="2" blue="2" />
        <dynamic />
    </light>
</sector>

Dupliquer votre Secteur

Actuellement room2 et une copie de room. Ce que nous voulons est une autre pièce à coté de notre ancienne pièce. Pour ce faire, nous devons translater notre lumière et nos murs de 20 unités dans une direction. Nous choisissons la direction X positive. Pour ce faire, nous ajoutons une balise <move> à notre Objet mesh comme ceci :

<move>
    <v x="20" y="0" z="0" />
</move>

Dans le contexte de room2, ce sera :

<sector name="room2">
    <meshobj name="walls">
        <plugin>thing</plugin>
        <params>
            <factory>walls</factory>
        </params>
        <move>
            <v x="20" y="0" z="0" />
        </move>
    </meshobj>
    <light name="light1">
        <center x="20" y="0" z="0" />
        <radius>20</radius>
        <color red="2" green="2" blue="2" />
        <dynamic />
    </light>
</sector>

Noter que nous avons déplacé la lumière, nous avons maintenant 2 salles côte à côte. Malheureusement, elles ne sont pas connectées entre elles. Nous ne les avons pas séparées en secteurs indépendants, mais un passage réduit est une bonne opportunité de profiter des portails et des secteurs. Nous allons créer un portail flottant pour ne pas brouiller la géométrie en ajoutant un polygone dans une face. Normalement ajouter un polygone portail à un mesh serait une meilleure solution, de cette façon les portails s'aligneraient correctement avec les murs, mais ce portail est uniquement pour un exemple illustratif.

Portails

Pour débuter, nous placerons un portail de room vers room2. Ajouter ceci au secteur room (par exemple à droite de la lumière) :

<portals>
    <portal name="port1">
        <sector>room2</sector>
    </portal>
</portals>

Ceci créera un portail vers room2 mais ce n'est pas fini. Nous devons spécifier les dimensions du portail (un polygone) comme ceci :

<portals>
    <portal name="port1">
        <v x="9.7" y="1" z="1" />
        <v x="9.7" y="1" z="0" />
        <v x="9.7" y="-1" z="0" />
        <v x="9.7" y="-1" z="1" />
        <sector>room2</sector>
    </portal>
</portals>

Une fois encore, nous ne serons pas capable de voir le portail car nos priorité de rendu ne sont pas définies, signifiant que nos murs zfill ne savent pas qu'ils sont raccordés derrière notre portail. Pour notre cas spécial, nous avons besoin d'utiliser la priorité objet. Les objets avec la priorité objet sont rendus derrière ceux avec la priorité walls. Et le priorité de rendu par défaut pour les objets avec <zfill/> est walls.

<portals>
    <portal name="port1">
        <v x="9.7" y="1" z="1" />
        <v x="9.7" y="1" z="0" />
        <v x="9.7" y="-1" z="0" />
        <v x="9.7" y="-1" z="1" />
        <sector>room2</sector>
    </portal>
    <priority>object</priority>
</portals>

Finalement, nous serons capable de voir notre portail, malheureusement dû à la nature et à la position de notre portail, il nous téléportera à la même position dans le secteur voisin, nous avons besoin d'un peu d'espace de téléportation et voici comment nous allons faire :

<portals>
    <portal name="port1">
        <v x="9.7" y="1" z="1" />
        <v x="9.7" y="1" z="0" />
        <v x="9.7" y="-1" z="0" />
        <v x="9.7" y="-1" z="1" />
        <wv x="1" y="0" z="0" />
        <ww x="-1" y="0" z="0" />
        <sector>room2</sector>
        <float />
    </portal>
    <priority>object</priority>
</portals>

Nous devrons nous téléporter en utilisant des coordonnées négatives. Si vous souhaitez visualiser ceci, c'est comme si nous avons déplacé le monde d'une unité devant le joueur (à moins que bien sûr nous voulions faire pivoter notre espace, auquel cas nous aurions besoin d'une coordonnée <wv/> positive et une matrice rotation). La dernière chose nécessaire est la balise <float /> pour indiquer que c'est un portail flottant et non pas la frontière d'un secteur.

Nous en avons fini, vous devrez être capable de charger votre niveau (si vous avez été assidu) et de passer de la salle 1 à la salle 2 sans pouvoir le faire en sens inverse, je ne ferai pas la conception de ce deuxième portail.


Langage: EnglishBrazilianChineseEspañolEsperantoFrançaisMagyar
Make a translation

| Article | Discussion | View source | History |