@solidrt/3d 0.0.65 → 0.0.66

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.
package/AGENTS.md CHANGED
@@ -217,7 +217,7 @@ displacement - and `cullMargin` (world units, Godot's
217
217
  `extra_cull_margin`) for bounded displacement such as wind. Sprites
218
218
  cull by their quad's reach at any facing. A SKINNED part is culled by
219
219
  the union of its joints' boxes (the bake computes each joint's
220
- influence box in joint space, `ModelSkin.jointBounds`, .srtm VERSION
220
+ influence box in joint space, `ModelSkin.jointBounds`, .sol3m VERSION
221
221
  5; the joint nodes carry them as culling-only bounds, outside the
222
222
  picking index), so the box follows the pose with no per-frame JS -
223
223
  Unity's bone bounds, Godot's per-bone AABBs; no `updateWhenOffscreen`
@@ -409,7 +409,7 @@ that pop in and shrink away on tap, the shelf cascading out and back
409
409
  through `<Show>`. Each natural settle calls the node's `onTransitionEnd`
410
410
  (plain field like the pointer handlers) with `{ component }` - never on
411
411
  a cancel, snap, leave or exit; the raw "spatialTransitionEnd" engine
412
- event (srt:events, carrying the CORE node id `_node`) stays for
412
+ event (sol:events, carrying the CORE node id `_node`) stays for
413
413
  flux:spatial consumers.
414
414
 
415
415
  ### Geometry layout, indices and topology
@@ -495,7 +495,7 @@ so the mesh picks and culls where it is now drawn (the box follows at
495
495
  the next flush, the triangle index is rebuilt by the next query - a
496
496
  deforming mesh needs no re-attach). transformGeometry and
497
497
  the edge builders share extra streams with their source; merge
498
- concatenates every stream; the `.srtm` container refuses streams (run
498
+ concatenates every stream; the `.sol3m` container refuses streams (run
499
499
  time data). `setDrawRange(mesh, first, count?)` draws indices `[first,
500
500
  first + count)` of the mesh's geometry (Three's `setDrawRange`, on the
501
501
  mesh because the scene owns the entries), applied to every entry of the
@@ -550,12 +550,12 @@ are Solid-free and
550
550
  GPU-free BY DESIGN so they can be checked headless and run under bun:
551
551
  `src/model-data.ts` re-exports exactly this set as the published
552
552
  `@solidrt/3d/model` entry (the bake tool and app bake scripts), and
553
- `tests/model-data.test.ts` imports it under `srt test`, on the bare flux
554
- binary, so a gui or `srt:` import creeping into any of them fails there
553
+ `tests/model-data.test.ts` imports it under `sol test`, on the bare flux
554
+ binary, so a gui or `sol:` import creeping into any of them fails there
555
555
  (a headless `flux:` import would not); keep them that way.
556
556
  `src/splat-data.ts` is its own published entry the same way
557
557
  (`@solidrt/3d/splat`, guarded by `tests/splat-data.test.ts`).
558
- The tests under `tests/` run with `bun run srt test packages/3d` from the
558
+ The tests under `tests/` run with `bun run sol test packages/3d` from the
559
559
  repo root, or one file, or `--filter <text>` for the tests whose name
560
560
  contains it: the pure modules on the bare flux binary, and the files
561
561
  that need a GPU (`.test.tsx`, importing `@solidrt/test`) on the
@@ -1664,10 +1664,10 @@ specular, `envIrradiance` - the fully rough sample along the normal, as
1664
1664
  Three's getIBLIrradiance and Godot read it - added to the hemisphere
1665
1665
  for the diffuse) and every `phong({ reflectivity })` material mirrors,
1666
1666
  typically the skybox's own cube turned with it. The cube to use is a
1667
- BAKED one: `bun run srt tool 3d/environment sky.hdr -o assets/sky.srte`
1667
+ BAKED one: `bun run sol tool 3d/environment sky.hdr -o assets/sky.sol3e`
1668
1668
  turns an equirectangular Radiance .hdr (Poly Haven's are CC0) into the
1669
1669
  six faces plus the GGX-prefiltered mip chain in linear float, and
1670
- `await loadEnvironment("assets/sky.srte")` uploads it as an explicit
1670
+ `await loadEnvironment("assets/sky.sol3e")` uploads it as an explicit
1671
1671
  "rgba16f" chain (createCubeTexture's array-of-levels form: no generated
1672
1672
  mipmaps, so no half-float render support needed - it works on every
1673
1673
  device; created after an await, so not auto-freed). Unity convolves at
@@ -1682,7 +1682,7 @@ is a coarse average - fine for a sky gradient, wrong for a photograph.
1682
1682
  A 128 environment (2 MiB, the default) lights any surface; for a
1683
1683
  mirror-finish showpiece bake at 256, and for a crisp backdrop pair it
1684
1684
  with a separate hi-res LDR skybox (a 2k panorama through equirectToCube)
1685
- as `background` while the .srte stays the `environment`. Scene-level like Three's
1685
+ as `background` while the .sol3e stays the `environment`. Scene-level like Three's
1686
1686
  `scene.environment`, Unity's environment reflections and Godot's
1687
1687
  sky-lit reflections: ONE `uEnv` samplerCube bound on every target the
1688
1688
  scene draws into (a 1x1 black placeholder while unset) and one
@@ -1750,7 +1750,7 @@ one), then the PREFILTER: the faces convolved on the GPU into a second,
1750
1750
  `mipmap: true` cube target level by level (`renderTarget(chain, face,
1751
1751
  level)`, one small pass each - 48 at 128 - the bake tool's GGX
1752
1752
  importance sampling as a fragment, `createPrefilter` in environment.ts,
1753
- with the same roughness-to-level rule as a .srte chain), so `standard`
1753
+ with the same roughness-to-level rule as a .sol3e chain), so `standard`
1754
1754
  blurs a probe by roughness exactly like a baked environment; `prefilter:
1755
1755
  false` skips it and hands out the sharp faces (Three's CubeCamera: a
1756
1756
  mirror at every roughness). COST: the chain's passes are tiny, but a
@@ -1808,7 +1808,7 @@ clamp (`repeat` also wraps vertically and bleeds the poles). An HDR
1808
1808
  panorama uploaded as rgba16f converts into a half-float cube (sharp:
1809
1809
  a skybox, or `mipmap: true` for the box chain); its PREFILTERED form is
1810
1810
  the bake tool above, whose CPU pipeline (`src/environment-bake.ts`:
1811
- decodeHdr, panoramaToCube, prefilterCube, the .srte encode/decode) is
1811
+ decodeHdr, panoramaToCube, prefilterCube, the .sol3e encode/decode) is
1812
1812
  pure TypeScript and bun-tested - there is no runtime .hdr decoder.
1813
1813
 
1814
1814
  ### Fog
@@ -2324,8 +2324,8 @@ for the loaders that scope is the caller's at the call, captured before
2324
2324
  the await, so a model loaded inside a memo goes with the memo's rerun
2325
2325
  and one loaded in a component with its unmount. A load that settles
2326
2326
  after its scope is gone (unmounted mid-load) is freed on arrival and
2327
- resolves already disposed - nothing owns it any more. `loadModel` reads the baked `.srtm` written by `srt tool
2328
- 3d/model <in.gltf|glb> -o assets/<name>.srtm`: the same parse run once
2327
+ resolves already disposed - nothing owns it any more. `loadModel` reads the baked `.sol3m` written by `sol tool
2328
+ 3d/model <in.gltf|glb> -o assets/<name>.sol3m`: the same parse run once
2329
2329
  at build time, stored in the GPU layout, so loading is views onto the
2330
2330
  file's bytes plus the image decodes. Numbers from a 32k-vertex, 6-texture model
2331
2331
  on a release client: `parseGltf` 124 ms on flux (22 ms under bun) against
@@ -2336,7 +2336,7 @@ models and a binary import (`import bytes from "./x.glb" with { type:
2336
2336
 
2337
2337
  #### Compressed textures
2338
2338
 
2339
- `srt tool 3d/model <in> -o assets/<name>.srtm` bakes the images
2339
+ `sol tool 3d/model <in> -o assets/<name>.sol3m` bakes the images
2340
2340
  too: each becomes a KTX2 compressed texture with its mip chain. The file is the
2341
2341
  same for every platform; at load each device turns the images into the
2342
2342
  block format its GPU samples (BC7 on desktops, ETC2 elsewhere), which
@@ -2456,12 +2456,12 @@ import type { ModelData } from "@solidrt/3d/model"
2456
2456
  // takes `placements`), materials as glTF-shaped records, app data in
2457
2457
  // `extras` (JSON) and `blobs` (named bytes, each an aligned block).
2458
2458
  let data: ModelData = { nodes, parts, skins: [], clips: [], materials, images: [], bounds, extras: { spawn }, blobs: { grid } }
2459
- await Bun.write("assets/level.srtm", encodeModel(data))
2459
+ await Bun.write("assets/level.sol3m", encodeModel(data))
2460
2460
  ```
2461
2461
 
2462
- `loadModel("assets/level.srtm")` then builds it like any authored model;
2462
+ `loadModel("assets/level.sol3m")` then builds it like any authored model;
2463
2463
  `model.extras` and `model.blobs` hand the app data back (blobs are views
2464
- onto the loaded bytes). `srt tool 3d/model` is the same entry applied
2464
+ onto the loaded bytes). `sol tool 3d/model` is the same entry applied
2465
2465
  to a glTF, so the two bakes share one code path.
2466
2466
 
2467
2467
  ### Async loading
@@ -2479,7 +2479,7 @@ PENDING_ASYNC_UNTRACKED_READ, and any element the component builds before
2479
2479
  the suspending read is orphaned on the boundary's retry and never freed
2480
2480
  (the dev leak sentinel reports it) - so the suspending component creates
2481
2481
  no elements of its own. Async here means the file read: the parse and
2482
- createModel run synchronously on main. Bake anything big to .srtm; when
2482
+ createModel run synchronously on main. Bake anything big to .sol3m; when
2483
2483
  a source glTF must be parsed at runtime, do the parse in an isolate
2484
2484
  (parseGltf's result is plain data and copies across) and keep
2485
2485
  createModel on main.
@@ -2552,10 +2552,10 @@ rigged one; linear and premultiplied as glTF stores it) and the default
2552
2552
  material takes `vertexColors: true` for such parts - the callback's
2553
2553
  fourth argument says so, and a material shared by painted and unpainted
2554
2554
  parts is made once per variant, like the skinned split.
2555
- A `.srtm` baked before the material records carried the PBR fields
2555
+ A `.sol3m` baked before the material records carried the PBR fields
2556
2556
  (file version 3), or before the vertex formats took the WebGPU spelling
2557
2557
  and byte counts (file version 5), is rejected by loadModel - re-bake
2558
- with `srt tool 3d/model`. A baked part keeps a quantized export's
2558
+ with `sol tool 3d/model`. A baked part keeps a quantized export's
2559
2559
  bytes: u8 colors, u8/u16 joints and normalized weights, u16 uvs land in
2560
2560
  their own formats, positions and normals as floats.
2561
2561
 
@@ -2695,10 +2695,10 @@ mesh (JS-written records, no nodes) cannot morph: rejected at add().
2695
2695
 
2696
2696
  Not in the subset, dropped: tangents and further UV sets; samplers are
2697
2697
  ignored (every texture repeats); additive blending draws as base color.
2698
- The follow-ups are filed in okf/backlog/3d-model-loader.md. The `.srtm`
2698
+ The follow-ups are filed in okf/backlog/3d-model-loader.md. The `.sol3m`
2699
2699
  container is VERSION 11 (node table in the header, node-local vertices,
2700
2700
  skins, clips, packed morph targets, app data, images under their
2701
- names); older bakes are rejected - re-bake with `srt tool 3d/model`.
2701
+ names); older bakes are rejected - re-bake with `sol tool 3d/model`.
2702
2702
 
2703
2703
  ## Splats
2704
2704
 
@@ -2715,12 +2715,12 @@ successors) as ordinary content, the model-loading split repeated:
2715
2715
  times opacity, so the first n are the scene at n), y-down captures
2716
2716
  (.ply, .splat) stood up to y-up (positions and covariances rotated
2717
2717
  together; `keepOrientation` opts out, `.spz` is y-up already), bounds
2718
- measured. `encodeSplat`/`decodeSplat` round-trip the `.srts` container
2718
+ measured. `encodeSplat`/`decodeSplat` round-trip the `.sol3s` container
2719
2719
  (the record and SH blocks, next bullet); decode is a header parse
2720
- plus byte VIEWS, nothing per-splat. `srt tool 3d/splat <in> [-o
2721
- out.srts] [--sh 0..3] [--keep-orientation]` is the parse and bake
2720
+ plus byte VIEWS, nothing per-splat. `sol tool 3d/splat <in> [-o
2721
+ out.sol3s] [--sh 0..3] [--keep-orientation]` is the parse and bake
2722
2722
  under bun (tools/splat.ts); an app bake script uses the same entry.
2723
- - The `.srts` record (version 2) is 32 bytes = two rgba32ui texels:
2723
+ - The `.sol3s` record (version 2) is 32 bytes = two rgba32ui texels:
2724
2724
  center float32x3 + sRGB color and opacity unorm8x4, then the
2725
2725
  covariance upper triangle as six float16 + a spare word
2726
2726
  (SPLAT_ATTRIBUTES as a byte layout, SPLAT_RECORD_TEXELS). `--sh 1..3`
@@ -2731,7 +2731,7 @@ successors) as ordinary content, the model-loading split repeated:
2731
2731
  rgb interleaved), 32/48/96 bytes per splat of texture, so the
2732
2732
  default is 0 and a bake opts in. The y-up flip negates the
2733
2733
  coefficients whose basis is odd in (y, z).
2734
- - On the runtime, `loadSplat(path)` reads a `.srts` (fetch + decode,
2734
+ - On the runtime, `loadSplat(path)` reads a `.sol3s` (fetch + decode,
2735
2735
  the loadModel shape) and `createSplatMesh(data, { count?, material?,
2736
2736
  label? })` / `<SplatMesh>` shows it: a RecordMesh in the INDEXED form
2737
2737
  (see "Instance order") - the records handed to the engine as the
@@ -2828,7 +2828,7 @@ successors) as ordinary content, the model-loading split repeated:
2828
2828
  ambient probe, this does not). glTF's default metallic factor is 1,
2829
2829
  so an untextured asset is all metal, and createModel's default is
2830
2830
  `standard`: give a model scene an `environment` (loadEnvironment's
2831
- baked .srte, or the skybox's cube), or pass `phong` as the material.
2831
+ baked .sol3e, or the skybox's cube), or pass `phong` as the material.
2832
2832
  - Light intensities are the same numbers for `phong` and `standard`: 1
2833
2833
  lights a white matte surface to 1 face-on. A Three scene's intensities
2834
2834
  are a factor pi larger for the same look; divide when porting.
@@ -2901,7 +2901,7 @@ successors) as ordinary content, the model-loading split repeated:
2901
2901
  - A generated cube chain (`mipmap: true` from six faces) is a box
2902
2902
  filter, not the GGX convolution the roughness-to-level rule assumes:
2903
2903
  rough reflections read too sharp and the diffuse `envIrradiance` is a
2904
- 4x4 average. Bake with `srt tool 3d/environment` for anything
2904
+ 4x4 average. Bake with `sol tool 3d/environment` for anything
2905
2905
  photographed; the JS sky gradients in the examples get away with it.
2906
2906
  - The background covers the whole target with depth off, drawn first: it
2907
2907
  REPLACES the clearColor visually (the clear still runs; you just never
@@ -1,6 +1,6 @@
1
1
  # @solidrt/3d examples
2
2
 
3
- One concept per file; run with `bun run srt run <file>` from an app that
3
+ One concept per file; run with `bun run sol run <file>` from an app that
4
4
  depends on `@solidrt/3d` (or in-repo from the package directory).
5
5
 
6
6
  - `scene-basic.tsx` - the whole v1 surface: a `<Scene>` composited as a
@@ -57,8 +57,8 @@ depends on `@solidrt/3d` (or in-repo from the package directory).
57
57
  the environment as tinted reflections, the dielectric row the same
58
58
  sky as a faint face-on gloss. Drag to look around.
59
59
  - `environment.tsx` - a baked HDR environment lighting the scene ALONE
60
- (no lights, no hemisphere): `loadEnvironment` reads the .srte that
61
- `bun run srt tool 3d/environment <panorama>.hdr -o assets/environment.srte`
60
+ (no lights, no hemisphere): `loadEnvironment` reads the .sol3e that
61
+ `bun run sol tool 3d/environment <panorama>.hdr -o assets/environment.sol3e`
62
62
  bakes from any equirectangular .hdr (Poly Haven's are CC0; the asset
63
63
  is not committed, bake one first), used as background and environment
64
64
  with ACES tone mapping. A metal row and a red dielectric row, roughness
@@ -200,4 +200,4 @@ depends on `@solidrt/3d` (or in-repo from the package directory).
200
200
  stays above the boundary - the two rules that avoid
201
201
  PENDING_ASYNC_UNTRACKED_READ and the suspend-retry element leak. Needs
202
202
  the asset baked into the running app:
203
- `bun run srt tool 3d/model examples/model.glb -o assets/model.srtm`.
203
+ `bun run sol tool 3d/model examples/model.glb -o assets/model.sol3m`.
@@ -22,7 +22,7 @@
22
22
  // plane, so the far pillars sink into the horizon instead of clipping
23
23
  // (`examples/fog.tsx` is the fog tour).
24
24
  import { createSignal, flush, onFrame, pct, render } from "@solidrt/core"
25
- import { registerDebug } from "srt:dev"
25
+ import { registerDebug } from "sol:dev"
26
26
  import { box, DirectionalLight, HemisphereLight, phong, Mesh, PerspectiveCamera, plane, Scene, sphere } from "@solidrt/3d"
27
27
  import type { Geometry, Vec3 } from "@solidrt/3d"
28
28
 
@@ -30,7 +30,7 @@ import {
30
30
  sphere,
31
31
  } from "@solidrt/3d"
32
32
  import type { FirstPersonCameraHandle, MeshNode, MoveResult, SceneHandle, Vec3, Volume } from "@solidrt/3d"
33
- import { registerDebug } from "srt:dev"
33
+ import { registerDebug } from "sol:dev"
34
34
 
35
35
  // Layer bit the level geometry adds to its drawn layer: what every
36
36
  // collision query selects, so pickups (drawn only) never block the walker.
@@ -14,7 +14,7 @@
14
14
  import { createSignal, For, pct, render, Show } from "@solidrt/core"
15
15
  import { box, Group, Mesh, PerspectiveCamera, plane, Scene, unlit } from "@solidrt/3d"
16
16
  import type { NodeTransition, SceneHandle, SceneTapEvent, Vec3 } from "@solidrt/3d"
17
- import { registerDebug } from "srt:dev"
17
+ import { registerDebug } from "sol:dev"
18
18
 
19
19
  const COUNT = 5
20
20
  // Crate spacing along x, and the pause before a tapped-away crate is
@@ -13,7 +13,7 @@ import { createInputMap, createPointerFeed, createSignal, gamepad, keyboard, loc
13
13
  import type { PointerEvent } from "@solidrt/core"
14
14
  import { box, cylinder, DirectionalLight, FirstPersonCamera, firstPersonActions, firstPersonBindings, HemisphereLight, phong, Mesh, PerspectiveCamera, plane, Scene } from "@solidrt/3d"
15
15
  import type { FirstPersonCameraHandle, Vec3 } from "@solidrt/3d"
16
- import { registerDebug } from "srt:dev"
16
+ import { registerDebug } from "sol:dev"
17
17
 
18
18
  // Half extent of the walkable courtyard in world units; the walls stand
19
19
  // just outside it.
@@ -18,7 +18,7 @@
18
18
  import { createInputMap, createPointerFeed, createSignal, flush, For, gamepad, pct, render } from "@solidrt/core"
19
19
  import { box, DirectionalLight, HemisphereLight, Instance, InstancedMesh, phong, Mesh, OrbitCamera, orbitActions, orbitBindings, plane, Scene, worldPosition } from "@solidrt/3d"
20
20
  import type { InstanceNode, NodeTransition, SceneHandle, Vec3 } from "@solidrt/3d"
21
- import { registerDebug } from "srt:dev"
21
+ import { registerDebug } from "sol:dev"
22
22
 
23
23
  type Tint = [number, number, number, number]
24
24
 
package/examples/fog.tsx CHANGED
@@ -19,7 +19,7 @@
19
19
  // repeats; `suns` is the two suns' world positions and `project`
20
20
  // (`{ point }`) is where a world point is on screen, for a pixel probe.
21
21
  import { createSignal, flush, onFrame, pct, render } from "@solidrt/core"
22
- import { registerDebug } from "srt:dev"
22
+ import { registerDebug } from "sol:dev"
23
23
  import { cone, cylinder, DirectionalLight, HemisphereLight, phong, Mesh, PerspectiveCamera, plane, Scene, sphere, unlit } from "@solidrt/3d"
24
24
  import type { FogOptions, SceneHandle, Vec3 } from "@solidrt/3d"
25
25
 
package/examples/lod.tsx CHANGED
@@ -21,7 +21,7 @@
21
21
  import { onFrame, pct, render } from "@solidrt/core"
22
22
  import { addInstance, cone, cylinder, DirectionalLight, HemisphereLight, icosahedron, InstancedLod, phong, Lod, Mesh, mergeGeometries, plane, Scene, transformGeometry, useScene } from "@solidrt/3d"
23
23
  import type { InstancedMeshNode } from "@solidrt/3d"
24
- import { registerDebug } from "srt:dev"
24
+ import { registerDebug } from "sol:dev"
25
25
 
26
26
  const TREES = 1000
27
27
  // Half the side of the square field the trees scatter over.
@@ -3,7 +3,7 @@
3
3
  // bundle - the shape every app with real content ends up needing. Bake
4
4
  // the asset once and drop it in your app's assets tree:
5
5
  //
6
- // bun run srt tool 3d/model examples/model.glb -o assets/model.srtm
6
+ // bun run sol tool 3d/model examples/model.glb -o assets/model.sol3m
7
7
  //
8
8
  // (loadGltf("assets/model.glb") has the exact same async shape; the bake
9
9
  // just removes the runtime parse.)
@@ -51,7 +51,7 @@ function Rover(props: { turn: () => number }) {
51
51
  // The async value: a memo returning a Promise. Its read below suspends
52
52
  // until the file is read and the model built, then resumes under the
53
53
  // <Loading> boundary in App.
54
- let loaded = createMemo(() => loadModel("assets/model.srtm", { label: "rover" }))
54
+ let loaded = createMemo(() => loadModel("assets/model.sol3m", { label: "rover" }))
55
55
 
56
56
  // Everything derived from the model - framing, mounting - happens in
57
57
  // this memo, AFTER the suspending read, so nothing here runs or builds
@@ -4,7 +4,7 @@
4
4
  // with parseGltf and turned into a Group of meshes by createModel. The
5
5
  // glb rides in the bundle as a binary import; a model under assets/ goes
6
6
  // through loadGltf (same parser, read with flux:fs) or, baked once with
7
- // `srt tool 3d/model`, through loadModel (no parsing at all). Every part
7
+ // `sol tool 3d/model`, through loadModel (no parsing at all). Every part
8
8
  // keeps its node name and is an ordinary mesh: pointer events, transforms
9
9
  // and materials work per part. The materials are createModel's default
10
10
  // `standard` from the file's PBR factors, so the scene carries an
@@ -20,7 +20,7 @@
20
20
  // shadows morph too.
21
21
 
22
22
  import { createSignal, onCleanup, onFrame, pct, render } from "@solidrt/core"
23
- import { registerDebug } from "srt:dev"
23
+ import { registerDebug } from "sol:dev"
24
24
  import { DirectionalLight, geometryAttribute, geometryVertexCount, getMorphNames, getMorphWeights, HemisphereLight, Instance, InstancedMesh, phong, Mesh, PerspectiveCamera, plane, Scene, setMorphWeights, sphere, withMorphTargets } from "@solidrt/3d"
25
25
  import type { InstanceNode, MeshNode } from "@solidrt/3d"
26
26
 
@@ -17,7 +17,7 @@
17
17
  // `helpers` debug command ({ on?: boolean }) toggles them.
18
18
 
19
19
  import { createSignal, onFrame, pct, render } from "@solidrt/core"
20
- import { registerDebug } from "srt:dev"
20
+ import { registerDebug } from "sol:dev"
21
21
  import { computeVertexNormals, cylinder, DirectionalLight, fillAttribute, geometryAttribute, geometryVertexCount, Group, HemisphereLight, phong, Mesh, normalsHelper, PerspectiveCamera, Scene, sphere, toNonIndexed, unlit, updateVertices, withNormals } from "@solidrt/3d"
22
22
 
23
23
  // The crease angles in degrees: flat, the default, everything smoothed.
package/examples/pick.tsx CHANGED
@@ -24,7 +24,7 @@
24
24
  import { createInputMap, createPointerFeed, createSignal, displayScale, pct, render } from "@solidrt/core"
25
25
  import { box, cone, getRotation, Group, Mesh, OrbitCamera, orbitActions, orbitBindings, PerspectiveCamera, plane, Scene, setMeshParams, setTransform, sphere, torus, unlit, useScene } from "@solidrt/3d"
26
26
  import type { Geometry, MeshNode, NodePointerEvent, NodeTapEvent, NodeWheelEvent, OrbitCameraHandle, SceneHandle, Vec3 } from "@solidrt/3d"
27
- import { registerDebug } from "srt:dev"
27
+ import { registerDebug } from "sol:dev"
28
28
 
29
29
  type Color = [number, number, number]
30
30
 
@@ -18,7 +18,7 @@
18
18
  import { createSignal, onFrame, pct, render } from "@solidrt/core"
19
19
  import { createTexture } from "@solidrt/core/gpu"
20
20
  import type { TextureId } from "@solidrt/core/gpu"
21
- import { registerDebug } from "srt:dev"
21
+ import { registerDebug } from "sol:dev"
22
22
  import { add, axesHelper, box3Helper, createModel, DirectionalLight, edgesGeometry, equirectToCube, gridHelper, Group, Mesh, parseGltf, PerspectiveCamera, Scene, setGeometry, setMaterial, unlit, wireframeGeometry } from "@solidrt/3d"
23
23
  import type { SceneNode } from "@solidrt/3d"
24
24
  import modelBytes from "./model.glb" with { type: "binary" }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solidrt/3d",
3
- "version": "0.0.65",
3
+ "version": "0.0.66",
4
4
  "license": "MIT",
5
5
  "funding": "https://github.com/sponsors/wellawaretech",
6
6
  "author": "Antoine van Wel",
@@ -20,10 +20,10 @@
20
20
  "AGENTS.md"
21
21
  ],
22
22
  "devDependencies": {
23
- "@solidrt/test": "0.0.65"
23
+ "@solidrt/test": "0.0.66"
24
24
  },
25
25
  "peerDependencies": {
26
26
  "@solidjs/signals": "2.0.0-rc.13",
27
- "@solidrt/core": "0.0.65"
27
+ "@solidrt/core": "0.0.66"
28
28
  }
29
29
  }
@@ -1,10 +1,10 @@
1
- // Environment baking: the pure pipeline behind `srt tool 3d/environment`
1
+ // Environment baking: the pure pipeline behind `sol tool 3d/environment`
2
2
  // and its tests. A Radiance .hdr panorama is decoded to linear float, laid
3
3
  // onto the six faces of a cube, convolved level by level with the GGX lobe
4
4
  // `standard`'s split sum samples (Karis's importance sampling, the source
5
5
  // lod picked from each sample's solid angle - the Filament and Unity
6
6
  // method; Godot and Three convolve the same way at runtime), and packed
7
- // into the .srte container loadEnvironment uploads as an explicit rgba16f
7
+ // into the .sol3e container loadEnvironment uploads as an explicit rgba16f
8
8
  // chain. Runs under bun and on the runtime alike: no GPU, no flux imports.
9
9
  //
10
10
  // Cube faces hold what a GL lookup of a world direction returns (GL's own
@@ -428,15 +428,15 @@ export function prefilterCube(base: CubeFaces, size: number): CubeFaces[] {
428
428
  return levels
429
429
  }
430
430
 
431
- // The .srte container: "SRTE" u32 | version u32 | size u32 | levels u32,
431
+ // The .sol3e container: "SOLE" u32 | version u32 | size u32 | levels u32,
432
432
  // then the faces as float32 rgba, level-major, face-major - the exact
433
433
  // buffers createCubeTexture's explicit chain takes, viewed in place.
434
- /** "SRTE" read as a little-endian u32. */
435
- const MAGIC = 0x45545253
434
+ /** "SOLE" read as a little-endian u32. */
435
+ const MAGIC = 0x454c4f53
436
436
  const VERSION = 1
437
437
  const HEADER_BYTES = 16
438
438
 
439
- /** Serialize a prefiltered chain (prefilterCube's result) into the .srte container. */
439
+ /** Serialize a prefiltered chain (prefilterCube's result) into the .sol3e container. */
440
440
  export function encodeEnvironment(levels: CubeFaces[], size: number): Uint8Array {
441
441
  if (levels.length !== mipLevels(size)) {
442
442
  throw new Error("encodeEnvironment: a " + size + " chain has " + mipLevels(size) + " levels, got " + levels.length)
@@ -459,14 +459,14 @@ export function encodeEnvironment(levels: CubeFaces[], size: number): Uint8Array
459
459
  return out
460
460
  }
461
461
 
462
- /** Read a .srte container back into its size and chain, the faces viewing
462
+ /** Read a .sol3e container back into its size and chain, the faces viewing
463
463
  * the bytes in place (copied only if the buffer is not float-aligned). */
464
464
  export function decodeEnvironment(bytes: Uint8Array): { size: number; levels: CubeFaces[] } {
465
465
  if (bytes.byteLength < HEADER_BYTES) throw new Error("decodeEnvironment: not an environment file (too short)")
466
466
  let view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength)
467
467
  if (view.getUint32(0, true) !== MAGIC) throw new Error("decodeEnvironment: not an environment file (bad magic)")
468
468
  let version = view.getUint32(4, true)
469
- if (version !== VERSION) throw new Error("decodeEnvironment: version " + version + ", expected " + VERSION + " - re-bake with srt tool 3d/environment")
469
+ if (version !== VERSION) throw new Error("decodeEnvironment: version " + version + ", expected " + VERSION + " - re-bake with sol tool 3d/environment")
470
470
  let size = view.getUint32(8, true)
471
471
  let count = view.getUint32(12, true)
472
472
  if (size < 1 || count !== mipLevels(size)) throw new Error("decodeEnvironment: a " + size + " chain has " + mipLevels(size) + " levels, file says " + count)
@@ -1,5 +1,5 @@
1
- // Environment helpers: the baked HDR environment loader (the .srte chain
2
- // `srt tool 3d/environment` writes), the equirectangular-to-cube
1
+ // Environment helpers: the baked HDR environment loader (the .sol3e chain
2
+ // `sol tool 3d/environment` writes), the equirectangular-to-cube
3
3
  // conversion a fetched LDR panorama needs at runtime, the GPU prefilter
4
4
  // that turns a rendered cube (a reflection probe's, a baked sky's) into
5
5
  // the roughness chain, and the placeholder cube a scene binds as uEnv
@@ -28,8 +28,8 @@ import type { CreateOptions, DrawId, ProgramId, RenderPipelineId, SamplerOptions
28
28
  import { decodeEnvironment, levelRoughness, mipLevels } from "./environment-bake.ts"
29
29
 
30
30
  /**
31
- * Read a baked environment (`srt tool 3d/environment sky.hdr -o
32
- * assets/sky.srte`) and upload it: the HDR cube with its GGX-prefiltered
31
+ * Read a baked environment (`sol tool 3d/environment sky.hdr -o
32
+ * assets/sky.sol3e`) and upload it: the HDR cube with its GGX-prefiltered
33
33
  * mip chain, as an explicit "rgba16f" chain - no generated mipmaps, so it
34
34
  * works on every device. The id is what `environment={{ cube }}` and
35
35
  * `background={{ cube }}` take (Three's `scene.environment` from an
@@ -147,7 +147,7 @@ const EQUIRECT_FACE = glsl`
147
147
  * photographed sky uploaded as such, "rgba8" (default) for data,
148
148
  * "rgba16f" for an HDR panorama (the cube keeps the range; renderable on
149
149
  * every device with half-float rendering, else it throws - the prefiltered
150
- * form of that panorama is `srt tool 3d/environment` plus
150
+ * form of that panorama is `sol tool 3d/environment` plus
151
151
  * loadEnvironment). The panorama's center column faces -Z and its top
152
152
  * row is +Y. Leave its wrap at the default clamp: `repeat` would also
153
153
  * wrap vertically and bleed the poles across the top and bottom rows,
@@ -280,7 +280,7 @@ export function bufferFormat(): BufferFormat {
280
280
  * `source`, a `mipmap: true` cube of the same size and format (a cube
281
281
  * draw target rendered sharp), one pass per face per level - 48 small
282
282
  * passes at 128. Three's PMREMGenerator, Unity's and Godot's probe
283
- * convolution, on the same roughness-to-level rule as the .srte chain
283
+ * convolution, on the same roughness-to-level rule as the .sol3e chain
284
284
  * (levelRoughness), so `standard` reads both alike.
285
285
  */
286
286
  export function createPrefilter(size: number, source: TextureId, format: BufferFormat, label: string): Prefilter {
package/src/glsl.ts CHANGED
@@ -815,7 +815,7 @@ export function resolveFragment(source: string = DEFAULT_RESOLVE): string {
815
815
  * roughness - 0 the sharp base level, 1 the level whose faces are
816
816
  * ENV_ROUGH_FACE (4) texels wide, linear between (Godot's
817
817
  * `roughness * MAX_ROUGHNESS_LOD`; Unity's six LOD steps; Three maps
818
- * onto a 16-texel floor): the level a baked chain (`srt tool
818
+ * onto a 16-texel floor): the level a baked chain (`sol tool
819
819
  * 3d/environment`, loadEnvironment) convolves at that roughness, and a
820
820
  * generated chain merely box-filters - scaled by the intensity: the
821
821
  * prefiltered radiance of the split sum (`standard` multiplies it by PBR's
package/src/mixer.ts CHANGED
@@ -44,7 +44,7 @@
44
44
 
45
45
  import * as spatial from "flux:spatial"
46
46
  import type { NodeId } from "flux:spatial"
47
- import { on } from "srt:events"
47
+ import { on } from "sol:events"
48
48
  import type { ModelChannel, ModelClip } from "./gltf.ts"
49
49
  import { channelElements, sampleChannel } from "./clip.ts"
50
50
  import type { Vec3 } from "./math.ts"
package/src/model-data.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  // @solidrt/3d/model - the model DATA side of the package without the
2
- // runtime: the glTF parser, the .srtm container and the pure geometry kit,
2
+ // runtime: the glTF parser, the .sol3m container and the pure geometry kit,
3
3
  // for a script that bakes an app's own geometry under bun (or any host
4
4
  // with no flux). The package root imports `flux:*` and so loads only on
5
5
  // the runtime; this entry imports nothing that does. tools/model.flux.ts
@@ -7,11 +7,11 @@
7
7
  // app's bake script and the tool share one path:
8
8
  //
9
9
  // import { box, encodeModel, transformGeometry } from "@solidrt/3d/model"
10
- // writeFileSync("assets/terrain.srtm", encodeModel({ nodes, parts, ... }))
10
+ // writeFileSync("assets/terrain.sol3m", encodeModel({ nodes, parts, ... }))
11
11
  //
12
12
  // createModel / loadModel on the runtime read what it writes. Keep this
13
13
  // entry pure. tests/model-data.test.ts imports it on the bare flux binary
14
- // and fails the moment a gui or srt: import creeps into the chain; a
14
+ // and fails the moment a gui or sol: import creeps into the chain; a
15
15
  // headless flux: import it would not notice, and a bake script under bun
16
16
  // would.
17
17
 
package/src/model-file.ts CHANGED
@@ -1,4 +1,4 @@
1
- // The baked model container (.srtm): ModelData as one file whose payload IS
1
+ // The baked model container (.sol3m): ModelData as one file whose payload IS
2
2
  // the GPU layout, so loading it is a header parse plus typed-array views -
3
3
  // no per-vertex work. Written by tools/model.flux.ts (from parseGltf),
4
4
  // read by loadModel on flux; both ends are this pure module. An image
@@ -6,7 +6,7 @@
6
6
  // the image's name.
7
7
  //
8
8
  // Layout, all little-endian:
9
- // "SRTM" u32 | version u32 | jsonLength u32 | json (padded to 4) | payload
9
+ // "SOLM" u32 | version u32 | jsonLength u32 | json (padded to 4) | payload
10
10
  // The JSON header describes each block's byte range into the payload; every
11
11
  // block starts 4-aligned so Float32Array/Uint32Array views sit on it
12
12
  // directly. Images travel as their encoded files (PNG/JPEG bytes), app
@@ -23,14 +23,14 @@ import { layoutStride, vertexView, VERTEX_FORMATS } from "./geometry.ts"
23
23
  import type { VertexAttribute } from "@solidrt/core/gpu"
24
24
  import type { Geometry, VertexLayout } from "./geometry.ts"
25
25
 
26
- /** "SRTM" read as a little-endian u32. */
27
- const MAGIC = 0x4d545253
26
+ /** "SOLM" read as a little-endian u32. */
27
+ const MAGIC = 0x4d4c4f53
28
28
  // Version 3 retained the node hierarchy - a node table (name/parent/TRS)
29
29
  // in the header, parts referencing their node, vertices NODE-LOCAL
30
30
  // instead of world-baked - and carries skins (joints + inverse binds,
31
31
  // parts in the "skinned" layout) and animation clips (channel
32
32
  // times/values as payload blocks). Version-2 files world-baked and have
33
- // none of it, so they are rejected - re-bake with `srt tool 3d/model`.
33
+ // none of it, so they are rejected - re-bake with `sol tool 3d/model`.
34
34
  // Version 4 adds the metalness/roughness fields to the material records
35
35
  // (metalness, roughness, metalnessRoughnessMap); a version-3 file lacks
36
36
  // them, so it is rejected the same way rather than read as all-metal.
@@ -39,7 +39,7 @@ const MAGIC = 0x4d545253
39
39
  // carry packed channels; a version-5 file's "vec3" words do not parse.
40
40
  // Version 7 changes the named "skinned" layout's joints from float32x4 to
41
41
  // uint8x4 (an integer shader input), so a version-6 skinned part would
42
- // decode at the wrong stride; it is rejected. Re-bake with `srt tool
42
+ // decode at the wrong stride; it is rejected. Re-bake with `sol tool
43
43
  // 3d/model`.
44
44
  // Version 8 carries morph targets: a part's packed targets block (names,
45
45
  // the sparse-by-vertex texels, the extent - see packMorphTargets), the
@@ -55,7 +55,7 @@ const MAGIC = 0x4d545253
55
55
  // shared blocks, see the header). A version-9 file has none of these and is rejected like
56
56
  // every earlier version rather than read as a file without them, so a
57
57
  // stale bake never silently drops the data an app relies on. Re-bake
58
- // with `srt tool 3d/model`.
58
+ // with `sol tool 3d/model`.
59
59
  // Version 11 names the images: an image record is its block and the
60
60
  // image's name (ModelImage.name), which labels its texture. A
61
61
  // version-10 file has blocks alone and is rejected the same way.
@@ -138,7 +138,7 @@ type Header = {
138
138
  blobs?: Record<string, Block>
139
139
  }
140
140
 
141
- /** Serialize a model into the .srtm container. */
141
+ /** Serialize a model into the .sol3m container. */
142
142
  export function encodeModel(data: ModelData): Uint8Array {
143
143
  let blocks: Uint8Array[] = []
144
144
  let offset = 0
@@ -237,7 +237,7 @@ export function encodeModel(data: ModelData): Uint8Array {
237
237
  }
238
238
 
239
239
  /**
240
- * Read a .srtm container back into ModelData. The geometry arrays are
240
+ * Read a .sol3m container back into ModelData. The geometry arrays are
241
241
  * VIEWS onto `bytes` (copied once only when the input is not 4-aligned),
242
242
  * so the bytes must outlive the model.
243
243
  */
package/src/model.ts CHANGED
@@ -1,4 +1,4 @@
1
- // Models in a scene: ModelData (parsed glTF or a decoded .srtm) becomes a
1
+ // Models in a scene: ModelData (parsed glTF or a decoded .sol3m) becomes a
2
2
  // Group carrying the file's node hierarchy - nested Groups with the file's
3
3
  // local TRS, each part's mesh under its node - with the images uploaded as
4
4
  // textures and a material per glTF material: Three's `gltf.scene`, an
@@ -13,7 +13,7 @@
13
13
  // them and detaches the group. loadGltf / loadModel are the
14
14
  // read-then-create conveniences over flux:fs; parseGltf / decodeModel +
15
15
  // createModel are the primitives under them, for bytes obtained any other
16
- // way (a binary import, a fetch). Compressed images (KTX2, what `srt tool
16
+ // way (a binary import, a fetch). Compressed images (KTX2, what `sol tool
17
17
  // 3d/model` bakes) are turned into this device's block format by
18
18
  // transcodeModelImages, the one asynchronous step between the two.
19
19
 
@@ -439,7 +439,7 @@ function buildOwned(owner: Owner | null, opts: ModelOptions | undefined, build:
439
439
  * Read a .glb or .gltf (with its external .bin and image files, resolved
440
440
  * next to it) and build the model. The parse runs on the runtime - fine
441
441
  * for models of tens of thousands of vertices; bake bigger ones with
442
- * `srt tool 3d/model` and use loadModel.
442
+ * `sol tool 3d/model` and use loadModel.
443
443
  */
444
444
  export async function loadGltf(path: string, opts?: ModelOptions): Promise<Model> {
445
445
  let owner = getOwner()
@@ -456,7 +456,7 @@ export async function loadGltf(path: string, opts?: ModelOptions): Promise<Model
456
456
  return buildOwned(owner, opts, () => createModel(data, opts))
457
457
  }
458
458
 
459
- /** Read a baked .srtm model (`srt tool 3d/model`) and build it: no parsing,
459
+ /** Read a baked .sol3m model (`sol tool 3d/model`) and build it: no parsing,
460
460
  * the geometry views the file's bytes directly. */
461
461
  export async function loadModel(path: string, opts?: ModelOptions): Promise<Model> {
462
462
  let owner = getOwner()
package/src/node.ts CHANGED
@@ -8,7 +8,7 @@
8
8
 
9
9
  import * as spatial from "flux:spatial"
10
10
  import type { NodeId, NodeMotionSpec, NodeTransition } from "flux:spatial"
11
- import { on } from "srt:events"
11
+ import { on } from "sol:events"
12
12
  import { createMutableTexture, destroyTexture } from "@solidrt/core/gpu"
13
13
  import type { ShaderParams, TextureId } from "@solidrt/core/gpu"
14
14
  import type { PointerEvent as ElementPointerEvent, WheelEvent as ElementWheelEvent } from "@solidrt/core"
@@ -776,7 +776,7 @@ export type { TransformUpdate } from "./math.ts"
776
776
  * orchestrator is always an ancestor). Clearing cancels running tracks in
777
777
  * place (the node keeps its mid-flight transform) and later writes snap. Each natural settle calls the node's
778
778
  * `onTransitionEnd` with the component (the raw "spatialTransitionEnd"
779
- * engine event on srt:events stays for flux:spatial consumers; it carries
779
+ * engine event on sol:events stays for flux:spatial consumers; it carries
780
780
  * the core id, `_node`).
781
781
  */
782
782
  export function setTransition(node: SceneNode, transition: NodeTransition | string | null): void {
package/src/scene.ts CHANGED
@@ -635,7 +635,7 @@ export type ReflectionProbeOptions = {
635
635
  export type ReflectionProbe = {
636
636
  /** The cube map: what `environment={{ cube }}` and `background={{
637
637
  * cube }}` take. The prefiltered chain (roughness 0 sharp at level 0,
638
- * blurred below, the same rule as a baked .srte), or with `prefilter:
638
+ * blurred below, the same rule as a baked .sol3e), or with `prefilter:
639
639
  * false` the sharp faces alone - then `standard` reflects it at its
640
640
  * roughness 0 look whatever its roughness. */
641
641
  cube: TextureId
package/src/splat-data.ts CHANGED
@@ -1,15 +1,15 @@
1
1
  // @solidrt/3d/splat - the splat DATA side of the package without the
2
2
  // runtime: the capture parsers (.ply, .splat, gunzipped .spz), the
3
- // covariance bake and the .srts container, for `srt tool 3d/splat` and any
3
+ // covariance bake and the .sol3s container, for `sol tool 3d/splat` and any
4
4
  // app bake script under bun. The package root imports `flux:*` and so
5
5
  // loads only on the runtime; this entry imports nothing that does (the
6
6
  // model-data rule; tests/splat-data.test.ts imports it on the bare flux
7
- // binary and fails the moment a gui or srt: import creeps into the chain).
7
+ // binary and fails the moment a gui or sol: import creeps into the chain).
8
8
  //
9
9
  // import { encodeSplat, parseSplat } from "@solidrt/3d/splat"
10
- // writeFileSync("assets/scan.srts", encodeSplat(parseSplat(bytes)))
10
+ // writeFileSync("assets/scan.sol3s", encodeSplat(parseSplat(bytes)))
11
11
  //
12
- // loadSplat / createSplatMesh on the runtime read what it writes: a .srts
12
+ // loadSplat / createSplatMesh on the runtime read what it writes: a .sol3s
13
13
  // record IS the texel data the splat shader fetches (two rgba32ui texels
14
14
  // per splat, SPLAT_ATTRIBUTES as a byte layout) and the record the core
15
15
  // sorts by depth, so runtime loading is a header parse plus byte views -
@@ -113,8 +113,8 @@ const SPZ_COLOR_SCALE = 0.15
113
113
  const SPZ_SCALE_OFFSET = 10
114
114
  const SPZ_SCALE_STEP = 16
115
115
 
116
- /** "SRTS" read as a little-endian u32. */
117
- const MAGIC = 0x53545253
116
+ /** "SOLS" read as a little-endian u32. */
117
+ const MAGIC = 0x534c4f53
118
118
  // Version 2: the 32-byte two-texel record, importance-sorted, y-up unless
119
119
  // the bake kept orientation, plus the optional SH texel block; the header
120
120
  // carries count, shDegree, bounds and both block ranges. (Version 1 was
@@ -164,10 +164,10 @@ let colorByte = (v: number) => Math.round(Math.min(1, Math.max(0, v)) * 255)
164
164
  * Parse a captured splat cloud - a trainer's .ply, the de-facto .splat
165
165
  * interchange, or a gunzipped .spz (Niantic; the container is
166
166
  * gzip-compressed, and this entry stays decompression-free, so hand it
167
- * the inflated bytes - `srt tool 3d/splat` does) - into baked SplatData:
167
+ * the inflated bytes - `sol tool 3d/splat` does) - into baked SplatData:
168
168
  * covariance precomputed, y-up by default, importance-sorted (size times
169
169
  * opacity), bounds measured. Runs anywhere (bun, the runtime); for a
170
- * capture of real size run it at pack time and ship encodeSplat's .srts.
170
+ * capture of real size run it at pack time and ship encodeSplat's .sol3s.
171
171
  */
172
172
  export function parseSplat(bytes: Uint8Array, opts?: ParseSplatOptions): SplatData {
173
173
  let format = opts?.format ?? sniffFormat(bytes)
@@ -185,7 +185,7 @@ function sniffFormat(bytes: Uint8Array): SplatFormat {
185
185
  if (dv.getUint32(0, true) === SPZ_MAGIC) return "spz"
186
186
  }
187
187
  if (bytes.length >= 2 && bytes[0] === 0x1f && bytes[1] === 0x8b) {
188
- throw new Error("parseSplat: gzip-compressed input (.spz files are); gunzip the bytes first - srt tool 3d/splat does")
188
+ throw new Error("parseSplat: gzip-compressed input (.spz files are); gunzip the bytes first - sol tool 3d/splat does")
189
189
  }
190
190
  if (bytes.length > 0 && bytes.length % SPLAT_IN_BYTES === 0) return "splat"
191
191
  throw new Error("parseSplat: unrecognized input - not a .ply, not a gunzipped .spz, and not whole 32-byte .splat records")
@@ -537,8 +537,8 @@ function shBytesOf(count: number, shDegree: number): number {
537
537
  }
538
538
 
539
539
  /**
540
- * Serialize a splat cloud into the .srts container, all little-endian:
541
- * "SRTS" u32 | version u32 | jsonLength u32 | json (padded to 4) |
540
+ * Serialize a splat cloud into the .sol3s container, all little-endian:
541
+ * "SOLS" u32 | version u32 | jsonLength u32 | json (padded to 4) |
542
542
  * payload. The JSON header carries count, shDegree, bounds and the byte
543
543
  * range of the record block and (above degree 0) the SH block; the
544
544
  * payload is both blocks verbatim.
@@ -574,7 +574,7 @@ export function encodeSplat(data: SplatData): Uint8Array {
574
574
  }
575
575
 
576
576
  /**
577
- * Read a .srts container back into SplatData. The records and the SH
577
+ * Read a .sol3s container back into SplatData. The records and the SH
578
578
  * block are VIEWS onto `bytes` (copied once only when the input is not
579
579
  * 4-aligned), so the bytes must outlive the data - which is the point:
580
580
  * loading a bake is a header parse, and the views upload as-is.
@@ -585,7 +585,7 @@ export function decodeSplat(bytes: Uint8Array): SplatData {
585
585
  let dv = new DataView(bytes.buffer, bytes.byteOffset, 12)
586
586
  if (dv.getUint32(0, true) !== MAGIC) throw new Error("decodeSplat: not a splat file (bad magic)")
587
587
  let version = dv.getUint32(4, true)
588
- if (version !== VERSION) throw new Error("decodeSplat: version " + version + ", expected " + VERSION + " - re-bake with `srt tool 3d/splat`")
588
+ if (version !== VERSION) throw new Error("decodeSplat: version " + version + ", expected " + VERSION + " - re-bake with `sol tool 3d/splat`")
589
589
  let jsonLength = dv.getUint32(8, true)
590
590
  let header: Header = JSON.parse(new TextDecoder().decode(bytes.subarray(12, 12 + jsonLength)))
591
591
  let payload = 12 + jsonLength + ((4 - (jsonLength % 4)) % 4)
package/src/splat.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  // The splat RUNTIME side: the stock splat material and createSplatMesh
2
2
  // over a baked SplatData (parse and bake live in ./splat-data.ts, the
3
- // runtime-free `@solidrt/3d/splat` entry; `srt tool 3d/splat` writes the
4
- // .srts this loads). A splat cloud here is an ordinary record mesh in the
3
+ // runtime-free `@solidrt/3d/splat` entry; `sol tool 3d/splat` writes the
4
+ // .sol3s this loads). A splat cloud here is an ordinary record mesh in the
5
5
  // INDEXED form - the records live in an rgba32ui data texture the vertex
6
6
  // stage fetches by id, SPLAT_GROUP splats share one drawn instance (a
7
7
  // merged-quad geometry; the instancing frontend was the measured wall),
@@ -393,7 +393,7 @@ export function createSplatMesh(data: SplatData, opts?: SplatMeshOptions): Splat
393
393
  return mesh
394
394
  }
395
395
 
396
- /** Read a baked .srts splat cloud (`srt tool 3d/splat`): no parsing, the
396
+ /** Read a baked .sol3s splat cloud (`sol tool 3d/splat`): no parsing, the
397
397
  * records and the SH block view the file's bytes and upload as-is at
398
398
  * createSplatMesh. */
399
399
  export async function loadSplat(path: string): Promise<SplatData> {
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env bun
2
2
  /// <reference path="./node-env.d.ts" />
3
3
 
4
- // srt tool 3d/environment: bake a Radiance .hdr panorama into a .srte
4
+ // sol tool 3d/environment: bake a Radiance .hdr panorama into a .sol3e
5
5
  // environment file - the six cube faces and their GGX-prefiltered mip
6
6
  // chain in linear float, the exact chain loadEnvironment uploads as an
7
7
  // explicit rgba16f cube (no runtime conversion, no generated mipmaps, no
@@ -10,7 +10,7 @@
10
10
  // at runtime every time the sky changes. Put the output under assets/ so
11
11
  // it ships with the app.
12
12
  //
13
- // srt tool 3d/environment <in.hdr> [-o <out.srte>] [--size <edge>]
13
+ // sol tool 3d/environment <in.hdr> [-o <out.sol3e>] [--size <edge>]
14
14
  //
15
15
  // --size is the cube's face edge: 128 (default) is Unity's probe default
16
16
  // and enough for every surface short of a mirror; 256 (Godot's radiance
@@ -28,7 +28,7 @@ const MAX_SIZE = 1024
28
28
 
29
29
  function usage(error?: string): never {
30
30
  if (error) console.error(error)
31
- console.log("Usage: srt tool 3d/environment <in.hdr> [-o <out.srte>] [--size <edge>]")
31
+ console.log("Usage: sol tool 3d/environment <in.hdr> [-o <out.sol3e>] [--size <edge>]")
32
32
  process.exit(error ? 1 : 0)
33
33
  }
34
34
 
@@ -54,7 +54,7 @@ for (let i = 0; i < args.length; i++) {
54
54
  else usage("Unexpected argument " + arg)
55
55
  }
56
56
  if (input === undefined) usage("Missing input file")
57
- if (output === undefined) output = basename(input, extname(input)) + ".srte"
57
+ if (output === undefined) output = basename(input, extname(input)) + ".sol3e"
58
58
 
59
59
  let started = performance.now()
60
60
  let panorama = decodeHdr(new Uint8Array(readFileSync(input)))
@@ -1,4 +1,4 @@
1
- // srt tool 3d/model: bake a glTF into a .srtm model file - the parse
1
+ // sol tool 3d/model: bake a glTF into a .sol3m model file - the parse
2
2
  // (src/gltf.ts) run once here, the result written in the exact layout
3
3
  // loadModel views without any per-vertex work at runtime. Same parser,
4
4
  // same subset, same result as loadGltf; this only moves the cost to build
@@ -20,7 +20,7 @@
20
20
  // `@solidrt/3d/model` entry (src/model-data.ts), the same surface an
21
21
  // app's own bake script uses under bun.
22
22
  //
23
- // srt tool 3d/model <in.gltf|in.glb> [-o <out.srtm>] [--compress|--no-compress]
23
+ // sol tool 3d/model <in.gltf|in.glb> [-o <out.sol3m>] [--compress|--no-compress]
24
24
 
25
25
  import { file, glob } from "flux:fs"
26
26
  import { decodeImage, encodeTexture } from "flux:image"
@@ -42,7 +42,7 @@ const IMAGES_IN_FLIGHT = 4
42
42
  // of the texture settings are written from.
43
43
  const PROJECT_ROOT = "."
44
44
 
45
- const USAGE = "Usage: srt tool 3d/model <in.gltf|in.glb> [-o <out.srtm>] [--compress|--no-compress]"
45
+ const USAGE = "Usage: sol tool 3d/model <in.gltf|in.glb> [-o <out.sol3m>] [--compress|--no-compress]"
46
46
 
47
47
  function usage(error?: string): never {
48
48
  if (error) console.error(error)
@@ -149,7 +149,7 @@ for (let i = 0; i < argv.length; i++) {
149
149
  else usage("Unexpected argument " + arg)
150
150
  }
151
151
  if (input === undefined) usage("Missing input file")
152
- if (output === undefined) output = basename(input, extname(input)) + ".srtm"
152
+ if (output === undefined) output = basename(input, extname(input)) + ".sol3m"
153
153
 
154
154
  // The parse is synchronous, so the external files it will open are read
155
155
  // ahead of it (the same prefetch loadGltf does).
@@ -1,4 +1,4 @@
1
- // The node surface the tools use, declared here so `srt check
1
+ // The node surface the tools use, declared here so `sol check
2
2
  // packages/3d/tools/<name>.ts` typechecks them on the package's flux-typed
3
3
  // program (the nearest tsconfig is the repo root's). The tools run under
4
4
  // bun, but bun's own types cannot join this program: their globals
package/tools/splat.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env bun
2
2
  /// <reference path="./node-env.d.ts" />
3
3
 
4
- // srt tool 3d/splat: bake a captured splat cloud into a .srts file - the
4
+ // sol tool 3d/splat: bake a captured splat cloud into a .sol3s file - the
5
5
  // parse, covariance bake and SH packing (src/splat-data.ts) run once here
6
6
  // under bun, the result written in the exact texel layout createSplatMesh
7
7
  // uploads and the engine sorts, without any per-splat work at runtime.
@@ -9,7 +9,7 @@
9
9
  // Everything here comes from the runtime-free `@solidrt/3d/splat` entry,
10
10
  // the same surface an app's own bake script uses.
11
11
  //
12
- // srt tool 3d/splat <in.ply|in.splat|in.spz> [-o <out.srts>] [--sh <0..3>] [--keep-orientation]
12
+ // sol tool 3d/splat <in.ply|in.splat|in.spz> [-o <out.sol3s>] [--sh <0..3>] [--keep-orientation]
13
13
  //
14
14
  // Inputs: a trainer's .ply, the de-facto .splat interchange, or Niantic's
15
15
  // .spz (gunzipped here; version 2 or 3). A y-down capture (.ply, .splat)
@@ -25,7 +25,7 @@ import { encodeSplat, parseSplat } from "../src/splat-data.ts"
25
25
 
26
26
  function usage(error?: string): never {
27
27
  if (error) console.error(error)
28
- console.log("Usage: srt tool 3d/splat <in.ply|in.splat|in.spz> [-o <out.srts>] [--sh <0..3>] [--keep-orientation]")
28
+ console.log("Usage: sol tool 3d/splat <in.ply|in.splat|in.spz> [-o <out.sol3s>] [--sh <0..3>] [--keep-orientation]")
29
29
  process.exit(error ? 1 : 0)
30
30
  }
31
31
 
@@ -51,7 +51,7 @@ for (let i = 0; i < args.length; i++) {
51
51
  else usage("Unexpected argument " + arg)
52
52
  }
53
53
  if (input === undefined) usage("Missing input file")
54
- if (output === undefined) output = basename(input, extname(input)) + ".srts"
54
+ if (output === undefined) output = basename(input, extname(input)) + ".sol3s"
55
55
 
56
56
  let bytes = new Uint8Array(readFileSync(input))
57
57
  // .spz is gzip-compressed; the parser takes the inflated bytes.