@3driseai/3drise-viewer 0.1.7 → 0.1.8

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.
Files changed (259) hide show
  1. package/dist/components/Clouds.d.ts.map +1 -1
  2. package/dist/components/Clouds.js +0 -1
  3. package/dist/components/CloudsGenerator.d.ts +32 -0
  4. package/dist/components/CloudsGenerator.d.ts.map +1 -0
  5. package/dist/components/CloudsGenerator.js +58 -0
  6. package/dist/components/EnvironmentManager.d.ts +47 -5
  7. package/dist/components/EnvironmentManager.d.ts.map +1 -1
  8. package/dist/components/EnvironmentManager.js +35 -66
  9. package/dist/components/HdrEnvironment.d.ts +20 -0
  10. package/dist/components/HdrEnvironment.d.ts.map +1 -0
  11. package/dist/components/HdrEnvironment.js +44 -0
  12. package/dist/components/LandscapeBuilder.d.ts +23 -0
  13. package/dist/components/LandscapeBuilder.d.ts.map +1 -0
  14. package/dist/components/LandscapeBuilder.js +25 -0
  15. package/dist/components/LandscapeObject.d.ts +24 -0
  16. package/dist/components/LandscapeObject.d.ts.map +1 -0
  17. package/dist/components/LandscapeObject.js +27 -0
  18. package/dist/components/ObjectNode.d.ts.map +1 -1
  19. package/dist/components/ObjectNode.js +10 -0
  20. package/dist/components/OceanBuilder.d.ts +35 -0
  21. package/dist/components/OceanBuilder.d.ts.map +1 -0
  22. package/dist/components/OceanBuilder.js +53 -0
  23. package/dist/components/SceneBuilder.d.ts.map +1 -1
  24. package/dist/components/SkySystem.d.ts +27 -6
  25. package/dist/components/SkySystem.d.ts.map +1 -1
  26. package/dist/components/SkySystem.js +6 -5
  27. package/dist/components/SunLight.d.ts.map +1 -1
  28. package/dist/components/SunLight.js +4 -1
  29. package/dist/components/TerrainBuilder.d.ts +30 -0
  30. package/dist/components/TerrainBuilder.d.ts.map +1 -0
  31. package/dist/components/TerrainBuilder.js +44 -0
  32. package/dist/components/index.d.ts +17 -1
  33. package/dist/components/index.d.ts.map +1 -1
  34. package/dist/components/index.js +10 -0
  35. package/dist/components/landscape/LandscapeMesh.d.ts +18 -0
  36. package/dist/components/landscape/LandscapeMesh.d.ts.map +1 -0
  37. package/dist/components/landscape/LandscapeMesh.js +278 -0
  38. package/dist/components/landscape/index.d.ts +3 -0
  39. package/dist/components/landscape/index.d.ts.map +1 -0
  40. package/dist/components/landscape/index.js +1 -0
  41. package/dist/components/landscape/types.d.ts +13 -0
  42. package/dist/components/landscape/types.d.ts.map +1 -0
  43. package/dist/components/landscape/types.js +1 -0
  44. package/dist/components/terrain/Canyon.d.ts +23 -0
  45. package/dist/components/terrain/Canyon.d.ts.map +1 -0
  46. package/dist/components/terrain/Canyon.js +29 -0
  47. package/dist/components/terrain/Dunes.d.ts +22 -0
  48. package/dist/components/terrain/Dunes.d.ts.map +1 -0
  49. package/dist/components/terrain/Dunes.js +25 -0
  50. package/dist/components/terrain/Hills.d.ts +17 -0
  51. package/dist/components/terrain/Hills.d.ts.map +1 -0
  52. package/dist/components/terrain/Hills.js +20 -0
  53. package/dist/components/terrain/Mountains.d.ts +19 -0
  54. package/dist/components/terrain/Mountains.d.ts.map +1 -0
  55. package/dist/components/terrain/Mountains.js +22 -0
  56. package/dist/components/terrain/TerrainSurface.d.ts +22 -0
  57. package/dist/components/terrain/TerrainSurface.d.ts.map +1 -0
  58. package/dist/components/terrain/TerrainSurface.js +94 -0
  59. package/dist/components/terrain/index.d.ts +7 -0
  60. package/dist/components/terrain/index.d.ts.map +1 -0
  61. package/dist/components/terrain/index.js +7 -0
  62. package/dist/components/terrain/types.d.ts +17 -0
  63. package/dist/components/terrain/types.d.ts.map +1 -0
  64. package/dist/components/terrain/types.js +1 -0
  65. package/dist/components/volumetricClouds/Cirrus.d.ts +14 -0
  66. package/dist/components/volumetricClouds/Cirrus.d.ts.map +1 -0
  67. package/dist/components/volumetricClouds/Cirrus.js +13 -0
  68. package/dist/components/volumetricClouds/Cumulonimbus.d.ts +17 -0
  69. package/dist/components/volumetricClouds/Cumulonimbus.d.ts.map +1 -0
  70. package/dist/components/volumetricClouds/Cumulonimbus.js +20 -0
  71. package/dist/components/volumetricClouds/Cumulus.d.ts +14 -0
  72. package/dist/components/volumetricClouds/Cumulus.d.ts.map +1 -0
  73. package/dist/components/volumetricClouds/Cumulus.js +17 -0
  74. package/dist/components/volumetricClouds/Stratocumulus.d.ts +12 -0
  75. package/dist/components/volumetricClouds/Stratocumulus.d.ts.map +1 -0
  76. package/dist/components/volumetricClouds/Stratocumulus.js +16 -0
  77. package/dist/components/volumetricClouds/VolumetricCloudsPass.d.ts +42 -0
  78. package/dist/components/volumetricClouds/VolumetricCloudsPass.d.ts.map +1 -0
  79. package/dist/components/volumetricClouds/VolumetricCloudsPass.js +298 -0
  80. package/dist/components/volumetricClouds/index.d.ts +8 -0
  81. package/dist/components/volumetricClouds/index.d.ts.map +1 -0
  82. package/dist/components/volumetricClouds/index.js +7 -0
  83. package/dist/components/volumetricClouds/types.d.ts +17 -0
  84. package/dist/components/volumetricClouds/types.d.ts.map +1 -0
  85. package/dist/components/volumetricClouds/types.js +1 -0
  86. package/dist/components/water/Host.d.ts +12 -0
  87. package/dist/components/water/Host.d.ts.map +1 -0
  88. package/dist/components/water/Host.js +12 -0
  89. package/dist/components/water/Lake.d.ts +18 -0
  90. package/dist/components/water/Lake.d.ts.map +1 -0
  91. package/dist/components/water/Lake.js +21 -0
  92. package/dist/components/water/OceanSurface.d.ts +27 -0
  93. package/dist/components/water/OceanSurface.d.ts.map +1 -0
  94. package/dist/components/water/OceanSurface.js +60 -0
  95. package/dist/components/water/Sea.d.ts +18 -0
  96. package/dist/components/water/Sea.d.ts.map +1 -0
  97. package/dist/components/water/Sea.js +17 -0
  98. package/dist/components/water/Shore.d.ts +16 -0
  99. package/dist/components/water/Shore.d.ts.map +1 -0
  100. package/dist/components/water/Shore.js +15 -0
  101. package/dist/components/water/Storm.d.ts +14 -0
  102. package/dist/components/water/Storm.d.ts.map +1 -0
  103. package/dist/components/water/Storm.js +13 -0
  104. package/dist/components/water/WaterBody.d.ts +31 -0
  105. package/dist/components/water/WaterBody.d.ts.map +1 -0
  106. package/dist/components/water/WaterBody.js +76 -0
  107. package/dist/components/water/index.d.ts +9 -0
  108. package/dist/components/water/index.d.ts.map +1 -0
  109. package/dist/components/water/index.js +11 -0
  110. package/dist/components/water/types.d.ts +20 -0
  111. package/dist/components/water/types.d.ts.map +1 -0
  112. package/dist/components/water/types.js +1 -0
  113. package/dist/constants.d.ts.map +1 -1
  114. package/dist/constants.js +9 -0
  115. package/dist/hooks/index.d.ts +24 -1
  116. package/dist/hooks/index.d.ts.map +1 -1
  117. package/dist/hooks/index.js +12 -0
  118. package/dist/hooks/useClipmap.d.ts +71 -0
  119. package/dist/hooks/useClipmap.d.ts.map +1 -0
  120. package/dist/hooks/useClipmap.js +81 -0
  121. package/dist/hooks/useCloudLive.d.ts +29 -0
  122. package/dist/hooks/useCloudLive.d.ts.map +1 -0
  123. package/dist/hooks/useCloudLive.js +43 -0
  124. package/dist/hooks/useCloudNoise.d.ts +28 -0
  125. package/dist/hooks/useCloudNoise.d.ts.map +1 -0
  126. package/dist/hooks/useCloudNoise.js +128 -0
  127. package/dist/hooks/useCloudSun.d.ts +49 -0
  128. package/dist/hooks/useCloudSun.d.ts.map +1 -0
  129. package/dist/hooks/useCloudSun.js +84 -0
  130. package/dist/hooks/useCubeCamera.d.ts +27 -9
  131. package/dist/hooks/useCubeCamera.d.ts.map +1 -1
  132. package/dist/hooks/useCubeCamera.js +28 -70
  133. package/dist/hooks/useEnvironmentProbe.d.ts +32 -0
  134. package/dist/hooks/useEnvironmentProbe.d.ts.map +1 -0
  135. package/dist/hooks/useEnvironmentProbe.js +35 -0
  136. package/dist/hooks/useFrameRenderer.d.ts +15 -0
  137. package/dist/hooks/useFrameRenderer.d.ts.map +1 -0
  138. package/dist/hooks/useFrameRenderer.js +23 -0
  139. package/dist/hooks/useLandscapeLive.d.ts +29 -0
  140. package/dist/hooks/useLandscapeLive.d.ts.map +1 -0
  141. package/dist/hooks/useLandscapeLive.js +41 -0
  142. package/dist/hooks/useLandscapeMaps.d.ts +32 -0
  143. package/dist/hooks/useLandscapeMaps.d.ts.map +1 -0
  144. package/dist/hooks/useLandscapeMaps.js +138 -0
  145. package/dist/hooks/useOceanLive.d.ts +29 -0
  146. package/dist/hooks/useOceanLive.d.ts.map +1 -0
  147. package/dist/hooks/useOceanLive.js +38 -0
  148. package/dist/hooks/useOceanMaterial.d.ts +39 -0
  149. package/dist/hooks/useOceanMaterial.d.ts.map +1 -0
  150. package/dist/hooks/useOceanMaterial.js +65 -0
  151. package/dist/hooks/useTerrainClipmap.d.ts +12 -0
  152. package/dist/hooks/useTerrainClipmap.d.ts.map +1 -0
  153. package/dist/hooks/useTerrainClipmap.js +10 -0
  154. package/dist/hooks/useTerrainLive.d.ts +34 -0
  155. package/dist/hooks/useTerrainLive.d.ts.map +1 -0
  156. package/dist/hooks/useTerrainLive.js +45 -0
  157. package/dist/index.d.ts +26 -0
  158. package/dist/index.d.ts.map +1 -1
  159. package/dist/index.js +16 -0
  160. package/dist/presets/landscapePresets.d.ts +60 -0
  161. package/dist/presets/landscapePresets.d.ts.map +1 -0
  162. package/dist/presets/landscapePresets.js +194 -0
  163. package/dist/presets/landscapeTypes.d.ts +195 -0
  164. package/dist/presets/landscapeTypes.d.ts.map +1 -0
  165. package/dist/presets/landscapeTypes.js +315 -0
  166. package/dist/presets/oceanSurfacePresets.d.ts +33 -0
  167. package/dist/presets/oceanSurfacePresets.d.ts.map +1 -0
  168. package/dist/presets/oceanSurfacePresets.js +245 -0
  169. package/dist/presets/terrainPresets.d.ts +28 -0
  170. package/dist/presets/terrainPresets.d.ts.map +1 -0
  171. package/dist/presets/terrainPresets.js +293 -0
  172. package/dist/presets/volumetricCloudPresets.d.ts +38 -0
  173. package/dist/presets/volumetricCloudPresets.d.ts.map +1 -0
  174. package/dist/presets/volumetricCloudPresets.js +480 -0
  175. package/dist/shaders/clouds/CirrusMaterial.d.ts +84 -0
  176. package/dist/shaders/clouds/CirrusMaterial.d.ts.map +1 -0
  177. package/dist/shaders/clouds/CirrusMaterial.js +167 -0
  178. package/dist/shaders/clouds/CloudCompositeMaterial.d.ts +20 -0
  179. package/dist/shaders/clouds/CloudCompositeMaterial.d.ts.map +1 -0
  180. package/dist/shaders/clouds/CloudCompositeMaterial.js +82 -0
  181. package/dist/shaders/clouds/CloudResolveMaterial.d.ts +22 -0
  182. package/dist/shaders/clouds/CloudResolveMaterial.d.ts.map +1 -0
  183. package/dist/shaders/clouds/CloudResolveMaterial.js +77 -0
  184. package/dist/shaders/clouds/CloudVolumeMaterial.d.ts +143 -0
  185. package/dist/shaders/clouds/CloudVolumeMaterial.d.ts.map +1 -0
  186. package/dist/shaders/clouds/CloudVolumeMaterial.js +249 -0
  187. package/dist/shaders/clouds/SkyBackgroundMaterial.d.ts +21 -0
  188. package/dist/shaders/clouds/SkyBackgroundMaterial.d.ts.map +1 -0
  189. package/dist/shaders/clouds/SkyBackgroundMaterial.js +42 -0
  190. package/dist/shaders/glsl/cloudCore.glsl.d.ts +24 -0
  191. package/dist/shaders/glsl/cloudCore.glsl.d.ts.map +1 -0
  192. package/dist/shaders/glsl/cloudCore.glsl.js +348 -0
  193. package/dist/shaders/glsl/landscapeCore.glsl.d.ts +49 -0
  194. package/dist/shaders/glsl/landscapeCore.glsl.d.ts.map +1 -0
  195. package/dist/shaders/glsl/landscapeCore.glsl.js +518 -0
  196. package/dist/shaders/glsl/noiseBake.glsl.d.ts +30 -0
  197. package/dist/shaders/glsl/noiseBake.glsl.d.ts.map +1 -0
  198. package/dist/shaders/glsl/noiseBake.glsl.js +164 -0
  199. package/dist/shaders/glsl/oceanCore.glsl.d.ts +52 -0
  200. package/dist/shaders/glsl/oceanCore.glsl.d.ts.map +1 -0
  201. package/dist/shaders/glsl/oceanCore.glsl.js +421 -0
  202. package/dist/shaders/glsl/terrainCore.glsl.d.ts +78 -0
  203. package/dist/shaders/glsl/terrainCore.glsl.d.ts.map +1 -0
  204. package/dist/shaders/glsl/terrainCore.glsl.js +625 -0
  205. package/dist/shaders/landscape/LandscapeMaterial.d.ts +73 -0
  206. package/dist/shaders/landscape/LandscapeMaterial.d.ts.map +1 -0
  207. package/dist/shaders/landscape/LandscapeMaterial.js +136 -0
  208. package/dist/shaders/ocean/OceanSurfaceMaterial.d.ts +57 -0
  209. package/dist/shaders/ocean/OceanSurfaceMaterial.d.ts.map +1 -0
  210. package/dist/shaders/ocean/OceanSurfaceMaterial.js +268 -0
  211. package/dist/shaders/terrain/TerrainMaterial.d.ts +80 -0
  212. package/dist/shaders/terrain/TerrainMaterial.d.ts.map +1 -0
  213. package/dist/shaders/terrain/TerrainMaterial.js +291 -0
  214. package/dist/types/cloudConfigs.d.ts +244 -0
  215. package/dist/types/cloudConfigs.d.ts.map +1 -0
  216. package/dist/types/cloudConfigs.js +282 -0
  217. package/dist/types/index.d.ts +8 -0
  218. package/dist/types/index.d.ts.map +1 -1
  219. package/dist/types/index.js +4 -1
  220. package/dist/types/landscapeConfigs.d.ts +218 -0
  221. package/dist/types/landscapeConfigs.d.ts.map +1 -0
  222. package/dist/types/landscapeConfigs.js +256 -0
  223. package/dist/types/oceanConfigs.d.ts +290 -0
  224. package/dist/types/oceanConfigs.d.ts.map +1 -0
  225. package/dist/types/oceanConfigs.js +380 -0
  226. package/dist/types/terrainConfigs.d.ts +251 -0
  227. package/dist/types/terrainConfigs.d.ts.map +1 -0
  228. package/dist/types/terrainConfigs.js +292 -0
  229. package/dist/utils/cloudUniforms.d.ts +14 -0
  230. package/dist/utils/cloudUniforms.d.ts.map +1 -0
  231. package/dist/utils/cloudUniforms.js +122 -0
  232. package/dist/utils/frameRenderer.d.ts +33 -0
  233. package/dist/utils/frameRenderer.d.ts.map +1 -0
  234. package/dist/utils/frameRenderer.js +24 -0
  235. package/dist/utils/handleCloudsAnimations.d.ts +16 -0
  236. package/dist/utils/handleCloudsAnimations.d.ts.map +1 -0
  237. package/dist/utils/handleCloudsAnimations.js +64 -0
  238. package/dist/utils/landscapeGeometry.d.ts +61 -0
  239. package/dist/utils/landscapeGeometry.d.ts.map +1 -0
  240. package/dist/utils/landscapeGeometry.js +126 -0
  241. package/dist/utils/landscapeHeight.d.ts +44 -0
  242. package/dist/utils/landscapeHeight.d.ts.map +1 -0
  243. package/dist/utils/landscapeHeight.js +65 -0
  244. package/dist/utils/landscapeTextures.d.ts +94 -0
  245. package/dist/utils/landscapeTextures.d.ts.map +1 -0
  246. package/dist/utils/landscapeTextures.js +290 -0
  247. package/dist/utils/landscapeUniforms.d.ts +20 -0
  248. package/dist/utils/landscapeUniforms.d.ts.map +1 -0
  249. package/dist/utils/landscapeUniforms.js +61 -0
  250. package/dist/utils/oceanUniforms.d.ts +47 -0
  251. package/dist/utils/oceanUniforms.d.ts.map +1 -0
  252. package/dist/utils/oceanUniforms.js +216 -0
  253. package/dist/utils/rtin.d.ts +63 -0
  254. package/dist/utils/rtin.d.ts.map +1 -0
  255. package/dist/utils/rtin.js +202 -0
  256. package/dist/utils/terrainUniforms.d.ts +14 -0
  257. package/dist/utils/terrainUniforms.d.ts.map +1 -0
  258. package/dist/utils/terrainUniforms.js +196 -0
  259. package/package.json +2 -2
@@ -0,0 +1,138 @@
1
+ import { useEffect, useMemo, useRef, useState } from 'react';
2
+ import * as THREE from 'three';
3
+ import { buildFieldTexture, buildTextureArray, decodeHeightmap, loadImage, smoothHeightfield, textureFromImage, } from '../utils/landscapeTextures.js';
4
+ const EMPTY = {
5
+ height: null,
6
+ heightSize: new THREE.Vector2(1, 1),
7
+ field: null,
8
+ fieldSize: new THREE.Vector2(1, 1),
9
+ gradScale: 1,
10
+ diffuse: null,
11
+ normal: null,
12
+ splat0: null,
13
+ splat1: null,
14
+ ao: null,
15
+ means: [],
16
+ heightField: null,
17
+ ready: false,
18
+ error: null,
19
+ layerCount: 0,
20
+ };
21
+ function disposeState(state) {
22
+ state.height?.dispose();
23
+ state.field?.dispose();
24
+ state.diffuse?.dispose();
25
+ state.normal?.dispose();
26
+ state.splat0?.dispose();
27
+ state.splat1?.dispose();
28
+ state.ao?.dispose();
29
+ }
30
+ /** Only the URLs and the packing size matter; nothing here should re-run because
31
+ * a slider moved. */
32
+ function mapsKey(config, quality) {
33
+ return JSON.stringify([
34
+ config.heightMap,
35
+ config.heightEncoding,
36
+ config.splatMaps,
37
+ config.aoMap ?? '',
38
+ quality.arrayResolution,
39
+ quality.anisotropy,
40
+ config.surfaces.map((s) => [s.diffuse, s.normal ?? '', s.displacement ?? '']),
41
+ ]);
42
+ }
43
+ export function useLandscapeMaps(config, quality) {
44
+ const key = useMemo(() => mapsKey(config, quality), [config, quality]);
45
+ const [state, setState] = useState(EMPTY);
46
+ const current = useRef(EMPTY);
47
+ useEffect(() => {
48
+ let cancelled = false;
49
+ const surfaces = config.surfaces.filter((s) => !!s.diffuse);
50
+ if (!config.heightMap || surfaces.length === 0) {
51
+ setState({ ...EMPTY, error: null });
52
+ return () => { cancelled = true; };
53
+ }
54
+ const run = async () => {
55
+ const size = quality.arrayResolution;
56
+ const [heightImage, splatImages, aoImage, diffuseImages, normalImages, heightImages] = await Promise.all([
57
+ loadImage(config.heightMap),
58
+ Promise.all(config.splatMaps.slice(0, 2).map((url) => loadImage(url))),
59
+ config.aoMap ? loadImage(config.aoMap) : Promise.resolve(null),
60
+ Promise.all(surfaces.map((s) => loadImage(s.diffuse))),
61
+ Promise.all(surfaces.map((s) => (s.normal ? loadImage(s.normal) : Promise.resolve(null)))),
62
+ Promise.all(surfaces.map((s) => (s.displacement ? loadImage(s.displacement) : Promise.resolve(null)))),
63
+ ]);
64
+ if (cancelled)
65
+ return;
66
+ // Smoothed before anything else uses it. An 8-bit heightmap's own
67
+ // quantisation is a 1.33 m staircase over 340 m of relief, which is
68
+ // what RTIN's error metric measures instead of the terrain, and what
69
+ // the surface gradient would otherwise be computed from.
70
+ const raw = decodeHeightmap(heightImage, config.heightEncoding);
71
+ const heightField = smoothHeightfield(raw, 1);
72
+ const field = buildFieldTexture(heightField);
73
+ const height = textureFromImage(heightImage, THREE.NoColorSpace);
74
+ // No mips and no filtering surprises: the vertex stage samples this
75
+ // at lod 0 and the bicubic filter does its own footprint widening.
76
+ height.minFilter = THREE.LinearFilter;
77
+ height.magFilter = THREE.LinearFilter;
78
+ height.generateMipmaps = false;
79
+ const diffuse = buildTextureArray(diffuseImages, size, THREE.SRGBColorSpace);
80
+ const normal = buildTextureArray(normalImages, size, THREE.NoColorSpace, heightImages,
81
+ // A flat normal for a surface with no normal map.
82
+ [128, 128, 255, 128]);
83
+ diffuse.texture.anisotropy = quality.anisotropy;
84
+ normal.texture.anisotropy = quality.anisotropy;
85
+ const splats = splatImages.map((image) => {
86
+ const texture = textureFromImage(image, THREE.NoColorSpace);
87
+ texture.generateMipmaps = false;
88
+ texture.minFilter = THREE.LinearFilter;
89
+ return texture;
90
+ });
91
+ const ao = aoImage ? textureFromImage(aoImage, THREE.NoColorSpace) : null;
92
+ if (cancelled) {
93
+ height.dispose();
94
+ field.texture.dispose();
95
+ diffuse.texture.dispose();
96
+ normal.texture.dispose();
97
+ splats.forEach((t) => t.dispose());
98
+ ao?.dispose();
99
+ return;
100
+ }
101
+ const next = {
102
+ height,
103
+ heightSize: new THREE.Vector2(heightField.tileSize, heightField.tileSize),
104
+ field: field.texture,
105
+ fieldSize: new THREE.Vector2(heightField.tileSize, heightField.tileSize),
106
+ gradScale: field.gradScale,
107
+ diffuse: diffuse.texture,
108
+ normal: normal.texture,
109
+ splat0: splats[0] ?? null,
110
+ splat1: splats[1] ?? null,
111
+ ao,
112
+ means: diffuse.means,
113
+ heightField,
114
+ ready: true,
115
+ error: null,
116
+ layerCount: surfaces.length,
117
+ };
118
+ const previous = current.current;
119
+ current.current = next;
120
+ setState(next);
121
+ // Only now — swapping first would blink the ground away mid-edit.
122
+ disposeState(previous);
123
+ };
124
+ run().catch((error) => {
125
+ if (cancelled)
126
+ return;
127
+ const message = error instanceof Error ? error.message : String(error);
128
+ // eslint-disable-next-line no-console
129
+ console.error('[landscape] map load failed:', message);
130
+ setState({ ...EMPTY, error: message });
131
+ });
132
+ return () => { cancelled = true; };
133
+ // eslint-disable-next-line react-hooks/exhaustive-deps
134
+ }, [key]);
135
+ useEffect(() => () => { disposeState(current.current); }, []);
136
+ return state;
137
+ }
138
+ export default useLandscapeMaps;
@@ -0,0 +1,29 @@
1
+ import type { Object3D } from 'three';
2
+ /**
3
+ * Live ocean editing, the counterpart to `useTerrainLive` and `useCloudLive`.
4
+ *
5
+ * A slider drag fires on every pointer-move. Routing that through Redux would
6
+ * dispatch and re-render the tree sixty times a second, and for `quality` it is
7
+ * worse than that: a new quality object rebuilds every clipmap ring. So the
8
+ * controller finds the water with `findById(id)` and writes straight into the
9
+ * renderer; Redux only hears about it on slider end.
10
+ *
11
+ * const live = useOceanLive(settings.id);
12
+ * <BaseControllerUi onLiveChange={live.config} onSettingsChange={dispatch} ... />
13
+ *
14
+ * Pass the ID, not a resolved Object3D. The panel is routinely open before the
15
+ * thing it controls exists — water ships disabled, so the group is not in the
16
+ * scene at all until the section toggle is flipped — and a findById() memoised
17
+ * in the controller resolves to null exactly once and stays null for the rest of
18
+ * the session, after which every slider silently does nothing. Resolving here,
19
+ * at call time, is what makes that impossible.
20
+ */
21
+ /** Where the renderer stashes its handle on the root object's userData. */
22
+ export declare const OCEAN_LIVE_KEY = "__oceanLive";
23
+ export interface OceanLiveHandle {
24
+ config(key: string, value: number | boolean | string): void;
25
+ quality(key: string, value: number | boolean | string): void;
26
+ }
27
+ export declare function useOceanLive(target?: Object3D | string | null): OceanLiveHandle;
28
+ export default useOceanLive;
29
+ //# sourceMappingURL=useOceanLive.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useOceanLive.d.ts","sourceRoot":"","sources":["../../src/hooks/useOceanLive.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAGtC;;;;;;;;;;;;;;;;;;GAkBG;AAEH,2EAA2E;AAC3E,eAAO,MAAM,cAAc,gBAAgB,CAAC;AAE5C,MAAM,WAAW,eAAe;IAC5B,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,IAAI,CAAC;IAC5D,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,IAAI,CAAC;CAChE;AAID,wBAAgB,YAAY,CAAC,MAAM,CAAC,EAAE,QAAQ,GAAG,MAAM,GAAG,IAAI,GAAG,eAAe,CAY/E;AAED,eAAe,YAAY,CAAC"}
@@ -0,0 +1,38 @@
1
+ import { useMemo } from 'react';
2
+ import { findById } from '../utils/sceneQuery.js';
3
+ /**
4
+ * Live ocean editing, the counterpart to `useTerrainLive` and `useCloudLive`.
5
+ *
6
+ * A slider drag fires on every pointer-move. Routing that through Redux would
7
+ * dispatch and re-render the tree sixty times a second, and for `quality` it is
8
+ * worse than that: a new quality object rebuilds every clipmap ring. So the
9
+ * controller finds the water with `findById(id)` and writes straight into the
10
+ * renderer; Redux only hears about it on slider end.
11
+ *
12
+ * const live = useOceanLive(settings.id);
13
+ * <BaseControllerUi onLiveChange={live.config} onSettingsChange={dispatch} ... />
14
+ *
15
+ * Pass the ID, not a resolved Object3D. The panel is routinely open before the
16
+ * thing it controls exists — water ships disabled, so the group is not in the
17
+ * scene at all until the section toggle is flipped — and a findById() memoised
18
+ * in the controller resolves to null exactly once and stays null for the rest of
19
+ * the session, after which every slider silently does nothing. Resolving here,
20
+ * at call time, is what makes that impossible.
21
+ */
22
+ /** Where the renderer stashes its handle on the root object's userData. */
23
+ export const OCEAN_LIVE_KEY = '__oceanLive';
24
+ const NOOP = { config: () => { }, quality: () => { } };
25
+ export function useOceanLive(target) {
26
+ return useMemo(() => {
27
+ const resolve = () => {
28
+ const object = typeof target === 'string' ? findById(target) : target;
29
+ const handle = object?.userData?.[OCEAN_LIVE_KEY];
30
+ return handle ?? NOOP;
31
+ };
32
+ return {
33
+ config: (key, value) => resolve().config(key, value),
34
+ quality: (key, value) => resolve().quality(key, value),
35
+ };
36
+ }, [target]);
37
+ }
38
+ export default useOceanLive;
@@ -0,0 +1,39 @@
1
+ import * as THREE from 'three';
2
+ import { type RootState } from '@react-three/fiber';
3
+ import type { SkySettings, TimeSettings } from '@3driseai/3drise-core';
4
+ import { OceanSurfaceMaterial } from '../shaders/ocean/OceanSurfaceMaterial';
5
+ import type { OceanConfig, OceanQualityConfig } from '../types/oceanConfigs';
6
+ /**
7
+ * Everything the two water hosts share: the material, the live-edit handle, and
8
+ * the per-frame uniform push.
9
+ *
10
+ * It exists so the world ocean and a placed body cannot drift apart. They differ
11
+ * in exactly one thing — the mesh — and the moment the frame loop is written
12
+ * twice, one of them gets a fix the other does not. That is the same mistake the
13
+ * environment made with two `SkySystem`s, documented in
14
+ * `claude/connector-pattern.md`.
15
+ *
16
+ * The caller owns the mesh (or meshes) and does whatever positioning its host
17
+ * needs; this owns the shading.
18
+ */
19
+ export interface UseOceanMaterialOptions {
20
+ id: string;
21
+ config: OceanConfig;
22
+ quality: OceanQualityConfig;
23
+ skySettings?: SkySettings;
24
+ timeSettings?: TimeSettings;
25
+ sunIntensity?: number;
26
+ /** Runs after the uniforms are pushed, with the live overrides already
27
+ * merged in — where a host does its own per-frame work (snapping the
28
+ * clipmap to the camera, say) with the config it is actually rendering. */
29
+ onFrame?(config: OceanConfig, quality: OceanQualityConfig, state: RootState): void;
30
+ }
31
+ export interface OceanMaterialHandle {
32
+ material: OceanSurfaceMaterial;
33
+ /** Attach to the host's root group: it carries the scene id and the live
34
+ * handle a controller reaches through `findById`. */
35
+ rootRef: React.RefObject<THREE.Group | null>;
36
+ }
37
+ export declare function useOceanMaterial({ id, config, quality, skySettings, timeSettings, sunIntensity, onFrame, }: UseOceanMaterialOptions): OceanMaterialHandle;
38
+ export default useOceanMaterial;
39
+ //# sourceMappingURL=useOceanMaterial.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useOceanMaterial.d.ts","sourceRoot":"","sources":["../../src/hooks/useOceanMaterial.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAGvE,OAAO,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAI7E,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAE7E;;;;;;;;;;;;GAYG;AAEH,MAAM,WAAW,uBAAuB;IACpC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,WAAW,CAAC;IACpB,OAAO,EAAE,kBAAkB,CAAC;IAC5B,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;gFAE4E;IAC5E,OAAO,CAAC,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,kBAAkB,EAAE,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;CACtF;AAED,MAAM,WAAW,mBAAmB;IAChC,QAAQ,EAAE,oBAAoB,CAAC;IAC/B;0DACsD;IACtD,OAAO,EAAE,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC;CAChD;AAED,wBAAgB,gBAAgB,CAAC,EAC7B,EAAE,EACF,MAAM,EACN,OAAO,EACP,WAAW,EACX,YAAY,EACZ,YAAgB,EAChB,OAAO,GACV,EAAE,uBAAuB,GAAG,mBAAmB,CAkE/C;AAED,eAAe,gBAAgB,CAAC"}
@@ -0,0 +1,65 @@
1
+ import { useEffect, useMemo, useRef } from 'react';
2
+ import { useFrame } from '@react-three/fiber';
3
+ import { useCloudSun } from './useCloudSun.js';
4
+ import { OCEAN_LIVE_KEY } from './useOceanLive.js';
5
+ import { OceanSurfaceMaterial } from '../shaders/ocean/OceanSurfaceMaterial.js';
6
+ import { applySunUniforms } from '../utils/cloudUniforms.js';
7
+ import { applyTerrainAmbient } from '../utils/terrainUniforms.js';
8
+ import { applyOceanUniforms } from '../utils/oceanUniforms.js';
9
+ export function useOceanMaterial({ id, config, quality, skySettings, timeSettings, sunIntensity = 1, onFrame, }) {
10
+ const { state: sun, update: updateSun } = useCloudSun({ skySettings, timeSettings });
11
+ const material = useMemo(() => new OceanSurfaceMaterial(), []);
12
+ useEffect(() => () => { material.dispose(); }, [material]);
13
+ // Live controller overrides. A slider drag writes here on every pointer-move
14
+ // and the frame loop reads it on top of the config, so the water responds
15
+ // without a dispatch per frame — which for `quality` also means without
16
+ // rebuilding every clipmap ring sixty times a second. Cleared when the config
17
+ // identity changes, which is exactly slider-end committing the same value.
18
+ const liveConfig = useRef({});
19
+ const liveQuality = useRef({});
20
+ useEffect(() => { liveConfig.current = {}; }, [config]);
21
+ useEffect(() => { liveQuality.current = {}; }, [quality]);
22
+ const rootRef = useRef(null);
23
+ // Set in an effect, never as a userData JSX prop: R3F replaces the whole
24
+ // userData object on every render, which would drop the handle whenever
25
+ // anything above re-rendered.
26
+ const liveHandle = useMemo(() => ({
27
+ config: (key, value) => { liveConfig.current[key] = value; },
28
+ quality: (key, value) => { liveQuality.current[key] = value; },
29
+ }), []);
30
+ useEffect(() => {
31
+ const root = rootRef.current;
32
+ if (!root)
33
+ return;
34
+ root.userData.id = id;
35
+ root.userData[OCEAN_LIVE_KEY] = liveHandle;
36
+ return () => { delete root.userData[OCEAN_LIVE_KEY]; };
37
+ }, [id, liveHandle]);
38
+ useFrame((state) => {
39
+ const shader = material;
40
+ updateSun();
41
+ applySunUniforms(shader, sun, sunIntensity);
42
+ // Overwrites the two ambient colours applySunUniforms just set. Those are
43
+ // the cloud curve, tuned for cloud interiors; water has to be lit by — and
44
+ // reflect — the sky actually being drawn behind it, or a sunset sea comes
45
+ // out black under a blazing sky.
46
+ applyTerrainAmbient(shader, sun);
47
+ const cfg = { ...config, ...liveConfig.current };
48
+ const qual = { ...quality, ...liveQuality.current };
49
+ applyOceanUniforms(shader, cfg, qual);
50
+ shader.uniforms.u_time.value = state.clock.getElapsedTime();
51
+ // World size of one pixel at unit distance. The detail fade and the
52
+ // specular filtering are both screen-space decisions — whether a ripple
53
+ // is a shape or a shimmer depends on the field of view and the
54
+ // resolution, not on the distance — so the shader needs to know how big
55
+ // a pixel is. Recomputed per frame because a camera can zoom.
56
+ const camera = state.camera;
57
+ if (camera.isPerspectiveCamera) {
58
+ const height = Math.max(state.size.height * state.viewport.dpr, 1);
59
+ shader.uniforms.u_pixelScale.value = (2 * Math.tan((camera.fov * Math.PI) / 360)) / height;
60
+ }
61
+ onFrame?.(cfg, qual, state);
62
+ });
63
+ return { material, rootRef };
64
+ }
65
+ export default useOceanMaterial;
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Terrain's view of the shared clipmap.
3
+ *
4
+ * The ring builder moved to `useClipmap` when the ocean started using it — the
5
+ * geometry, the geomorph attributes and the shared snapped origin were never
6
+ * terrain-specific, only the height field on top of them is. This file stays so
7
+ * existing imports and the package's public surface keep working; there is no
8
+ * terrain-only behaviour left in it.
9
+ */
10
+ export { useClipmap, useClipmap as useTerrainClipmap, default } from './useClipmap';
11
+ export type { Clipmap as TerrainClipmap, ClipmapLevel as TerrainClipmapLevel, Clipmap, ClipmapLevel } from './useClipmap';
12
+ //# sourceMappingURL=useTerrainClipmap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTerrainClipmap.d.ts","sourceRoot":"","sources":["../../src/hooks/useTerrainClipmap.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,UAAU,EAAE,UAAU,IAAI,iBAAiB,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACpF,YAAY,EAAE,OAAO,IAAI,cAAc,EAAE,YAAY,IAAI,mBAAmB,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Terrain's view of the shared clipmap.
3
+ *
4
+ * The ring builder moved to `useClipmap` when the ocean started using it — the
5
+ * geometry, the geomorph attributes and the shared snapped origin were never
6
+ * terrain-specific, only the height field on top of them is. This file stays so
7
+ * existing imports and the package's public surface keep working; there is no
8
+ * terrain-only behaviour left in it.
9
+ */
10
+ export { useClipmap, useClipmap as useTerrainClipmap, default } from './useClipmap.js';
@@ -0,0 +1,34 @@
1
+ import type { Object3D } from 'three';
2
+ /**
3
+ * Live terrain editing, the counterpart to `useCloudLive`.
4
+ *
5
+ * A slider drag fires on every pointer-move. Routing that through Redux would
6
+ * dispatch and re-render the tree sixty times a second — and here it is worse
7
+ * than for the clouds, because a new `quality` object rebuilds every clipmap ring
8
+ * from scratch. So the controller finds the terrain with `findById(id)` and
9
+ * writes straight into the renderer; Redux only hears about it on slider end.
10
+ *
11
+ * const live = useTerrainLive(settings.id);
12
+ * <BaseControllerUi onLiveChange={live.config} onSettingsChange={dispatchToRedux} ... />
13
+ *
14
+ * Pass the ID, not a resolved Object3D. The panel is routinely open before the
15
+ * thing it controls exists — terrain ships disabled, so the group is not in the
16
+ * scene at all until the section toggle is flipped — and a findById() memoised in
17
+ * the controller resolves to null exactly once and stays null for the rest of the
18
+ * session. Every slider then silently does nothing until the controller happens to
19
+ * remount. Resolving here, at call time, is what makes that impossible.
20
+ */
21
+ /** Where TerrainSurface stashes its handle on the root object's userData. */
22
+ export declare const TERRAIN_LIVE_KEY = "__terrainLive";
23
+ export interface TerrainLiveHandle {
24
+ config(key: string, value: number | boolean | string): void;
25
+ quality(key: string, value: number | boolean | string): void;
26
+ }
27
+ /**
28
+ * Safe before the terrain mounts and after it unmounts: the handle is resolved at
29
+ * call time, not at hook time, so a controller opened before the scene is ready
30
+ * still works once it is, and a stale reference degrades to a no-op.
31
+ */
32
+ export declare function useTerrainLive(target?: Object3D | string | null): TerrainLiveHandle;
33
+ export default useTerrainLive;
34
+ //# sourceMappingURL=useTerrainLive.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTerrainLive.d.ts","sourceRoot":"","sources":["../../src/hooks/useTerrainLive.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAGtC;;;;;;;;;;;;;;;;;;GAkBG;AAEH,6EAA6E;AAC7E,eAAO,MAAM,gBAAgB,kBAAkB,CAAC;AAEhD,MAAM,WAAW,iBAAiB;IAC9B,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,IAAI,CAAC;IAC5D,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,IAAI,CAAC;CAChE;AAID;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,MAAM,CAAC,EAAE,QAAQ,GAAG,MAAM,GAAG,IAAI,GAAG,iBAAiB,CAcnF;AAED,eAAe,cAAc,CAAC"}
@@ -0,0 +1,45 @@
1
+ import { useMemo } from 'react';
2
+ import { findById } from '../utils/sceneQuery.js';
3
+ /**
4
+ * Live terrain editing, the counterpart to `useCloudLive`.
5
+ *
6
+ * A slider drag fires on every pointer-move. Routing that through Redux would
7
+ * dispatch and re-render the tree sixty times a second — and here it is worse
8
+ * than for the clouds, because a new `quality` object rebuilds every clipmap ring
9
+ * from scratch. So the controller finds the terrain with `findById(id)` and
10
+ * writes straight into the renderer; Redux only hears about it on slider end.
11
+ *
12
+ * const live = useTerrainLive(settings.id);
13
+ * <BaseControllerUi onLiveChange={live.config} onSettingsChange={dispatchToRedux} ... />
14
+ *
15
+ * Pass the ID, not a resolved Object3D. The panel is routinely open before the
16
+ * thing it controls exists — terrain ships disabled, so the group is not in the
17
+ * scene at all until the section toggle is flipped — and a findById() memoised in
18
+ * the controller resolves to null exactly once and stays null for the rest of the
19
+ * session. Every slider then silently does nothing until the controller happens to
20
+ * remount. Resolving here, at call time, is what makes that impossible.
21
+ */
22
+ /** Where TerrainSurface stashes its handle on the root object's userData. */
23
+ export const TERRAIN_LIVE_KEY = '__terrainLive';
24
+ const NOOP = { config: () => { }, quality: () => { } };
25
+ /**
26
+ * Safe before the terrain mounts and after it unmounts: the handle is resolved at
27
+ * call time, not at hook time, so a controller opened before the scene is ready
28
+ * still works once it is, and a stale reference degrades to a no-op.
29
+ */
30
+ export function useTerrainLive(target) {
31
+ return useMemo(() => {
32
+ const resolve = () => {
33
+ // Resolved per call, never cached. See the note above: the scene object
34
+ // usually does not exist yet when the controller first renders.
35
+ const object = typeof target === 'string' ? findById(target) : target;
36
+ const handle = object?.userData?.[TERRAIN_LIVE_KEY];
37
+ return handle ?? NOOP;
38
+ };
39
+ return {
40
+ config: (key, value) => resolve().config(key, value),
41
+ quality: (key, value) => resolve().quality(key, value),
42
+ };
43
+ }, [target]);
44
+ }
45
+ export default useTerrainLive;
package/dist/index.d.ts CHANGED
@@ -11,7 +11,33 @@ export * from './utils/shapes';
11
11
  export { applyGenerativeAnimations } from './utils/handleGenerativeEffectsAnimations';
12
12
  export { hasHoverAnimation } from './utils/hasHoverAnimation';
13
13
  export { findById } from './utils/sceneQuery';
14
+ export { hasFrameRenderer, registerFrameRenderer, renderFrame } from './utils/frameRenderer';
15
+ export type { FrameRenderer } from './utils/frameRenderer';
14
16
  export { resolveObject3D } from './utils/resolveObject3D';
15
17
  export type { Object3DRefLike, Object3DSource } from './utils/resolveObject3D';
16
18
  export * from './utils/textEffects';
19
+ export { applyTerrainUniforms } from './utils/terrainUniforms';
20
+ export { applyLandscapeMaps, applyLandscapeUniforms } from './utils/landscapeUniforms';
21
+ export type { LandscapeMapUniforms } from './utils/landscapeUniforms';
22
+ export { getLandscapeHeightAt, registerLandscapeHeightField, sampleLandscapeHeight, snapToLandscape, unregisterLandscapeHeightField, } from './utils/landscapeHeight';
23
+ export type { LandscapeHeightField } from './utils/landscapeHeight';
24
+ export { buildLandscapeGeometry, rtinTileFor, setLandscapeBounds } from './utils/landscapeGeometry';
25
+ export type { LandscapeChunk, LandscapeGeometry } from './utils/landscapeGeometry';
26
+ export { Rtin, RtinTile } from './utils/rtin';
27
+ export { buildTextureArray, decodeHeightmap, loadImage } from './utils/landscapeTextures';
28
+ export type { DecodedHeightmap } from './utils/landscapeTextures';
29
+ export { applyOceanUniforms, buildWaveTable, seaState } from './utils/oceanUniforms';
30
+ export type { WaveTable } from './utils/oceanUniforms';
31
+ export { applyCameraUniforms, applyCirrusUniforms, applyDeckUniforms, applySunUniforms, } from './utils/cloudUniforms';
32
+ export { applyCloudsKeyframeAnimations, applyCloudsMouseMove, resolveDeckConfig, } from './utils/handleCloudsAnimations';
33
+ export { volumetricCloudPresets, cirrusPresets, getCloudPresetsForType, getCloudPresetByName, getCirrusPresetByName, searchCloudPresetsByTags, } from './presets/volumetricCloudPresets';
34
+ export type { VolumetricCloudPreset, CirrusPreset } from './presets/volumetricCloudPresets';
35
+ export { terrainPresets, getTerrainPresetsForType, getTerrainPresetByName, searchTerrainPresetsByTags, } from './presets/terrainPresets';
36
+ export type { TerrainPreset } from './presets/terrainPresets';
37
+ export { getLandscapePresetByName, landscapePresetAssetNames, landscapePresets, resolveLandscapePreset, searchLandscapePresetsByTags, } from './presets/landscapePresets';
38
+ export type { LandscapeAssetResolver, LandscapePreset, ResolvedLandscapePreset, } from './presets/landscapePresets';
39
+ export { LANDSCAPE_DETAIL, detectLandscapeDetail, getLandscapeShape, getLandscapeType, landscapeQualityForDetail, landscapeShapes, landscapeTypePacks, landscapeTypeAvailability, landscapeTypes, repeatForMetres, resolveLandscapeType, } from './presets/landscapeTypes';
40
+ export type { LandscapeAssetIndex, LandscapeDetail, LandscapePackRef, LandscapeShapeDef, LandscapeTypeAvailability, LandscapeTypeDef, ResolvedLandscapeType, } from './presets/landscapeTypes';
41
+ export { oceanSurfacePresets, getOceanPresetsForType, getOceanPresetByName, searchOceanPresetsByTags, } from './presets/oceanSurfacePresets';
42
+ export type { OceanPreset } from './presets/oceanSurfacePresets';
17
43
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,YAAY,EAAE,cAAc,EAAE,kBAAkB,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAG1F,OAAO,EAAE,iBAAiB,IAAI,iBAAiB,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAG5F,cAAc,SAAS,CAAC;AAGxB,cAAc,cAAc,CAAC;AAG7B,cAAc,SAAS,CAAC;AAExB,YAAY,EAAE,oBAAoB,IAAI,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AAGjG,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,iBAAiB,EAAE,WAAW,GAAG,MAAM,iBAAiB,CAAC;AACrG,OAAO,EAAE,mBAAmB,IAAI,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AACvF,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,yBAAyB,EAAE,MAAM,2CAA2C,CAAC;AACtF,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC/E,cAAc,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -14,5 +14,21 @@ export * from './utils/shapes.js';
14
14
  export { applyGenerativeAnimations } from './utils/handleGenerativeEffectsAnimations.js';
15
15
  export { hasHoverAnimation } from './utils/hasHoverAnimation.js';
16
16
  export { findById } from './utils/sceneQuery.js';
17
+ export { hasFrameRenderer, registerFrameRenderer, renderFrame } from './utils/frameRenderer.js';
17
18
  export { resolveObject3D } from './utils/resolveObject3D.js';
18
19
  export * from './utils/textEffects.js';
20
+ export { applyTerrainUniforms } from './utils/terrainUniforms.js';
21
+ export { applyLandscapeMaps, applyLandscapeUniforms } from './utils/landscapeUniforms.js';
22
+ export { getLandscapeHeightAt, registerLandscapeHeightField, sampleLandscapeHeight, snapToLandscape, unregisterLandscapeHeightField, } from './utils/landscapeHeight.js';
23
+ export { buildLandscapeGeometry, rtinTileFor, setLandscapeBounds } from './utils/landscapeGeometry.js';
24
+ export { Rtin, RtinTile } from './utils/rtin.js';
25
+ export { buildTextureArray, decodeHeightmap, loadImage } from './utils/landscapeTextures.js';
26
+ export { applyOceanUniforms, buildWaveTable, seaState } from './utils/oceanUniforms.js';
27
+ export { applyCameraUniforms, applyCirrusUniforms, applyDeckUniforms, applySunUniforms, } from './utils/cloudUniforms.js';
28
+ export { applyCloudsKeyframeAnimations, applyCloudsMouseMove, resolveDeckConfig, } from './utils/handleCloudsAnimations.js';
29
+ // Presets
30
+ export { volumetricCloudPresets, cirrusPresets, getCloudPresetsForType, getCloudPresetByName, getCirrusPresetByName, searchCloudPresetsByTags, } from './presets/volumetricCloudPresets.js';
31
+ export { terrainPresets, getTerrainPresetsForType, getTerrainPresetByName, searchTerrainPresetsByTags, } from './presets/terrainPresets.js';
32
+ export { getLandscapePresetByName, landscapePresetAssetNames, landscapePresets, resolveLandscapePreset, searchLandscapePresetsByTags, } from './presets/landscapePresets.js';
33
+ export { LANDSCAPE_DETAIL, detectLandscapeDetail, getLandscapeShape, getLandscapeType, landscapeQualityForDetail, landscapeShapes, landscapeTypePacks, landscapeTypeAvailability, landscapeTypes, repeatForMetres, resolveLandscapeType, } from './presets/landscapeTypes.js';
34
+ export { oceanSurfacePresets, getOceanPresetsForType, getOceanPresetByName, searchOceanPresetsByTags, } from './presets/oceanSurfacePresets.js';
@@ -0,0 +1,60 @@
1
+ import type { LandscapeConfig, LandscapeSurface } from '../types/landscapeConfigs';
2
+ /**
3
+ * Starter landscapes.
4
+ *
5
+ * **A preset names files, not URLs.** Where those files actually live is the
6
+ * client's business — they are uploaded assets served from Digital Ocean Spaces,
7
+ * and the viewer has no idea what a bucket is. So each preset carries bare file
8
+ * names and `resolveLandscapePreset` turns them into a config once the caller
9
+ * supplies a lookup. That is the same rule as everywhere else in this package:
10
+ * rendering lives here, everything that knows about the app lives in the client.
11
+ *
12
+ * A preset is also a PATCH over the defaults, never a whole config, so a knob
13
+ * added later is picked up by every preset instead of being frozen at whatever
14
+ * the preset was written with.
15
+ */
16
+ export interface LandscapePreset {
17
+ name: string;
18
+ description: string;
19
+ tags: string[];
20
+ /** File names this preset needs. Resolution happens in the client. */
21
+ assets: {
22
+ heightMap: string;
23
+ splatMaps?: string[];
24
+ aoMap?: string;
25
+ };
26
+ /** Surfaces with `diffuse` / `normal` / `displacement` as FILE NAMES. */
27
+ surfaces: LandscapeSurface[];
28
+ /** Everything that is not an asset reference. */
29
+ settings: Partial<LandscapeConfig>;
30
+ }
31
+ export declare const landscapePresets: LandscapePreset[];
32
+ /** Turns one file name into a URL, or null when the asset is not there. */
33
+ export type LandscapeAssetResolver = (fileName: string) => string | null;
34
+ export interface ResolvedLandscapePreset {
35
+ /** The config patch, with every asset reference resolved to a URL. */
36
+ config: Partial<LandscapeConfig>;
37
+ /** File names the resolver could not find. Empty means the preset is whole. */
38
+ missing: string[];
39
+ }
40
+ /**
41
+ * Fill a preset's file names in from wherever the caller keeps its assets.
42
+ *
43
+ * Surfaces whose diffuse cannot be resolved are dropped rather than rendered as
44
+ * a hole — a surface with no albedo is skipped by the renderer anyway, and an
45
+ * empty slot in the middle of the list would silently shift every splat channel
46
+ * after it. A missing normal or height map is not fatal: those degrade to a flat
47
+ * normal and a linear blend, which is what the reference implementation does for
48
+ * every surface always.
49
+ *
50
+ * The heightmap is the one thing that cannot be missing — without it there is no
51
+ * landscape — so an unresolved heightmap returns a config with `enabled: false`
52
+ * and the name in `missing`, for the panel to say so.
53
+ */
54
+ export declare function resolveLandscapePreset(preset: LandscapePreset, resolve: LandscapeAssetResolver): ResolvedLandscapePreset;
55
+ export declare function getLandscapePresetByName(name: string): LandscapePreset | undefined;
56
+ /** Every file name the built-in presets need, for a client that wants to check
57
+ * what is uploaded before offering them. */
58
+ export declare function landscapePresetAssetNames(): string[];
59
+ export declare function searchLandscapePresetsByTags(tags: string[]): LandscapePreset[];
60
+ //# sourceMappingURL=landscapePresets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"landscapePresets.d.ts","sourceRoot":"","sources":["../../src/presets/landscapePresets.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAA;AAGlF;;;;;;;;;;;;;GAaG;AAEH,MAAM,WAAW,eAAe;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,sEAAsE;IACtE,MAAM,EAAE;QACJ,SAAS,EAAE,MAAM,CAAA;QACjB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAA;QACpB,KAAK,CAAC,EAAE,MAAM,CAAA;KACjB,CAAA;IACD,yEAAyE;IACzE,QAAQ,EAAE,gBAAgB,EAAE,CAAA;IAC5B,iDAAiD;IACjD,QAAQ,EAAE,OAAO,CAAC,eAAe,CAAC,CAAA;CACrC;AAkED,eAAO,MAAM,gBAAgB,EAAE,eAAe,EAwD7C,CAAA;AAED,2EAA2E;AAC3E,MAAM,MAAM,sBAAsB,GAAG,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAA;AAExE,MAAM,WAAW,uBAAuB;IACpC,sEAAsE;IACtE,MAAM,EAAE,OAAO,CAAC,eAAe,CAAC,CAAA;IAChC,+EAA+E;IAC/E,OAAO,EAAE,MAAM,EAAE,CAAA;CACpB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,sBAAsB,CAClC,MAAM,EAAE,eAAe,EACvB,OAAO,EAAE,sBAAsB,GAChC,uBAAuB,CAwCzB;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAElF;AAED;6CAC6C;AAC7C,wBAAgB,yBAAyB,IAAI,MAAM,EAAE,CAapD;AAED,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,eAAe,EAAE,CAK9E"}