Documentation is work in progress and not completeEditor
3D System

Dirty Flag Render Loop

The render loop uses a render-on-demand pattern. requestAnimationFrame runs every frame, but renderer.render() only fires when the dirty flag is set — so an idle shape consumes no GPU time.

The Loop

private startLoop(): void {
  const loop = () => {
    if (this.disposed) return;
    this.animFrameId = requestAnimationFrame(loop);
    this.orbit.update();
    if (this.dirty) {
      this.renderer.render(this.scene, this.camera);
      this.dirty = false;
    }
  };
  loop();
}

orbit.update() still runs every frame because OrbitControls damping needs continuous updates when enabled. Only the render call is gated.

Events That Mark the Scene Dirty

EventLocation
OrbitControls change eventThreeDEngine.ts:71
Gizmo drag (change event)ThreeDEngine.ts:107
selectObject()ThreeDEngine.ts:173
addPrimitive()ThreeDEngine.ts:187
removeObject()ThreeDEngine.ts:233
setGizmoMode()ThreeDEngine.ts:238
updateTransform()ThreeDEngine.ts:243
updateMaterial()ThreeDEngine.ts:248
updateGeometry()ThreeDEngine.ts:253
updateEnvironment()ThreeDEngine.ts:263
resize()ThreeDEngine.ts:312
setInteracting() on ThreeDShapeElementThreeDShapeElement.ts:55
markDirty() called directlyThreeDEngine.ts:153-154

Working With the Pattern

  • After any operation that changes the visual state of the scene, call engine.markDirty().
  • Never call renderer.render() directly — let the loop handle it.
  • Marking dirty is cheap. When in doubt, mark it.