Semua dengan kedatangan! Nama saya Grisha dan saya adalah pendiri CGDevs. Liburan sudah dekat, seseorang telah mengenakan pohon Natal, makan jeruk keprok dan penuh dengan suasana tahun baru. Tapi hari ini bukan tentang itu. Hari ini kita akan berbicara tentang format luar biasa yang disebut LDraw dan tentang plugin untuk Unity, yang saya terapkan dan unggah ke OpenSource. Tautan ke proyek dan kode sumber untuk artikel, seperti biasa, terlampir. Jika Anda menyukai Lego seperti halnya saya - selamat datang di Cat.
Format LDrawMari kita mulai dengan apa itu LDraw?
LDraw adalah standar terbuka untuk program CAD LEGO yang memungkinkan pengguna untuk membuat model dan adegan LEGO. Secara umum, ada berbagai program dan plugin yang dapat digunakan untuk memvisualisasikan LDraw (misalnya, ada plugin untuk Blender).
Formatnya sendiri didokumentasikan dengan baik, dan kami akan berbicara tentang versi terbarunya, atau lebih tepatnya, tentang 1.0.2.
LDraw adalah format teks yang file-nya harus dibuat dengan pengkodean UTF-8. File yang didukung oleh format harus memiliki ekstensi ldr, dat atau mdp. Setiap baris file adalah perintah terpisah yang bertanggung jawab untuk fungsi tertentu.
Detail penting dari format ini adalah sistem koordinat tangan kanan (Y diarahkan) - kita akan membahas lebih rinci nanti dalam konteks unit, serta fakta bahwa formatnya bersifat rekursif (sebagian besar file berisi indikasi file lain).
Perintah LDrawSecara umum, informasi ini dapat ditemukan di
dokumentasi resmi , tetapi mari kita lihat sedikit dalam konteks Unity. Secara total, format LDraw mendukung 6 jenis perintah.
0. Perintah
komentar atau meta adalah perintah khusus yang hampir tidak akan kita sentuh di plugin. Contoh:
0 !META command additional parameters
1.
Tautan ke file . Bahkan, tim yang paling sulit diintegrasikan dan menarik. Sepertinya -
1 colour xyzabcdefghi file
, di mana parameternya adalah matriks TRS (lebih lanjut tentang TRS dapat ditemukan
dalam artikel ini ). Dalam konteks unit dalam bentuk
/ adg 0 \ | beh 0 | | cfi 0 | \ xyz 1 /
2.
Line - tidak digunakan dalam kasus Unity, perlu untuk menekankan tepi dengan warna tertentu dalam sistem CAD.
3.4.
Segitiga dan bujur sangkar . Perintahnya cukup sederhana, tetapi ada satu nuansa penting, karena format LDraw tidak dirancang untuk pemodelan 3D, memotong segitiga dan kotak di dalamnya tidak terstandarisasi. Ini penting, karena unit, tergantung pada lintasan segitiga, menentukan arah normal yang dihitung, serta sisi mana dari segitiga itu di belakang dan mana yang di depan (yang juga penting untuk menggambar dan menyisihkan)
Contoh perintah:
Segitiga -
3 colour x1 y1 z1 x2 y2 z2 x3 y3 z3
Kotak -
4 colour x1 y1 z1 x2 y2 z2 x3 y3 z3 x4 y4 z4
5.
Jalur opsional - juga tidak digunakan.
Warna dalam LDrawSeperti yang Anda lihat di sebagian besar tim yang bertanggung jawab untuk rendering, warnanya muncul segera setelah jenis perintah. Warna-warna tersebut didokumentasikan dengan baik dalam dua artikel ini
www.ldraw.org/article/299.html dan
www.ldraw.org/article/547.html , tetapi
mari kita bicara tentang fitur yang saya temui selama implementasi. Di sini perlu sedikit lebih banyak bicara tentang format dan apa yang disebut format “Ruang Lingkup”. Ada 3 jenis file dalam format.
DAT - pada kenyataannya, ini adalah elemen dasar dari mana bagian sudah dirakit, atau beberapa bagian dasar. Jika Anda tidak memberikan detail individual, warna yang ditunjukkan di dalamnya tidak penting. Paling sering ada warna standar dari standar resmi.
LDR adalah hal yang paling menarik dalam hal warna, dan di mana Lingkup berperan. Aturannya cukup sederhana, meskipun situs tersebut menggambarkan bahasa yang rumit. Jika Anda merujuk ke yang lain dari satu ldr, abaikan warna yang ditentukan di root.
Misalnya, bagian dari file 30051-1 - X-wing Fighter - Mini.mpd (X-wing pada gambar di atas):
Contoh 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
Di semua file dat, kami memperhitungkan warna yang ditentukan, dan dalam perintah
1 72 0 -8 -70 1 0 0 0 0 0 0 0 30051 - Nose.ldr - abaikan 72, dan gunakan nilai dari file
30051 - Nose.ldr .
MDP adalah file model, paling sering berisi deskripsi beberapa file ldr. Dari segi warna, itu juga tidak terlalu penting. Satu-satunya hal yang kami perhitungkan saat parsing adalah meta-command
FILE .
Model dalam LDrawBagian terbaik dalam format LDraw adalah bahwa ia memiliki banyak penggemar di antara penggemar lego. Banyak kit menarik dapat ditemukan di situs web resmi
omr.ldraw.org , tetapi selain itu, banyak yang dapat ditemukan di forum terpisah.
Kami berbicara tentang format, sekarang saatnya untuk berbicara sedikit tentang plugin untuk Unity.
Plugin untuk UnityPlugin menyediakan kemampuan untuk menghasilkan model 3D berdasarkan file LDraw. Anda dapat melihat hasilnya dalam gambar dari artikel. Penting: jika Anda memiliki perangkat yang lemah, lebih baik hanya membuka adegan mini di folder Demo. Model tidak dioptimalkan dan selalu menghasilkan backface.
Sekarang mari kita bicara sedikit tentang implementasi. Saat ini, sebagian besar di atas didukung.
Salah satu fitur yang mungkin paling penting adalah sistem koordinat yang berbeda. Masalahnya adalah bahwa formatnya adalah sistem koordinat tangan kanan, sedangkan Unity adalah sistem koordinat kidal. Apa ini, pada dasarnya, berarti bahwa semua belokan dan matriks TRS tidak akan berfungsi dengan benar. Negatif Y mudah dikalahkan - kami mencerminkan semua koordinat relatif terhadap Vector3.up dan dapatkan yang diperlukan (kalikan dengan -1). Tetapi dalam kasus matriks TRS, semuanya lebih rumit. Karena formatnya rekursif, tidak mungkin untuk mencerminkan matriks, karena Matrix. Identitas akan berubah menjadi matriks refleksi di mana-mana dan setiap sarang akan mencerminkan model kami di sepanjang sumbu Y, yang akan mengarah ke tampilan yang salah (jika Anda mempertahankan skala positif). Sejauh ini, saya sampai pada keputusan yang salah dalam bentuk mengizinkan skala negatif, yang perlu diperbaiki di versi mendatang.
Fitur kedua adalah orientasi segitiga. Untuk paha depan, disadari bahwa segitiga terlihat satu arah:
Kode Persiapan untuk Kotak 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]]); } }
Tapi di sini jelas untuk menentukan, berdasarkan format, ke arah mana segitiga pada prinsipnya harus diarahkan - tugas yang tidak sepele. Untuk alasan ini, kedua belah pihak selalu dihasilkan sekarang.
Selain itu, karena fakta bahwa formatnya bersifat rekursif, sistem hierarki Unity menjadi berguna seperti yang belum pernah terjadi sebelumnya.
Dengan menggunakan rekursi dalam dua metode, kami menghasilkan jerat yang kami butuhkan dan menerapkan TRS (implementasinya dapat ditemukan
dalam artikel sebelumnya ), dan dengan demikian kami mendapatkan semua offset yang diperlukan dalam format yang nyaman:
Metode untuk menghasilkan model di atas panggung 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); } }
Dan sebagai hasilnya, kami mendapatkan visualisasi yang sangat indah:


Lihat
repositori di Github untuk lebih jelasnya.
Secara umum, ada banyak ide tentang pengembangan plugin;
- Menghaluskan beberapa bentuk
- Generasi wajah depan saja
- Konstruktor dan unggah model kembali ke format LDraw
- Shader pendingin untuk plastik dengan hamburan di bawah permukaan (dan set material yang tepat secara umum)
- Buka bungkus UV untuk Lightmaps
- Optimalisasi model (sekarang sebagian besar terdiri dari 500 k +, dan misalnya model menara Eiffel adalah 2,8 juta poligon)
Tetapi saat ini, plugin memungkinkan Anda untuk menggunakan model dari Lego di Unity3d, yang cukup keren. (Semua gambar untuk artikel dibuat menggunakan plugin) Semua
kode proyek diposting di bawah lisensi MIT, tetapi saya menyarankan Anda untuk melihat lisensi untuk model spesifik pada sumber daya LDraw.
Terima kasih atas perhatian Anda, saya harap Anda mempelajari sesuatu yang baru untuk diri Anda sendiri, dan Anda tertarik dengan format dan plugin! Jika ada waktu, saya akan terus mengembangkannya dan dengan senang hati akan membantu dalam masalah yang sulit ini.