3D Scanning and Printing

This week focuses on additive manufacturing and 3D scanning — designing objects that take advantage of what 3D printing can do that subtractive methods can't.

Assignment Requirements

Individual Assignment:

Project Documentation

For this assignment I designed two triply periodic minimal surface structures in Fusion 360. These are shapes with complex, repeating internal geometry that would be impossible to produce with subtractive manufacturing — you can't reach the inside with a drill or mill — making them perfect candidates for 3D printing.

Both models were created using the same process: I started with a solid cube, then used Fusion 360's Volumetric Lattice tool to replace the solid body with a lattice pattern. The tool lets you pick from different surface types and adjust cell size and thickness.

How to Find the Volumetric Lattice Tool in Fusion 360

The Volumetric Lattice tool isn't in the most obvious place — here's where to find it and how to use it:

Location of the Volumetric Lattice tool in Fusion 360 menu

Where to find the Volumetric Lattice tool in Fusion 360 — it's under the Mesh workspace, not the standard Solid modeling workspace

Using the Volumetric Lattice tool in Fusion 360

Using the Volumetric Lattice tool — select your solid body, choose a surface type (Gyroid, Schwarz D, etc.), and adjust cell size and wall thickness

Volumetric Lattice Tool — Key Features

  • Surface types: Gyroid, Schwarz D (Diamond), Schwarz P (Primitive), Neovius, and others — each produces a different repeating minimal surface geometry
  • Cell size: Controls how large each repeating unit is. Smaller cells = more detail but harder to print; larger cells = easier to print but less structural density
  • Wall thickness: How thick the lattice walls are. Thicker = stronger but heavier; thinner = lighter but more fragile
  • Fill type: You can choose between surface-only (hollow walls) or solid fill (thickened walls)
  • Important: After generating the lattice, you must convert it to a mesh (right-click → Convert to Mesh) before exporting as STL. If you skip this step, the slicer will just see a solid cube.

When I first tried to export the lattice to Bambu Studio for slicing, it just showed up as a solid cube — the slicer couldn't interpret the lattice data directly. After some troubleshooting, the solution I came up with was to convert the lattice structure to a mesh inside Fusion 360 before exporting the STL. That's why the models below look a bit faceted rather than perfectly smooth — the mesh conversion approximates the curved surfaces with flat triangles. Once 3D printed though, you won't be able to tell the difference at normal print resolution.

Gyroid Lattice Structure

The gyroid was discovered by NASA scientist Alan Schoen in 1970 while he was researching ultra-lightweight structures for space applications. It's a triply periodic minimal surface — meaning it repeats infinitely in all three directions and has zero mean curvature at every point (like a soap film). What makes it unique is that it has no straight lines and no planar symmetry — every surface curves smoothly in all directions.

Gyroids show up in nature too. Butterfly wings get some of their iridescent color from nanoscale gyroid structures, and certain types of sea urchin skeletons use the same geometry. In engineering, gyroids are used for lightweight structural parts because they distribute stress evenly across the entire surface, and their open-cell structure makes them useful for bone implants since tissue can grow through the channels.

I selected the Gyroid option in the Volumetric Lattice tool and adjusted the cell density to get a good balance between detail and printability.

Loading 3D model...

Gyroid lattice structure — designed in Fusion 360

📦 Download Gyroid STL

Finished Gyroid Print

3D printed gyroid lattice structure

The finished gyroid lattice print — came out clean

Gyroid Print Settings & Troubleshooting

I printed the gyroid on a Bambu Lab A1 with Bambu Lab blue PLA Basic using the following settings:

  • Infill pattern → Gyroid: Kind of funny — printing a gyroid with a gyroid infill pattern. But it actually makes sense: the gyroid infill follows similar curved paths as the model itself, which means the print head moves more smoothly and consistently rather than making sharp direction changes. This reduces vibration artifacts and gives better layer adhesion on the curved surfaces.
  • Added thin tree supports: Tree supports branch out and only touch the model where needed, which means less scarring on the surface when you remove them. For a lattice structure with lots of small overhangs, tree supports reach into tight spots that normal block supports can't without filling the entire interior.
  • Increased wall thickness: More walls means the outer shell of each lattice surface is thicker and stronger. On a model like this where the walls are the structure, adding wall thickness directly improves rigidity and reduces the chance of thin sections failing mid-print.
  • Increased infill density to 30%: Higher infill gives the walls more internal support to bond to, which helps bridge the gaps between lattice surfaces. At lower densities, the thin curved sections don't have enough backing material and can warp or collapse during printing.
  • Slow down by height: The printer automatically reduces speed on smaller layers near the top of the model, giving them more time to cool and solidify.

All other settings were left at the Bambu Studio slicer defaults.

Schwarz D (Diamond) Structure

The Schwarz Diamond surface was first described by German mathematician Hermann Schwarz in 1890, making it one of the oldest known triply periodic minimal surfaces. Schwarz was a student of Karl Weierstrass, and his work on minimal surfaces laid the groundwork for an entire branch of differential geometry. The "D" stands for Diamond because when you look at the surface's topology, it follows the same connectivity pattern as the carbon atoms in a diamond crystal lattice.

Compared to the gyroid, the diamond structure has sharper transitions and more defined channels running through it. This makes it particularly interesting for applications like heat exchangers (the channels allow fluid to flow through efficiently) and acoustic panels (the geometry scatters sound waves). It's also been studied for use in battery electrodes because the two interlocking channel networks can hold different materials while maximizing the surface area between them.

I used the same cube and Volumetric Lattice workflow, but selected the Schwarz Diamond option instead.

Loading 3D model...

Schwarz D (Diamond) structure — designed in Fusion 360

📦 Download Diamond STL

Finished Schwarz D Print

3D printed Schwarz D diamond lattice structure

The finished Schwarz D diamond print — came out clean

Schwarz D Print Settings

I printed on a Bambu Lab A1 Mini with Bambu Lab white PLA Basic using the following settings:

  • Infill pattern → Gyroid at 30% density: Gyroid infill prints faster than hexagonal because the nozzle moves in smooth continuous curves rather than making sharp direction changes at each corner. The 30% density gives the thin lattice walls enough internal support to bond to, which helps bridge the gaps between surfaces. At lower densities, the curved sections don't have enough backing material and can warp or collapse during printing.
  • Increased wall loops: Adding more wall loops makes the printed walls thicker, which strengthens the model and reduces the chance of thin sections breaking mid-print. It also hides the internal infill pattern from being visible through the surface.
  • Tree supports: Tree supports branch out from a central trunk and only touch the model where needed. They use less material than standard block supports, are easier to remove, and leave less scarring on the surface. For a lattice structure with lots of small overhangs, tree supports reach into tight spots that normal block supports can't without filling the entire interior.
  • Slow down by height: This setting automatically reduces print speed as the model gets taller. As the lattice narrows toward the top, each layer has less area and less time to cool before the next layer goes down. Slowing down gives each layer more time to solidify, preventing heat buildup that can cause warping or blobbing on small cross-sections.

All other settings were left at the Bambu Studio slicer defaults.

Scanning with Polycam

For the 3D scanning assignment, I used the free trial of Polycam to scan a small antler I found near my house. Polycam works by using photogrammetry — you walk around the object and take a bunch of overlapping photos from different angles. The app then analyzes the photos, identifies common features between them, and stitches them together to reconstruct a 3D mesh of the object. The more photos you take and the more overlap between them, the better the final scan turns out.

Exporting & Converting

The free version of Polycam doesn't let you export as STL or OBJ — the only free export option was a GLTF file. To get it into a usable format, I used convert3d.org, a free online GLTF to STL converter. I converted the scan into an STL and then imported it into Fusion 360 just to see how it looked — I didn't make any changes to the model in Fusion, I just wanted to view it there. It turned out surprisingly well — the detail on the antler came through clearly and the mesh was clean enough to work with.

Converted STL Scan

This is the raw converted STL from the Polycam scan after running it through the GLTF to STL converter:

📦 Download Converted Antler STL

Fusion 360 Import

After importing the STL into Fusion 360, the mesh was clean and detailed enough to work with directly:

Loading 3D model...

Antler scan — imported and exported from Fusion 360

📦 Download Fusion 360 Antler STL

📦 Download Antler Bambu Studio Project (.3mf)

3D Printing the Scan

I decided to 3D print the scanned antler. Unfortunately, the scanner got the scale of the model wrong — it came in much smaller than the real thing. To fix this, I scaled the model up by 350% in the slicer to get it to a size that looked just about accurate compared to the original antler.

Before printing, I cleaned the build plate with isopropyl alcohol to ensure proper bed adhesion. This removes any oils or residue from previous prints and helps the first layer stick evenly across the entire surface.

Bambu Studio slicer settings for antler print

Bambu Studio slicer view of the antler model scaled to 350%

Finished Antler Print

3D printed antler from Polycam scan

The finished 3D printed antler from the Polycam scan

One of the things I'm most happy with on this page is the interactive 3D model viewers. Instead of just showing static screenshots of the STL files, you can rotate, zoom, and inspect the models right in the browser. Here's how I set it up — it's actually not that complicated and could be useful for other Fab Academy students who want to show their 3D work.

The Technology: Three.js + STLLoader

The viewers use Three.js, a JavaScript library for rendering 3D graphics in the browser using WebGL. Three.js does all the heavy lifting — lighting, camera, materials, rendering — and its STLLoader module can read STL files directly, which is perfect since that's what we export from Fusion 360 and slicers.

No plugins, no downloads, no special software needed on the viewer's end — it runs in any modern browser.

Step 1: Add the Import Map

At the bottom of your HTML file (before the closing </body> tag), add an import map that tells the browser where to find Three.js. This loads it from a CDN so you don't need to download anything:

<script type="importmap">
{
  "imports": {
    "three": "https://cdn.jsdelivr.net/npm/three@0.170.0/build/three.module.js",
    "three/addons/": "https://cdn.jsdelivr.net/npm/three@0.170.0/examples/jsm/"
  }
}
</script>

Step 2: Create a Container in Your HTML

Add a <div> where you want the 3D viewer to appear. Give it an ID, set a height, and style it however you like:

<div id="stl-viewer"
     style="width: 100%; height: 500px; background: #1a1a2e;
            border-radius: 12px; overflow: hidden;
            position: relative; cursor: grab;">
  <p id="viewer-loading" style="position: absolute; top: 50%;
     left: 50%; transform: translate(-50%, -50%);
     color: #888;">Loading 3D model...</p>
</div>

Step 3: Write the Viewer Script

Add a <script type="module"> block that imports Three.js, sets up the scene, loads your STL file, and renders it with orbit controls:

<script type="module">
import * as THREE from 'three';
import { STLLoader } from 'three/addons/loaders/STLLoader.js';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';

// Get the container element
const container = document.getElementById('stl-viewer');

// Create the scene
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x1a1a2e);

// Camera
const camera = new THREE.PerspectiveCamera(
  45, container.clientWidth / container.clientHeight, 0.1, 1000
);

// Renderer
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(container.clientWidth, container.clientHeight);
renderer.setPixelRatio(window.devicePixelRatio);
container.appendChild(renderer.domElement);

// Orbit controls — lets the user click and drag to rotate
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.autoRotate = true;       // model spins slowly
controls.autoRotateSpeed = 2;

// Lighting
scene.add(new THREE.AmbientLight(0xffffff, 0.6));
const dirLight = new THREE.DirectionalLight(0xffffff, 1);
dirLight.position.set(5, 10, 7);
scene.add(dirLight);

// Load the STL file
new STLLoader().load('path/to/your-model.stl', function(geometry) {
  geometry.computeVertexNormals();

  // Material — change the color hex to whatever you want
  const material = new THREE.MeshPhongMaterial({
    color: 0x3498db,      // blue
    specular: 0x444444,
    shininess: 60
  });
  const mesh = new THREE.Mesh(geometry, material);

  // Center the model
  geometry.computeBoundingBox();
  const center = new THREE.Vector3();
  geometry.boundingBox.getCenter(center);
  mesh.position.sub(center);

  // Position camera based on model size
  const size = new THREE.Vector3();
  geometry.boundingBox.getSize(size);
  const maxDim = Math.max(size.x, size.y, size.z);
  camera.position.set(0, maxDim * 0.5, maxDim * 1.8);
  controls.update();

  scene.add(mesh);

  // Hide loading text
  document.getElementById('viewer-loading').style.display = 'none';
});

// Animation loop
function animate() {
  requestAnimationFrame(animate);
  controls.update();
  renderer.render(scene, camera);
}
animate();

// Handle window resize
window.addEventListener('resize', function() {
  camera.aspect = container.clientWidth / container.clientHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(container.clientWidth, container.clientHeight);
});
</script>

Step 4: Customize

The main things you'd change for your own models:

  • STL path: Change 'path/to/your-model.stl' to the relative path to your STL file
  • Color: Change the color: 0x3498db hex value — 0x3498db is blue, 0xe67e22 is orange, 0x2ecc71 is green, etc.
  • Background: Change 0x1a1a2e in the scene background to any color
  • Container height: Adjust the height: 500px in the container div
  • Auto-rotate: Set controls.autoRotate = false if you don't want the model to spin

Multiple Viewers on One Page

To show multiple models (like I do with the gyroid and diamond on this page), just create multiple container divs with different IDs and call the setup code for each one. I wrapped the setup in a reusable initViewer() function so I can call it for each model with different parameters.

Tips

  • File size matters: Large STL files (10MB+) will take a while to load. If your model is huge, consider reducing the mesh density in Fusion 360 before exporting.
  • Works with any STL: Anything you export from Fusion 360, Blender, PrusaSlicer, Bambu Studio — if it's an STL, it'll load.
  • No server needed: The Three.js library loads from a CDN, and the STL file loads from your own site's file structure. No backend required.
  • Mobile friendly: Touch gestures work for rotate (one finger), zoom (pinch), and pan (two fingers).
  • GLB models too: For the machine week page (week 12), I used Google's <model-viewer> web component instead, which loads GLB files. That's even simpler — just one HTML tag — but only works with GLB/GLTF format, not STL.

For the week 5 group assignment, our team tested different 3D printing capabilities and documented our lab's printers. You can view the full group page here: Week 5 Group Assignment.

My Contributions

I contributed two sections to the group assignment:

  • Infill Reference Card Print: I printed the "All 20 Infill Reference Card" on the Bambu X1 Carbon using the AMS to print in two colors — black for the background and white for the text and infill pattern samples. The card showcases all 20 infill patterns available in Bambu Studio (Rectilinear, Grid, Triangles, Gyroid, Honeycomb, Lightning, etc.), and I wrote detailed descriptions of each pattern covering their properties, strengths, and best use cases.
  • Lab 3D Printers: I documented all three of our lab's Bambu Lab printers — the A1, A1 Mini, and X1 Carbon — including their build volumes, motion systems, nozzle options, max speeds, and special features like the X1 Carbon's CoreXY system, lidar-assisted bed leveling, and enclosed build chamber.

Useful Links