LDraw + Unity. Comment j'ai généré Lego

Tout à venir! Je m'appelle Grisha et je suis le fondateur de CGDevs. Les vacances approchent, quelqu'un a déjà habillé un sapin de Noël, mangé des mandarines et est pleinement chargé de l'ambiance du nouvel an. Mais aujourd'hui, ce n'est pas ça. Aujourd'hui, nous allons parler d'un merveilleux format appelé LDraw et du plugin pour Unity, que j'ai implémenté et téléchargé sur OpenSource. Un lien vers le projet et le code source de l'article, comme toujours, sont joints. Si vous aimez Lego autant que moi, bienvenue chez Cat.



Format LDraw

Commençons par ce qu'est LDraw? LDraw est un standard ouvert pour les programmes de CAO LEGO qui permet aux utilisateurs de créer des modèles et des scènes LEGO. En général, il existe différents programmes et plugins avec lesquels vous pouvez visualiser LDraw (par exemple, il existe un plugin pour Blender).

Le format lui-même est bien documenté, et nous parlerons de sa dernière version, ou plutôt de 1.0.2.

LDraw est un format texte dont les fichiers doivent être créés avec le codage UTF-8. Les fichiers pris en charge par le format doivent avoir l'extension ldr, dat ou mdp. Chaque ligne du fichier est une commande distincte responsable d'une fonction spécifique.

Un détail important du format est le système de coordonnées droitier (Y est dirigé vers le haut) - nous discuterons plus en détail plus tard dans le contexte de l'unité, ainsi que le fait que le format est récursif (la plupart des fichiers contiennent une indication d'autres fichiers).



Commandes LDraw

En général, ces informations peuvent être trouvées dans la documentation officielle , mais regardons un peu dans le contexte d'Unity. Au total, le format LDraw prend en charge 6 types de commandes.

0. Un commentaire ou une méta-commande sont des commandes spéciales que nous toucherons à peine dans le plugin. Exemple: 0 !META command additional parameters

1. Lien vers le fichier . En fait, l'équipe la plus difficile à intégrer et intéressante. Il ressemble à 1 colour xyzabcdefghi file , où les paramètres sont la matrice TRS (plus d'informations sur TRS peuvent être trouvées dans cet article ). Dans le cadre de l'unité sous la forme

 / adg 0 \ | beh 0 | | cfi 0 | \ xyz 1 / 

2. Ligne - non utilisée dans le cas d'Unity, il est nécessaire de souligner les bords avec une certaine couleur dans les systèmes de CAO.

3.4. Triangle et carré . Les commandes sont assez simples, mais il y a une nuance importante, car le format LDraw n'est pas conçu pour la modélisation 3D, le contournement des triangles et des carrés n'est pas normalisé. Ceci est important, car l'unité, en fonction de la traversée du triangle, détermine la direction de la normale calculée, ainsi que le côté du triangle qui est l'arrière et celui qui est l'avant (ce qui est également important pour le dessin et le refroidissement)

Exemple de commande:
Triangle - 3 colour x1 y1 z1 x2 y2 z2 x3 y3 z3
Carré - 4 colour x1 y1 z1 x2 y2 z2 x3 y3 z3 x4 y4 z4

5. Ligne facultative - également non utilisée.



Couleurs dans LDraw

Comme vous pouvez le voir dans la plupart des équipes chargées du rendu, la couleur vient immédiatement après le type de commande. Les couleurs sont bien documentées dans ces deux articles www.ldraw.org/article/299.html et www.ldraw.org/article/547.html , mais parlons des fonctionnalités que j'ai rencontrées lors de l'implémentation. Ici, il vaut la peine de parler un peu plus des formats et du format dit «Scope». Il existe 3 types de fichiers au format.

DAT - en fait, ce sont les éléments de base à partir desquels les pièces sont déjà assemblées, ou certaines pièces de base. Si vous ne rendez pas de détails individuels, la couleur qui y est indiquée n'est pas importante. Le plus souvent, il existe des couleurs standard de la norme officielle.

LDR est la chose la plus intéressante en termes de couleurs et où Scope joue un rôle. La règle est assez simple, même si le site décrit des langages complexes. Si vous vous référez à un autre à partir d'un ldr, ignorez la couleur spécifiée dans la racine.

Par exemple, une partie du fichier 30051-1 - X-wing Fighter - Mini.mpd (X-wing dans l'image ci-dessus):

Exemple
 1 71 -10 0 50 0 0 1 0 1 0 -1 0 0 60470a.dat 1 71 10 0 50 0 0 -1 0 1 0 1 0 0 60470a.dat 0 STEP 1 19 0 8 50 0 0 -1 0 1 0 1 0 0 4032b.dat 0 STEP 0 ROTSTEP 35 55 0 ABS 1 19 0 -16 0 0 0 -1 0 1 0 1 0 0 3623.dat 1 72 0 -16 50 0 0 -1 0 1 0 1 0 0 3022.dat 0 STEP 1 72 0 -8 -70 1 0 0 0 1 0 0 0 1 30051 - Nose.ldr 


Dans tous les fichiers dat, nous prenons en compte la couleur spécifiée et dans la commande 1 72 0 -8 -70 1 0 0 0 1 0 0 0 1 30051 - Nose.ldr - ignorez 72 et utilisons les valeurs du fichier 30051 - Nose.ldr .

MDP est un fichier modèle, le plus souvent il contient une description de plusieurs fichiers ldr. En termes de couleur, ce n'est pas non plus très important. La seule chose que nous prenons en compte lors de l'analyse est la méta-commande FILE .



Modèles dans LDraw

La meilleure partie du format LDraw est qu'il a beaucoup de fans parmi les fans de lego. De nombreux kits intéressants peuvent être trouvés sur le site officiel omr.ldraw.org , mais en plus de cela, beaucoup peuvent être trouvés sur des forums séparés.

Nous avons parlé du format, maintenant il est temps de parler un peu du plugin pour Unity.



Plugin pour Unity

Le plugin offre la possibilité de générer des modèles 3D basés sur des fichiers LDraw. Vous pouvez voir les résultats dans les photos de l'article. Important: si vous avez un appareil faible, il est préférable d'ouvrir uniquement les mini scènes dans le dossier Demo. Les modèles ne sont pas optimisés et génèrent toujours une face arrière.

Parlons maintenant un peu de la mise en œuvre. À l'heure actuelle, la plupart des éléments ci-dessus sont pris en charge.

L'une des caractéristiques peut-être les plus importantes est les différents systèmes de coordonnées. Le problème est que le format est un système de coordonnées droitier, tandis que Unity est un système de coordonnées gauche. Ce que cela signifie, en substance, que tous les virages et la matrice TRS ne fonctionneront pas correctement. Le Y négatif est facile à battre - nous reflétons toutes les coordonnées par rapport à Vector3.up et obtenons les nécessaires (multipliez par -1). Mais dans le cas de la matrice TRS, tout est plus compliqué. Étant donné que le format est récursif, il est tout simplement impossible de refléter la matrice, car Matrix.Identity se transformera en une matrice de réflexion partout et chaque imbrication reflétera notre modèle le long de l'axe Y, ce qui conduira à un affichage incorrect (si vous gardez une échelle positive). Jusqu'à présent, je suis arrivé à une décision incorrecte sous la forme d'autoriser une échelle négative, qui devra être refaite dans les futures versions.

La deuxième caractéristique est l'orientation des triangles. Pour les quads, on se rend compte que les triangles se ressemblent:

Code de préparation des carrés
 public override void PrepareMeshData(List<int> triangles, List<Vector3> verts) { var v = _Verts; var nA = Vector3.Cross(v[1] - v[0], v[2] - v[0]); var nB = Vector3.Cross(v[1] - v[0], v[2] - v[0]); var vertLen = verts.Count; triangles.AddRange(new[] { vertLen + 1, vertLen + 2, vertLen, vertLen + 1, vertLen + 3, vertLen + 2 }); var indexes = Vector3.Dot(nA, nB) > 0 ? new int[] {0, 1, 3, 2} : new int[] {0, 1, 2, 3}; for (int i = 0; i < indexes.Length; i++) { verts.Add(v[indexes[i]]); } } 


Mais ici, il est sans ambiguïté de déterminer, sur la base du format, dans quelle direction les triangles doivent être dirigés en principe - une tâche non triviale. Pour cette raison, les deux côtés sont toujours générés maintenant.

De plus, du fait que le format est récursif, le système hiérarchique Unity est devenu plus pratique que jamais.

En utilisant la récursivité dans deux méthodes, nous générons les mailles dont nous avons besoin et appliquons TRS (l'implémentation peut être trouvée dans l'article précédent ), et de cette façon nous obtenons tous les décalages nécessaires dans un format pratique:

Méthodes de génération d'un modèle sur scène
 public class LDrawModel { public GameObject CreateMeshGameObject(Matrix4x4 trs, Material mat = null, Transform parent = null) { if (_Commands.Count == 0) return null; GameObject go = new GameObject(_Name); var triangles = new List<int>(); var verts = new List<Vector3>(); for (int i = 0; i < _Commands.Count; i++) { var sfCommand = _Commands[i] as LDrawSubFile; if (sfCommand == null) { _Commands[i].PrepareMeshData(triangles, verts); } else { sfCommand.GetModelGameObject(go.transform); } } if (mat != null) { var childMrs = go.transform.GetComponentsInChildren<MeshRenderer>(); foreach (var meshRenderer in childMrs) { meshRenderer.material = mat; } } if (verts.Count > 0) { var visualGO = new GameObject("mesh"); visualGO.transform.SetParent(go.transform); var mf = visualGO.AddComponent<MeshFilter>(); mf.sharedMesh = PrepareMesh(verts, triangles); var mr = visualGO.AddComponent<MeshRenderer>(); if (mat != null) { mr.sharedMaterial = mat; } } go.transform.ApplyLocalTRS(trs); go.transform.SetParent(parent); return go; } } public class LDrawSubFile : LDrawCommand { public void GetModelGameObject(Transform parent) { _Model.CreateMeshGameObject(_Matrix, GetMaterial(), parent); } } 


Et en conséquence, nous obtenons de si belles visualisations:





Voir le référentiel sur Github pour plus de détails.

En général, il y a beaucoup d'idées sur le développement du plugin, je veux introduire des fonctionnalités telles que:

  1. Lissage de certaines formes
  2. Génération de face avant uniquement
  3. Constructeur et téléchargement des modèles au format LDraw
  4. Le shader plus frais pour le plastique avec diffusion souterraine (et le bon ensemble de matériaux en général)
  5. Déballer UV pour Lightmaps
  6. Optimisation des modèles (maintenant la plupart d'entre eux se composent de 500k +, et par exemple le modèle de la tour Eiffel est de 2,8 millions de polygones)

Mais pour le moment, le plugin vous permet d'utiliser des modèles de Lego dans Unity3d, ce qui est plutôt cool. (Toutes les images de l'article ont été faites à l'aide du plugin) Tout le code du projet est publié sous la licence MIT, mais je vous conseille de regarder la licence pour des modèles spécifiques sur les ressources LDraw.

Merci de votre attention, j'espère que vous avez appris quelque chose de nouveau par vous-même et que le format et le plugin vous intéressent! S'il reste du temps, je continuerai à le développer et serai heureux de vous aider dans cette affaire difficile.

Source: https://habr.com/ru/post/fr433364/


All Articles