I've encountered a problem with the STL loader when I want to load a single STL file that contains multiple solids. Below is an example in a three.js viewer and meshlab (2 cubes in a single STL file).
What is the problem?
If you can demonstrate a three.js bug, can you provide a test case so we can reproduce your results? Please see "How to report a bug" in the guidelines.
Thanks, I'll look into the guidelines and come back to you
How common are STL files with more than one solid? The current loader interface only supports returning a single geometry.
However, skimming at the sources, the loader doesn't check for solid
/endsolid
. It just reads all the facets and place them in a geometry. I'm surprised that you are not seeing your two blocks merged in a single geometry.
Could you share the file?
What is the problem?
The problem is that if you open an ASCII STL file with multiple solids three.js, meaning multiple
solid solid_name
...
endsolid solid_name
solid another_solid_name
...
endsolid another_solid_name
they are treated as a single solid. It would be useful to be able to assign them different colors and other properties.
The behavior is also a bit inconsistent with what done with binary STL files, where multiple solids are often identified with colors, which is a supported scenario in the current loader.
@AlbertoPa Thanks. Any interest in trying to fix it?
@WestLangley I will give it a try. I need the feature for a tool I am working on.
What I envision is adding the ability to assign different colors (random since the number of solids isn't known until the file is read) and the label to each object. This could be useful in scenarios where ray tracing is used to identify clicked objects to make the scene interact with some other functionality (my use case).
Doing this with the ASCII STL is not difficult. However, binary STL formats don't agree on how color is stored, so it will require some extra work. Do you have any preference on where to start/how to do it?
Do you have any preference on where to start/how to do it?
@AlbertoPa No, but @Mugen87 is knowledgable on this topic. Perhaps he can give you some guidance.
However, binary STL formats don't agree on how color is stored, so it will require some extra work. Do you have any preference on where to start/how to do it?
AFAIK, STL and colors are tricky. The format was originally not invented with color support. This is explained in this nice article about STL: https://all3dp.com/what-is-stl-file-format-extension-3d-printing/
In the last section, we said that the STL file format cannot handle multi-color models. The reason the STL file format lacks color information is simple. When rapid prototyping evolved in the 1980s, no one thought of color printing. Nowadays, 3D printing materials and processes have evolved rapidly.
However it鈥檚 not completely fair to say that STL cannot handle colors. It turns out that there are non-standard versions of the STL format that are indeed capable of carrying color information.
The articles also says:
As we saw earlier, the STL file format cannot store additional information such as color, material etc. of the facets or triangles. It only stores information about the vertices and the normal vector. This means that if you want to use multiple colors or multiple materials for your prints, then the STL file format is not the right choice. The OBJ format is a popular format enjoying good support which has a way to specify color, material etc. Therefore, this is the right choice for this task.
Apart from that, I thought color parsing of binary STL is already implemented?
Thanks @Mugen87.
Based on your comment, the only aspect to implement is the capability of being able to distinguish solids in ASCII STL files where these are identified by labels, which is simple.
The only aspect to decide would be how to assign a color to different surfaces so that they can be identified, but that is quite arbitrary (random flat color?). Currently they are all assigned the same properties, so they can't be distinguished.
The only aspect to decide would be how to assign a color to different surfaces so that they can be identified,
The loader could organize each solid as a separate geometry. Or it generates a single geometry (like currently implemented) but uses BufferGeometry.groups
so you can apply multiple materials to the final mesh. In this way, each solid can have its own material and this surface color.
I gave it a try with groups and it seems to work well. The user will have to provide as many materials as the length of geometry.groups:
https://github.com/AlbertoPa/three.js/commit/c65f6636887c53fc32d9de77ff3d3cdf5437e178
As a demo, I concatenated some of the STL used in the three.js examples to form an ASCII file with multiple solids. I have used a random color assignment in when defining materials. Here is the result:
If this is OK, I will change also the jsm.
Adding BufferGeometry.groups
would be a great addition to the loader! However, can you also implement this for binary files? I think supporting both formats is the best way to avoid user support requests like "Why does it work for ASCII but not for binary?".
I agree. In binary STL, however, there is no concept of "solid" . We could assign triangles with the same color to the same group. Is this what you mean?
In binary STL, however, there is no concept of "solid" .
Oh sorry, I was not aware of that. In this case I would keep it simple and just start with ASCII files. Adding an additional note to the loaders comment section should be sufficient to clarify things (something like "Binary STL files do not supports 'solids'. Hence, multi material support is only added for ASCII files so far.").
Looking forward to your PR! 馃槉
Thank you for your help!
I'll make sure the code is clean and check the guidelines, then make a PR (first to three.js :-)).
Submitted (PR #17272).
OT, but is it possible, once geometry groups are created to recover them (their name for example) via raycasting?
OT, but is it possible, once geometry groups are created to recover them (their name for example) via raycasting?
I'm not sure I understand. Groups don't have a name. A group object is defined like so:
{
start: number;
count: number;
materialIndex: number;
}
Mesh.raycast()
does honor groups but it only returns the material index of the group data.
@Mugen87 thank you. I have resolved my issue by comparing the materialIndex of the face hit by the ray to the materialIndex of each of the groups, so that I can identify the solid clicked.
When I mentioned names, I was referring to the "name" property I see when I examine the code in a step-by-step debugger (default name of the object?).
Closing. @AlbertoPa Thanks for enhancing STLLoader
馃憤