Embedding 3D objects beyond STLs in Discourse?

I just saw this post on twitter:

I wasn’t previously aware of glTF but it looks really promising to me.

I remember that in the early days of MakerForums, we used to have a member here who got very angry and was abusive when we didn’t immediately figure out how to implement his idea of integrating a live model into the forum. I didn’t feel any great need to suffer additional abuse for not figuring out how to implement his idea after working out how to import a lot of content from G+, but it didn’t mean the idea itself was a bad one — it was just abusively presented.

Now that there’s a standard with apparently wide industry support, and now that FreeCAD supports exports to that format, I wonder if we’re in a place where you could upload a model in glTF and have a viewer in Discourse to present it.

Anyone interested in building that out? I’m a back end developer without the needed front end skills to succeed in reasonable time there, but most of my developer interactions with the Discourse team have been encouraging and positive, so if anyone with front end experience wanted to look into this I’d think it could be a fun and useful project, applicable here but also beyond MakerForums.

4 Likes

It should be doable using threejs. Here is an example link from threejs.

https://threejs.org/examples/webgl_loader_gltf.html

I had looked into using threejs a few years ago to implement other formats like stl but it was to much work at the time. I can take a look again.

No promises. :slight_smile:

3 Likes

Wow, that’s a cool demo!

“No promises” is a good motto!

I dug a little deeper to learn more…

The viewer in the demo from the FreeCAD project lets you control visibility of each node, which is great for exploring models, like, say, making the frame of a 3D printer disappear so you can see all the hidden hardware. However, that viewer from OpenCascade is not, as far as I can tell, open source, so integrating it into oneboxing in Discourse might be license-hard.

The current glTF export from FreeCAD is one file per body, so it’s not so trivial to just upload a single file. However, they say that’s possible with more work. I haven’t read the code to have any sense how much more work.

Threejs has a Discourse, so maybe they would be interested in this? They even have a Showcase category.

I note that threejs does not have STEP import and they suggest glTF instead thus requiring conversion. CascadeStudio uses threejs and loads STEP, IGES, and STL directly. I see that it gets those from opencascade.js.

1 Like

Wow I remember when web pages could barely render a font…

Ya I’m that old!

5 Likes

I remember using a 300buad dialup modem that I had to place the hansdet into the modem to use.

3 Likes

Oh my yes …

2 Likes

I had a 300 baud modem on my Atari 800. (yes, I’m that old) Funny, I was just reminiscing about VRML about an hour ago. That kind of died on the vine. This helmet demo is crazy good though!

3 Likes

Here is the github for the preliminary work I’ve been doing on embedding a model viewer into discourse/onebox.

This is just an html/threejs based page for displaying different model formats. It currently will display stl,amf,gcode, and gltf files.

If you want to try it out, clone the repo on your laptop and load the page in your browser using “file://”.

This is a work in progress so dont consider it to be complete or safe to use in a production environment.

I’ve been focused on getting things to work, not security.

2 Likes

Thank you! I see it working for rendering the default model. :tada:

Looking for edge cases to try to be useful, I see that gitlab uses ?inline=false for direct downloads, so I tried %3f to encode the ? into the parameter, like this: https://gitlab.com/project-monocle/XGantryBlocks/-/raw/master/BlockSet.stl%3finline=false It didn’t render. Tried it with a literal ? in case the browser was being too “smart” and double-encoding, but that didn’t fix it.

The Model loaders that threejs uses are based on FileLoader which uses xmlhttprequest so they should be able to handle query strings but they dont inherently know what to do with them.

https://threejs.org/docs/#api/en/loaders/FileLoader

This means we would probably need to implement our own loader and pass the data to the model types Loader.parse for processing.

I’ll see what I can do.

2 Likes

Huh, then I would have expected %3f to have been passed through and to have worked. I just checked %253F in case it was double-decoding but that didn’t work either.

Not sure how important it is overall to recognize query parameters. Dropbox has ?dl=0 but I think they try to break embedding anyway because they don’t want to function as a CDN.

Discourse has a “download locally” option (at least for images) that would make sense here, so even if something wasn’t explicitly an upload it would turn into one behind the scenes and then it would be rendering a URL like https://discourse.example.org/uploads/default/original/3X/a/b/abcdef1234567890.stl which wouldn’t have any parameters on it.

So to wrap it in a discourse plugin I don’t know that a custom plugin would be needed as long as “download remote images to local” could be configured to include model files.

1 Like

I was incorrect when I said that the threejs loaders didn’t know what to do with the query strings. The conditional that looks for the file extension was choking on the params. I fixed that.

Unfortunately, gitlab does not want people using cross origin requests. When I try requesting that url, I get a CORS policy error because gitlab does not send a ‘Access-Control-Allow-Origin’ header in their response.

Access to XMLHttpRequest at ‘https://gitlab.com/project-monocle/XGantryBlocks/-/raw/master/BlockSet.stl?inline=false’ from origin ‘null’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.

There have been several attempts to get CORS enabled for all origins like Github does but they have refused. The closest they have is their handling of gitlab pages which has the peculiar trait of only sending a ‘Access-Control-Allow-Origin’ header in the response if you have send an “Origin” header in your request. But the browser is the one that is suppose to add that header, not your code, so the browser will filter it out and display a “refused to set unsafe header” message.

Refused to set unsafe header “Origin”

This is entirely an issue with browser security settings. It is actually the browser that generates the CORS related errors. You can access these URLs without issue using tools like curl or wget.

So Im at a bit of an impasse on viewing gitlab files.

If you want to read more about Gitlab’s CORS settings see the below links.

1 Like

You can check the behaviour for yourself with curl.

With pages.gitlab.io, you can see that you dont get the ‘Access-Control-Allow-Origin: *’ header unless you send an ‘Origin’ header.

> :~> curl -D- http://pages.gitlab.io/gatsby/index.html --output test.dump 2> /dev/null | grep Access-Control-Allow-Origin
> :~> curl -D- http://pages.gitlab.io/gatsby/index.html -H 'Origin: example.com' --output test.dump 2> /dev/null | grep Access-Control-Allow-Origin
> Access-Control-Allow-Origin: *
> :~>

If you try that with gitlab.com urls, you dont get the ‘Access-Control-Allow-Origin: *’ header either way.

:~> curl -D- 'https://gitlab.com/project-monocle/XGantryBlocks/-/raw/master/BlockSet.stl?inline=false' --output test.dump 2> /dev/null | grep Access-Control-Allow-Origin
:~> curl -D- 'https://gitlab.com/project-monocle/XGantryBlocks/-/raw/master/BlockSet.stl?inline=false' -H 'Origin: example.com' --output test.dump 2> /dev/null | grep Access-Control-Allow-Origin
:~>

At work I just wrote up an Access-Control-Allow-Origin feature for our product for a customer, so I have no excuse for not thinking of CORS. Sorry for having sent you down a rabbit hole! :blush: :frowning:

That’s one more reason to work on handling uploads vs. embedding, at whatever point this lands in a plugin, if you get that far; the back end can download gitlab URLs, and the models would pop into existence after the system rewrites the URLs to local upload: psuedo-URLs that get rendered into proper links on the system.

1 Like

Can it display SCAD files?

Rendering OpenSCAD code to a mesh can take days for some models, and you have to run that code somewhere. No, that’s not a target here.

If you want to do something like OpenSCAD in a browser, CascadeStudio is probably the best answer. It uses javascript rather than the OpenSCAD DSL, but it’s very similar in use and like OpenSCAD is using OpenCascade.

The OpenSCAD program itself frankly needs an overhaul due to speed issues. The code is hard to sort through to understand too. I have not tried OpenCascade.

While this is certainly a tangent relative to the OT, OpenCascade is an open source library, and company that creates the library, that is used in OpenSCAD, FreeCAD, and many open source and proprietary projects and products. By using OpenSCAD you are also using OpenCascade. CascadeStudio is a project to implement a modelling tool entirely in the browser using threejs, opencascade.js (compiling OpenCascade into javascript), and other packages.

When it comes to speed, I think that I and many other users of OpenSCAD don’t really know how to write OpenSCAD code for speed. I note that nophead’s models are complex and tend to render quickly relative to my own, and I feel like I could learn a lot from studying NopSCADlib. I have had trouble being motivated to do that, however, because in OpenSCAD it is generally complex to make chamfers, and slow and complex to make fillets, and in FreeCAD it’s relatively simple and fast.

But this topic is about rendering models in the browser and eventually inside discourse, and I think it would be helpful to start separate topics for talking about modeling applications. :slight_smile:

For a list of potential formats to support take a look at the ThreeJS examples page and search for loaders.

https://threejs.org/examples/

Anything not on that list would require writing a loader to support it and is not even on my radar. :slight_smile:

2 Likes