@3driseai/3drise-viewer 0.1.6 → 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 (277) 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/CustomPrimitive.js +1 -1
  7. package/dist/components/EnvironmentManager.d.ts +47 -5
  8. package/dist/components/EnvironmentManager.d.ts.map +1 -1
  9. package/dist/components/EnvironmentManager.js +35 -66
  10. package/dist/components/GeometryShape.d.ts.map +1 -1
  11. package/dist/components/GeometryShape.js +19 -3
  12. package/dist/components/HdrEnvironment.d.ts +20 -0
  13. package/dist/components/HdrEnvironment.d.ts.map +1 -0
  14. package/dist/components/HdrEnvironment.js +44 -0
  15. package/dist/components/LandscapeBuilder.d.ts +23 -0
  16. package/dist/components/LandscapeBuilder.d.ts.map +1 -0
  17. package/dist/components/LandscapeBuilder.js +25 -0
  18. package/dist/components/LandscapeObject.d.ts +24 -0
  19. package/dist/components/LandscapeObject.d.ts.map +1 -0
  20. package/dist/components/LandscapeObject.js +27 -0
  21. package/dist/components/ObjectNode.d.ts.map +1 -1
  22. package/dist/components/ObjectNode.js +11 -9
  23. package/dist/components/OceanBuilder.d.ts +35 -0
  24. package/dist/components/OceanBuilder.d.ts.map +1 -0
  25. package/dist/components/OceanBuilder.js +53 -0
  26. package/dist/components/ParticlesR3f.d.ts.map +1 -1
  27. package/dist/components/ParticlesR3f.js +63 -12
  28. package/dist/components/PointCloud.d.ts.map +1 -1
  29. package/dist/components/PointCloud.js +50 -10
  30. package/dist/components/SceneBuilder.d.ts.map +1 -1
  31. package/dist/components/SkySystem.d.ts +27 -6
  32. package/dist/components/SkySystem.d.ts.map +1 -1
  33. package/dist/components/SkySystem.js +6 -5
  34. package/dist/components/SunLight.d.ts.map +1 -1
  35. package/dist/components/SunLight.js +4 -1
  36. package/dist/components/TerrainBuilder.d.ts +30 -0
  37. package/dist/components/TerrainBuilder.d.ts.map +1 -0
  38. package/dist/components/TerrainBuilder.js +44 -0
  39. package/dist/components/index.d.ts +17 -1
  40. package/dist/components/index.d.ts.map +1 -1
  41. package/dist/components/index.js +10 -0
  42. package/dist/components/landscape/LandscapeMesh.d.ts +18 -0
  43. package/dist/components/landscape/LandscapeMesh.d.ts.map +1 -0
  44. package/dist/components/landscape/LandscapeMesh.js +278 -0
  45. package/dist/components/landscape/index.d.ts +3 -0
  46. package/dist/components/landscape/index.d.ts.map +1 -0
  47. package/dist/components/landscape/index.js +1 -0
  48. package/dist/components/landscape/types.d.ts +13 -0
  49. package/dist/components/landscape/types.d.ts.map +1 -0
  50. package/dist/components/landscape/types.js +1 -0
  51. package/dist/components/terrain/Canyon.d.ts +23 -0
  52. package/dist/components/terrain/Canyon.d.ts.map +1 -0
  53. package/dist/components/terrain/Canyon.js +29 -0
  54. package/dist/components/terrain/Dunes.d.ts +22 -0
  55. package/dist/components/terrain/Dunes.d.ts.map +1 -0
  56. package/dist/components/terrain/Dunes.js +25 -0
  57. package/dist/components/terrain/Hills.d.ts +17 -0
  58. package/dist/components/terrain/Hills.d.ts.map +1 -0
  59. package/dist/components/terrain/Hills.js +20 -0
  60. package/dist/components/terrain/Mountains.d.ts +19 -0
  61. package/dist/components/terrain/Mountains.d.ts.map +1 -0
  62. package/dist/components/terrain/Mountains.js +22 -0
  63. package/dist/components/terrain/TerrainSurface.d.ts +22 -0
  64. package/dist/components/terrain/TerrainSurface.d.ts.map +1 -0
  65. package/dist/components/terrain/TerrainSurface.js +94 -0
  66. package/dist/components/terrain/index.d.ts +7 -0
  67. package/dist/components/terrain/index.d.ts.map +1 -0
  68. package/dist/components/terrain/index.js +7 -0
  69. package/dist/components/terrain/types.d.ts +17 -0
  70. package/dist/components/terrain/types.d.ts.map +1 -0
  71. package/dist/components/terrain/types.js +1 -0
  72. package/dist/components/volumetricClouds/Cirrus.d.ts +14 -0
  73. package/dist/components/volumetricClouds/Cirrus.d.ts.map +1 -0
  74. package/dist/components/volumetricClouds/Cirrus.js +13 -0
  75. package/dist/components/volumetricClouds/Cumulonimbus.d.ts +17 -0
  76. package/dist/components/volumetricClouds/Cumulonimbus.d.ts.map +1 -0
  77. package/dist/components/volumetricClouds/Cumulonimbus.js +20 -0
  78. package/dist/components/volumetricClouds/Cumulus.d.ts +14 -0
  79. package/dist/components/volumetricClouds/Cumulus.d.ts.map +1 -0
  80. package/dist/components/volumetricClouds/Cumulus.js +17 -0
  81. package/dist/components/volumetricClouds/Stratocumulus.d.ts +12 -0
  82. package/dist/components/volumetricClouds/Stratocumulus.d.ts.map +1 -0
  83. package/dist/components/volumetricClouds/Stratocumulus.js +16 -0
  84. package/dist/components/volumetricClouds/VolumetricCloudsPass.d.ts +42 -0
  85. package/dist/components/volumetricClouds/VolumetricCloudsPass.d.ts.map +1 -0
  86. package/dist/components/volumetricClouds/VolumetricCloudsPass.js +298 -0
  87. package/dist/components/volumetricClouds/index.d.ts +8 -0
  88. package/dist/components/volumetricClouds/index.d.ts.map +1 -0
  89. package/dist/components/volumetricClouds/index.js +7 -0
  90. package/dist/components/volumetricClouds/types.d.ts +17 -0
  91. package/dist/components/volumetricClouds/types.d.ts.map +1 -0
  92. package/dist/components/volumetricClouds/types.js +1 -0
  93. package/dist/components/water/Host.d.ts +12 -0
  94. package/dist/components/water/Host.d.ts.map +1 -0
  95. package/dist/components/water/Host.js +12 -0
  96. package/dist/components/water/Lake.d.ts +18 -0
  97. package/dist/components/water/Lake.d.ts.map +1 -0
  98. package/dist/components/water/Lake.js +21 -0
  99. package/dist/components/water/OceanSurface.d.ts +27 -0
  100. package/dist/components/water/OceanSurface.d.ts.map +1 -0
  101. package/dist/components/water/OceanSurface.js +60 -0
  102. package/dist/components/water/Sea.d.ts +18 -0
  103. package/dist/components/water/Sea.d.ts.map +1 -0
  104. package/dist/components/water/Sea.js +17 -0
  105. package/dist/components/water/Shore.d.ts +16 -0
  106. package/dist/components/water/Shore.d.ts.map +1 -0
  107. package/dist/components/water/Shore.js +15 -0
  108. package/dist/components/water/Storm.d.ts +14 -0
  109. package/dist/components/water/Storm.d.ts.map +1 -0
  110. package/dist/components/water/Storm.js +13 -0
  111. package/dist/components/water/WaterBody.d.ts +31 -0
  112. package/dist/components/water/WaterBody.d.ts.map +1 -0
  113. package/dist/components/water/WaterBody.js +76 -0
  114. package/dist/components/water/index.d.ts +9 -0
  115. package/dist/components/water/index.d.ts.map +1 -0
  116. package/dist/components/water/index.js +11 -0
  117. package/dist/components/water/types.d.ts +20 -0
  118. package/dist/components/water/types.d.ts.map +1 -0
  119. package/dist/components/water/types.js +1 -0
  120. package/dist/constants.d.ts +1 -0
  121. package/dist/constants.d.ts.map +1 -1
  122. package/dist/constants.js +15 -0
  123. package/dist/hooks/index.d.ts +24 -1
  124. package/dist/hooks/index.d.ts.map +1 -1
  125. package/dist/hooks/index.js +12 -0
  126. package/dist/hooks/useClipmap.d.ts +71 -0
  127. package/dist/hooks/useClipmap.d.ts.map +1 -0
  128. package/dist/hooks/useClipmap.js +81 -0
  129. package/dist/hooks/useCloudLive.d.ts +29 -0
  130. package/dist/hooks/useCloudLive.d.ts.map +1 -0
  131. package/dist/hooks/useCloudLive.js +43 -0
  132. package/dist/hooks/useCloudNoise.d.ts +28 -0
  133. package/dist/hooks/useCloudNoise.d.ts.map +1 -0
  134. package/dist/hooks/useCloudNoise.js +128 -0
  135. package/dist/hooks/useCloudSun.d.ts +49 -0
  136. package/dist/hooks/useCloudSun.d.ts.map +1 -0
  137. package/dist/hooks/useCloudSun.js +84 -0
  138. package/dist/hooks/useCubeCamera.d.ts +27 -9
  139. package/dist/hooks/useCubeCamera.d.ts.map +1 -1
  140. package/dist/hooks/useCubeCamera.js +28 -70
  141. package/dist/hooks/useEnvironmentProbe.d.ts +32 -0
  142. package/dist/hooks/useEnvironmentProbe.d.ts.map +1 -0
  143. package/dist/hooks/useEnvironmentProbe.js +35 -0
  144. package/dist/hooks/useFrameRenderer.d.ts +15 -0
  145. package/dist/hooks/useFrameRenderer.d.ts.map +1 -0
  146. package/dist/hooks/useFrameRenderer.js +23 -0
  147. package/dist/hooks/useLandscapeLive.d.ts +29 -0
  148. package/dist/hooks/useLandscapeLive.d.ts.map +1 -0
  149. package/dist/hooks/useLandscapeLive.js +41 -0
  150. package/dist/hooks/useLandscapeMaps.d.ts +32 -0
  151. package/dist/hooks/useLandscapeMaps.d.ts.map +1 -0
  152. package/dist/hooks/useLandscapeMaps.js +138 -0
  153. package/dist/hooks/useMaterialApplication.d.ts.map +1 -1
  154. package/dist/hooks/useMaterialApplication.js +2 -3
  155. package/dist/hooks/useMaterialOptions.d.ts +2 -2
  156. package/dist/hooks/useMaterialOptions.d.ts.map +1 -1
  157. package/dist/hooks/useMaterialOptions.js +13 -31
  158. package/dist/hooks/useObjectEdges.d.ts.map +1 -1
  159. package/dist/hooks/useObjectEdges.js +3 -49
  160. package/dist/hooks/useOceanLive.d.ts +29 -0
  161. package/dist/hooks/useOceanLive.d.ts.map +1 -0
  162. package/dist/hooks/useOceanLive.js +38 -0
  163. package/dist/hooks/useOceanMaterial.d.ts +39 -0
  164. package/dist/hooks/useOceanMaterial.d.ts.map +1 -0
  165. package/dist/hooks/useOceanMaterial.js +65 -0
  166. package/dist/hooks/useTerrainClipmap.d.ts +12 -0
  167. package/dist/hooks/useTerrainClipmap.d.ts.map +1 -0
  168. package/dist/hooks/useTerrainClipmap.js +10 -0
  169. package/dist/hooks/useTerrainLive.d.ts +34 -0
  170. package/dist/hooks/useTerrainLive.d.ts.map +1 -0
  171. package/dist/hooks/useTerrainLive.js +45 -0
  172. package/dist/index.d.ts +26 -0
  173. package/dist/index.d.ts.map +1 -1
  174. package/dist/index.js +16 -0
  175. package/dist/presets/landscapePresets.d.ts +60 -0
  176. package/dist/presets/landscapePresets.d.ts.map +1 -0
  177. package/dist/presets/landscapePresets.js +194 -0
  178. package/dist/presets/landscapeTypes.d.ts +195 -0
  179. package/dist/presets/landscapeTypes.d.ts.map +1 -0
  180. package/dist/presets/landscapeTypes.js +315 -0
  181. package/dist/presets/oceanSurfacePresets.d.ts +33 -0
  182. package/dist/presets/oceanSurfacePresets.d.ts.map +1 -0
  183. package/dist/presets/oceanSurfacePresets.js +245 -0
  184. package/dist/presets/terrainPresets.d.ts +28 -0
  185. package/dist/presets/terrainPresets.d.ts.map +1 -0
  186. package/dist/presets/terrainPresets.js +293 -0
  187. package/dist/presets/volumetricCloudPresets.d.ts +38 -0
  188. package/dist/presets/volumetricCloudPresets.d.ts.map +1 -0
  189. package/dist/presets/volumetricCloudPresets.js +480 -0
  190. package/dist/shaders/clouds/CirrusMaterial.d.ts +84 -0
  191. package/dist/shaders/clouds/CirrusMaterial.d.ts.map +1 -0
  192. package/dist/shaders/clouds/CirrusMaterial.js +167 -0
  193. package/dist/shaders/clouds/CloudCompositeMaterial.d.ts +20 -0
  194. package/dist/shaders/clouds/CloudCompositeMaterial.d.ts.map +1 -0
  195. package/dist/shaders/clouds/CloudCompositeMaterial.js +82 -0
  196. package/dist/shaders/clouds/CloudResolveMaterial.d.ts +22 -0
  197. package/dist/shaders/clouds/CloudResolveMaterial.d.ts.map +1 -0
  198. package/dist/shaders/clouds/CloudResolveMaterial.js +77 -0
  199. package/dist/shaders/clouds/CloudVolumeMaterial.d.ts +143 -0
  200. package/dist/shaders/clouds/CloudVolumeMaterial.d.ts.map +1 -0
  201. package/dist/shaders/clouds/CloudVolumeMaterial.js +249 -0
  202. package/dist/shaders/clouds/SkyBackgroundMaterial.d.ts +21 -0
  203. package/dist/shaders/clouds/SkyBackgroundMaterial.d.ts.map +1 -0
  204. package/dist/shaders/clouds/SkyBackgroundMaterial.js +42 -0
  205. package/dist/shaders/glsl/cloudCore.glsl.d.ts +24 -0
  206. package/dist/shaders/glsl/cloudCore.glsl.d.ts.map +1 -0
  207. package/dist/shaders/glsl/cloudCore.glsl.js +348 -0
  208. package/dist/shaders/glsl/landscapeCore.glsl.d.ts +49 -0
  209. package/dist/shaders/glsl/landscapeCore.glsl.d.ts.map +1 -0
  210. package/dist/shaders/glsl/landscapeCore.glsl.js +518 -0
  211. package/dist/shaders/glsl/noiseBake.glsl.d.ts +30 -0
  212. package/dist/shaders/glsl/noiseBake.glsl.d.ts.map +1 -0
  213. package/dist/shaders/glsl/noiseBake.glsl.js +164 -0
  214. package/dist/shaders/glsl/oceanCore.glsl.d.ts +52 -0
  215. package/dist/shaders/glsl/oceanCore.glsl.d.ts.map +1 -0
  216. package/dist/shaders/glsl/oceanCore.glsl.js +421 -0
  217. package/dist/shaders/glsl/terrainCore.glsl.d.ts +78 -0
  218. package/dist/shaders/glsl/terrainCore.glsl.d.ts.map +1 -0
  219. package/dist/shaders/glsl/terrainCore.glsl.js +625 -0
  220. package/dist/shaders/landscape/LandscapeMaterial.d.ts +73 -0
  221. package/dist/shaders/landscape/LandscapeMaterial.d.ts.map +1 -0
  222. package/dist/shaders/landscape/LandscapeMaterial.js +136 -0
  223. package/dist/shaders/ocean/OceanSurfaceMaterial.d.ts +57 -0
  224. package/dist/shaders/ocean/OceanSurfaceMaterial.d.ts.map +1 -0
  225. package/dist/shaders/ocean/OceanSurfaceMaterial.js +268 -0
  226. package/dist/shaders/terrain/TerrainMaterial.d.ts +80 -0
  227. package/dist/shaders/terrain/TerrainMaterial.d.ts.map +1 -0
  228. package/dist/shaders/terrain/TerrainMaterial.js +291 -0
  229. package/dist/types/cloudConfigs.d.ts +244 -0
  230. package/dist/types/cloudConfigs.d.ts.map +1 -0
  231. package/dist/types/cloudConfigs.js +282 -0
  232. package/dist/types/index.d.ts +8 -0
  233. package/dist/types/index.d.ts.map +1 -1
  234. package/dist/types/index.js +4 -1
  235. package/dist/types/landscapeConfigs.d.ts +218 -0
  236. package/dist/types/landscapeConfigs.d.ts.map +1 -0
  237. package/dist/types/landscapeConfigs.js +256 -0
  238. package/dist/types/oceanConfigs.d.ts +290 -0
  239. package/dist/types/oceanConfigs.d.ts.map +1 -0
  240. package/dist/types/oceanConfigs.js +380 -0
  241. package/dist/types/terrainConfigs.d.ts +251 -0
  242. package/dist/types/terrainConfigs.d.ts.map +1 -0
  243. package/dist/types/terrainConfigs.js +292 -0
  244. package/dist/utils/cloudUniforms.d.ts +14 -0
  245. package/dist/utils/cloudUniforms.d.ts.map +1 -0
  246. package/dist/utils/cloudUniforms.js +122 -0
  247. package/dist/utils/frameRenderer.d.ts +33 -0
  248. package/dist/utils/frameRenderer.d.ts.map +1 -0
  249. package/dist/utils/frameRenderer.js +24 -0
  250. package/dist/utils/handleCloudsAnimations.d.ts +16 -0
  251. package/dist/utils/handleCloudsAnimations.d.ts.map +1 -0
  252. package/dist/utils/handleCloudsAnimations.js +64 -0
  253. package/dist/utils/landscapeGeometry.d.ts +61 -0
  254. package/dist/utils/landscapeGeometry.d.ts.map +1 -0
  255. package/dist/utils/landscapeGeometry.js +126 -0
  256. package/dist/utils/landscapeHeight.d.ts +44 -0
  257. package/dist/utils/landscapeHeight.d.ts.map +1 -0
  258. package/dist/utils/landscapeHeight.js +65 -0
  259. package/dist/utils/landscapeTextures.d.ts +94 -0
  260. package/dist/utils/landscapeTextures.d.ts.map +1 -0
  261. package/dist/utils/landscapeTextures.js +290 -0
  262. package/dist/utils/landscapeUniforms.d.ts +20 -0
  263. package/dist/utils/landscapeUniforms.d.ts.map +1 -0
  264. package/dist/utils/landscapeUniforms.js +61 -0
  265. package/dist/utils/oceanUniforms.d.ts +47 -0
  266. package/dist/utils/oceanUniforms.d.ts.map +1 -0
  267. package/dist/utils/oceanUniforms.js +216 -0
  268. package/dist/utils/pointsMaterialOwnership.d.ts +9 -0
  269. package/dist/utils/pointsMaterialOwnership.d.ts.map +1 -0
  270. package/dist/utils/pointsMaterialOwnership.js +14 -0
  271. package/dist/utils/rtin.d.ts +63 -0
  272. package/dist/utils/rtin.d.ts.map +1 -0
  273. package/dist/utils/rtin.js +202 -0
  274. package/dist/utils/terrainUniforms.d.ts +14 -0
  275. package/dist/utils/terrainUniforms.d.ts.map +1 -0
  276. package/dist/utils/terrainUniforms.js +196 -0
  277. package/package.json +2 -2
@@ -0,0 +1,18 @@
1
+ import React from 'react';
2
+ import type { LandscapeLayerProps } from './types';
3
+ /**
4
+ * The landscape renderer, shared by the world ground and the placed object.
5
+ *
6
+ * Unlike the cloud pass this does not take over the render loop, and unlike the
7
+ * terrain it is a bounded tile — which is what buys the two things the
8
+ * procedural terrain cannot have: it frustum-culls per chunk, and it CASTS into
9
+ * the scene's shadow map, because the sun's shadow camera already covers it.
10
+ *
11
+ * Three things happen per frame and none of them re-render React: the config is
12
+ * pushed into uniforms (with any live controller overrides on top), the bounds
13
+ * are refreshed if the elevation moved, and the height field's world origin is
14
+ * kept in step for CPU queries.
15
+ */
16
+ declare const LandscapeMesh: React.FC<LandscapeLayerProps>;
17
+ export default LandscapeMesh;
18
+ //# sourceMappingURL=LandscapeMesh.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LandscapeMesh.d.ts","sourceRoot":"","sources":["../../../src/components/landscape/LandscapeMesh.tsx"],"names":[],"mappings":"AACA,OAAO,KAAkD,MAAM,OAAO,CAAA;AA0BtE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAA;AAElD;;;;;;;;;;;;GAYG;AACH,QAAA,MAAM,aAAa,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CA8QhD,CAAA;AA8BD,eAAe,aAAa,CAAA"}
@@ -0,0 +1,278 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import * as THREE from 'three';
3
+ import { useCallback, useEffect, useMemo, useRef } from 'react';
4
+ import { useFrame, useThree } from '@react-three/fiber';
5
+ import { useObjectReady } from '../../hooks/useObjectReady.js';
6
+ import { useLandscapeMaps } from '../../hooks/useLandscapeMaps.js';
7
+ import { LANDSCAPE_LIVE_KEY } from '../../hooks/useLandscapeLive.js';
8
+ import { LandscapeMaterial, createLandscapeDepthMaterial, createLandscapeDistanceMaterial, createLandscapeUniforms, landscapeShapeKey, } from '../../shaders/landscape/LandscapeMaterial.js';
9
+ import { applyLandscapeMaps, applyLandscapeUniforms } from '../../utils/landscapeUniforms.js';
10
+ import { buildLandscapeGeometry, setLandscapeBounds } from '../../utils/landscapeGeometry.js';
11
+ import { registerLandscapeHeightField, unregisterLandscapeHeightField, } from '../../utils/landscapeHeight.js';
12
+ import { LANDSCAPE_LIVE_AUTOSPLAT_KEYS, LANDSCAPE_LIVE_CONFIG_KEYS, LANDSCAPE_LIVE_QUALITY_KEYS, LANDSCAPE_LIVE_SURFACE_KEYS, } from '../../types/landscapeConfigs.js';
13
+ /**
14
+ * The landscape renderer, shared by the world ground and the placed object.
15
+ *
16
+ * Unlike the cloud pass this does not take over the render loop, and unlike the
17
+ * terrain it is a bounded tile — which is what buys the two things the
18
+ * procedural terrain cannot have: it frustum-culls per chunk, and it CASTS into
19
+ * the scene's shadow map, because the sun's shadow camera already covers it.
20
+ *
21
+ * Three things happen per frame and none of them re-render React: the config is
22
+ * pushed into uniforms (with any live controller overrides on top), the bounds
23
+ * are refreshed if the elevation moved, and the height field's world origin is
24
+ * kept in step for CPU queries.
25
+ */
26
+ const LandscapeMesh = ({ id = '3drise-landscape', config, quality, applyTransform = true, onObjectReady, onObjectDispose, }) => {
27
+ const gl = useThree((state) => state.gl);
28
+ const maps = useLandscapeMaps(config, quality);
29
+ const surfaces = useMemo(() => config.surfaces.filter((s) => !!s.diffuse), [config.surfaces]);
30
+ const count = Math.max(1, surfaces.length);
31
+ // Uniforms are shared by reference with the depth and distance materials, so
32
+ // a write here reaches the shadow pass too and the shadow cannot drift from
33
+ // the surface it belongs to.
34
+ const uniforms = useMemo(() => createLandscapeUniforms(count), [count]);
35
+ const shape = useMemo(() => ({
36
+ count,
37
+ samples: config.surfaceSamples,
38
+ splats: config.splatMaps.length,
39
+ auto: config.splatSource === 'auto' || config.splatMaps.length === 0,
40
+ stochastic: quality.stochastic && surfaces.some((s) => s.aperiodic),
41
+ triplanar: quality.triplanar && surfaces.some((s) => s.triplanar),
42
+ ao: !!config.aoMap,
43
+ }), [
44
+ count,
45
+ config.surfaceSamples,
46
+ config.splatMaps.length,
47
+ config.splatSource,
48
+ config.aoMap,
49
+ quality.stochastic,
50
+ quality.triplanar,
51
+ surfaces,
52
+ ]);
53
+ const shapeKey = landscapeShapeKey(shape);
54
+ // Shape lives in #defines, so a change of shape is a new program. Rebuilding
55
+ // the material is the honest way to say that; the controller commits those
56
+ // knobs on release so it happens once per edit, not once per frame of a drag.
57
+ const material = useMemo(() => new LandscapeMaterial(shape, uniforms), [shapeKey, uniforms]);
58
+ const depthMaterial = useMemo(() => createLandscapeDepthMaterial(uniforms), [uniforms]);
59
+ const distanceMaterial = useMemo(() => createLandscapeDistanceMaterial(uniforms), [uniforms]);
60
+ useEffect(() => () => {
61
+ material.dispose();
62
+ depthMaterial.dispose();
63
+ distanceMaterial.dispose();
64
+ }, [material, depthMaterial, distanceMaterial]);
65
+ // RTIN's error map is normalised, so a world-unit budget divides by the
66
+ // elevation scale. Quantised, because a float that jitters in the last digit
67
+ // would rebuild the mesh for nothing. Note this reads the COMMITTED
68
+ // elevation: a live drag moves the surface without re-meshing, and the error
69
+ // catches up on release.
70
+ const normalisedError = useMemo(() => {
71
+ const raw = quality.meshError / Math.max(config.elevationScale, 1e-3);
72
+ return Math.round(raw * 1e5) / 1e5;
73
+ }, [quality.meshError, config.elevationScale]);
74
+ const geometry = useMemo(() => {
75
+ if (!maps.heightField)
76
+ return null;
77
+ return buildLandscapeGeometry(maps.heightField, {
78
+ size: config.size,
79
+ chunks: quality.chunks,
80
+ maxError: normalisedError,
81
+ });
82
+ }, [maps.heightField, config.size, quality.chunks, normalisedError]);
83
+ useEffect(() => () => { geometry?.dispose(); }, [geometry]);
84
+ useEffect(() => {
85
+ if (maps.ready)
86
+ applyLandscapeMaps(uniforms, maps);
87
+ }, [maps, uniforms]);
88
+ // ---- live controller overrides -----------------------------------------
89
+ // A drag writes here every pointer-move and the frame loop reads it on top of
90
+ // the config, so the landscape responds without a dispatch per frame. Cleared
91
+ // when the config identity changes, which is exactly slider-end committing
92
+ // the same value.
93
+ const liveConfig = useRef({});
94
+ const liveSurfaces = useRef({});
95
+ const liveAutoSplat = useRef({});
96
+ const liveQuality = useRef({});
97
+ const dirty = useRef(true);
98
+ // Cleared by the block they belong to, and by that block only: surfaces and
99
+ // the auto-splat rows live in `config`, so a quality edit must not drop a
100
+ // surface override that has not been committed yet.
101
+ useEffect(() => {
102
+ liveConfig.current = {};
103
+ liveSurfaces.current = {};
104
+ liveAutoSplat.current = {};
105
+ dirty.current = true;
106
+ }, [config]);
107
+ useEffect(() => { liveQuality.current = {}; dirty.current = true; }, [quality]);
108
+ const rootRef = useRef(null);
109
+ const meshRefs = useRef([]);
110
+ // The live handle a controller reaches through findById(id).userData.
111
+ //
112
+ // It filters. A controller hands over every key its slider owns and this
113
+ // drops anything that is not purely a uniform, because a rebuild key applied
114
+ // live half-applies: `size` scales the triplanar projection from a uniform
115
+ // while the mesh, built at the committed size, stays where it was. The key
116
+ // sets live in landscapeConfigs so the panel and the renderer cannot drift.
117
+ const liveHandle = useMemo(() => ({
118
+ config: (key, value) => {
119
+ if (!LANDSCAPE_LIVE_CONFIG_KEYS.includes(key))
120
+ return;
121
+ liveConfig.current[key] = value;
122
+ dirty.current = true;
123
+ },
124
+ quality: (key, value) => {
125
+ if (!LANDSCAPE_LIVE_QUALITY_KEYS.includes(key))
126
+ return;
127
+ liveQuality.current[key] = value;
128
+ dirty.current = true;
129
+ },
130
+ surface: (index, key, value) => {
131
+ if (!LANDSCAPE_LIVE_SURFACE_KEYS.includes(key))
132
+ return;
133
+ liveSurfaces.current[`${index}:${key}`] = value;
134
+ dirty.current = true;
135
+ },
136
+ autoSplat: (key, value) => {
137
+ if (!LANDSCAPE_LIVE_AUTOSPLAT_KEYS.includes(key))
138
+ return;
139
+ liveAutoSplat.current[key] = value;
140
+ dirty.current = true;
141
+ },
142
+ }), []);
143
+ // Attached from a CALLBACK REF, not from an effect, and never as a userData
144
+ // JSX prop (R3F replaces the whole userData object on every render, which
145
+ // would drop the handle whenever anything above re-rendered).
146
+ //
147
+ // The effect version is what broke live editing outright. This component used
148
+ // to return null until the maps had loaded, so on the first render there was
149
+ // no group; the effect ran, found `rootRef.current` null, and returned. Its
150
+ // deps were [id, liveHandle], neither of which changes when the maps finish
151
+ // loading — so it never ran again, `userData.id` was never set, findById()
152
+ // never resolved the landscape, and every controller's live handle fell back
153
+ // to the no-op for the rest of the session. Nothing errored; the panel simply
154
+ // did nothing until the pointer came up. A callback ref cannot miss the
155
+ // mount, whatever the render gating does later.
156
+ const attachRoot = useCallback((group) => {
157
+ rootRef.current = group;
158
+ if (!group)
159
+ return;
160
+ group.userData.id = id;
161
+ group.userData[LANDSCAPE_LIVE_KEY] = liveHandle;
162
+ }, [id, liveHandle]);
163
+ useEffect(() => () => {
164
+ const root = rootRef.current;
165
+ if (root)
166
+ delete root.userData[LANDSCAPE_LIVE_KEY];
167
+ }, []);
168
+ useObjectReady(rootRef, { id, type: 'landscape', config, quality }, onObjectReady, onObjectDispose);
169
+ // ---- CPU height field ---------------------------------------------------
170
+ useEffect(() => {
171
+ if (!maps.heightField)
172
+ return;
173
+ return () => unregisterLandscapeHeightField(id);
174
+ }, [id, maps.heightField]);
175
+ const appliedElevation = useRef({ scale: NaN, bias: NaN });
176
+ useFrame(() => {
177
+ if (!geometry)
178
+ return;
179
+ const merged = mergeLive(config, liveConfig.current, liveSurfaces.current, liveAutoSplat.current);
180
+ const mergedQuality = Object.keys(liveQuality.current).length === 0
181
+ ? quality
182
+ : { ...quality, ...liveQuality.current };
183
+ if (dirty.current) {
184
+ applyLandscapeUniforms(uniforms, merged, mergedQuality);
185
+ material.wireframe = mergedQuality.wireframe;
186
+ material.envMapIntensity = merged.envMapIntensity;
187
+ // Shadow flags are per mesh, so the live path has to reach the chunks
188
+ // rather than the material.
189
+ for (const mesh of meshRefs.current) {
190
+ if (!mesh)
191
+ continue;
192
+ mesh.castShadow = mergedQuality.castShadows;
193
+ mesh.receiveShadow = mergedQuality.receiveShadows;
194
+ }
195
+ applyAnisotropy(mergedQuality.anisotropy);
196
+ // rotationY is a live key, and it is a transform rather than a
197
+ // uniform — the JSX prop carries the committed value, so the drag has
198
+ // to be written onto the object itself or the slider moves nothing.
199
+ const root = rootRef.current;
200
+ if (root && applyTransform) {
201
+ root.rotation.y = THREE.MathUtils.degToRad(merged.rotationY);
202
+ }
203
+ dirty.current = false;
204
+ }
205
+ if (appliedElevation.current.scale !== merged.elevationScale
206
+ || appliedElevation.current.bias !== merged.elevationBias) {
207
+ appliedElevation.current = { scale: merged.elevationScale, bias: merged.elevationBias };
208
+ setLandscapeBounds(geometry, merged.elevationScale, merged.elevationBias);
209
+ }
210
+ const root = rootRef.current;
211
+ if (root && maps.heightField) {
212
+ registerLandscapeHeightField(id, {
213
+ data: maps.heightField.data,
214
+ gridSize: maps.heightField.gridSize,
215
+ tileSize: maps.heightField.tileSize,
216
+ size: merged.size,
217
+ origin: root.getWorldPosition(new THREE.Vector3()),
218
+ rotationY: root.rotation.y,
219
+ elevationScale: merged.elevationScale,
220
+ elevationBias: merged.elevationBias,
221
+ });
222
+ }
223
+ });
224
+ // Anisotropy is capped by the device, not by the panel, and re-uploading the
225
+ // arrays is not free — so it is applied only when the value actually changes,
226
+ // whether that came from a commit or from a live drag.
227
+ const appliedAnisotropy = useRef(NaN);
228
+ const applyAnisotropy = useCallback((requested) => {
229
+ const value = Math.min(requested, gl.capabilities.getMaxAnisotropy());
230
+ if (appliedAnisotropy.current === value)
231
+ return;
232
+ appliedAnisotropy.current = value;
233
+ if (maps.diffuse) {
234
+ maps.diffuse.anisotropy = value;
235
+ maps.diffuse.needsUpdate = true;
236
+ }
237
+ if (maps.normal) {
238
+ maps.normal.anisotropy = value;
239
+ maps.normal.needsUpdate = true;
240
+ }
241
+ }, [gl, maps.diffuse, maps.normal]);
242
+ useEffect(() => {
243
+ appliedAnisotropy.current = NaN;
244
+ applyAnisotropy(quality.anisotropy);
245
+ }, [applyAnisotropy, quality.anisotropy]);
246
+ // The group is ALWAYS rendered, even before the maps have loaded and even when
247
+ // the config is incomplete — only the chunks inside it are gated. TerrainSurface
248
+ // does the same, and this is why: the root is what carries `userData.id`, so it
249
+ // is what findById() resolves, and a controller that opens before the ground
250
+ // exists has to find something to write into. Returning null here is what broke
251
+ // live editing.
252
+ const ready = !!geometry && maps.ready;
253
+ return (_jsx("group", { ref: attachRoot, position: applyTransform ? config.origin : undefined, rotation: applyTransform ? [0, THREE.MathUtils.degToRad(config.rotationY), 0] : undefined, children: ready && geometry.chunks.map((chunk, i) => (_jsx("mesh", { ref: (m) => { meshRefs.current[i] = m; }, geometry: chunk.geometry, material: material, castShadow: quality.castShadows, receiveShadow: quality.receiveShadows, customDepthMaterial: depthMaterial, customDistanceMaterial: distanceMaterial }, i))) }));
254
+ };
255
+ /** Config with the live controller's overrides on top. Cheap enough to build per
256
+ * frame — it is at most eight small objects — and only rebuilt when something
257
+ * actually wrote. */
258
+ function mergeLive(config, live, liveSurfaces, liveAutoSplat) {
259
+ const keys = Object.keys(liveSurfaces);
260
+ const surfaces = keys.length === 0
261
+ ? config.surfaces
262
+ : config.surfaces.map((surface, index) => {
263
+ let next = null;
264
+ for (const key of keys) {
265
+ const [i, field] = key.split(':');
266
+ if (Number(i) !== index)
267
+ continue;
268
+ next = next ?? { ...surface };
269
+ next[field] = liveSurfaces[key];
270
+ }
271
+ return next ?? surface;
272
+ });
273
+ const autoSplat = Object.keys(liveAutoSplat).length === 0
274
+ ? config.autoSplat
275
+ : { ...config.autoSplat, ...liveAutoSplat };
276
+ return { ...config, ...live, surfaces, autoSplat };
277
+ }
278
+ export default LandscapeMesh;
@@ -0,0 +1,3 @@
1
+ export { default as LandscapeMesh } from './LandscapeMesh';
2
+ export type { LandscapeLayerProps } from './types';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/landscape/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAC1D,YAAY,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAA"}
@@ -0,0 +1 @@
1
+ export { default as LandscapeMesh } from './LandscapeMesh.js';
@@ -0,0 +1,13 @@
1
+ import type { ObjectReadyProps } from '../../types/objectReady';
2
+ import type { LandscapeConfig, LandscapeQualityConfig } from '../../types/landscapeConfigs';
3
+ /** Shared by both hosts. The ground host reads its transform out of the config;
4
+ * the placed host is wrapped in a CreatedObject and leaves those at zero. */
5
+ export interface LandscapeLayerProps extends ObjectReadyProps {
6
+ /** Scene id, so a controller can findById() the landscape and drive it live. */
7
+ id?: string;
8
+ config: LandscapeConfig;
9
+ quality: LandscapeQualityConfig;
10
+ /** Ground host only. The placed host gets its transform from CreatedObject. */
11
+ applyTransform?: boolean;
12
+ }
13
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/components/landscape/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAC/D,OAAO,KAAK,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAA;AAE3F;8EAC8E;AAC9E,MAAM,WAAW,mBAAoB,SAAQ,gBAAgB;IACzD,gFAAgF;IAChF,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,MAAM,EAAE,eAAe,CAAA;IACvB,OAAO,EAAE,sBAAsB,CAAA;IAC/B,+EAA+E;IAC/E,cAAc,CAAC,EAAE,OAAO,CAAA;CAC3B"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,23 @@
1
+ import React from 'react';
2
+ import type { TerrainLayerProps } from './types';
3
+ /**
4
+ * Mesa and canyon country — built by subtraction, which is what makes it read
5
+ * correctly.
6
+ *
7
+ * A canyon is not a mountain range with the sign flipped: it is a plateau with a
8
+ * drainage network cut into it. So `plateau` flattens the top of the height range
9
+ * first, and `valleyDepth` then removes material along the zero set of a ridged
10
+ * noise field — which is a connected, branching line, so the channels join up
11
+ * into a network instead of appearing as unrelated gouges.
12
+ *
13
+ * `terraces` is doing more work here than anywhere else. Sedimentary rock erodes
14
+ * in bands, and the horizontal banding on the walls is most of what makes a mesa
15
+ * read as a mesa rather than as a lumpy plateau. `terraceSharpness` near 1 gives
16
+ * the near-vertical riser that a hard stratum leaves standing.
17
+ *
18
+ * The most expensive of the four: near-vertical walls mean the shadow march walks
19
+ * a long way before it clears an occluder.
20
+ */
21
+ declare const Canyon: React.FC<TerrainLayerProps>;
22
+ export default Canyon;
23
+ //# sourceMappingURL=Canyon.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Canyon.d.ts","sourceRoot":"","sources":["../../../src/components/terrain/Canyon.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkB,MAAM,OAAO,CAAC;AAEvC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAEjD;;;;;;;;;;;;;;;;;GAiBG;AACH,QAAA,MAAM,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CASvC,CAAC;AAEF,eAAe,MAAM,CAAC"}
@@ -0,0 +1,29 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useMemo } from 'react';
3
+ import TerrainSurface from './TerrainSurface.js';
4
+ /**
5
+ * Mesa and canyon country — built by subtraction, which is what makes it read
6
+ * correctly.
7
+ *
8
+ * A canyon is not a mountain range with the sign flipped: it is a plateau with a
9
+ * drainage network cut into it. So `plateau` flattens the top of the height range
10
+ * first, and `valleyDepth` then removes material along the zero set of a ridged
11
+ * noise field — which is a connected, branching line, so the channels join up
12
+ * into a network instead of appearing as unrelated gouges.
13
+ *
14
+ * `terraces` is doing more work here than anywhere else. Sedimentary rock erodes
15
+ * in bands, and the horizontal banding on the walls is most of what makes a mesa
16
+ * read as a mesa rather than as a lumpy plateau. `terraceSharpness` near 1 gives
17
+ * the near-vertical riser that a hard stratum leaves standing.
18
+ *
19
+ * The most expensive of the four: near-vertical walls mean the shadow march walks
20
+ * a long way before it clears an occluder.
21
+ */
22
+ const Canyon = ({ config, quality, ...rest }) => {
23
+ // Cliff faces are where the analytic shadow earns its keep and also where it
24
+ // is most likely to run out of march before it escapes the wall. Floored, the
25
+ // same way Cumulonimbus floors its step budget.
26
+ const resolvedQuality = useMemo(() => ({ ...quality, shadowSteps: Math.max(quality.shadowSteps, 16) }), [quality]);
27
+ return _jsx(TerrainSurface, { config: config, quality: resolvedQuality, ...rest });
28
+ };
29
+ export default Canyon;
@@ -0,0 +1,22 @@
1
+ import React from 'react';
2
+ import type { TerrainLayerProps } from './types';
3
+ /**
4
+ * A dune field. The one landform that is not primarily fBm.
5
+ *
6
+ * Dunes form transverse to the prevailing wind, so the shape is a wave train:
7
+ * `bearing` sets its direction, `duneWavelength` its spacing, and the fBm's job
8
+ * is to bend the crest lines and vary the height along them rather than to be the
9
+ * terrain. `duneAsymmetry` is what stops it looking like corrugated iron — a real
10
+ * dune is a long windward ramp and a short slip face at the angle of repose, and
11
+ * at zero the two sides are mirror images.
12
+ *
13
+ * Strata and canyon carving are forced off; sand has no bedding planes.
14
+ *
15
+ * The defaults also carry more specular and more ground bounce than the other
16
+ * three, which is not decoration: sand's low-sun sheen and the light it throws
17
+ * back into its own lee are most of why a dune field reads as sand rather than as
18
+ * beige hills.
19
+ */
20
+ declare const Dunes: React.FC<TerrainLayerProps>;
21
+ export default Dunes;
22
+ //# sourceMappingURL=Dunes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Dunes.d.ts","sourceRoot":"","sources":["../../../src/components/terrain/Dunes.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkB,MAAM,OAAO,CAAC;AAEvC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAEjD;;;;;;;;;;;;;;;;GAgBG;AACH,QAAA,MAAM,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAMtC,CAAC;AAEF,eAAe,KAAK,CAAC"}
@@ -0,0 +1,25 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useMemo } from 'react';
3
+ import TerrainSurface from './TerrainSurface.js';
4
+ /**
5
+ * A dune field. The one landform that is not primarily fBm.
6
+ *
7
+ * Dunes form transverse to the prevailing wind, so the shape is a wave train:
8
+ * `bearing` sets its direction, `duneWavelength` its spacing, and the fBm's job
9
+ * is to bend the crest lines and vary the height along them rather than to be the
10
+ * terrain. `duneAsymmetry` is what stops it looking like corrugated iron — a real
11
+ * dune is a long windward ramp and a short slip face at the angle of repose, and
12
+ * at zero the two sides are mirror images.
13
+ *
14
+ * Strata and canyon carving are forced off; sand has no bedding planes.
15
+ *
16
+ * The defaults also carry more specular and more ground bounce than the other
17
+ * three, which is not decoration: sand's low-sun sheen and the light it throws
18
+ * back into its own lee are most of why a dune field reads as sand rather than as
19
+ * beige hills.
20
+ */
21
+ const Dunes = ({ config, ...rest }) => {
22
+ const resolved = useMemo(() => ({ ...config, terraces: 0, plateau: 0, valleyDepth: 0 }), [config]);
23
+ return _jsx(TerrainSurface, { config: resolved, ...rest });
24
+ };
25
+ export default Dunes;
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ import type { TerrainLayerProps } from './types';
3
+ /**
4
+ * Rolling hills and plains — the same fBm with the ridge fold near zero, so the
5
+ * crests stay rounded, and a heavier domain warp so the shapes still have a grain
6
+ * rather than reading as billows.
7
+ *
8
+ * The friendly default, and the one worth reaching for when the terrain is a
9
+ * setting rather than the subject: it is the cheapest of the four (fewest
10
+ * octaves, shallow relief, so the shadow march exits early) and the least likely
11
+ * to fight whatever is placed on it.
12
+ *
13
+ * Strata and canyon carving are forced off — a terraced hill is a quarry.
14
+ */
15
+ declare const Hills: React.FC<TerrainLayerProps>;
16
+ export default Hills;
17
+ //# sourceMappingURL=Hills.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Hills.d.ts","sourceRoot":"","sources":["../../../src/components/terrain/Hills.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkB,MAAM,OAAO,CAAC;AAEvC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAEjD;;;;;;;;;;;GAWG;AACH,QAAA,MAAM,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAMtC,CAAC;AAEF,eAAe,KAAK,CAAC"}
@@ -0,0 +1,20 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useMemo } from 'react';
3
+ import TerrainSurface from './TerrainSurface.js';
4
+ /**
5
+ * Rolling hills and plains — the same fBm with the ridge fold near zero, so the
6
+ * crests stay rounded, and a heavier domain warp so the shapes still have a grain
7
+ * rather than reading as billows.
8
+ *
9
+ * The friendly default, and the one worth reaching for when the terrain is a
10
+ * setting rather than the subject: it is the cheapest of the four (fewest
11
+ * octaves, shallow relief, so the shadow march exits early) and the least likely
12
+ * to fight whatever is placed on it.
13
+ *
14
+ * Strata and canyon carving are forced off — a terraced hill is a quarry.
15
+ */
16
+ const Hills = ({ config, ...rest }) => {
17
+ const resolved = useMemo(() => ({ ...config, terraces: 0, plateau: 0, valleyDepth: 0 }), [config]);
18
+ return _jsx(TerrainSurface, { config: resolved, ...rest });
19
+ };
20
+ export default Hills;
@@ -0,0 +1,19 @@
1
+ import React from 'react';
2
+ import type { TerrainLayerProps } from './types';
3
+ /**
4
+ * Alpine terrain — ridged fBm with derivative damping, rock splatted by slope and
5
+ * a snow line held off the steep faces.
6
+ *
7
+ * The reference case for the height field, because its silhouette shows every
8
+ * term at once: the ridge fold makes the crest lines, the domain warp bends them
9
+ * into a range instead of a field of bumps, and the erosion damping is what puts
10
+ * flat floors in the valleys between them. Turn erosion to zero and it reads as
11
+ * noise immediately.
12
+ *
13
+ * Canyon-only shaping is forced off. Both terms are gated on the landform inside
14
+ * the shader anyway, so a stale value would do nothing visible while making the
15
+ * panel read as though it should.
16
+ */
17
+ declare const Mountains: React.FC<TerrainLayerProps>;
18
+ export default Mountains;
19
+ //# sourceMappingURL=Mountains.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Mountains.d.ts","sourceRoot":"","sources":["../../../src/components/terrain/Mountains.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkB,MAAM,OAAO,CAAC;AAEvC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAEjD;;;;;;;;;;;;;GAaG;AACH,QAAA,MAAM,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAG1C,CAAC;AAEF,eAAe,SAAS,CAAC"}
@@ -0,0 +1,22 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useMemo } from 'react';
3
+ import TerrainSurface from './TerrainSurface.js';
4
+ /**
5
+ * Alpine terrain — ridged fBm with derivative damping, rock splatted by slope and
6
+ * a snow line held off the steep faces.
7
+ *
8
+ * The reference case for the height field, because its silhouette shows every
9
+ * term at once: the ridge fold makes the crest lines, the domain warp bends them
10
+ * into a range instead of a field of bumps, and the erosion damping is what puts
11
+ * flat floors in the valleys between them. Turn erosion to zero and it reads as
12
+ * noise immediately.
13
+ *
14
+ * Canyon-only shaping is forced off. Both terms are gated on the landform inside
15
+ * the shader anyway, so a stale value would do nothing visible while making the
16
+ * panel read as though it should.
17
+ */
18
+ const Mountains = ({ config, ...rest }) => {
19
+ const resolved = useMemo(() => ({ ...config, plateau: 0, valleyDepth: 0 }), [config]);
20
+ return _jsx(TerrainSurface, { config: resolved, ...rest });
21
+ };
22
+ export default Mountains;
@@ -0,0 +1,22 @@
1
+ import React from 'react';
2
+ import type { TerrainLayerProps } from './types';
3
+ /**
4
+ * The terrain renderer. One clipmap, one material, four landforms — they differ
5
+ * by the shaping operator the height field applies, not by having separate
6
+ * renderers, the same way three of the four cloud types share one marcher.
7
+ *
8
+ * Unlike the cloud pass this does NOT take over the render loop, and that is the
9
+ * entire reason to build terrain as geometry: it depth-sorts against scene
10
+ * objects, it receives the sun's shadow map so anything standing on it casts onto
11
+ * it, scene fog applies, and the cloud pass composites over it correctly because
12
+ * it is simply in the scene when that pass renders. A raymarched terrain would
13
+ * have none of that.
14
+ *
15
+ * Per frame it does three things: resolves the sun (from the same
16
+ * `skySystemManager` the sun rig and the clouds read, so a time slider moves all
17
+ * three together), pushes the config into uniforms, and re-snaps the clipmap to
18
+ * the camera. Nothing here re-renders React.
19
+ */
20
+ declare const TerrainSurface: React.FC<TerrainLayerProps>;
21
+ export default TerrainSurface;
22
+ //# sourceMappingURL=TerrainSurface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TerrainSurface.d.ts","sourceRoot":"","sources":["../../../src/components/terrain/TerrainSurface.tsx"],"names":[],"mappings":"AACA,OAAO,KAAqC,MAAM,OAAO,CAAC;AAU1D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAEjD;;;;;;;;;;;;;;;;GAgBG;AACH,QAAA,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAgG/C,CAAC;AAEF,eAAe,cAAc,CAAC"}