[TUTO] L'optimisation (version 1)

Ce forum regroupe tous les tutoriaux réalisés par des membres de Mapping-Area pour Half-Life 2.

Modérateurs: Co-Admin, Modérateur, Staff

[TUTO] L'optimisation (version 1)

Messagede NykO18 le 01 Mar 2005, 04:43

Information: La version 2 se trouve ici :
http://nyko18.free.fr/temp/tuto_opti/
C'est la même, mais en mieux et avec 50 pages de plus.





Optimisation des cartes HL²

Après de nombreuses réactions de gens se plaignant de la très importante durée nécessaire à la compilation de leur carte, et surtout la lourdeur et l'impossibilité de jouer à beaucoup de cartes sans ramer, j'ai décidé de faire un petit tutorial sur l'optimisation des cartes HL².

Pour illustrer mes propos, j'ai décidé de prendre une de mes cartes que j'ai tenté d'optimiser le plus possible.
Je tient tout de suite à vous prévenir : je ne me vante absolument pas de connaître tout sur l'optimisation, je tient seulement à partager ce que je sais dans ce domaine.

Le tutorial est aussi disponible sur mon site à cette adresse :
http://nyko18.free.fr/0nline/?p=critiques&id=Optimisation_Half-Life_2~Jeu

Index

1. La texture Nodraw
2. Les func_detail
3. Les Props
4. Les func_lod
5. Les Occluders
6. La lumière
7. Conclusion

1. La texture Nodraw

Le premier conseil que je tiendrais à donner à n'importe qui qui fait des cartes est le plus simple : Toujours utiliser la texture tools/toolsnodraw lors de la création d'un objet. Toujours, toujours !
Cette texture spéciale permet de ne pas tenir compte lors de la compilation des faces sur lesquelles elle est appliquée.

Pourquoi faire ? Simplement parce que lorsque vous créez une salle par exemple la plupart des faces n'ont absolument pas besoin d'être affichées et calculées. Prenons un exemple simple, une salle cubique avec 4 colonnes. Commençons par faire une salle, un pavé sur lequel on va appliquer l'outil Hollow.

Voici ce que l'on obtient :

Image

Comme vous pouvez le voir, il y a un problème. (ah bon, vous ne le voyez pas ?)
Si jamais vous n'utilisez pas la texture "nodraw" il va y avoir des faces dessinées pour rien. Regardez, vous allez voir que toutes les faces colorées en rouge/orange n'ont aucun besoin d'être dessinées :

Image

Elles n'ont pas besoin d'être calculées soit parce qu'elles sont cachées darrière un autre bloc comme le plafond pour les faces du dessus ou un autre mur pour celles sur les tranches, mais aussi parce qu'on ne pourra pas voir cette salle de l'extérieur, donc pas besoin de dessiner les faces sur l'extérieur.

Voici ce qui est beaucoup plus correct :

Image

Ca ne semble pas grand chose, mais l'on économise tout de même beaucoup de faces par cette méthode. Au lieu de 36 faces, le moteur n'en calcule plus que 6, les 6 que le joueur voit, les 4 murs, le sol et le plafond.
Toujours pas convaincu(e) ? Alors regardez ce qui se passe lorsque je selectionne toutes les faces ayant la texture nodraw sur ma carte :

Image

Ca vous parrait toujours aussi peu ? Sachant qu'il y a 18346 faces au total sur cette carte, on économise au moteur du jeu le calcul de 41% de ces faces, ce qui est énorme ! Il y a comme ca beaucoup de faces qu'il n'est pas necessaire de calculer, voyez cette dernière image :

Image

Le dessus et le dessous des murs et des colonnes étant collés au sol et au plafond, il n'est pas necessaire non plus de les faire calculer par le moteur. Voici ce que je pouvais dire sur la texture nodraw, très très importante dans le mapping HL².


2. Les func_detail

Un autre fondement de l'optimisation des maps est l'entité func_detail !
Tous les morceaux d'architecture complexes ou pas, que vous considérez comme des détails DOIVENT être tranformés en func_detail. Les colonnes, les fenêtres, les rebords, les cloisons, les poutres, .. tout ce qui est détail.
Reprenons notre petite carte pour voir ce qu'il se passe lorsque l'on arrive dans le jeu. Voici ce que font les colonnes sur nos pauvres plafond et sol :

Image

Comme vous pouvez le constater, il y a énormément de faces créées automatiquement autour de ces cylindres. Je ne vous exliquerai pas pourquoi -- ca prendrait un certain temps -- mais il faut savoir que n'importe quel volume qui touche une surface du même genre génère autant de faces que d'arrêtes touchant la surface. Le cylindre est donc le pire des cas.

Pour éviter ce genre de désagréments, transformez tout cela en func_detail et voici le résultat obtenu en tranformant les colonnes :

Image

Pour plus de commodité, je vous conseille de régler, dans les options de Hammer, l'entité bloc par défaut sur func_detail. (Tools > Options > Default SolidEntity Class) Ainsi vous n'aurez qu'a faire CTRL+T ou "Tie To Entity" en selectionnant vos objets pour les tranformer en func_detail.
Pour repérer ces endroits anormaux où trop de faces apparaissent, activez la console de HL² et tapez y "mat_wireframe 3".

Alucard_DH a écrit:Un autre précision,
Il y a 4 modes d'affichage pour le mode Wireframe (commande mat_wireframe x)

mat_wireframe 0 : jeu normal sans fil de fer
mat_wireframe 1 : affiche la découpe des tous les polygones en polygone triangulaire (la est le piege, c'est n'est pas cette decoupe la qu'il faut prend en compte pour le calcul des poly, la jeu pouavant afficher des poly carré ), de plus affiche les blocs cachés calculés par transparence : bien pour voir ce que le vis calcule
mat_wireframe 2 : meme que le 2 mais sans transparence : aucun interet Moqueur
mat_wireframe 3 : affiche la vraie découpe des polygones (voir ou il faut utiliser des func_details, brush lod et wall)


Gardez en mémoire également qu'il ne faut pas trop abuser des func_detail, l'optimisation a ses limites et un abus de func_detail peut entraîner une détérioration drastique des performances. Regardez les cartes fournies avec le SDK pour savoir à peu près combien et où en utiliser.


3. Les Props

Depuis Half-Life 1, les petits objets comme les plus gros qui sont considérés comme plus détaillés sur la normale ne sont plus composés de brushes (blocs dans Hammer : cubes, cylindres, etc.) Ce sont maintenant des modèles 3D créés depuis un autre logiciel tel que XSI|Mod Tool, 3DSMax ou encore Maya.. Comme indiqué sur le site VERC Collective, les Props devraient être utilisés pour les objets suivants :

    * Les petits objets du monde (cannettes, meubles, ordinateurs, portes, etc.).
    * Les gros objets qui demandent un haut niveau de détail [...].
    * Tout ce qui necessite d'être déplacé ou soumis aux lois de la physique. (ramassés, lancés, cognés, etc).
    * Tout ce qui est "verdure" (herbe, plantes, etc.).
    * Les objets qui vont apparaître de nombreuses fois dans le niveau.

Bien que tous ces objets nécessitent beaucoup moins de ressources que le reste des objets en brushes, il faut tout de même faire attention à ne pas dépasser certaines limites. On peut trouver sur les pages du VERC Collective de Valve les limites suivantes a respecter pour garder de bonnes performances :

    * prop_detail : Des dizaines de milliers
    * prop_static : Des milliers
    * prop_dynamic : Des centaines
    * prop_physics : Des dizaines à des centaines
    * prop_ragdoll : Moins de 10

Néanmoins, il y a des moyens d'augmenter ces limites, ou, tout du moins, en mettre plus que la normale sans faire ramer plus.
Prenons pour cette partie une de mes cartes. Elle se déroule dans un bâtiment, mon IUT, et est composée de couloirs et de salles.
Prenons pour exemple une des salles de classe et plus particulièrement, les néons au plafond :

Image

Ces néons au plafond sont fixes, ils ne peuvent pas tomber ni sortir de cette salle. Lorsque vous vous trouvez dans la salle d'a côté ou dans le couloir, il n'est absolument pas nécessaire de les afficher. Or, à cause des quelques ratés de VIS lors de son calcul de visibilité, cela peut très bien arriver..
C'est pour cela qu'il existe d'autres méthodes dont la suivante. La salle mesure environ 280x280 et est entourée de murs et de portes donnant sur un couloir. Or, du couloir on a pas besoin de voir les néons qui se trouvent dans cette salle, à part devant les portes.

La distance maximale à laquelle on peut voir les néons du fond (fléchés) c'est le bord du couloir (fléché aussi). La distance séparant ces deux points est 340. On va alors régler plusieurs choses dans les propriétés du prop_static.

    * Premièrement, si vous vous fichez qu'en tirant sur ces néons ca fasse un bruit de verre, mettez collision sur "Not Solid", ça sera ça de moins à gérer pour le moteur physique.
    * Deuxièmement, mettez "Disable Shadows" sur Yes parce qu'il n'est pas necessaire de faire apparaître des ombres sur une lumière..
    * Ensuite, on va régler "Start Fade Dist/Pixels" sur la distance maximale à laquelle on peut le voir, donc 340. Ce qui signifie qu'a partir de 340 pixels, le néon va commencer à disparaître.
    * Obligatoirement, il faudra ensuite entrer une autre valeur dans "End Fade Dist/Pixels", une valeur plus élevée. Elle correspondra à la distance à partir de laquel le néon aura totalement disparu. Entre les deux distances, le néon disparaîtra au fur et à mesure. J'ai par habitude de le régler sur environ 256 de plus que le "Start Fade Dist/Pixels" pour que la disparition ne soit pas trop violente AU CAS OU on arrive à voir le model quand même. Donc au final, environ 600.


Cette méthode est assez efficace mais il en existe d'autres. Retenez juste que tout prop ne pouvant pas être atteint devrait être Non-Solide et tout prop ne se déplaçant pas devrait disparaître quand on ne le vois plus. Dans le même genre, les petits objets comme les papiers, canettes, bouteilles, etc.. devraient disparaître assez rapidement, comme à 512 pixels et il n'est pas souvent necessaire de leur faire projetter des ombres.


4. Les func_lod

Dans la même lignée de les props, il y a également les func_lod.
En gros, c'est le même système de disparition au bout d'une certaine distance, mais appliqué aux brushes ce coup-ci. C'est à dire à n'importe quel bloc d'architecture de Hammer.

Un comptoir, un escalier intérieur ou autre mobilier créé à partir de brushes est un bon candidat pour devenir un func_lod. J'ai par exemple décidé de faire disparaitre les murs intérieurs d'un bâtiment ainsi que les bordures de fenêtres lorsque l'on est assez loin de celui-ci.
Pensez-y, cela peut-être très salvateur.

Gardez en mémoire également que, tout comme les func_detail, il ne faut pas trop abuser des func_lod. L'optimisation a ses limites et un abus de func_lod peut entraîner une détérioration drastique des performances. Regardez les cartes fournies avec le SDK pour savoir à peu près combien et où en utiliser.


5. Les Occluders

Directement en relation avec les props, voici venir les occluders.
Les occluders sont des blocs qui permettent de controler la visibilité derrière eux. Ils ne jouent que sur l'apparition et la disparition des Props (models), ne peuvent pas se situer en dehors du monde mais peuvent être activés ou désactivés durant une partie.

Les func_occluders sont créés avec un brush de type "block". Il doivent avoir la texture tools\toolsoccluder sur les faces qui doivent cacher les props et la texture tools\toolsnodraw sur celles qui n'ont aucun effet. Si des blocs possèdent cette texture sans être des func_occluder, cela dégradera les performances.

Note: Trop d'occluders tue les occluders. Chaque occluder doit être placé de façon à cacher suffisemment de géométrie. S'il s'avère qu'ils empêchent un grand nombre de props d'être affichés, alors ils améliorent les performances. Sinon, il peuvent s'avérer plus gourmants en ressources que d'afficher tout simplement les props. Pour le savoir, affichez les FPS depuis la console (cl_showfps 2) et comparez la vitesse d'affichage avant et après avoir tapé "r_occlusion 0" dans la console. Ceci désactive les occluders. (tapez "r_occlusion 1" pour réactiver)

Image

Ici, les occluders permettent de cacher tout le mobilier de la classe située derrière les portes. Lorsque les portes s'ouvrent, l'occluder est désactivé (par un output de la porte OnOpen > mon_occluder > Disabled) et réactivé lorsque la porte se referme. (OnFullyClosed > mon_occluder > Enabled)

Voir la map maps\sdk_occluder.vmf pour un exemple.

6. La lumière

Tiré directement du site officiel :

Le moteur Source utilise des données de "lightmap" pour simuler la lumière et les ombres sur les brushes. L'augmentation de ce "lightmap" procure des ombres plus fines, mais demande plus de mémoire. La densité et qualité du "lightmap" peut être altérée pour améliorer les performances.

Ces réglages se font depuis l'outil "Texture Application". La taille du "lightmap" est mesurée en luxels par unités. Les valeurs plus faibles équivalent à des résolutions plus élevées. L'échelle par défaut est de 16 luxels par unité. Une plus grande résolution du "lightmap" augmente le temps que RAD prend pour compiler le niveau. Vous pouvez diminuer ce temps en diminuant la demande en mémoire de la lumière. Il suffit de diminuer la résolution du "lightmap" sur les faces qui n'ont pas besoin d'un grand niveau de détail au niveau des ombres. Les bons candidats à des grandes échelles du "lightmap" sont les surfaces complètement dans l'ombre, complètement illuminées ou loin de tout endroit où le joueur peut se rendre.

Image

Pour avoir un aperçu du "lightmap" de votre carte, réglez le type de vue 3D sur "3D Lightmap Grid".
Voir la map maps\sdk_lightmaps.vmf pour des exemples de "lightmap".


7. Conclusion

En conclusion, apprennez ce tuto par coeur et appliquez-le tout de suite !
Par expérience, il est très désagréable de devoir faire l'optimisation à la fin de sa map. Il faut alors chercher toutes les faces à ne pas dessiner pour leur mettre la texture nodraw, régler tous les props un par un pour contrôler leur visibilité et changer le "lightmap" sur chaque face.. tandis que si vous le faites pendant la création, cela sera beaucoup moins contraignant.
Il existe d'autres méthodes d'optimisation comme les hints et les func_areaportals mais je n'y connais pas encore grand chose. Si quelqu'un souhaite s'y mettre clairement avec des exemples, il est le bienvenu :)




Sur ce, j'espère vous avoir un peu aidé pour l'optimisation de vos maps,
bon mapping à vous tous et n'hesitez pas à me donner toutes vos techniques pour que j'apprenne et ajoute :D !







Historique:
01/03/05:
- Ajout des func_lod
Dernière édition par NykO18 le 15 Aoû 2005, 22:10, édité 7 fois.
Avatar de l’utilisateur
NykO18
VIP
VIP
 
Messages: 8253
Inscription: 19 Jan 2005, 22:16
Localisation: Cergy, France

Messagede azura_404 le 01 Mar 2005, 08:51

Merci, c'est un bon Tuto qui je pense pourrait être mis en ligne sur le site !!! Continu bien toi aussi ! @+++ :gg (en tout cas moi ça m'aide).
Je me nomme sans nom...

Image
http://www.eastwestmod.com
Avatar de l’utilisateur
azura_404
Concepteur
 
Messages: 688
Inscription: 30 Jan 2005, 18:09

Messagede Thos le 01 Mar 2005, 19:08

Merci , je sens que ça va me servir :)
C'est très bien écrit et très clair :gg
Thos
Clandestin
 
Messages: 6
Inscription: 01 Mar 2005, 01:38
Localisation: Ath

Messagede KMi le 01 Mar 2005, 19:38

Lol bon tuto :D

Surtout pour les prop ( je savais pas tout sa )


Ps : tu parles d'opti mais sur ton premier montage, c'est pas super opti la maniere dont ta place tes brush :P
fini !
Avatar de l’utilisateur
KMi
VIP
VIP
 
Messages: 3295
Inscription: 06 Juil 2004, 23:55
Localisation: Belgique : Genval

Messagede moroes le 01 Mar 2005, 19:47

:gg impek ! Un grand merci!
Level Designer @ Ubisoft Paris
My LinkedIn ProfileMy portfolioI hate mountains - L4D
Avatar de l’utilisateur
moroes
VIP
VIP
 
Messages: 4754
Inscription: 26 Aoû 2003, 14:58
Localisation: Paris

Messagede NykO18 le 01 Mar 2005, 19:53

De rien les gens.
Ps : tu parles d'opti mais sur ton premier montage, c'est pas super opti la maniere dont ta place tes brush

Pourquoi est-ce que ce n'est pas optimisé de les placer ainsi ?
Explique ! :D
Avatar de l’utilisateur
NykO18
VIP
VIP
 
Messages: 8253
Inscription: 19 Jan 2005, 22:16
Localisation: Cergy, France

Messagede Neernitt le 01 Mar 2005, 21:03

Cool ce tuto, j'ai pas eu le temps de le lire, mais il à l'air vraiment intéréssent, surtout que l'optimisation des maps est une chose trés importante.
Narf !
Avatar de l’utilisateur
Neernitt
Half-Mapsteur
 
Messages: 2141
Inscription: 05 Jan 2005, 18:17
Localisation: o=[=====-

Messagede Neernitt le 01 Mar 2005, 21:51

C'est bon j'ai lu, et.......... c'est intéréssent.
Ce qui va me servire beaucoup et dont je ne connaissait pas l'éxistance sont les Les func_lod. :D
Narf !
Avatar de l’utilisateur
Neernitt
Half-Mapsteur
 
Messages: 2141
Inscription: 05 Jan 2005, 18:17
Localisation: o=[=====-

Messagede lebouzil le 01 Mar 2005, 21:54

Wahou ca en jette NykO18 !
J'ai appris pas mal de trucs interessants comme les func_lod et les occluders ! Merci bien à toi.
Mais il faudrai vraiment rajouter un chapitre sur le fonctionnement de Vis ! C'est quand meme lui le principal acteur dans l'optimisation... Il peut tres bien servir à rien, mais, bien utilisé il peut optimiser un map à lui tout seul...
Malheuresement je ne connais que lopti de vis sous HL1. Celle sous HL² ressemble mais à lair plus évolué quand meme...
Avatar de l’utilisateur
lebouzil
VIP
VIP
 
Messages: 1139
Inscription: 02 Nov 2003, 16:18
Localisation: Ici ou là

Messagede KMi le 01 Mar 2005, 22:06

NykO18 a écrit:De rien les gens.
Ps : tu parles d'opti mais sur ton premier montage, c'est pas super opti la maniere dont ta place tes brush

Pourquoi est-ce que ce n'est pas optimisé de les placer ainsi ?
Explique ! :D


lol je te montre, voila deux screen :)

Sa genere moins de decoupe :)
Fichiers joints
opti1.JPG
opti1.JPG (125.52 Ko) Vu 4085 fois
opti.JPG
opti.JPG (159.72 Ko) Vu 4088 fois
fini !
Avatar de l’utilisateur
KMi
VIP
VIP
 
Messages: 3295
Inscription: 06 Juil 2004, 23:55
Localisation: Belgique : Genval

Messagede Alucard_DH le 01 Mar 2005, 22:09

Je ne suis pas vraiment d'accord pour l'utilisation des func_details :read

Tu dits de généraliser l'utilisation du func_details pour tous les blocs complexes mais apparement tu ne sais pas comment fonctionne le vis :read

J'explique :
le vis précalcule ce que le jeu va ensuite afficher, le calcul est fait par "pièce" et la jeu affiche les blocs de la façon suivante :
- pour les blocs standards (les brushs non entités) : le jeu calcul la piece en cours et les pieces adjacentes à 1 peice de distance (soit juste les pieces voisines)
- tandis que pour les blocs entités (dont les func_details justment), le jeu affiche ceux de la piece en cours, ceux des pieces voisines, plus ceux des pieces voisines aux pieces voisines (soit 2 pieces plus loin) ce qui entrainne l'affichage de blocs completement invisibles au yeux du joueur, l'utilisation abusive des blocs entités entrainnera donc une augmentation du nombre de poly plutot qu'une diminution

Enfin j'ajouterai que tu dits d'utiliser les func_details mais ils ont plusieurs inconvennients : ils disparaissent à une certaine distance ce qui ne fait pas trop réaliste, à n'utiliser donc que pour des petits objets (d'où le nom detail)
Je recommende plutot l'utilisation des entités func_brush et func_wall à la place

Enfin une autre méthode qui évite l'utilisation d'entité et donc l'affichage de blocs invisibles (methode qui aurait été plus adéquate a ton exemple des colonnes) : surélévé la base de la colone (ou de tout autre objet) à 1 unité du sol, le décalage sera invisible et le sol ne sera pas découpé :lu
Avatar de l’utilisateur
Alucard_DH
VIP
VIP
 
Messages: 4730
Inscription: 12 Aoû 2003, 02:11
Localisation: Lille (59) / Lannion (22)

Messagede Neernitt le 01 Mar 2005, 22:32

Alucard_DH a écrit:Enfin j'ajouterai que tu dits d'utiliser les func_details mais ils ont plusieurs inconvennients : ils disparaissent à une certaine distance ce qui ne fait pas trop réaliste, à n'utiliser donc que pour des petits objets (d'où le nom detail)

Regarde les maps du sdk, celle ou il y a un batiment rouge, je sais plus le nom, le batiment entier est en détail, et il est assé grand, on peux aller dedans et le voir de loin, de meme de nombreux batiments sont en détails.
Narf !
Avatar de l’utilisateur
Neernitt
Half-Mapsteur
 
Messages: 2141
Inscription: 05 Jan 2005, 18:17
Localisation: o=[=====-

Messagede Pipolipo le 01 Mar 2005, 22:36

Hum dans la famille prise de tête de je voudrais hammer :oops:
Avatar de l’utilisateur
Pipolipo
Mapophile
 
Messages: 167
Inscription: 08 Fév 2005, 05:30
Localisation: Aisne

Messagede Seb le 01 Mar 2005, 22:38

Post-It gagné :P
Avatar de l’utilisateur
Seb
Administrateur
Administrateur
 
Messages: 3370
Inscription: 07 Aoû 2003, 18:08
Localisation: Bordeaux

Messagede NykO18 le 01 Mar 2005, 22:52

Je ne suis pas totalement d'accord non plus sur certains points avec toi Alucard.
Alucard_DH a écrit:Tu dits de généraliser l'utilisation du func_details pour tous les blocs complexes mais apparement tu ne sais pas comment fonctionne le vis :read

Je sais comment fonctionne le VIS, merci de t'inquiéter pour moi :D

Alucard_DH a écrit:Enfin j'ajouterai que tu dits d'utiliser les func_details mais ils ont plusieurs inconvennients : ils disparaissent à une certaine distance ce qui ne fait pas trop réaliste, à n'utiliser donc que pour des petits objets (d'où le nom detail)

Et la tu te trompe, ils ne disparaissent pas. Ou alors vraiment très loin car j'ai tout un monument en func_detail et même à 4096 de distance on le voit encore. Ce sont les func_lod qui disparaissent.

Alucard_DH a écrit:tandis que pour les blocs entités (dont les func_details justment), le jeu affiche ceux de la piece en cours, ceux des pieces voisines, plus ceux des pieces voisines aux pieces voisines (soit 2 pieces plus loin) ce qui entrainne l'affichage de blocs completement invisibles au yeux du joueur, l'utilisation abusive des blocs entités entrainnera donc une augmentation du nombre de poly plutot qu'une diminution

Ceci ne marche malheureusement que pour les maps composées de réseaux de pièces fermées hermetiquement.. car dans le cas d'une map en extérieur ou avec des passages en extérieur -- celles qui ont le plus besoin d'être optimisées -- on ne peut pas dire que le VIS fasse des miracles. Et dès lors, peut importe ou se trouvent les func_detail, ils sont de toute façon affichés..

Alucard_DH a écrit:Enfin une autre méthode qui évite l'utilisation d'entité et donc l'affichage de blocs invisibles (methode qui aurait été plus adéquate a ton exemple des colonnes) : surélévé la base de la colone (ou de tout autre objet) à 1 unité du sol, le décalage sera invisible et le sol ne sera pas découpé :lu

Méthode très très très pas recommandée. Notemment parce que les ombres vont devenir assez étranges dans la zone et aussi tout simplement parce que même si c'est qu'une unité ca se voit très bien..

Je rajouterai aussi que quand tu ouvres certaines maps solo de HL², il est assez surprenant de voir certains batiments entièrement en func_detail et de très nombreux blocs assez volumineux également..
Néanmoins, je prend en compte tes remarques, et je vais comparer les deux méthodes dès que j'aurais le temps, malheureusement, il ne sera pas toujours facile d'appliquer ta méthode magique du "surélevé de 1 unité" car dans le cas d'une bordure de trotoir, ca risque de faire très moche.

PS: Merci Trakiss :gg
Dernière édition par NykO18 le 01 Mar 2005, 23:06, édité 1 fois.
Avatar de l’utilisateur
NykO18
VIP
VIP
 
Messages: 8253
Inscription: 19 Jan 2005, 22:16
Localisation: Cergy, France

Suivante

Retourner vers Cours & astuces

Qui est en ligne

Utilisateurs parcourant ce forum: Aucun utilisateur enregistré et 1 invité