From 8d02e5191bfc32d1d2c736c2cdfbc372aa85c795 Mon Sep 17 00:00:00 2001 From: wass08 Date: Wed, 11 Mar 2026 07:45:53 +0100 Subject: [PATCH] rule for layers --- .claude/rules/layers.md | 1 + .cursor/rules/creating-rules.mdc | 3 +- .cursor/rules/layers.mdc | 57 ++++++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 1 deletion(-) create mode 120000 .claude/rules/layers.md create mode 100644 .cursor/rules/layers.mdc diff --git a/.claude/rules/layers.md b/.claude/rules/layers.md new file mode 120000 index 00000000..de51970d --- /dev/null +++ b/.claude/rules/layers.md @@ -0,0 +1 @@ +../../.cursor/rules/layers.mdc \ No newline at end of file diff --git a/.cursor/rules/creating-rules.mdc b/.cursor/rules/creating-rules.mdc index 4ac11580..1c3639e6 100644 --- a/.cursor/rules/creating-rules.mdc +++ b/.cursor/rules/creating-rules.mdc @@ -1,6 +1,6 @@ --- description: How to create and maintain project rules -globs: +globs: .cursor/rules/** alwaysApply: false --- @@ -76,3 +76,4 @@ Concrete guidance with examples. | `events` | Typed event bus — emitting and listening to node and grid events | | `node-schemas` | Zod schema pattern for node types, createNode, updateNode | | `spatial-queries` | Placement validation (canPlaceOnFloor/Wall/Ceiling) for tools | +| `layers` | Three.js layer constants, ownership, and rendering separation | diff --git a/.cursor/rules/layers.mdc b/.cursor/rules/layers.mdc new file mode 100644 index 00000000..74b82407 --- /dev/null +++ b/.cursor/rules/layers.mdc @@ -0,0 +1,57 @@ +--- +description: Three.js layer conventions — which layer each object type lives on and why +globs: packages/viewer/**,apps/editor/** +alwaysApply: false +--- + +# Three.js Layers + +Three.js `Layers` control which objects each camera and render pass sees. We use them to separate scene geometry, editor helpers, and zone overlays into distinct rendering buckets without duplicating scene structure. + +## Layer Map + +| Constant | Value | Package | Purpose | +|---|---|---|---| +| `SCENE_LAYER` | `0` | `@pascal-app/viewer` | Default Three.js layer — all regular scene geometry | +| `EDITOR_LAYER` | `1` | `apps/editor` | Editor-only helpers: grid, tool previews, cursor meshes, snap guides | +| `ZONE_LAYER` | `2` | `@pascal-app/viewer` | Zone floor fills and wall borders — composited in a separate post-processing pass | + +Import the constants from their owning packages: + +```ts +// In viewer code +import { SCENE_LAYER, ZONE_LAYER } from '@pascal-app/viewer' + +// In editor code +import { EDITOR_LAYER } from '@/lib/constants' +``` + +## Why Separate Zones onto Layer 2 + +Zones use semi-transparent, `depthTest: false` materials that must be composited *on top of* the scene without being fed into SSGI or TRAA. The post-processing pipeline in `post-processing.tsx` renders a dedicated `zonePass` with a `Layers` mask that enables only `ZONE_LAYER` (and disables `SCENE_LAYER`), then blends its output into the final composite manually: + +```ts +const zoneLayers = useMemo(() => { + const l = new Layers() + l.enable(ZONE_LAYER) + l.disable(SCENE_LAYER) + return l +}, []) + +zonePass.setLayers(zoneLayers) +``` + +This keeps zones out of the SSGI depth/normal buffers (which would produce incorrect AO on transparent surfaces) while still letting them appear correctly over the scene. + +## Why Separate Editor Helpers onto Layer 1 + +The editor camera enables `EDITOR_LAYER` so tools and helpers are visible during editing. The thumbnail generator disables `EDITOR_LAYER` so exports show clean geometry without snap lines or cursor spheres. + +## Rules + +- **Never hardcode layer numbers.** Always use the named constants. +- **`SCENE_LAYER` and `ZONE_LAYER` belong in `@pascal-app/viewer`** — they are renderer concerns, not editor concerns. +- **`EDITOR_LAYER` belongs in `apps/editor`** — the viewer must never import it; editor behaviour is injected via props/children. +- **Zone meshes must set `layers={ZONE_LAYER}`** so they are picked up by `zonePass` and excluded from `scenePass` depth buffers. +- **Editor helper meshes must set `layers={EDITOR_LAYER}`** so they are invisible to the thumbnail camera and the viewer's render passes. +- **Do not add new layers without updating this rule** and the post-processing pipeline accordingly.