This was team work. Three of us shipped it: two 3D artists owning materials, lighting and art direction, and me owning the code. I acted as informal technical lead, which mostly meant unblocking their workflow and running training sessions. Where I say "I built" below, I mean the engineering. Everything visually good about it, they did.
The problem
On a mass customisation platform, a customer uploads artwork and needs to see it on the actual product before committing to a print run. It looks like a rendering problem, but most of the work is in the data.
The product exists as a CAD drawing or a die specification, not as a 3D model. The artwork is a flat file that knows nothing about the surface it will wrap around. And whatever you build has to run unattended across hundreds of client sites with different products, without an artist touching each one.
Code-driven 3D box preview from CAD
It reads CAD drawings and produces an interactive 3D box preview with custom movement instead of a static render, so there is no modelling step and no artist involved per product.
The hard part wasn't reading the file
It was everything after that. A CAD drawing gives you points and lines, and I had to turn those into panels that know their own thickness, cutouts, crease lines and how they move, generically enough to hold for any box, whether it follows a FEFCO standard or a client invented the die themselves. Anything hardcoded per style would have collapsed on the first custom one.
Then that structure has to survive the trip into BabylonJS as something you can actually use. You orbit it, fold it, print artwork across its surfaces, and change dimensions or board material live, and the geometry re-derives on the spot instead of waiting for a re-render.
Image layer warping in SVG
Photoshop's Puppet Warp reimplemented inside a Python pipeline, so artwork could be deformed to fit a product surface automatically, in SVG, as part of a batch process rather than by hand in an editor.
The configuration was the real problem
The demo proved the approach early, so what was left was the work around it. Every warp needed a configuration file, and those were built by hand. I had built a few myself, so I knew no client would ever sit through it, which meant the feature would exist and never get used.
So the work became deriving that configuration automatically, mapping a mesh of thousands of warp points across a 2D image without anyone placing them. That took setup from two to four hours down to about fifteen minutes, which is what turned it from something we could demo into something clients would run themselves.
AR visualisation embedded in QR codes
We tried delivering product visualisation through a QR code, so that a printed sample could carry its own augmented reality preview with no app install.
Why it stayed a prototype
Scanning the code with a phone took you to a web page, which then asked you to scan the same code again through its camera view so it could track the printed square and anchor a 2D or 3D asset on top of it. It worked, but asking someone to scan the same thing twice to see one animation was not an experience any of us wanted to defend, so we left it there.
Why BabylonJS
I inherited it rather than choosing it. I arrived knowing 3D and animation and nothing about WebGL, so the engine was settled before I had an opinion worth having.
Why I kept it once I could have changed it
Later I had enough standing to move us to three.js if I thought it was the better tool, and I looked at it properly. The tooling is what decided it: three.js was missing a few things I had come to rely on, the scene explorer most of all. By then staying was a choice, even if not a dramatic one.
What running at platform scale changes
A preview that works on one product in a demo is a different piece of software from one that works on every product across a thousand client sites, on hardware you do not control, with input files you did not author and cannot fix.
The one I still think about was not a 3D problem at all. A client wanted valid product option combinations restricted to a whitelist, which was scoped in a meeting at millions and turned out to describe billions. SQL had no index that could answer the question, so it moved to Elasticsearch and shipped on time.
No screenshots, assets or code from this work appear on this site. What is described here is the problem and the approach, which is what I can share.
What I took from it
Most of what I do now traces back to this. The dieline generator on this site is the same idea rebuilt from scratch against a public standard, generating real geometry from three dimensions and folding it in the browser. It exists partly so there is something in this domain I can actually show you.