Documentation is work in progress and not completeEditor
3D System

3D Troubleshooting

Each entry below gives the underlying cause first, because most of these symptoms have a single specific explanation rooted in how the 3D system is built.

Imported model shows as a cube

**Cause:** The project was saved and reloaded. Imported models carry geometryType: "imported", and restoreScene() skips them because their binary mesh data is not in the snapshot. The fallback in restoreFromConfig() creates a box when it meets an unreconstructable type.

**Solution:** Re-import the model file after loading the project. The binary data must be present at load time.

Textures missing on imported GLB

**Cause:** GLB files are self-contained and should include textures. If they appear missing, the model may use features the import pipeline does not support, such as certain KHR extensions. The system does not modify imported materials — it uses whatever the loader produces.

**Solution:** Verify the textures are actually embedded using a GLTF inspection tool, and re-export from Blender with Pack Resources enabled.

Shape disappears when deselected

**Cause:** This was the original bug that motivated the per-shape renderer architecture. With isolated renderers it should no longer occur.

**Solution:** Verify that setInteracting(false) only disables orbit and marks dirty — it should never call pause() or dispose(). Check that element.visible is not being set to false on deselect.

Gizmo not appearing on selection

**Cause:** The gizmo attaches only when selectObject(id) is called with a valid ID and the mesh exists in the scene manager.

**Solution:** Ensure the shape is in 3D editing mode, and that the click successfully raycasts to a mesh. The mesh needs geometry with triangles the raycaster can intersect.

3D canvas bleeding outside the canvas boundary

**Cause:** The host div is missing overflow: hidden.

**Solution:** ThreeDShapeRenderer sets overflow: hidden on the container, and Canvas.tsx sets it on the outer positioning div. Verify both are present.

Escape not closing the shape picker

**Cause:** Another component is capturing the keydown before it reaches the picker listener.

**Solution:** The picker registers its handler on window with no capture option. Look for stopPropagation() calls in parent components.

Properties panel not showing the 3D tab

**Cause:** The element's type is not 'threed-shape', or the getThreeDInstance callback is not returning the instance for the selected element.

**Solution:** Verify the element was created with type: "threed-shape", and that the instance registry maps element IDs to ThreeDShapeElement instances correctly.

Performance drops with multiple 3D shapes

**Cause:** Each shape runs its own render loop. Even with the dirty flag, several shapes with active orbit damping consume real GPU time.

  • Minimize the number of simultaneous 3D shapes.
  • Use pause() for shapes not visible or being edited.
  • Reduce renderer size for shapes that are small on the canvas.
  • Lower texture resolution and reduce polygon counts on imported models.