@tileflow/dev 0.1.0-alpha.36 → 0.1.0-alpha.38

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,7 +7,15 @@ textures. Animations, skins and morph targets are not evaluated; export their st
7
7
 
8
8
  ## Separate colour from architectural role
9
9
 
10
- Material names select a palette slot: `surface`, `secondary`, `glass`, `accent` or `roof`.
10
+ A material's name is the part it belongs to: an architectural part, `surface`, `secondary`,
11
+ `glass`, `accent` or `roof`, or a part of the model's own, such as `water`, `vegetation`, `wood` or
12
+ `stone`. Names are lower-case words joined by hyphens or underscores, at most 32 characters, and a
13
+ level names at most 16 parts; materials of the same part share its name. The map colours a part
14
+ through `buildings.threeDimensional.modelColors` under its name; a part it does not colour keeps
15
+ its material's colour. Name pools `water`, planting `vegetation` and timber `wood` where they fit:
16
+ Streets colours these from its water and tree colours in every theme. A GLB whose materials name
17
+ only `bark`, `leaves`, `fronds` or `stem` is a tree model, not a building model.
18
+
11
19
  The optional `material.extras.tileflow.lightingRole` selects lighting independently:
12
20
 
13
21
  ```json
@@ -29,25 +37,29 @@ roles are `unclassified`, `wall`, `door`, `roof`, `window`, `lamp` and `logo`. A
29
37
  geometry; it does not turn on light by itself. The map supplies emission through
30
38
  `buildings.threeDimensional.modelLighting`.
31
39
 
32
- Legacy models without an explicit role use these defaults:
40
+ A material without an explicit role takes its part's default:
41
+
42
+ | Part | Lighting role |
43
+ | -------------------------------- | -------------- |
44
+ | `surface`, `secondary`, `accent` | `wall` |
45
+ | `glass` | `window` |
46
+ | `roof` | `roof` |
47
+ | Any other part | `unclassified` |
33
48
 
34
- | Palette slot | Lighting role |
35
- | -------------------------------- | ------------- |
36
- | `surface`, `secondary`, `accent` | `wall` |
37
- | `glass` | `window` |
38
- | `roof` | `roof` |
49
+ A part names a colour, not a material: physical properties and emission remain controlled by the
50
+ authored material and its independent lighting role.
39
51
 
40
52
  Doors, lamps and logos require an explicit role. Use `unclassified` for a part that must not inherit
41
53
  a role. Invalid role names fail preparation. An exporter's numeric material suffix, such as
42
54
  `surface.001`, is ignored.
43
55
 
44
- Keep a stone relief in a wall role when it should receive the wall's lighting. A separate colour
45
- slot can distinguish its stone without creating a separate light source. Mark roof geometry as
56
+ Keep a stone relief in a wall role when it should receive the wall's lighting. A part of its own,
57
+ such as `stone`, can distinguish its colour without creating a separate light source. Mark roof geometry as
46
58
  roof even when it shares a colour with a facade.
47
59
 
48
60
  ## Physical materials
49
61
 
50
- The importer retains these glTF 2.0 channels independently of palette and role:
62
+ The importer retains these glTF 2.0 channels independently of part and role:
51
63
 
52
64
  | Channel | Inputs |
53
65
  | ------------------ | --------------------------------------------------------------------------------- |
@@ -60,6 +72,7 @@ The importer retains these glTF 2.0 channels independently of palette and role:
60
72
  | Unlit | `KHR_materials_unlit` |
61
73
 
62
74
  `TEXCOORD_0`, `TEXCOORD_1`, glTF sampler wrapping/filtering and `KHR_texture_transform` are retained.
75
+ `TEXCOORD_1` must lie between zero and one, since prepared files store it with sixteen bits.
63
76
  Every referenced channel must have its declared UV set. UV and colour seams survive welding.
64
77
  Colour textures and lit output use the scene's gamma-2.2 transfer approximation.
65
78
  Role emission mixes the complete material radiance toward its target, including authored emission.
@@ -107,8 +120,8 @@ A `door` role lights the surface. To project its spill, declare a rectangle in
107
120
 
108
121
  `start` and `end` form the horizontal lower edge. The spill faces the right of that edge when
109
122
  viewed from above. `height` sets the rectangle's height; optional `depth` narrows the spill around
110
- recessed jambs. Node transforms apply to the emitter. Its role supplies emission and its part
111
- supplies the fallback palette colour. No emitter is inferred from material colour or geometry.
123
+ recessed jambs. Node transforms apply to the emitter. Its role supplies emission and its part, by name,
124
+ supplies the fallback colour. No emitter is inferred from material colour or geometry.
112
125
 
113
126
  Each level accepts 128 emitters. Each projects a four-triangle, depth-tested spill with reach
114
127
  `clamp(1.3 * height, 4, 10)` metres. This authored effect does not cast a new light or shadow onto
@@ -116,11 +129,30 @@ other meshes. It follows the model's visibility and theme; zero emission removes
116
129
 
117
130
  ## Ambient visibility
118
131
 
119
- Preparation estimates each vertex's local ambient visibility using 48 deterministic,
120
- cosine-weighted hemisphere samples, a two-metre reach and a two-millimetre origin bias. A spatial
121
- hierarchy limits intersection work; repeated positions and normals share samples. Nearby
122
- occluders contribute more than distant ones. Each level is prepared independently, including
123
- occlusion between its distinct primitives. Footprint meshes do not occlude.
132
+ Preparation estimates local ambient visibility with deterministic, cosine-weighted hemisphere
133
+ samples, a two-metre reach and a two-millimetre origin bias. A spatial hierarchy limits
134
+ intersection work. Nearby occluders contribute more than distant ones. Each level is prepared
135
+ independently, including occlusion between its distinct primitives. Footprint meshes do not
136
+ occlude.
137
+
138
+ The near and mid levels carry visibility in an occlusion texture. Preparation lays the level's
139
+ triangles flat in one atlas: connected triangles facing within 20 degrees of each other share a
140
+ chart, curved strips are cut where they would waste their rectangle, and charts under two texels
141
+ share a palette of uniform grey texels. Shade detail grows with the square root of the level's
142
+ surface: about 89·A^0.54 texels of visible shade for A square metres, so a large building takes
143
+ coarser shade per metre than a small one. The near level's atlas budget allows for packing and
144
+ has two floors: 65,536 texels, so small detailed buildings keep their mouldings distinct, and
145
+ 1.3 texels a metre, so towers keep each storey's mullions and slabs apart. It takes at most
146
+ 524,288 texels; the mid level takes a quarter of it. The density is the highest at which
147
+ the atlas fits its budget. Each texel averages four points inside it, 12 rays each with turned
148
+ patterns; points hidden just behind other surfaces are skipped. The atlas is a greyscale JPEG of
149
+ quality 35, about a tenth of a byte a texel, on the second UV set, and becomes
150
+ every material's occlusion texture. Vertices are split where charts meet; triangles keep their
151
+ order.
152
+
153
+ Contact shade therefore follows the surface instead of spreading between distant vertices. A
154
+ level whose materials already use an occlusion texture or the second UV set, or whose charts
155
+ cannot fit the budget, and the far level keep 48-sample visibility on their vertices.
124
156
 
125
157
  The result travels independently of colour. Do not bake ambient occlusion into `COLOR_0`: colour
126
158
  also affects direct sunlight and emission. The runtime applies prepared visibility only to the
@@ -130,10 +162,11 @@ ambient contribution; solar visibility still comes from the dynamic shadow map.
130
162
  `threeDimensional.occlusion: false` also disables model ambient occlusion. Changing these
131
163
  runtime controls does not prepare the geometry again.
132
164
 
133
- Preparation cost grows with unique vertices, samples and nearby geometry. It is paid when a raw
134
- model is prepared, never per frame. Runtime occlusion adds no draw pass or texture and uses the
135
- existing visibility byte. It describes opaque geometry at rest; it does not follow moving parts,
136
- other models, the ground or surrounding buildings.
165
+ Preparation cost grows with texels, rays and nearby geometry; a large landmark's near level takes
166
+ seconds to tens of seconds. It is paid when a raw model is prepared, never per frame. A texture
167
+ used only for occlusion is uploaded with one channel, at most 0.7 MB with mipmaps for a near level.
168
+ Visibility describes opaque geometry at rest; it does not follow moving parts, other models, the
169
+ ground or surrounding buildings.
137
170
 
138
171
  ## Files and compatibility
139
172
 
@@ -144,36 +177,42 @@ for placement and limits.
144
177
 
145
178
  Prepared files retain a 16-byte vertex:
146
179
 
147
- | Bytes | Content |
148
- | ----- | -------------------------------- |
149
- | 0–5 | Quantized position |
150
- | 6–7 | Padding |
151
- | 8–10 | Normal |
152
- | 11 | Padding |
153
- | 12 | Palette slot |
154
- | 13 | Shade within that slot |
155
- | 14 | Ambient visibility, 0–255 |
156
- | 15 | Architectural lighting role, 0–6 |
157
-
158
- The model root's `extras.tileflow.lightingRoles: 1` declares the last byte. Older files without
159
- that marker use the legacy palette mapping. Existing fully exposed visibility values stay fully
160
- exposed; reprepare the original GLBs to obtain geometric occlusion. Geometry, normals and palette
161
- slots are not modified by the visibility calculation.
180
+ | Bytes | Content |
181
+ | ----- | ------------------------------------- |
182
+ | 0–5 | Quantized position |
183
+ | 6–7 | Padding |
184
+ | 8–10 | Normal |
185
+ | 11 | Padding |
186
+ | 12 | Part, an index into the level's parts |
187
+ | 13 | Shade within that part |
188
+ | 14 | Ambient visibility, 0–255 |
189
+ | 15 | Architectural lighting role, 0–6 |
190
+
191
+ Each level node's `extras.tileflow.parts` lists the names its part indices count through. Older
192
+ files without that list count through `surface`, `secondary`, `glass`, `accent` and `roof`. The
193
+ model root's `extras.tileflow.lightingRoles: 1` declares the last byte; older files without that
194
+ marker take each part's default role. Existing fully exposed visibility values stay fully exposed;
195
+ reprepare the original GLBs to obtain geometric occlusion. The occlusion texture splits vertices
196
+ along its charts without moving them or changing their normals or parts.
162
197
 
163
198
  Roles and visibility survive meshoptimizer compression. The existing `_PAINT` accessor and vertex
164
199
  stride are retained; the role occupies previously unused padding. Prepared files are an SDK
165
200
  transport format, while material extras are the authoring interface.
166
201
 
167
- Physical data is optional `extras.tileflow.surface` metadata on each level, with `version: 1`.
168
- Two VEC4 accessors address a separate 32-byte stream: UV0/UV1 followed by linear vertex RGBA.
202
+ Physical data is optional `extras.tileflow.surface` metadata on each level, with `version: 2`.
203
+ Three accessors address two streams: a 24-byte float stream holding UV0 and linear vertex RGBA,
204
+ and a 4-byte stream holding UV1 as normalised sixteen-bit values, so UV1 lies between zero and
205
+ one. Runtimes that read the earlier `version: 1` layout cannot read it, and current runtimes no
206
+ longer read `version: 1`: prepare models again with the matching Dev release.
169
207
  The metadata also holds material draw ranges, channel references, embedded images and emitters.
170
208
  Ranges preserve each source mesh's vertical emission bounds independently of its material.
171
- The original primitive layout remains unchanged. Older readers draw its legacy geometry and
172
- palette; they ignore the optional physical data. New readers preserve the legacy shading path
209
+ The original primitive layout remains unchanged. Older readers draw its geometry and part
210
+ colours; they ignore the optional physical data. New readers preserve the legacy shading path
173
211
  when physical data is absent. Reprepare source GLBs to obtain the new channels.
174
212
 
175
213
  The auxiliary stream costs 32 bytes per retained vertex on the GPU. Each resident texture uses
176
- four bytes per pixel, plus about one third for mipmaps when enabled. Decoded images stay available
214
+ four bytes per pixel, or one when only occlusion reads it, plus about one third for mipmaps when
215
+ enabled. Decoded images stay available
177
216
  for context restoration until the model is evicted. Physical materials add one draw per material
178
217
  range per colour/shadow pass; explicit emitters add one four-triangle draw each. No environment
179
218
  cube map or screen-space effect is required.
@@ -3,7 +3,7 @@
3
3
  Open the local preview and select **Layers**. The panel inspects the current map without changing its
4
4
  authored style. **By module** groups physical layers using compiler contributions; shared layers retain
5
5
  every owner. **Draw order** lists the renderer's public layer sequence, latest draw calls first.
6
- Custom runtime layers are included even though they are absent from Style JSON. DevTools overlays
6
+ Custom runtime layers are included even though they are absent from Style JSON. Inspector overlays
7
7
  are excluded. Unknown ownership is labeled **Unattributed**, rather than guessed from an ID.
8
8
 
9
9
  Press **I** or the element-picker icon and click an element on the map. Its layer becomes selected in
@@ -1,13 +1,13 @@
1
- # Map DevTools and compiler inspection
1
+ # Inspector and compiler inspection
2
2
 
3
3
  Start with the [@tileflow/dev guide](https://github.com/tileflow/tileflow-sdk/blob/main/packages/dev/README.md) for installation and a complete first example.
4
4
 
5
- The CLI opens Map DevTools through `tileflow preview`. It uses one map and one watched artifact
6
- session by default. A developer-tools panel groups Map, Layers, Tiles, Assets, Debug and Diagnostics. Camera controls
5
+ The CLI opens Inspector through `tileflow preview`. It uses one map and one watched artifact
6
+ session by default. The panel groups Map, Layers, Tiles, Assets, Debug and Diagnostics. Camera controls
7
7
  occupy a separate row below the navigation. Use the three-dot menu to dock left, right or below
8
8
  the map and choose System, Light or Dark appearance. Drag the divider to resize it; focused dividers
9
9
  also support arrow keys. Dock position and dimensions persist locally. Layer observations and highlights stay local to the preview. The map fills the remaining
10
- workspace without brand headers or map-status badges. Closing the panel leaves a small **DevTools**
10
+ workspace without brand headers or map-status badges. Closing the panel leaves a small **Inspector**
11
11
  button to reopen it; capture and comparison controls are absent from the interface.
12
12
 
13
13
  Add `--against-map ...` or `--against-config ...` for synchronized comparison. Custom local servers
@@ -34,7 +34,7 @@ const fetch = createTileflowComparisonRequestHandler({
34
34
  });
35
35
  ```
36
36
 
37
- Set `fitViewport: true` on each dev handler embedded in a resizable Map DevTools pane. Scene previews
37
+ Set `fitViewport: true` on each dev handler embedded in a resizable Inspector pane. Scene previews
38
38
  then fit their pane while captures retain the scene's declared frame. Standalone dev handlers keep
39
39
  the fixed scene viewport by default.
40
40
 
@@ -1,6 +1,6 @@
1
1
  # Map design diagnostics
2
2
 
3
- Open **Diagnostics** in Map DevTools to investigate a map's rules, visual resources and current-view
3
+ Open **Diagnostics** in Inspector to investigate a map's rules, visual resources and current-view
4
4
  composition. The list groups findings under **Readability**, **Style**, **Assets** and **Performance**.
5
5
  **Problem** means a confirmed configuration or resource failure. **Review** means an observed
6
6
  situation may be intentional. Counts refer to grouped findings, not quality scores.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tileflow/dev",
3
- "version": "0.1.0-alpha.36",
3
+ "version": "0.1.0-alpha.38",
4
4
  "license": "Apache-2.0",
5
5
  "description": "Node development utilities for Tileflow configs and builds.",
6
6
  "type": "module",
@@ -84,7 +84,7 @@
84
84
  "dependencies": {
85
85
  "@mapbox/vector-tile": "3.0.0",
86
86
  "@maplibre/maplibre-gl-style-spec": "26.4.4",
87
- "@tileflow/core": ">=0.1.0-alpha.39 <0.1.0-beta.0",
87
+ "@tileflow/core": ">=0.1.0-alpha.41 <0.1.0-beta.0",
88
88
  "chokidar": "4.0.3",
89
89
  "fontkit": "2.0.4",
90
90
  "jiti": "^2.7.0",
@@ -96,13 +96,13 @@
96
96
  "three": "0.185.1"
97
97
  },
98
98
  "devDependencies": {
99
- "@tileflow/maps": "0.1.0-alpha.13"
99
+ "@tileflow/maps": "0.1.0-alpha.15"
100
100
  },
101
101
  "optionalDependencies": {
102
102
  "sharp": "0.35.5"
103
103
  },
104
104
  "scripts": {
105
- "build": "tsup src/artifacts.ts src/config.ts src/fonts.ts src/icons.ts src/inspect.ts src/preview.ts src/server.ts src/tilesets.ts src/validation.ts --format esm --dts --clean --platform node --external sharp && tsup --config tsup.devtools.config.ts",
105
+ "build": "tsup src/artifacts.ts src/config.ts src/fonts.ts src/icons.ts src/inspect.ts src/preview.ts src/server.ts src/tilesets.ts src/validation.ts --format esm --dts --clean --platform node --external sharp && tsup --config tsup.inspector.config.ts",
106
106
  "test": "tsx --test test/*.test.ts",
107
107
  "typecheck": "tsc -p tsconfig.json --noEmit",
108
108
  "lint": "tsc -p tsconfig.json --noEmit",