There's a lot more inside a 3D viewer than you'd expect
A 3D viewer in the browser looks simple on the surface. But once you start building one, you realize it takes 17+ internal modules working together — rendering, camera control, lighting, object selection, cross-section cutting, animation, and more.
Lessons from previous experience
When I was building a 3D viewer at my previous job, I ran into a recurring problem. As features were added one by one, modules started referencing each other directly. Changing one thing would break something else, again and again.
I also studied the open-source project 3dviewer.net, which exports 280+ functions and classes all at once. It felt like "where do I even start?"
How Voxel3D is designed
So with Voxel3D, I designed it differently from the beginning.
- You only need to know one entry point: the Voxel3D class
- The 17 internal modules are completely hidden — you can't access them directly
- Modules don't know about each other; they're connected through a central coordinator
const viewer = new Voxel3D({ container: '#app' });
viewer.loadModel('model.glb');
viewer.selectObject(mesh);
Behind these 3 lines, rendering, accelerated object lookup, selection detection, highlighting, and tree synchronization all work together automatically. But as a user, you don't need to know any of that.
Architecture
┌─────────────────────────────────────────────┐
│ External Consumer │
│ import { Voxel3D } from '...' │
├─────────────────────────────────────────────┤
│ Voxel3D (Facade) │
│ 180+ Public API Methods │
├──────┬──────┬──────┬──────┬──────┬──────────┤
│Scene │Camera│BVH │Select│Clip │ ...17+ │
│Mgr │Mgr │Mgr │Mgr │Mgr │ Managers │
├──────┴──────┴──────┴──────┴──────┴──────────┤
│ LogSystem ErrorSystem EventSystem │
└─────────────────────────────────────────────┘
Building a good 3D viewer is as much a software design challenge as it is a 3D technology one.