Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LDrawLoader #15453

Merged
merged 5 commits into from Dec 31, 2018

Conversation

@yomboprime
Copy link
Collaborator

commented Dec 20, 2018

Adding LDrawLoader. The LDraw format specification defines a format for Lego pieces (and other block based construction games)

The attractive of this format is the vast amount of pieces out there. The official library (LDraw.org) in the LDraw site has over 11000 pieces and 700 complete models released under CC BY 2.0 license, and there are lots of sites with more models.

Unfortunately the more complex models cannot be loaded. The big Millenium Falcon at LDraw.org does not load; nonetheless, the X-wing does. The format consists of a tree of hundreds of subobjects at the level of primitives like the Lego studs. I have implemented each subobject as a THREE.Object3D. This can be optimized to a single mesh. Let me see in some days if I manage to load large models.

The loading of all those piece files has some handicaps. The specification lets a file be in some standard subfolders, and could be in any of them. So I've set two options: The application can set a previously prepared map (from file name to file path), or this map can be left unset; in that case each file is tried to download from each standard location successively. This latter option can be useful in a Node.js application which access a local database with the full 11000 pieces, and downloads also complete models from Internet (the map of file paths cannot be known in advance) All paths are always under the one set by the usual loader's .setPath().

In the example I've put some basic models and some more complex. The "Star Wars AT-AT" seems the one whith more deep level of the subobject tree, so it gives problems (out of memory) if I try to set a path map for it. As I've left this one without path map, There will be 404 errors when loading this model . It is expected, as the different locations are tried.

I've made an internal cache of file contents, partly because the THREE.Cache gives the content of the 404 response for a previously petition error. But also to allow implementing "embedded subfiles", which is another feature of the language. Also the path map, even if not provided, is updated in the load process, so that every file name is searched only once (this gives less 404 errors when not providing the path map)

Finally, the material definition requirements are complex, with scopes and so on. I implemented this but at the end it doesn't matter because in practice all materials are defined in the first file (LDConfig.ldr) before the main model file.

BTW every materials, piece, part or model file are all in the same format composed of one-line commands. The file extensions can be .dat, .ldr, .mpd and some more.

I've not implemented all the language extensions defined in the link above. The format has evolved since its creation in 1995 and it has a lot of them. One of interest for performance reasons is The BFC (Back Face Culling) extension. For now all materials are double-sided. This needs careful thinking as primitives can be used as they are, or "inside out" (for example use a cylinder primitive as an exterior or as an interior surface)

Also, I added a small attribution div as stated in the LDraw.org attributtion guidelines

P.S.: Do you have means to play easily the example, or shall I made a live repo?

Thanks

@yomboprime

This comment has been minimized.

Copy link
Collaborator Author

commented Dec 20, 2018

I've put the example live on github pages

Unfortunately it seems that it takes 8 to 10 seconds to load a model for the first time.

@Mugen87

This comment has been minimized.

Copy link
Collaborator

commented Dec 20, 2018

Yeah, the initial page call issues 131 network requests (according to Chrome dev tools). Any chances to pack all .dat files of a model into something like an archive?

In any event, you should consider to use a loading indicator for your demo. Otherwise many users will navigate away without looking at the model...

@yomboprime

This comment has been minimized.

Copy link
Collaborator Author

commented Dec 20, 2018

Yeah, the initial page call issues 131 network requests (according to Chrome dev tools). Any chances to pack all .dat files of a model into something like an archive?

Yes, I can do that.

In any event, you should consider to use a loading indicator for your demo. Otherwise many users will navigate away without looking at the model...

With the packing the loader should give a valid progress indication. Right now it only tracks the loading of the main file (prints out in the console) I'll add a progress bar also.

Edit: Now I've thought that using the already implemented 'embed files' feature –by executing an external script which adds all subfiles as embedded files to the main one– is the way to go.

@mrdoob mrdoob added this to the r100 milestone Dec 20, 2018

@yomboprime

This comment has been minimized.

Copy link
Collaborator Author

commented Dec 23, 2018

I've done the packing. The packed models now load with a single file petition and fast, as expected. 😊

I've added the packing utility under examples/js/utils/ldraw, it s a single Node.js script. It is used with the official parts library, and generates one packed file given a model file.

I've got to test some bigger files (complete scenarios), will post the results.

The online example is also updated.

@yomboprime

This comment has been minimized.

Copy link
Collaborator Author

commented Dec 24, 2018

I've optimized the rendering, now only one THREE.Object3D is created, with all triangles and lines in only one buffer. The rendering is much quicker now. The previous behaviour of creating lots of objects is optionally still there, for someone that wants the objects separated.

Also the overall load + parse operation is faster because much less objects are created.

Most of the models load in less than a second. The big models load in 2 seconds, and the really big AT-ST (the last model) loads in 4 seconds.

Happy Holidays 🎉🎉🎉

P.S. I have tested bigger models and there seems to be no limit on the model size.

@yomboprime

This comment has been minimized.

Copy link
Collaborator Author

commented Dec 25, 2018

I've solved a bug with the last triangle of each material, which was missing.

Also I've put nice labels in the model dropdown list.

That's all for now, the PR is ready.

Link to live example

@mrdoob mrdoob merged commit 931cbbc into mrdoob:dev Dec 31, 2018

2 checks passed

LGTM analysis: JavaScript 8 new alerts
Details
continuous-integration/travis-ci/pr The Travis CI build passed
Details
@mrdoob

This comment has been minimized.

Copy link
Owner

commented Dec 31, 2018

Thanks!

@yomboprime yomboprime deleted the yomboprime:ldraw branch Jan 6, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
3 participants
You can’t perform that action at this time.