J'étais en train de préparer le sample de mon prochain post sur ce blog (sur les progressive Mesh) lorsque je me suis rendu compte que je n'avais qu'un exemple à donner pour mettre en évidence le LOD (Level Of Detail).
J'ai donc cherché sur Internet des models 3D à incorporer rapidement dans mon programme. Je me suis tourné tout naturellement vers les programmes de MRM (MultiResolutionMesh) qui existent déjà et notamment vers celui de Stan Melax (www.melax.com) le grand nom du MRM. Il possède tout un tas de fichiers très interessants au format PLY. Fichtre ! Kesaco ?
En fait je m'en f...iche. Continuons. J'ouvre le fichier, il est aisément lisible : au format Txt il énumère dans un header le nombre de vertices, le nombre de faces, deux trois informations sans importances, puis contient toutes les positions des vertices du model et une énumération des indices des vertices de chaque face. Du genre :
ply
format ascii 1.0
element vertex 2903
property float32 x
property float32 y
property float32 z
element face 5804
property list uint8 int32 vertex_indices
end_header
0.605538 0.183122 -0.472278
0.649223 0.1297 -0.494875
0.601082 0.105512 -0.533343
[...]
3 0 1 2
3 1 3 4
3 5 6 2
3 6 7 8
3 7 9 10
[...]
Formidable.
J'utilisais à présent la même façon de procéder que Stan Melax et son programme en C : j'ai deux constantes qui sont deux tableaux à deux dimensions : le premier tableau donne pour chaque vertex les trois composantes X, Y et Z d'une position orthonormée 3D. Le second donne pour chaque face, les indices de chaque vertex qui la compose. Le truc bien lourd mais au combien rapide à faire :Pour prendre son modèle Rabbit, j'ai juste eu à faire un copié collé de son fichier .c (le C# n'est il pas le fils objet du C ? :) ). En gros pour expliquer en image, pour les vertices j'ai :
static float[,] rabbit_vertices = new float[RABBIT_VERTEX_NUM, 3]{
{-0.334392f,0.133007f,0.062259f},
{-0.350189f,0.150354f,-0.147769f},
{-0.234201f,0.343811f,-0.174307f},
{-0.200259f,0.285207f,0.093749f},
et pour les faces j'ai :
static int[,] rabbit_triangles = new int[RABBIT_TRIANGLE_NUM, 3]{
{126,134,133},
{342,138,134},
{133,134,138},
{126,342,134},
Je voulais donc opérer de même pour les autres modèles à ajouter à mon sample. Sauf que là : pas de fichier .c, mais .PLY. Bon ok je reviens, vais regarder à quoi ca correspond.
Ok allez voir là si ca vous interesse : http://www.cc.gatech.edu/projects/large_models/ply.html.
Donc je me vois face à trois solutions :
- A.J'abandonne ou je cherche ailleur.
- B.J'essaye, vertex par vertex, face par face, de réécrire les tableaux de vertices et de faces (au bas mot une semaine de travail par modèle).
- C.J'utilise les regular expression à l'aide de la Find and Replace dialog box de VS.
- D.La réponse D.
Evidemment, si vous avez lu le titre de ce post, vous aurez compris que je choisi la réponse C Jean Pierre. Je suis un grand fana des REGEXP depuis ma plus tendre... depuis que je développe en fait. J'ai débuté sous Linux (pas frapper svp) et j'ai donc rapidement aimé ce style de développement simple (oui c simple à écrire, impossible à relire certes..., mais simple à écrire) et efficace. Beaucoup de développeurs répugnent à utiliser les expressions régulières. Ils ont tord. Sous prétexte que le code est difficilement lisible ils préfèrent utiliser de longues suites de string.IndexOf, string.SubString etc. Rendant le code encore plus illsible et moins maintenable...
La je vais démontrer que je vais transformer un fichier Ply en deux tableaux à deux dimensions, de 5000 vertices et 10000 faces en moins de 20s chronos ! (faut imaginer le Valentin, seul dans son bureau le midi en train de se chronometrer a faire des Replaces ... ca vaut le détour)..
Voici le travail :
Secondes 1 à 3 :
Copié de la portion du fichier Ply consacrée aux vertices. 5000 lignes de :
[...]
0.605538 0.183122 -0.472278
0.649223 0.1297 -0.494875
0.601082 0.105512 -0.533343
[...]
Chaque ligne contient trois nombres correspondants a X, Y Z.
Secondes 4 à 10 :
Alt Tab pour revenir sur VS (un fichier txt vide m'attend).
Collé de la portion préalablement copiée.
Ctrl + H pour la Find and Replace dialog box de VS.
Je coche "Use Regular Expression".
Tout d'abord je supprime les espaces de fin de ligne :
Fin What=([ \t]*$)
Replace With=<Vide>
(Fin What et Replace With correspondent aux deux texbox de la dialog box)
En suite j'ajoute à chaque fin de ligne la string "f},". f pour que les nombres soient lus en flottants.
Fin What=$
Replace With=f\},
Je remplace ensuite le espaces entre chaque chiffres de chaque lignes (deux espaces par lignes restant donc) par la string "f, ".
Fin What=
Replace With=f,
Enfin, je fais débuter chaque ligne par une accolade.
Fin What=^
Replace With=\{
Terminé. La portion de fichier que j'ai donné un peu plus haut devient :
{0.605538f, 0.183122f, -0.472278f},
{0.649223f, 0.1297f, -0.494875f},
{0.601082f, 0.105512f, -0.533343f},
Je réitère l'opération pour le tableau de face (pareil sans avoir a mettre de f après chaque nombre). 10 * 2 = 20s. En une minute je créé 3 à 4 modèles 3D de plusieurs milliers de lignes de code.
L'image suivante explicite cela plus en détails.

La il s'agit juste d'une exemple assez trivial. Le replace à l'aide de regexp est réèllement puissant dans la vie du développeur et fait gagner enormément de temps. Surtout quand on arrive à maitriser le remplacement de portions de texte. Ne gardez pas cette merveilleuse technologie uniquement à l'intérieur de votre code.
Allez je retourne à mon sample MRM.
Notes :
Qqs liens interessants pour les régulars expressions :
Jettez un oeil à ce site d'ailleur :
Bonne lecture.