Hello threejs community! First off, thank you for all your hard work on three.js; I’ve been really impressed at how approachable I’ve found the whole ecosystem and its many examples. What a joy it is to be able to get such quick and impressive results with the tool!
Some quick background on what I’ve done to this point: I have a PCB design in kicad, and there’s a built-in 3d render that looks something like this:
I’d like to be able to use this 3d render in contexts outside of the built-in 3d viewer. Happily, there’s an “export to VRML” (and only to VRML), and with a few minor tweaks[1] I was able to adapt the three.js webgl_loader_vrml.html example to load and render the board! The trickiest part was figuring out that kicad is scaling the model to be a realistic few dozen mm in size, so three.js’s meter-long defaults were about a thousand times too big.
So at this point I’ve gotten a working model[2] render, and that’s very exciting! Like I said above, I was kind of amazed I could get this much up and running with relatively little effort.
There are a couple problems, though:
- The loading itself takes quite a while; I haven’t measured precisely, but from page load to the last “pop in” is on the order of 10 seconds in my testing.
- Once loaded, the frame rate is… not great. As shown above, I’m seeing ~24fps, and the orbital controls feel very sluggish.
The “weightiest” object in both cases is the RJ-45 jack on the right side of the screengrab there: it takes ~3-4 CPU-bound seconds to load in my setup, and toggling its visible
flag[3] more than halves the object/draw count from ~7000 down to ~3000.
Before I get too far into more of the details, I want to pause here and ask which, if any, of those numbers stand out to you. Like, 24fps is a little lower than seems to be the common target, but is a parser throughput on the order of 1MB/s considered fairly typical? When you hear “a few thousand objects/calls,” does that seem like it’d be beyond a common optimization target? I ask because from my perspective this isn’t a particularly large or complicated PCB, and a ten- or hundred-fold increase in complexity seems quite possible to me.
I’ve done a little exploring already with adding post-processing passes to cut down the object count (spoiler: it’s fairly straightforward to merge the geometries from the ~3000 object RJ-45 jack down to 7). With a bit of fiddling, that’s gotten me down to ~1500 objects/calls, which yields halfway decent frame rates for this PCB (north of 60fps, anyway). That said, it doesn’t look like it changes the shape of the profile very much to merge those objects, just shrinks the absolute timings. That suggests to me that ramping the complexity of the design is going to put me right back in the possibly-single-digit performance range.
So I suppose what I’m looking for at this point is whether or not I’m “barking up the wrong tree”: do I have a problem that’s outside the scope of what three.js is intended for? Or, have I done something to misuse the tool?
Namely, fixing parsing for numbers that end with a
.
(like10.
) and adding support forInline
nodes. The full diff for that is here: three.js VRMLLoader with fixes for kicad models · GitHub ↩︎Link to a branch containing this code: router/SYZYGY-PHY at wip/threejs-renderer · rustbox/router · GitHub ; the “first working render” is commit ↩︎
by way of the
shapes3D/ARJM...
toggle in the Models menu, if you’re playing along at home. ↩︎