<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Took3D</title>
    <description>The latest articles on DEV Community by Took3D (@took3d).</description>
    <link>https://dev.to/took3d</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4240608%2Fe4ca5998-3886-479b-9fb1-7d9267a0d18a.png</url>
      <title>DEV Community: Took3D</title>
      <link>https://dev.to/took3d</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/took3d"/>
    <language>en</language>
    <item>
      <title>From a 4 GB CAD Assembly to a 1.9 MB Web Page: What Actually Shrinks a 3D Product Model</title>
      <dc:creator>Took3D</dc:creator>
      <pubDate>Thu, 12 Nov 2026 09:42:57 +0000</pubDate>
      <link>https://dev.to/took3d/from-a-4-gb-cad-assembly-to-a-19-mb-web-page-what-actually-shrinks-a-3d-product-model-4o6c</link>
      <guid>https://dev.to/took3d/from-a-4-gb-cad-assembly-to-a-19-mb-web-page-what-actually-shrinks-a-3d-product-model-4o6c</guid>
      <description>&lt;p&gt;A field note on asset budgets for interactive 3D product configurators.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;On a recent delivery, the engineering team handed us a 4 GB STEP assembly. The product page had to render an interactive, configurable model on a normal mobile connection, with the first frame on screen before the rest of the page felt blocked. Our working budget for the first frame was 2 MB. We shipped at 1.9 MB.&lt;/p&gt;

&lt;p&gt;That gap is not closed by "enabling compression". It is closed by a specific sequence of decisions, and doing them in the wrong order wastes most of the effort. Here is what we learned, in the order we actually run it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the weight really comes from
&lt;/h2&gt;

&lt;p&gt;Before touching any codec, measure the assembly. In our experience the bulk sits in five places:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Triangle count from CAD tessellation.&lt;/strong&gt; CAD surfaces are exported with a tolerance meant for manufacturing, not for a screen. A single fillet can produce thousands of triangles nobody will ever see.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Internal and hidden geometry.&lt;/strong&gt; Bolts, brackets, cavities and back faces that are never visible in any allowed view.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Materials and textures.&lt;/strong&gt; Duplicated materials, uncompressed PNG textures, and 4K maps on parts that occupy 40 px on screen.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Uninstanced duplicates.&lt;/strong&gt; Twenty identical screws exported as twenty separate meshes instead of one mesh with twenty transforms.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Node and metadata overhead.&lt;/strong&gt; Deep scene graphs, unused cameras, PMI and embedded metadata carried straight through the exporter.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Feid2kwxjsi9igwmquipp.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Feid2kwxjsi9igwmquipp.jpg" alt="A configurable gym rig rendered as an interactive 3D product model" width="800" height="497"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The first three usually account for well over 90% of the file. Compression alone cannot fix geometry that should not be there.&lt;/p&gt;

&lt;h2&gt;
  
  
  The order that works
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Decimate and retopologise first.&lt;/strong&gt; Reduce triangle count against a target silhouette error, not a fixed percentage. Check the silhouette at the smallest viewport you support.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Delete non-visible geometry.&lt;/strong&gt; Anything that cannot appear in an allowed camera or configuration state goes. This is a modelling decision, not a compression setting.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Merge materials and compress textures.&lt;/strong&gt; Combine identical materials, move to KTX2 / Basis Universal for GPU-native formats, and size each map to its real on-screen footprint.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Instance repeated parts.&lt;/strong&gt; One mesh, many transforms. This is often the single largest win on assemblies with hardware.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Apply geometry compression last.&lt;/strong&gt; Only now do Draco or Meshopt make sense — you are compressing geometry that has already earned its place.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Split only if the budget still fails.&lt;/strong&gt; More on that below.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Draco vs Meshopt
&lt;/h2&gt;

&lt;p&gt;Both are mature and both will cut a GLB substantially, but they optimise for different things.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Draco&lt;/th&gt;
&lt;th&gt;Meshopt&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Strength&lt;/td&gt;
&lt;td&gt;Smallest payload when bandwidth is the bottleneck&lt;/td&gt;
&lt;td&gt;Fastest decode, lower CPU cost at runtime&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Typical use&lt;/td&gt;
&lt;td&gt;Static hero model, slow networks&lt;/td&gt;
&lt;td&gt;Configurators with frequent variant swaps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Decode&lt;/td&gt;
&lt;td&gt;Relatively expensive on low-end mobile&lt;/td&gt;
&lt;td&gt;Cheap, often noticeably faster to first frame&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tooling&lt;/td&gt;
&lt;td&gt;Widely supported in glTF pipelines&lt;/td&gt;
&lt;td&gt;Strong support in Three.js / glTF-Transform&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For a configurator that swaps finishes and options on every click, decode cost compounds. We generally prefer Meshopt there and reserve Draco for a static single-model page where bytes are the dominant constraint. Measure on a real mid-range phone; desktop numbers are misleading.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to split instead of compress
&lt;/h2&gt;

&lt;p&gt;There is a point where further compression deforms the product. The better move is to split the model into a small &lt;strong&gt;first-frame shell&lt;/strong&gt; plus on-demand chunks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Load the shell (silhouette + primary surfaces) within the 2 MB budget.&lt;/li&gt;
&lt;li&gt;Defer optional components, interiors and high-detail variants until the user interacts.&lt;/li&gt;
&lt;li&gt;Reuse the same geometry across variants rather than exporting a full model per option.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This also improves perceived performance: the page becomes interactive before everything has arrived, and Core Web Vitals stay intact because the heavy payload is off the critical path.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pre-ship checklist
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Silhouette checked at the smallest supported viewport after decimation&lt;/li&gt;
&lt;li&gt;[ ] No internal or never-visible geometry left in the scene&lt;/li&gt;
&lt;li&gt;[ ] Textures in KTX2 / Basis, sized to real on-screen pixels&lt;/li&gt;
&lt;li&gt;[ ] Repeated parts instanced&lt;/li&gt;
&lt;li&gt;[ ] No IP-sensitive metadata or PMI carried into the public GLB&lt;/li&gt;
&lt;li&gt;[ ] First-frame budget measured on a throttled mobile connection&lt;/li&gt;
&lt;li&gt;[ ] Variant swaps tested without re-downloading the base mesh&lt;/li&gt;
&lt;li&gt;[ ] Largest Contentful Paint measured with the 3D view enabled&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Takeaway
&lt;/h2&gt;

&lt;p&gt;A 4 GB CAD file is not a web problem, it is a pipeline problem. Retopologise, delete, merge, instance, then compress — and split when the budget still will not hold. The codec is the last step, not the first.&lt;/p&gt;

&lt;p&gt;We are Took3D, a Web3D studio building interactive 3D product configurators for manufacturers and retailers. Longer field notes on the CAD-to-web pipeline and on choosing between a 360 spin and a full configurator:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.took3d.com/company-news/reduce-glb-file-size-for-web.html" rel="noopener noreferrer"&gt;https://www.took3d.com/company-news/reduce-glb-file-size-for-web.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.took3d.com/company-news/how-to-prepare-cad-files-for-a-web-3d-configurator.html" rel="noopener noreferrer"&gt;https://www.took3d.com/company-news/how-to-prepare-cad-files-for-a-web-3d-configurator.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.took3d.com/company-news/360-spin-vs-3d-configurator.html" rel="noopener noreferrer"&gt;https://www.took3d.com/company-news/360-spin-vs-3d-configurator.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Questions about a specific assembly or platform are welcome in the comments.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
