Alles mit dem Kommen! Mein Name ist Grisha und ich bin der Gründer von CGDevs. Die Ferien stehen vor der Tür, jemand hat bereits einen Weihnachtsbaum verkleidet, Mandarinen gegessen und ist voll auf die Neujahrsstimmung eingestellt. Aber heute geht es nicht darum. Heute werden wir über ein wunderbares Format namens LDraw und über das Plugin für Unity sprechen, das ich implementiert und auf OpenSource hochgeladen habe. Der Link zum Projekt und der Quellcode für den Artikel sind wie immer beigefügt. Wenn Sie Lego genauso lieben wie ich - willkommen bei Cat.
LDraw-FormatBeginnen wir mit LDraw?
LDraw ist ein offener Standard für LEGO CAD-Programme, mit dem Benutzer LEGO Modelle und Szenen erstellen können. Im Allgemeinen gibt es verschiedene Programme und Plugins, mit denen Sie LDraw visualisieren können (zum Beispiel gibt es ein Plugin für Blender).
Das Format selbst ist gut dokumentiert und wir werden über die neueste Version bzw. über 1.0.2 sprechen.
LDraw ist ein Textformat, dessen Dateien mit UTF-8-Codierung erstellt werden müssen. Vom Format unterstützte Dateien müssen die Erweiterung ldr, dat oder mdp haben. Jede Zeile der Datei ist ein separater Befehl, der für eine bestimmte Funktion verantwortlich ist.
Ein wichtiges Detail des Formats ist das rechtshändige Koordinatensystem (Y ist nach oben gerichtet) - wir werden später im Kontext der Einheit ausführlicher darauf eingehen sowie auf die Tatsache, dass das Format rekursiv ist (die meisten Dateien enthalten Hinweise auf andere Dateien).
LDraw-BefehleIm Allgemeinen finden Sie diese Informationen in der
offiziellen Dokumentation , aber lassen Sie uns einen kleinen Blick auf den Kontext von Unity werfen. Insgesamt unterstützt das LDraw-Format 6 Arten von Befehlen.
0. Ein
Kommentar oder ein Meta-Befehl sind spezielle Befehle, die wir im Plugin kaum berühren werden. Beispiel:
0 !META command additional parameters
1.
Link zur Datei . In der Tat das am schwierigsten zu integrierende und interessanteste Team. Es sieht aus wie -
1 colour xyzabcdefghi file
, in der die Parameter die TRS-Matrix sind (mehr über TRS finden Sie
in diesem Artikel ). Im Kontext der Einheit in der Form
/ adg 0 \ | beh 0 | | cfi 0 | \ xyz 1 /
2.
Linie - wird bei Unity nicht verwendet. In CAD-Systemen müssen die Kanten mit einer bestimmten Farbe hervorgehoben werden.
3.4.
Dreieck und Quadrat . Die Befehle sind recht einfach, aber es gibt eine wichtige Nuance, da das LDraw-Format nicht für die 3D-Modellierung ausgelegt ist und die Umgehung von Dreiecken und Quadraten darin nicht standardisiert ist. Dies ist wichtig, da die Einheit in Abhängigkeit von der Durchquerung des Dreiecks die Richtung der berechneten Normalen sowie die Seite des Dreiecks die Rückseite und die Vorderseite bestimmt (was auch für das Zeichnen und Keulen wichtig ist).
Befehlsbeispiel:
Dreieck -
3 colour x1 y1 z1 x2 y2 z2 x3 y3 z3
Quadrat -
4 colour x1 y1 z1 x2 y2 z2 x3 y3 z3 x4 y4 z4
5.
Optionale Leitung - auch nicht verwendet.
Farben in LDrawWie Sie in den meisten Teams sehen können, die für das Rendern verantwortlich sind, kommt die Farbe unmittelbar nach der Art des Befehls. Die Farben sind in diesen beiden Artikeln
www.ldraw.org/article/299.html und
www.ldraw.org/article/547.html gut dokumentiert, aber
lassen Sie uns über die Funktionen sprechen, auf die ich während der Implementierung gestoßen bin. Hier lohnt es sich, etwas mehr über die Formate und das sogenannte "Scope" -Format zu sprechen. Es gibt 3 Arten von Dateien im Format.
DAT - in der Tat sind dies die Grundelemente, aus denen die Teile bereits zusammengesetzt sind, oder einige Grundteile. Wenn Sie keine einzelnen Details rendern, ist die darin angegebene Farbe nicht wichtig. Meistens gibt es Standardfarben des offiziellen Standards.
LDR ist das Interessanteste in Bezug auf Farben und wo Scope eine Rolle spielt. Die Regel ist recht einfach, obwohl die Site komplexe Sprachen beschreibt. Wenn Sie von einem ldr auf einen anderen verweisen, ignorieren Sie die im Stamm angegebene Farbe.
Beispiel: Teil der Datei 30051-1 - X-Wing Fighter - Mini.mpd (X-Wing im obigen Bild):
Beispiel 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
In allen Datendateien berücksichtigen wir die angegebene Farbe und im Befehl
1 72 0 -8 -70 1 0 0 0 1 0 0 0 1 30051 - Nose.ldr - ignorieren 72 und verwenden die Werte aus der Datei
30051 - Nose.ldr .
MDP ist eine Modelldatei, die meistens eine Beschreibung mehrerer ldr-Dateien enthält. In Bezug auf die Farbe ist es auch nicht sehr wichtig. Das einzige, was wir beim Parsen berücksichtigen, ist der Meta-Befehl
FILE .
Modelle in LDrawDas Beste am LDraw-Format ist, dass er viele Fans unter den Lego-Fans hat. Viele interessante Kits finden Sie auf der offiziellen Website
omr.ldraw.org , aber darüber hinaus finden Sie viele in separaten Foren.
Wir haben über das Format gesprochen, jetzt ist es Zeit, ein wenig über das Plugin für Unity zu sprechen.
Plugin für UnityDas Plugin bietet die Möglichkeit, 3D-Modelle basierend auf LDraw-Dateien zu generieren. Sie können die Ergebnisse in den Bildern aus dem Artikel sehen. Wichtig: Wenn Sie ein schwaches Gerät haben, ist es besser, nur Miniszenen im Demo-Ordner zu öffnen. Modelle sind nicht optimiert und erzeugen immer eine Hintergrundfläche.
Lassen Sie uns nun ein wenig über die Implementierung sprechen. Im Moment wird das meiste davon unterstützt.
Eines der vielleicht wichtigsten Merkmale sind die verschiedenen Koordinatensysteme. Das Problem ist, dass das Format ein rechtshändiges Koordinatensystem ist, während Unity ein linkshändiges Koordinatensystem ist. Dies bedeutet im Wesentlichen, dass alle Windungen und die TRS-Matrix nicht richtig funktionieren. Negatives Y ist leicht zu schlagen - wir reflektieren alle Koordinaten relativ zu Vector3.up und erhalten die erforderlichen (multiplizieren mit -1). Bei der TRS-Matrix ist jedoch alles komplizierter. Da das Format rekursiv ist, ist es einfach unmöglich, die Matrix wiederzugeben, da Matrix.Identity überall in eine Reflexionsmatrix umgewandelt wird und jede Verschachtelung unser Modell entlang der Y-Achse widerspiegelt, was zu einer falschen Anzeige führt (wenn Sie eine positive Skala beibehalten). Bisher bin ich zu einer falschen Entscheidung in Form einer negativen Skala gekommen, die in zukünftigen Versionen überarbeitet werden muss.
Das zweite Merkmal ist die Ausrichtung der Dreiecke. Bei Quads wird erkannt, dass die Dreiecke in eine Richtung aussehen:
Vorbereitungscode für Quadrate 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]]); } }
Hier ist es jedoch eindeutig zu bestimmen, in welche Richtung die Dreiecke im Prinzip gerichtet werden sollen - eine nicht triviale Aufgabe. Aus diesem Grund werden jetzt immer beide Seiten generiert.
Aufgrund der Tatsache, dass das Format rekursiv ist, hat sich das hierarchische System von Unity als nützlich erwiesen wie nie zuvor.
Mithilfe der Rekursion in zwei Methoden generieren wir die benötigten Netze und wenden TRS an (die Implementierung finden Sie
im vorherigen Artikel ). Auf diese Weise erhalten wir alle erforderlichen Offsets in einem praktischen Format:
Methoden zur Erstellung eines Modells auf der Bühne 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); } }
Als Ergebnis erhalten wir so schöne Visualisierungen:


Weitere Informationen finden Sie im
Repository auf Github .
Im Allgemeinen gibt es viele Ideen zur Entwicklung des Plugins. Ich möchte folgende Funktionen vorstellen:
- Einige Formen glätten
- Nur Erzeugung der Vorderseite
- Konstruieren und Hochladen von Modellen zurück in das LDraw-Format
- Der Cooler Shader für Kunststoff mit Streuung unter der Oberfläche (und der richtige Materialsatz im Allgemeinen)
- Packen Sie UV für Lightmaps aus
- Optimierung von Modellen (jetzt bestehen die meisten von ihnen aus über 500.000, und das Modell des Eiffelturms besteht beispielsweise aus 2,8 Millionen Polygonen)
Im Moment können Sie mit dem Plugin Modelle von Lego in Unity3d verwenden, was ziemlich cool ist. (Alle Bilder für den Artikel wurden mit dem Plugin erstellt.) Der gesamte
Projektcode wird unter der MIT-Lizenz veröffentlicht. Ich empfehle Ihnen jedoch, die Lizenz für bestimmte Modelle in LDraw-Ressourcen zu überprüfen.
Vielen Dank für Ihre Aufmerksamkeit, ich hoffe, Sie haben etwas Neues für sich gelernt und Sie interessieren sich für das Format und das Plugin! Wenn es Zeit gibt, werde ich sie weiterentwickeln und gerne in dieser schwierigen Angelegenheit helfen.