---
title: "Performance and optimization"
description: "Why primitive assemblies are light, and the honest tradeoffs when they are not."
sidebar:
  badge: "Engineering"
---

## Why assemblies stay light

A generated model is a handful of parametric primitives — boxes, spheres, cylinders, capsules, cones and torus rings. Their geometry is generated on the CPU at construction time with modest segment counts, so total vertex counts stay small compared to a scanned or sculpted mesh.

There is no runtime download of a GLB or texture atlas, and no decode step. The cost is a bit of JavaScript at construction and then ordinary Three.js rendering.

## Draw calls are the real budget

Each part is a separate THREE.Mesh, so a model with forty nodes issues roughly forty draw calls. On its own that is cheap, but a scene full of instances multiplies quickly, and draw calls — not vertices — are usually what caps frame rate on a primitive assembly.

If a model does not need per-part animation, merge its static geometry into one buffer so the whole thing draws in a single call. Parts that must move should stay separate so you can still address them through the runtime.

```ts
import { mergeGeometries } from 'three/examples/jsm/utils/BufferGeometryUtils.js';
// Merge only the parts that never animate; keep movable nodes separate.
```

## Instance repeated models

When the same model appears many times — crates, props, enemies — do not add many Groups. Draw the shared geometry with THREE.InstancedMesh and a per-instance matrix so the GPU renders every copy in one call.

This trades away per-part runtime access for that shared geometry, so reserve instancing for background or crowd objects and keep hero pieces as full factory Groups you can animate.

## When to simplify

The method is a poor fit for dense organic surfaces; forcing detail there inflates node counts without matching the reference. If a model is heavier than it should be, lower radialSegments in the spec before adding parts, and drop nodes that do not carry a critical feature.

Be honest about the target. A hero object earns more parts and higher segment counts; a distant prop should be the fewest primitives that still read correctly at its on-screen size.
