LDraw + Unity. As I, Lego generated

 3r33420. 3r3-31. Happy New Year! My name is Grisha, and I am the founder of CGDevs. The holidays are just around the corner, someone has already dressed up a Christmas tree, has eaten tangerines and is fully charged with New Year's mood. But today we will not talk about this. Today we will talk about a wonderful format called LDraw and about a plug-in for Unity, which I implemented and uploaded to OpenSource. Link to the project and source code to the article, as always, attached. If you are the same as I love Lego - welcome under cat. 3r3407.  3r33420. 3r3407.  3r33420. LDraw + Unity. As I, Lego generated 3r3404. 3r3407.  3r33420. LDraw format 3r3407.  3r33420. Let's start with what is LDraw? LDraw 3r3404. It is an open standard for LEGO CAD programs, allowing users to create LEGO models and scenes. In general, there are various programs and plugins that can be used to visualize LDraw (for example, there is a plugin for Blender). 3r3407.  3r33420. The format itself is well documented, and we will talk about its latest version, or rather, about ???. 3r3407.  3r33420. 3r3407.  3r33420. LDraw is a text format whose files must be created in UTF-8 encoding. Files supported by the format must have the extension ldr, dat or mdp. Each line of the file is a separate command responsible for a particular function. 3r3407.  3r33420. An important detail of the format is the right-handed coordinate system (Y pointing up) - we will discuss it in more detail later in the context of the unit, as well as the fact that the format is recursive (most of the files refer to other files) 3r3407.  3r33420. 3r3407.  3r33420. LDraw commands [/b] 3r3407.  3r33420. 3r3407.  3r33420. In general, this information can be found in
official documentation 3r3404. , but consider a little in the context of Unity. Total LDraw format supports 6 types of commands. 3r3407.  3r33420. 3r3407.  3r33420. 0. Comment or meta command 3r3184. - This is a special command, which we almost will not touch in the plugin. Example: 3r3145. 0! META command additional parameters 3r3407.  3r33420. 3r3407.  3r33420. 1. 3r3183. Link to file 3r3184. . In fact, the most difficult to integrate and interesting team. It looks like - 3r3145. 1 color x yz a b c d e f g h i file where the parameters are the TRS matrix (for more details about TRS, you can read 3r3-33283. in this article 3r3404.). In the context of a unit in the form
 3r33420. 3r3145. /a d g 0
 3r33420. | b e h 0 | 3r3407.  3r33420. | c f i 0 | 3r3407.  3r33420. x y z 1 / 3r3407.  3r33420. 3r3407.  3r33420. 2. 3r3183. Line 3r3184. - is not used in the case of Unity, you need to highlight the faces with a certain color in CAD systems. 3r3407.  3r33420. 3r3407.  3r33420. 3.4. 3r3183. Triangle and square
. The commands are quite simple, but there is one important nuance, since the LDraw format is not designed for 3D modeling, the detour of triangles and squares in it is not standardized. This is important, because somehow the unit determines the direction of the calculated normal, depending on the circumvention of the triangle, and which side of the triangle is the back and which front (which is also important for drawing and cooling) 3r3407.  3r33420. 3r3407.  3r33420. Example commands: 3r3407.  3r33420. Triangle - 3r3145. 3 color x1 y1 z1 x2 y2 z2 x3 y3 z3 3r3407.  3r33420. Square - 3r3145. 4 color x1 y1 z1 x2 y2 z2 x3 y3 z3 x4 y4 z4 3r3407.  3r33420. 3r3407.  3r33420. 5. Optional line - also not used. 3r3407.  3r33420. 3r3407.  3r33420. Colors in LDraw [/b] 3r3407.  3r33420. 3r3407.  3r33420. As you can see in most of the commands responsible for drawing, the color goes right after the type of command. The colors are well documented in these two articles
www.ldraw.org/article/299.html
and 3r3119. www.ldraw.org/article/547.html
, but let's talk about the features that I encountered in the implementation. There is a little more to talk about the formats and the so-called “Scope” format. In the format there are 3 types of files. 3r3407.  3r33420. 3r3407.  3r33420. DAT - in fact, these are the basic elements of which parts are already being assembled, or some basic details. If you do not render individual parts - the color specified in them is not important. Most often there are standard colors of the official standard. 3r3407.  3r33420. 3r3407.  3r33420. LDR - this is the most interesting, in terms of colors, and where Scope plays a role. The rule is quite simple, although the site describes complex languages. If you refer from one ldr to another, ignore the color specified in the root. 3r3407.  3r33420. 3r3407.  3r33420. For example, part of the file 30051-1 - X-wing Fighter - Mini.mpd (X-wing in the picture above): 3r3407.  3r33420. 3r3407.  3r33420.
Example [/b]
3r3145. ??? -??? ??? ??? -??? 60470a.dat
 3r33420. ??? ??? 0 -??? ??? ???a.dat
 3r33420. 0 STEP
 3r33420. ??? ??? 0 -??? ??? ???b.dat
 3r33420. 0 STEP
 3r33420. 0 ROTSTEP ??? ABS 3r3407.  3r33420. ??? -??? 0 -??? ??? ???.dat
 3r33420. ??? -??? 0 -??? ??? ???.dat
 3r33420. 0 STEP
 3r33420. ??? -8 -??? ??? ??? ??? - Nose.ldr 3r3407.  3r33420. 3r31616. 3r31616. 3r3407.  3r33420. 3r3407.  3r33420. In all dat files, we take into account the specified color, and in the command ??? -8 -??? ??? ??? ??? - Nose.ldr - ignore 7? and use the values ​​from the file 30051 - Nose.ldr . 3r3407.  3r33420. 3r3407.  3r33420. MDP - This is a model file, most often contains a description of several ldr files. From the point of view of color is also not particularly important. The only thing we take into account when parsing is the meta command [i] FILE 3r3184. . 3r3407.  3r33420. 3r3407.  3r33420. 3r3189. 3r3407.  3r33420. 3r3407.  3r33420. Models in LDraw 3r3407.  3r33420. 3r3407.  3r33420. The most beautiful thing in the LDraw format is that he has a lot of fans among Lego fans. Many interesting kits can be found on the official 3-333200 website. omr.ldraw.org
but, beyond this, many can be found on separate forums. 3r3407.  3r33420. We talked about the format, now it's time to talk a little about the plugin for Unity. 3r3407.  3r33420. 3r3407.  3r33420. 3r3208. 3r3407.  3r33420. 3r3407.  3r33420. Plugin for Unity 3r3407.  3r33420. 3r3407.  3r33420. 3r3403. Plugin
provides the ability to generate 3D models based on LDraw files. You can see the results in the pictures from the article. Important: if you have a weak device, it is better to open only mini scenes in the Demo folder. Models are not optimized and always generate backface. 3r3407.  3r33420. 3r3407.  3r33420. Now let's talk a little about implementation. Currently, most of the above is supported. 3r3407.  3r33420. 3r3407.  3r33420. One of, perhaps, the most important features are different coordinate systems. The problem is that in the format of the right-sided coordinate system, and in Unity - left-sided. What this essentially means is that all the turns and the TRS matrix will work incorrectly. Negative Y is easy to beat - we reflect all coordinates relative to Vector3.up and get the ones we need (multiply by -1). But in the case of the TRS matrix all the more difficult. Since the format is recursive, it is impossible to simply reflect the matrix, since Matrix.Identity everywhere will turn into a reflection matrix and each nesting will reflect our model along the Y axis, which will lead to incorrect display (if you keep a positive scale). So far I have come to a not quite right decision in the form of what allowed the negative scale, what will need to be redone in future versions. 3r3407.  3r33420. 3r3407.  3r33420. The second feature is the orientation of the triangles. For quads, it is realized that the triangles look in one direction:
 3r33420. 3r3407.  3r33420.
The preparation code for squares is [/b]
public override void PrepareMeshData (List
triangles, List
verts)
{
var v = _Verts; 3r33420. var nA = Vector3.Cross (v[1]- v[0], v[2]- v[0]); 3r33420. var nB = Vector3.Cross (v[1]- v[0], v[2]- v[0]); 3r33420. 3r33420. var vertLen = verts.Count; 3r33420. triangles.AddRange (new[]
{
vertLen + ?
vertLen + ?
vertLen,
vertLen + ? 3rrr2020. vertLen + ? for us, for us, for us, to apply –– ––––––– –––––––––– –––––––– –––––––– –––––––– –––––––––––––––– to appearing, ––––––– –––––––– –––––––– ––––––––––––––––– to appearing, –youryour ––420. 3r33420. 3r33420. var indexes = Vector3.Dot (nA, nB)> 0? new int[]{? ? ? 2}: new int[]{? ? ? 3}; 3r33420. for (int i = 0; i < indexes.Length; i++)
{
verts. Add (v[indexes[i]]);
} 3r3r204.} 3rr3361. 3r3362. 3r3407.  3r33420. 3r31616. 3r31616. 3r3407.  3r33420. But to uniquely determine based on the format, in which direction the triangles should be directed in principle - a non-trivial task. For this reason, now both sides are generated. 3r3407.  3r33420. 3r3407.  3r33420. In addition, due to the fact that the format is recursive, the hierarchical system of Unity has more than ever been appropriate. 3r3407.  3r33420. 3r3407.  3r33420. Using recursion in two methods, we generate the necessary meshes and apply TRS (the implementation can be read 3r3283. In the previous article 3r3404.), And thus we get all the biases necessary for us in a convenient format: 3r3407.  3r33420. 3r3407.  3r33420.
Methods for generating a model on stage [/b]
3r33420. public class LDrawModel
{
public GameObject CreateMeshGameObject (Matrix4x4 trs, Material mat = null, Transform parent = null)
{
if (_Commands.Count == 0) return null; 3r33420. GameObject go = new GameObject (_Name); 3r33420. 3r33420. var triangles = new List
(); 3r33420. var verts = new List
(); 3r33420. 3r33420. for (int i = 0; i < _Commands.Count; i++)
{
var sfCommand = _Commands[i]as LDrawSubFile;
if (sfCommand == null)
{
_Commands w2w? see, va. 3r33420. Else
{
SfCommand.GetModelGameObject (go.transform);
}
3 r???.
Foreach (var meshRenderer in childMrs)
{
MeshRenderer.material = mat;
}
} 3rrr2020. ("mesh");
visualGO.transform. SetParent (go.transform); 3r 3r3420. var mf = visualGO.AddComponent
(); 3r33420. 3r33420. mf.sharedMesh = PrepareMesh (verts, triangles); 3r33420. var mr = visualGO.AddComponent
(); 3r33420. if (mat! = null)
{
mr.sharedMaterial = mat; 3r33420. 3r33420.
3r33420. go.transform.ApplyLocalTRS (trs); 3r33420. 3r33420. go.transform.SetParent (parent); 3r33420. return go; 3r33420.
public class LDrawSubFile: LDrawCommand
{
public void GetModelGameObject (Transform parent)
{
_Model.CreateMeshGameObject (_Matrix, GetMaterial (), parent); 3r33420.
3r33333. 3r33333. 3r3407.  3r33420. 3r31616. 3r31616. 3r3407.  3r33420. 3r3407.  3r33420. And in the end we get such beautiful visualizations: 3r3407.  3r33420. 3r33333. 3r3407.  3r33420. . 3r3407.  3r33420. 3r3407.  3r33420. In general, the development of the plug-in a lot of ideas, I want to introduce such functionality as: 3r3407.  3r33420. 1. Smoothing some forms of 3r3407.  3r33420. 2. Generation of only front face
 3r33420. 3. Designer and unloading models back to the format LDraw
 3r33420. 4. By steeper the shader for plastic with subsurface scattering (and the correct set of materials in general) 3r3407.  3r33420. 5. Unwrap UV for lightmaps
 3r33420. 6. Optimization of models (now most of them consist of 500k +, and for example the model of the Eiffel Tower 2.8 million polygons) 3r3407.  3r33420. 3r3407.  3r33420. But at the moment, the plugin allows you to use Lego models in Unity3d, which is pretty cool. (All images for the article are made using the plugin) All 3r3403. project code 3r3404. laid out under the MIT license, but I advise you to look at the license for specific models on LDraw resources. 3r3407.  3r33420. 3r3407.  3r33420. Thank you for your attention, I hope you have learned something new for yourself, and you are interested in the format and the plugin! If there is time, I will continue to develop it and will be glad to help in this difficult task. 3r31616. 3r33420. 3r33420. 3r33420.
! function (e) {function t (t, n) {if (! (n in e)) {for (var r, a = e.document, i = a.scripts, o = i.length; o-- ;) if (-1! == i[o].src.indexOf (t)) {r = i[o]; break} if (! r) {r = a.createElement ("script"), r.type = "text /jаvascript", r.async =! ? r.defer =! ? r.src = t, r.charset = "UTF-8"; var d = function () {var e = a.getElementsByTagName ("script")[0]; e.parentNode.insertBefore (r, e)}; "[object Opera]" == e.opera? a.addEventListener? a.addEventListener ("DOMContentLoaded", d,! 1): e.attachEvent ("onload", d ): d ()}}} t ("//mediator.mail.ru/script/2820404/"""_mediator") () (); 3r33414. 3r33420. 3r31616. 3r33420. 3r33420. 3r33420. 3r33420.
+ 0 -

Add comment