scena3d 0.1.0 → 0.4.0
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/README.md +41 -11
- package/dist/index.cjs +1203 -50
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +534 -3
- package/dist/index.d.ts +534 -3
- package/dist/index.js +1204 -41
- package/dist/index.js.map +1 -1
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -54,29 +54,58 @@ game.onUpdate(() => { // ← SC
|
|
|
54
54
|
});
|
|
55
55
|
```
|
|
56
56
|
|
|
57
|
-
Neither library imports the other — the obstacle shape (`{ center, radius }`) is structural. Run the full demo (`npm run dev
|
|
57
|
+
Neither library imports the other — the obstacle shape (`{ center, radius }`) is structural. Run the full demo (`npm run dev` — gama3d comes from npm): a day-night cycle over terrain, lakes, a windblown forest, a seeded hamlet whose windows ignite at dusk, and a dirt road whose single authored curve is at once the visual ribbon, the scatter keep-out, and the wardens' patrol route. Append `?t=0.85` to freeze the time of day.
|
|
58
|
+
|
|
59
|
+
## A world as JSON
|
|
60
|
+
|
|
61
|
+
Everything above can also be declared instead of coded — a `SceneManifest` is plain data (store it, diff it, send it over the network), and `buildScene` applies all the cross-feature wiring automatically: scatters stay ashore, off roads and out of the village; the village avoids water and paths; its lamps and windows feed the day cycle.
|
|
62
|
+
|
|
63
|
+
```ts
|
|
64
|
+
const world = buildScene({
|
|
65
|
+
seed: 18,
|
|
66
|
+
palette: 'autumn',
|
|
67
|
+
terrain: { size: 90, amplitude: 5 },
|
|
68
|
+
water: { level: 0.25 },
|
|
69
|
+
dayCycle: { dayLength: 120 },
|
|
70
|
+
paths: [{ points: roadPoints, loop: true }],
|
|
71
|
+
village: { radius: 9, houses: 5 },
|
|
72
|
+
scatters: [{ density: 0.05, items: [{ type: 'tree', weight: 4 }, { type: 'rock' }],
|
|
73
|
+
lod: { distance: 34 } }], // far tiles collapse to cones
|
|
74
|
+
}, scene);
|
|
75
|
+
game.onUpdate((t) => world.update(t.delta));
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Run it: `npm run dev:manifest`. For handcrafted interiors there are kits — `assembleKit(['####', '#.S#', '#..D', '####'])` turns an ASCII map into snapped walls, floors, doorways, torches, spawn points and obstacles. And for levels authored in Blender/glTF, `extractMarkers(gltf.scene)` reads `spawn_*` / `route_*_0` / `obstacle_*` / `keepout_*` empties into spawns, ordered patrol routes and steering/scatter metadata.
|
|
58
79
|
|
|
59
80
|
## API
|
|
60
81
|
|
|
61
82
|
| Area | Exports |
|
|
62
83
|
|---|---|
|
|
63
|
-
| Props | `createTree`, `createRock`, `createCrate`, `createFence`, `createLamp` — each returns `{ object, obstacleRadius }` |
|
|
64
|
-
| Environment | `createTerrain` (with `heightAt(x, z)`), `createSky`, `createLightingRig(
|
|
84
|
+
| Props | `createTree`, `createRock`, `createCrate`, `createFence`, `createLamp`, `createBush`, `createGrassTuft`, `createHouse`, `createTower`, `createWell`, `createRuin` — each returns `{ object, obstacleRadius }` |
|
|
85
|
+
| Environment | `createTerrain` (with `heightAt(x, z)` and `waterLevel` sand bands), `createSky`, `createLightingRig(...)`, `applyFog(...)`, `createWater` + `aboveWater` mask, `createDayCycle` (one `timeOfDay` drives sun/sky/fog/lamps), `applyWind` (vegetation sway), `createPath` (ribbon + patrol route + keep-out from one curve) |
|
|
65
86
|
| Scattering | `scatter({ seed, area, surface, density \| count, items, mask, minSpacing, keepOut })` → `{ group, placements, obstacles, count }` |
|
|
87
|
+
| Generators | `createVillage({ seed, center, radius, houses, surface, mask })` → `{ group, props, obstacles, lamps, keepOut }` — a hamlet whose windows and lamps hand straight to `createDayCycle`, buildings to `ObstacleAvoidance`, clearing to `scatter` |
|
|
88
|
+
| Kits | `KIT_UNIT`, `assembleKit(asciiRows)` → `{ group, obstacles, spawns, torches, floorAt }` — grid-snapped walls/floors/doorways as two InstancedMeshes |
|
|
89
|
+
| Scene assembly | `buildScene(manifest, scene?)` → a whole wired world from plain JSON; `extractMarkers(root)` → `{ spawns, routes, obstacles, keepOut }` from naming conventions |
|
|
66
90
|
| Core | `Rng` (seeded), `valueNoise2`/`fractalNoise2`, `PALETTES`, `collectObstacles` |
|
|
67
91
|
|
|
68
|
-
Scatter placement uses density noise for natural clumping and clearings, a spatial hash for minimum spacing, and per-item visual variants; rendering merges everything into `InstancedMesh`es (one draw call per prop part).
|
|
92
|
+
Scatter placement uses density noise for natural clumping and clearings, a spatial hash for minimum spacing, and per-item visual variants; rendering merges everything into `InstancedMesh`es (one draw call per prop part). Opt into `lod: { distance, tileSize }` and placements bucket into tiles that swap to each item's `createFar` variant beyond the distance (10% hysteresis; call `result.update(camera)` each frame).
|
|
69
93
|
|
|
70
94
|
## Roadmap
|
|
71
95
|
|
|
72
96
|
- [x] Seeded props with obstacle metadata (tree, rock, crate, fence, lamp)
|
|
73
97
|
- [x] Instanced `scatter()` with masks, keep-out, spacing and clumping
|
|
74
98
|
- [x] Noise terrain with exact `heightAt` and height/slope color bands
|
|
75
|
-
- [x] Sky dome, lighting rigs, fog presets,
|
|
76
|
-
- [
|
|
77
|
-
- [
|
|
78
|
-
- [
|
|
79
|
-
- [
|
|
99
|
+
- [x] Sky dome, lighting rigs, fog presets, four theme palettes (incl. `winter`)
|
|
100
|
+
- [x] Water with shoreline masks; terrain sand bands
|
|
101
|
+
- [x] Day-night cycle: one `timeOfDay` drives sun, sky, fog and lamps igniting at dusk
|
|
102
|
+
- [x] Wind sway on scattered vegetation (per-instance phase)
|
|
103
|
+
- [x] Paths: one curve = visual ribbon + scatter keep-out + GAMA patrol route
|
|
104
|
+
- [x] Seed-stability snapshot tests (output frozen within a minor version)
|
|
105
|
+
- [x] Buildings (house, watchtower, well) and ruins; `createVillage` hamlet generator with the full gameplay handshake
|
|
106
|
+
- [x] Kits: ASCII maps → grid-snapped dungeon/compound pieces (`assembleKit`)
|
|
107
|
+
- [x] Declarative scene manifests (JSON → scene) and Blender marker conventions (`spawn_*`, `route_*`, `obstacle_*`, `keepout_*`)
|
|
108
|
+
- [x] LOD tiles for scatter (`createFar` variants, hysteresis)
|
|
80
109
|
- [ ] CC0 asset-pack adapters (Kenney/Quaternius) and a KTX2/Draco pipeline
|
|
81
110
|
- [ ] Docs site with live playground (reusing GAMA's runner)
|
|
82
111
|
|
|
@@ -84,10 +113,11 @@ Scatter placement uses density noise for natural clumping and clearings, a spati
|
|
|
84
113
|
|
|
85
114
|
```bash
|
|
86
115
|
npm install
|
|
87
|
-
npm test #
|
|
116
|
+
npm test # 62 vitest unit tests (determinism, metadata, scatter rules, snapshots)
|
|
88
117
|
npm run typecheck
|
|
89
118
|
npm run build # tsup → dist (ESM + CJS + d.ts)
|
|
90
|
-
npm run dev # the SCENA × GAMA forest demo
|
|
119
|
+
npm run dev # the SCENA × GAMA living-forest demo
|
|
120
|
+
npm run dev:manifest # the same kind of world, built from one JSON manifest
|
|
91
121
|
```
|
|
92
122
|
|
|
93
123
|
## License
|