@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.
- package/dist/components/Clouds.d.ts.map +1 -1
- package/dist/components/Clouds.js +0 -1
- package/dist/components/CloudsGenerator.d.ts +32 -0
- package/dist/components/CloudsGenerator.d.ts.map +1 -0
- package/dist/components/CloudsGenerator.js +58 -0
- package/dist/components/EnvironmentManager.d.ts +47 -5
- package/dist/components/EnvironmentManager.d.ts.map +1 -1
- package/dist/components/EnvironmentManager.js +35 -66
- package/dist/components/HdrEnvironment.d.ts +20 -0
- package/dist/components/HdrEnvironment.d.ts.map +1 -0
- package/dist/components/HdrEnvironment.js +44 -0
- package/dist/components/LandscapeBuilder.d.ts +23 -0
- package/dist/components/LandscapeBuilder.d.ts.map +1 -0
- package/dist/components/LandscapeBuilder.js +25 -0
- package/dist/components/LandscapeObject.d.ts +24 -0
- package/dist/components/LandscapeObject.d.ts.map +1 -0
- package/dist/components/LandscapeObject.js +27 -0
- package/dist/components/ObjectNode.d.ts.map +1 -1
- package/dist/components/ObjectNode.js +10 -0
- package/dist/components/OceanBuilder.d.ts +35 -0
- package/dist/components/OceanBuilder.d.ts.map +1 -0
- package/dist/components/OceanBuilder.js +53 -0
- package/dist/components/SceneBuilder.d.ts.map +1 -1
- package/dist/components/SkySystem.d.ts +27 -6
- package/dist/components/SkySystem.d.ts.map +1 -1
- package/dist/components/SkySystem.js +6 -5
- package/dist/components/SunLight.d.ts.map +1 -1
- package/dist/components/SunLight.js +4 -1
- package/dist/components/TerrainBuilder.d.ts +30 -0
- package/dist/components/TerrainBuilder.d.ts.map +1 -0
- package/dist/components/TerrainBuilder.js +44 -0
- package/dist/components/index.d.ts +17 -1
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +10 -0
- package/dist/components/landscape/LandscapeMesh.d.ts +18 -0
- package/dist/components/landscape/LandscapeMesh.d.ts.map +1 -0
- package/dist/components/landscape/LandscapeMesh.js +278 -0
- package/dist/components/landscape/index.d.ts +3 -0
- package/dist/components/landscape/index.d.ts.map +1 -0
- package/dist/components/landscape/index.js +1 -0
- package/dist/components/landscape/types.d.ts +13 -0
- package/dist/components/landscape/types.d.ts.map +1 -0
- package/dist/components/landscape/types.js +1 -0
- package/dist/components/terrain/Canyon.d.ts +23 -0
- package/dist/components/terrain/Canyon.d.ts.map +1 -0
- package/dist/components/terrain/Canyon.js +29 -0
- package/dist/components/terrain/Dunes.d.ts +22 -0
- package/dist/components/terrain/Dunes.d.ts.map +1 -0
- package/dist/components/terrain/Dunes.js +25 -0
- package/dist/components/terrain/Hills.d.ts +17 -0
- package/dist/components/terrain/Hills.d.ts.map +1 -0
- package/dist/components/terrain/Hills.js +20 -0
- package/dist/components/terrain/Mountains.d.ts +19 -0
- package/dist/components/terrain/Mountains.d.ts.map +1 -0
- package/dist/components/terrain/Mountains.js +22 -0
- package/dist/components/terrain/TerrainSurface.d.ts +22 -0
- package/dist/components/terrain/TerrainSurface.d.ts.map +1 -0
- package/dist/components/terrain/TerrainSurface.js +94 -0
- package/dist/components/terrain/index.d.ts +7 -0
- package/dist/components/terrain/index.d.ts.map +1 -0
- package/dist/components/terrain/index.js +7 -0
- package/dist/components/terrain/types.d.ts +17 -0
- package/dist/components/terrain/types.d.ts.map +1 -0
- package/dist/components/terrain/types.js +1 -0
- package/dist/components/volumetricClouds/Cirrus.d.ts +14 -0
- package/dist/components/volumetricClouds/Cirrus.d.ts.map +1 -0
- package/dist/components/volumetricClouds/Cirrus.js +13 -0
- package/dist/components/volumetricClouds/Cumulonimbus.d.ts +17 -0
- package/dist/components/volumetricClouds/Cumulonimbus.d.ts.map +1 -0
- package/dist/components/volumetricClouds/Cumulonimbus.js +20 -0
- package/dist/components/volumetricClouds/Cumulus.d.ts +14 -0
- package/dist/components/volumetricClouds/Cumulus.d.ts.map +1 -0
- package/dist/components/volumetricClouds/Cumulus.js +17 -0
- package/dist/components/volumetricClouds/Stratocumulus.d.ts +12 -0
- package/dist/components/volumetricClouds/Stratocumulus.d.ts.map +1 -0
- package/dist/components/volumetricClouds/Stratocumulus.js +16 -0
- package/dist/components/volumetricClouds/VolumetricCloudsPass.d.ts +42 -0
- package/dist/components/volumetricClouds/VolumetricCloudsPass.d.ts.map +1 -0
- package/dist/components/volumetricClouds/VolumetricCloudsPass.js +298 -0
- package/dist/components/volumetricClouds/index.d.ts +8 -0
- package/dist/components/volumetricClouds/index.d.ts.map +1 -0
- package/dist/components/volumetricClouds/index.js +7 -0
- package/dist/components/volumetricClouds/types.d.ts +17 -0
- package/dist/components/volumetricClouds/types.d.ts.map +1 -0
- package/dist/components/volumetricClouds/types.js +1 -0
- package/dist/components/water/Host.d.ts +12 -0
- package/dist/components/water/Host.d.ts.map +1 -0
- package/dist/components/water/Host.js +12 -0
- package/dist/components/water/Lake.d.ts +18 -0
- package/dist/components/water/Lake.d.ts.map +1 -0
- package/dist/components/water/Lake.js +21 -0
- package/dist/components/water/OceanSurface.d.ts +27 -0
- package/dist/components/water/OceanSurface.d.ts.map +1 -0
- package/dist/components/water/OceanSurface.js +60 -0
- package/dist/components/water/Sea.d.ts +18 -0
- package/dist/components/water/Sea.d.ts.map +1 -0
- package/dist/components/water/Sea.js +17 -0
- package/dist/components/water/Shore.d.ts +16 -0
- package/dist/components/water/Shore.d.ts.map +1 -0
- package/dist/components/water/Shore.js +15 -0
- package/dist/components/water/Storm.d.ts +14 -0
- package/dist/components/water/Storm.d.ts.map +1 -0
- package/dist/components/water/Storm.js +13 -0
- package/dist/components/water/WaterBody.d.ts +31 -0
- package/dist/components/water/WaterBody.d.ts.map +1 -0
- package/dist/components/water/WaterBody.js +76 -0
- package/dist/components/water/index.d.ts +9 -0
- package/dist/components/water/index.d.ts.map +1 -0
- package/dist/components/water/index.js +11 -0
- package/dist/components/water/types.d.ts +20 -0
- package/dist/components/water/types.d.ts.map +1 -0
- package/dist/components/water/types.js +1 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +9 -0
- package/dist/hooks/index.d.ts +24 -1
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +12 -0
- package/dist/hooks/useClipmap.d.ts +71 -0
- package/dist/hooks/useClipmap.d.ts.map +1 -0
- package/dist/hooks/useClipmap.js +81 -0
- package/dist/hooks/useCloudLive.d.ts +29 -0
- package/dist/hooks/useCloudLive.d.ts.map +1 -0
- package/dist/hooks/useCloudLive.js +43 -0
- package/dist/hooks/useCloudNoise.d.ts +28 -0
- package/dist/hooks/useCloudNoise.d.ts.map +1 -0
- package/dist/hooks/useCloudNoise.js +128 -0
- package/dist/hooks/useCloudSun.d.ts +49 -0
- package/dist/hooks/useCloudSun.d.ts.map +1 -0
- package/dist/hooks/useCloudSun.js +84 -0
- package/dist/hooks/useCubeCamera.d.ts +27 -9
- package/dist/hooks/useCubeCamera.d.ts.map +1 -1
- package/dist/hooks/useCubeCamera.js +28 -70
- package/dist/hooks/useEnvironmentProbe.d.ts +32 -0
- package/dist/hooks/useEnvironmentProbe.d.ts.map +1 -0
- package/dist/hooks/useEnvironmentProbe.js +35 -0
- package/dist/hooks/useFrameRenderer.d.ts +15 -0
- package/dist/hooks/useFrameRenderer.d.ts.map +1 -0
- package/dist/hooks/useFrameRenderer.js +23 -0
- package/dist/hooks/useLandscapeLive.d.ts +29 -0
- package/dist/hooks/useLandscapeLive.d.ts.map +1 -0
- package/dist/hooks/useLandscapeLive.js +41 -0
- package/dist/hooks/useLandscapeMaps.d.ts +32 -0
- package/dist/hooks/useLandscapeMaps.d.ts.map +1 -0
- package/dist/hooks/useLandscapeMaps.js +138 -0
- package/dist/hooks/useOceanLive.d.ts +29 -0
- package/dist/hooks/useOceanLive.d.ts.map +1 -0
- package/dist/hooks/useOceanLive.js +38 -0
- package/dist/hooks/useOceanMaterial.d.ts +39 -0
- package/dist/hooks/useOceanMaterial.d.ts.map +1 -0
- package/dist/hooks/useOceanMaterial.js +65 -0
- package/dist/hooks/useTerrainClipmap.d.ts +12 -0
- package/dist/hooks/useTerrainClipmap.d.ts.map +1 -0
- package/dist/hooks/useTerrainClipmap.js +10 -0
- package/dist/hooks/useTerrainLive.d.ts +34 -0
- package/dist/hooks/useTerrainLive.d.ts.map +1 -0
- package/dist/hooks/useTerrainLive.js +45 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16 -0
- package/dist/presets/landscapePresets.d.ts +60 -0
- package/dist/presets/landscapePresets.d.ts.map +1 -0
- package/dist/presets/landscapePresets.js +194 -0
- package/dist/presets/landscapeTypes.d.ts +195 -0
- package/dist/presets/landscapeTypes.d.ts.map +1 -0
- package/dist/presets/landscapeTypes.js +315 -0
- package/dist/presets/oceanSurfacePresets.d.ts +33 -0
- package/dist/presets/oceanSurfacePresets.d.ts.map +1 -0
- package/dist/presets/oceanSurfacePresets.js +245 -0
- package/dist/presets/terrainPresets.d.ts +28 -0
- package/dist/presets/terrainPresets.d.ts.map +1 -0
- package/dist/presets/terrainPresets.js +293 -0
- package/dist/presets/volumetricCloudPresets.d.ts +38 -0
- package/dist/presets/volumetricCloudPresets.d.ts.map +1 -0
- package/dist/presets/volumetricCloudPresets.js +480 -0
- package/dist/shaders/clouds/CirrusMaterial.d.ts +84 -0
- package/dist/shaders/clouds/CirrusMaterial.d.ts.map +1 -0
- package/dist/shaders/clouds/CirrusMaterial.js +167 -0
- package/dist/shaders/clouds/CloudCompositeMaterial.d.ts +20 -0
- package/dist/shaders/clouds/CloudCompositeMaterial.d.ts.map +1 -0
- package/dist/shaders/clouds/CloudCompositeMaterial.js +82 -0
- package/dist/shaders/clouds/CloudResolveMaterial.d.ts +22 -0
- package/dist/shaders/clouds/CloudResolveMaterial.d.ts.map +1 -0
- package/dist/shaders/clouds/CloudResolveMaterial.js +77 -0
- package/dist/shaders/clouds/CloudVolumeMaterial.d.ts +143 -0
- package/dist/shaders/clouds/CloudVolumeMaterial.d.ts.map +1 -0
- package/dist/shaders/clouds/CloudVolumeMaterial.js +249 -0
- package/dist/shaders/clouds/SkyBackgroundMaterial.d.ts +21 -0
- package/dist/shaders/clouds/SkyBackgroundMaterial.d.ts.map +1 -0
- package/dist/shaders/clouds/SkyBackgroundMaterial.js +42 -0
- package/dist/shaders/glsl/cloudCore.glsl.d.ts +24 -0
- package/dist/shaders/glsl/cloudCore.glsl.d.ts.map +1 -0
- package/dist/shaders/glsl/cloudCore.glsl.js +348 -0
- package/dist/shaders/glsl/landscapeCore.glsl.d.ts +49 -0
- package/dist/shaders/glsl/landscapeCore.glsl.d.ts.map +1 -0
- package/dist/shaders/glsl/landscapeCore.glsl.js +518 -0
- package/dist/shaders/glsl/noiseBake.glsl.d.ts +30 -0
- package/dist/shaders/glsl/noiseBake.glsl.d.ts.map +1 -0
- package/dist/shaders/glsl/noiseBake.glsl.js +164 -0
- package/dist/shaders/glsl/oceanCore.glsl.d.ts +52 -0
- package/dist/shaders/glsl/oceanCore.glsl.d.ts.map +1 -0
- package/dist/shaders/glsl/oceanCore.glsl.js +421 -0
- package/dist/shaders/glsl/terrainCore.glsl.d.ts +78 -0
- package/dist/shaders/glsl/terrainCore.glsl.d.ts.map +1 -0
- package/dist/shaders/glsl/terrainCore.glsl.js +625 -0
- package/dist/shaders/landscape/LandscapeMaterial.d.ts +73 -0
- package/dist/shaders/landscape/LandscapeMaterial.d.ts.map +1 -0
- package/dist/shaders/landscape/LandscapeMaterial.js +136 -0
- package/dist/shaders/ocean/OceanSurfaceMaterial.d.ts +57 -0
- package/dist/shaders/ocean/OceanSurfaceMaterial.d.ts.map +1 -0
- package/dist/shaders/ocean/OceanSurfaceMaterial.js +268 -0
- package/dist/shaders/terrain/TerrainMaterial.d.ts +80 -0
- package/dist/shaders/terrain/TerrainMaterial.d.ts.map +1 -0
- package/dist/shaders/terrain/TerrainMaterial.js +291 -0
- package/dist/types/cloudConfigs.d.ts +244 -0
- package/dist/types/cloudConfigs.d.ts.map +1 -0
- package/dist/types/cloudConfigs.js +282 -0
- package/dist/types/index.d.ts +8 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +4 -1
- package/dist/types/landscapeConfigs.d.ts +218 -0
- package/dist/types/landscapeConfigs.d.ts.map +1 -0
- package/dist/types/landscapeConfigs.js +256 -0
- package/dist/types/oceanConfigs.d.ts +290 -0
- package/dist/types/oceanConfigs.d.ts.map +1 -0
- package/dist/types/oceanConfigs.js +380 -0
- package/dist/types/terrainConfigs.d.ts +251 -0
- package/dist/types/terrainConfigs.d.ts.map +1 -0
- package/dist/types/terrainConfigs.js +292 -0
- package/dist/utils/cloudUniforms.d.ts +14 -0
- package/dist/utils/cloudUniforms.d.ts.map +1 -0
- package/dist/utils/cloudUniforms.js +122 -0
- package/dist/utils/frameRenderer.d.ts +33 -0
- package/dist/utils/frameRenderer.d.ts.map +1 -0
- package/dist/utils/frameRenderer.js +24 -0
- package/dist/utils/handleCloudsAnimations.d.ts +16 -0
- package/dist/utils/handleCloudsAnimations.d.ts.map +1 -0
- package/dist/utils/handleCloudsAnimations.js +64 -0
- package/dist/utils/landscapeGeometry.d.ts +61 -0
- package/dist/utils/landscapeGeometry.d.ts.map +1 -0
- package/dist/utils/landscapeGeometry.js +126 -0
- package/dist/utils/landscapeHeight.d.ts +44 -0
- package/dist/utils/landscapeHeight.d.ts.map +1 -0
- package/dist/utils/landscapeHeight.js +65 -0
- package/dist/utils/landscapeTextures.d.ts +94 -0
- package/dist/utils/landscapeTextures.d.ts.map +1 -0
- package/dist/utils/landscapeTextures.js +290 -0
- package/dist/utils/landscapeUniforms.d.ts +20 -0
- package/dist/utils/landscapeUniforms.d.ts.map +1 -0
- package/dist/utils/landscapeUniforms.js +61 -0
- package/dist/utils/oceanUniforms.d.ts +47 -0
- package/dist/utils/oceanUniforms.d.ts.map +1 -0
- package/dist/utils/oceanUniforms.js +216 -0
- package/dist/utils/rtin.d.ts +63 -0
- package/dist/utils/rtin.d.ts.map +1 -0
- package/dist/utils/rtin.js +202 -0
- package/dist/utils/terrainUniforms.d.ts +14 -0
- package/dist/utils/terrainUniforms.d.ts.map +1 -0
- package/dist/utils/terrainUniforms.js +196 -0
- package/package.json +2 -2
|
@@ -0,0 +1,380 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Config shapes for the ocean that lives in this package.
|
|
3
|
+
*
|
|
4
|
+
* Declared locally rather than in `@3driseai/3drise-core`, alongside
|
|
5
|
+
* `terrainConfigs.ts` and `cloudConfigs.ts`, because the material and the
|
|
6
|
+
* renderer are here and nothing outside the viewer needs to construct these by
|
|
7
|
+
* hand.
|
|
8
|
+
*
|
|
9
|
+
* Core's `OceanSettings` is the retired shape — a flat plane with a
|
|
10
|
+
* `materialSettings` block picked out of the water material registry — and is
|
|
11
|
+
* deliberately left alone: a saved project still carries one. Unlike terrain,
|
|
12
|
+
* where a legacy blob normalises to NOTHING, a legacy ocean normalises to a real
|
|
13
|
+
* ocean: a project saved before this system existed very possibly had water, and
|
|
14
|
+
* dropping it would delete it. See `normalizeOcean` at the bottom.
|
|
15
|
+
*
|
|
16
|
+
* An ocean is ONE wave model in two containers, not two renderers — the same way
|
|
17
|
+
* three of the four cloud types share one marcher and all four landforms share
|
|
18
|
+
* one height field. `waterType` shapes the spectrum; `host` chooses the mesh.
|
|
19
|
+
*/
|
|
20
|
+
// -----------------------------------------------------------------------------
|
|
21
|
+
// Defaults
|
|
22
|
+
// -----------------------------------------------------------------------------
|
|
23
|
+
const surfaceBase = {
|
|
24
|
+
host: 'world',
|
|
25
|
+
waveModel: 'gerstner',
|
|
26
|
+
seaLevel: 0,
|
|
27
|
+
size: [40, 40],
|
|
28
|
+
segments: 128,
|
|
29
|
+
edgeFade: 0.15,
|
|
30
|
+
windSpeed: 9,
|
|
31
|
+
windBearing: 210,
|
|
32
|
+
fetch: 300,
|
|
33
|
+
directionalSpread: 32,
|
|
34
|
+
waveComponents: 20,
|
|
35
|
+
amplitudeScale: 1,
|
|
36
|
+
choppiness: 0.85,
|
|
37
|
+
swell: 0.35,
|
|
38
|
+
steepness: 0.6,
|
|
39
|
+
foamAmount: 0.8,
|
|
40
|
+
foamDecay: 0.5,
|
|
41
|
+
foamSize: 6,
|
|
42
|
+
deepColor: '#052539',
|
|
43
|
+
shallowColor: '#1b7f8c',
|
|
44
|
+
foamColor: '#eef6f8',
|
|
45
|
+
absorption: 0.06,
|
|
46
|
+
clarity: 0.25,
|
|
47
|
+
roughness: 0.09,
|
|
48
|
+
specular: 1,
|
|
49
|
+
sssStrength: 0.7,
|
|
50
|
+
sssColor: '#2f8f74',
|
|
51
|
+
detailStrength: 0.55,
|
|
52
|
+
detailSize: 2.2,
|
|
53
|
+
reflection: 'planar',
|
|
54
|
+
refraction: 1,
|
|
55
|
+
ambient: 1,
|
|
56
|
+
aerialPerspective: 0.00009,
|
|
57
|
+
exposure: 1,
|
|
58
|
+
terrainInteraction: 'auto',
|
|
59
|
+
terrainShadow: 1,
|
|
60
|
+
shoreDepth: 3,
|
|
61
|
+
shoreFoam: 1,
|
|
62
|
+
};
|
|
63
|
+
/** Open ocean. The reference case: long swell under a wind sea, deep colour. */
|
|
64
|
+
export const defaultSeaConfig = {
|
|
65
|
+
...surfaceBase,
|
|
66
|
+
type: 'ocean',
|
|
67
|
+
waterType: 'sea',
|
|
68
|
+
preset: '',
|
|
69
|
+
enabled: true,
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* Inland water. Short fetch is doing all the work here — a lake in a gale still
|
|
73
|
+
* has small, short, steep waves, because there is no room upwind to build
|
|
74
|
+
* anything longer. Greener and murkier, because inland water is.
|
|
75
|
+
*/
|
|
76
|
+
export const defaultLakeConfig = {
|
|
77
|
+
...surfaceBase,
|
|
78
|
+
type: 'ocean',
|
|
79
|
+
waterType: 'lake',
|
|
80
|
+
preset: '',
|
|
81
|
+
enabled: true,
|
|
82
|
+
windSpeed: 3.5,
|
|
83
|
+
fetch: 2,
|
|
84
|
+
directionalSpread: 22,
|
|
85
|
+
waveComponents: 12,
|
|
86
|
+
choppiness: 0.5,
|
|
87
|
+
swell: 0.05,
|
|
88
|
+
foamAmount: 0.2,
|
|
89
|
+
deepColor: '#0d2c2a',
|
|
90
|
+
shallowColor: '#2c7d6b',
|
|
91
|
+
absorption: 0.14,
|
|
92
|
+
clarity: 0.45,
|
|
93
|
+
detailStrength: 0.7,
|
|
94
|
+
detailSize: 1.2,
|
|
95
|
+
aerialPerspective: 0.00006,
|
|
96
|
+
};
|
|
97
|
+
/** Storm sea. Steep, broken, and mostly foam at the top of the range. */
|
|
98
|
+
export const defaultStormConfig = {
|
|
99
|
+
...surfaceBase,
|
|
100
|
+
type: 'ocean',
|
|
101
|
+
waterType: 'storm',
|
|
102
|
+
preset: '',
|
|
103
|
+
enabled: true,
|
|
104
|
+
windSpeed: 22,
|
|
105
|
+
fetch: 600,
|
|
106
|
+
directionalSpread: 45,
|
|
107
|
+
waveComponents: 28,
|
|
108
|
+
choppiness: 1.1,
|
|
109
|
+
swell: 0.5,
|
|
110
|
+
steepness: 0.8,
|
|
111
|
+
foamAmount: 1.5,
|
|
112
|
+
foamDecay: 0.75,
|
|
113
|
+
foamSize: 12,
|
|
114
|
+
deepColor: '#0a1c26',
|
|
115
|
+
shallowColor: '#2b5f66',
|
|
116
|
+
clarity: 0.6,
|
|
117
|
+
roughness: 0.16,
|
|
118
|
+
sssStrength: 0.35,
|
|
119
|
+
aerialPerspective: 0.00016,
|
|
120
|
+
};
|
|
121
|
+
/**
|
|
122
|
+
* Coastal water. Narrow spread, because waves refract into alignment with the
|
|
123
|
+
* beach as they shoal, and a much stronger shoreline because that is the whole
|
|
124
|
+
* point of the type.
|
|
125
|
+
*/
|
|
126
|
+
export const defaultShoreConfig = {
|
|
127
|
+
...surfaceBase,
|
|
128
|
+
type: 'ocean',
|
|
129
|
+
waterType: 'shore',
|
|
130
|
+
preset: '',
|
|
131
|
+
enabled: true,
|
|
132
|
+
windSpeed: 7,
|
|
133
|
+
fetch: 80,
|
|
134
|
+
directionalSpread: 14,
|
|
135
|
+
waveComponents: 16,
|
|
136
|
+
choppiness: 0.95,
|
|
137
|
+
swell: 0.8,
|
|
138
|
+
foamAmount: 1,
|
|
139
|
+
foamDecay: 0.8,
|
|
140
|
+
deepColor: '#0a3a4a',
|
|
141
|
+
shallowColor: '#3fb5b0',
|
|
142
|
+
absorption: 0.09,
|
|
143
|
+
clarity: 0.35,
|
|
144
|
+
shoreDepth: 6,
|
|
145
|
+
shoreFoam: 1.4,
|
|
146
|
+
};
|
|
147
|
+
export const defaultOceanQuality = {
|
|
148
|
+
levels: 8,
|
|
149
|
+
segments: 96,
|
|
150
|
+
cellSize: 1.5,
|
|
151
|
+
curvature: 1 / (2 * 6371000),
|
|
152
|
+
reflectionScale: 0.5,
|
|
153
|
+
refractionScale: 0.5,
|
|
154
|
+
terrainShadowSteps: 10,
|
|
155
|
+
terrainShadowDistance: 4000,
|
|
156
|
+
detailFadeDistance: 900,
|
|
157
|
+
receiveShadows: true,
|
|
158
|
+
wireframe: false,
|
|
159
|
+
};
|
|
160
|
+
/** Per-type defaults, for the controller's type switcher. */
|
|
161
|
+
export const OCEAN_DEFAULTS = {
|
|
162
|
+
sea: defaultSeaConfig,
|
|
163
|
+
lake: defaultLakeConfig,
|
|
164
|
+
storm: defaultStormConfig,
|
|
165
|
+
shore: defaultShoreConfig,
|
|
166
|
+
};
|
|
167
|
+
/** Object-host bodies are small, still and shallow by default — a pool, not a
|
|
168
|
+
* shrunken sea. Applied on top of the type when the host is switched. */
|
|
169
|
+
export const OBJECT_HOST_OVERRIDES = {
|
|
170
|
+
host: 'object',
|
|
171
|
+
windSpeed: 2,
|
|
172
|
+
fetch: 0.05,
|
|
173
|
+
waveComponents: 10,
|
|
174
|
+
directionalSpread: 40,
|
|
175
|
+
choppiness: 0.35,
|
|
176
|
+
swell: 0,
|
|
177
|
+
foamAmount: 0.05,
|
|
178
|
+
detailStrength: 0.85,
|
|
179
|
+
detailSize: 0.4,
|
|
180
|
+
absorption: 0.25,
|
|
181
|
+
shoreDepth: 0.6,
|
|
182
|
+
};
|
|
183
|
+
export const OCEAN_SCHEMA = [
|
|
184
|
+
{ key: 'seaLevel', label: 'Sea level', group: 'form', min: -2000, max: 2000, step: 0.5, unit: 'm', hosts: ['world'], description: 'World height of the surface. Independent of the terrain sea level — the shoreline is computed from the difference, so two water bodies at different heights in one scene are fine.' },
|
|
185
|
+
{ key: 'size', label: 'Size', group: 'form', kind: 'vector2', hosts: ['object'], advanced: true, description: 'Extent of this body of water, in world units.' },
|
|
186
|
+
{ key: 'segments', label: 'Resolution', group: 'form', min: 16, max: 512, step: 8, hosts: ['object'], description: 'Grid resolution of this body. A wave shorter than two cells cannot be drawn, so this is what limits how fine the ripples can be.' },
|
|
187
|
+
{ key: 'edgeFade', label: 'Edge fade', group: 'form', min: 0, max: 0.5, step: 0.005, hosts: ['object'], description: 'Fraction of the half-extent over which the waves taper to nothing at the rim. Without it the boundary is a sawn-off cliff of water.' },
|
|
188
|
+
{ key: 'windSpeed', label: 'Wind speed', group: 'waves', min: 0, max: 40, step: 0.1, unit: 'm/s', description: 'Wind at 10 m. The whole sea state comes off this: peak wavelength and wave height both go as the square of it.' },
|
|
189
|
+
{ key: 'windBearing', label: 'Wind bearing', group: 'waves', min: 0, max: 360, step: 1, unit: 'deg', description: 'Direction the wind blows toward. The waves travel with it.' },
|
|
190
|
+
{ key: 'fetch', label: 'Fetch', group: 'waves', min: 0.01, max: 2000, step: 0.5, unit: 'km', description: 'Open water upwind. Short fetch means small, short, steep waves however hard it blows — which is why a lake in a gale looks nothing like an ocean in one.' },
|
|
191
|
+
{ key: 'directionalSpread', label: 'Spread', group: 'waves', min: 0, max: 90, step: 0.5, unit: 'deg', description: 'Angular spread of the wave train about the wind. At 0 the sea is corduroy; real seas run 25-40.' },
|
|
192
|
+
{ key: 'waveComponents', label: 'Wave count', group: 'waves', min: 4, max: 32, step: 1, description: 'Trochoids summed per vertex. Cost is linear in it. Past ~24 the extra components are shorter than the finest cell can carry and are faded out anyway.' },
|
|
193
|
+
{ key: 'amplitudeScale', label: 'Wave height', group: 'waves', min: 0, max: 3, step: 0.01, description: 'Multiplier over the physically derived height. 1 is the Pierson-Moskowitz fit for this wind and fetch.' },
|
|
194
|
+
{ key: 'choppiness', label: 'Choppiness', group: 'waves', min: 0, max: 1.5, step: 0.005, description: 'Horizontal displacement. Peaked crests and flat troughs instead of sine waves — and the source of the Jacobian that whitecaps are found from, so at 0 there is no foam to find.' },
|
|
195
|
+
{ key: 'swell', label: 'Swell', group: 'waves', min: 0, max: 1, step: 0.005, description: 'Energy pushed toward the long, low, narrow-band end. Swell is what has travelled out of the weather that made it.' },
|
|
196
|
+
{ key: 'steepness', label: 'Steepness', group: 'waves', min: 0, max: 1, step: 0.005, description: 'Extra steepening of the shorter components. Clamped below the point where a trochoid folds through itself.' },
|
|
197
|
+
{ key: 'foamAmount', label: 'Whitecaps', group: 'waves', min: 0, max: 2, step: 0.01, description: 'How much of the compressing surface reads as foam. Needs choppiness above zero.' },
|
|
198
|
+
{ key: 'foamDecay', label: 'Foam persistence', group: 'waves', min: 0, max: 1, step: 0.01, description: 'How far foam trails behind the crest that made it. At 0 it flickers on and off with the crest and reads as sparkle rather than foam.' },
|
|
199
|
+
{ key: 'foamSize', label: 'Foam texture', group: 'waves', min: 0.2, max: 40, step: 0.1, unit: 'm', advanced: true, description: 'Size of the break-up noise in the foam.' },
|
|
200
|
+
{ key: 'deepColor', label: 'Deep colour', group: 'surface', kind: 'color', description: 'The body colour of the water — what you see where there is nothing behind it.' },
|
|
201
|
+
{ key: 'shallowColor', label: 'Shallow colour', group: 'surface', kind: 'color', description: 'Water over something close behind it. The grazing tint, and the shallow end of the shoreline ramp.' },
|
|
202
|
+
{ key: 'foamColor', label: 'Foam colour', group: 'surface', kind: 'color', description: 'Whitecaps and shore foam.' },
|
|
203
|
+
{ key: 'absorption', label: 'Absorption', group: 'surface', min: 0, max: 1, step: 0.005, unit: '1/m', description: 'Beer-Lambert absorption per metre. Higher swallows the bottom sooner.' },
|
|
204
|
+
{ key: 'clarity', label: 'Turbidity', group: 'surface', min: 0, max: 1, step: 0.005, description: 'Suspended matter. Lifts the shallow colour and softens what is seen through the surface.' },
|
|
205
|
+
{ key: 'roughness', label: 'Roughness', group: 'surface', min: 0.01, max: 0.6, step: 0.005, description: 'Widens the specular lobe. This is sub-mesh ripple, not surface finish — water itself is smooth.' },
|
|
206
|
+
{ key: 'specular', label: 'Glitter', group: 'surface', min: 0, max: 3, step: 0.01, description: 'Specular strength. The sun path from horizon to camera is most of what says "water" at distance.' },
|
|
207
|
+
{ key: 'sssStrength', label: 'Subsurface', group: 'surface', min: 0, max: 2, step: 0.01, description: 'Sun scattering through the body of a wave — crests glowing when the sun is behind them.' },
|
|
208
|
+
{ key: 'sssColor', label: 'Subsurface colour', group: 'surface', kind: 'color', advanced: true, description: 'Colour of that glow. Green in coastal water, blue offshore.' },
|
|
209
|
+
{ key: 'detailStrength', label: 'Ripple detail', group: 'surface', min: 0, max: 2, step: 0.01, description: 'Per-fragment normal detail below mesh resolution. This is where the energy lost to the per-ring wave LOD goes.' },
|
|
210
|
+
{ key: 'detailSize', label: 'Ripple size', group: 'surface', min: 0.1, max: 20, step: 0.05, unit: 'm', description: 'Size of that detail.' },
|
|
211
|
+
{ key: 'ambient', label: 'Ambient', group: 'surface', min: 0, max: 3, step: 0.01, advanced: true, description: 'Sky-dome fill, from the same atmosphere the sky and clouds use.' },
|
|
212
|
+
{ key: 'aerialPerspective', label: 'Aerial perspective', group: 'surface', min: 0, max: 0.0006, step: 0.000002, unit: '1/m', description: 'Rate distant water fades into the sky behind it. Water needs more of this than ground, because most of what you see looking at the sea is the sky.' },
|
|
213
|
+
{ key: 'exposure', label: 'Exposure', group: 'surface', min: 0.2, max: 4, step: 0.01, advanced: true, description: 'Radiance scale, so water matches sky, clouds and terrain whether or not the cloud composite tonemaps the frame.' },
|
|
214
|
+
{ key: 'terrainShadow', label: 'Terrain shadow', group: 'shore', min: 0, max: 1, step: 0.01, description: 'Strength of the shadow marched down the sun vector against the terrain height field. Terrain does not write into the scene shadow map, so this is the only way a headland shadows the water beside it.' },
|
|
215
|
+
{ key: 'shoreDepth', label: 'Shore depth', group: 'shore', min: 0.05, max: 60, step: 0.05, unit: 'm', description: 'Depth over which the shallow colour and the shore foam ramp in.' },
|
|
216
|
+
{ key: 'shoreFoam', label: 'Shore foam', group: 'shore', min: 0, max: 2, step: 0.01, description: 'Foam where the ground comes up through the surface.' },
|
|
217
|
+
];
|
|
218
|
+
export const OCEAN_QUALITY_SCHEMA = [
|
|
219
|
+
{ key: 'levels', label: 'Clipmap levels', group: 'quality', min: 2, max: 12, step: 1, description: 'Each ring doubles its cell size, so visible radius is roughly cellSize x segments x 2^(levels-1). Levels only buy reach; there is no point past where haze has dissolved the surface.' },
|
|
220
|
+
{ key: 'segments', label: 'Ring resolution', group: 'quality', min: 32, max: 320, step: 8, description: 'Grid resolution per ring side. Vertex cost is levels x segments^2 x 0.75, since every ring above the first is hollow.' },
|
|
221
|
+
{ key: 'cellSize', label: 'Cell size', group: 'quality', min: 0.1, max: 32, step: 0.1, unit: 'm', description: 'Finest cell, at the camera, and the shortest wave that can be drawn anywhere. Waves are metres, not kilometres, so on water this matters more than reach does.' },
|
|
222
|
+
{ key: 'curvature', label: 'Planetary curvature', group: 'quality', min: 0, max: 0.0000012, step: 0.00000001, advanced: true, description: '1/(2R). Drops the surface with the square of distance so it meets a real horizon.' },
|
|
223
|
+
{ key: 'detailFadeDistance', label: 'Detail fade distance', group: 'quality', min: 50, max: 8000, step: 25, unit: 'm', description: 'Distance over which the fragment-stage ripple fades out. Removes far-field shimmer and buys back most of its own cost.' },
|
|
224
|
+
{ key: 'terrainShadowSteps', label: 'Terrain shadow steps', group: 'quality', min: 0, max: 32, step: 1, description: 'Steps in the terrain shadow march, nearest the camera. 0 turns it off entirely — the biggest single saving when the scene has terrain.' },
|
|
225
|
+
{ key: 'terrainShadowDistance', label: 'Terrain shadow distance', group: 'quality', min: 0, max: 40000, step: 100, unit: 'm', description: 'Range over which that march fades out. It runs per vertex, so lowering this drops whole rings out of it.' },
|
|
226
|
+
{ key: 'reflectionScale', label: 'Reflection resolution', group: 'quality', min: 0, max: 1, step: 0.05, description: 'Planar reflection target size, as a fraction of the frame. 0 disables the pass and falls back to the environment map.' },
|
|
227
|
+
{ key: 'refractionScale', label: 'Refraction resolution', group: 'quality', min: 0, max: 1, step: 0.05, description: 'Refraction and depth grab size, as a fraction of the frame. The shoreline reads its depth from this.' },
|
|
228
|
+
];
|
|
229
|
+
export const defaultOceanWaterSettings = {
|
|
230
|
+
id: '3drise-water',
|
|
231
|
+
type: 'ocean',
|
|
232
|
+
config: { ...defaultSeaConfig, enabled: false },
|
|
233
|
+
quality: { ...defaultOceanQuality },
|
|
234
|
+
};
|
|
235
|
+
// =============================================================================
|
|
236
|
+
// Normalisation
|
|
237
|
+
// =============================================================================
|
|
238
|
+
//
|
|
239
|
+
// A published scene loads whatever was in the database the day it was saved.
|
|
240
|
+
//
|
|
241
|
+
// **This is where the ocean deliberately differs from the terrain.**
|
|
242
|
+
// `normalizeTerrain` returns null for a legacy blob, because a project saved
|
|
243
|
+
// before terrain existed never had ground and defaulting one in would give it a
|
|
244
|
+
// landscape it was never authored with. A project saved before THIS system very
|
|
245
|
+
// possibly had water — the old ocean is a visible flat plane with a water
|
|
246
|
+
// material — so returning null would DELETE it. A legacy blob is therefore
|
|
247
|
+
// mapped, not dropped.
|
|
248
|
+
//
|
|
249
|
+
// Each block still merges over its own defaults separately, so editing quality
|
|
250
|
+
// does not hand the surface a new config object and rebuild the clipmap.
|
|
251
|
+
const WATER_TYPES = ['sea', 'lake', 'storm', 'shore'];
|
|
252
|
+
const WATER_HOSTS = ['world', 'object'];
|
|
253
|
+
const isRecord = (v) => typeof v === 'object' && v !== null;
|
|
254
|
+
/**
|
|
255
|
+
* The five water material variants the old ocean shipped with, onto the closest
|
|
256
|
+
* new type and the numbers that make it read the same way. This is why the
|
|
257
|
+
* preset list is seeded from the same five names: they were already the
|
|
258
|
+
* vocabulary.
|
|
259
|
+
*/
|
|
260
|
+
const LEGACY_VARIANTS = {
|
|
261
|
+
Lake: { waterType: 'lake', settings: {} },
|
|
262
|
+
Ocean: { waterType: 'sea', settings: {} },
|
|
263
|
+
Storm: { waterType: 'storm', settings: {} },
|
|
264
|
+
Tropical: {
|
|
265
|
+
waterType: 'sea',
|
|
266
|
+
settings: {
|
|
267
|
+
windSpeed: 5,
|
|
268
|
+
fetch: 120,
|
|
269
|
+
deepColor: '#0a5a7a',
|
|
270
|
+
shallowColor: '#4fd6c8',
|
|
271
|
+
absorption: 0.04,
|
|
272
|
+
clarity: 0.12,
|
|
273
|
+
sssColor: '#39c8b0',
|
|
274
|
+
},
|
|
275
|
+
},
|
|
276
|
+
Arctic: {
|
|
277
|
+
waterType: 'sea',
|
|
278
|
+
settings: {
|
|
279
|
+
windSpeed: 13,
|
|
280
|
+
deepColor: '#0b2436',
|
|
281
|
+
shallowColor: '#7fb6c9',
|
|
282
|
+
sssColor: '#8fd0e0',
|
|
283
|
+
clarity: 0.15,
|
|
284
|
+
foamAmount: 1.1,
|
|
285
|
+
},
|
|
286
|
+
},
|
|
287
|
+
};
|
|
288
|
+
/**
|
|
289
|
+
* A blob in the retired shape: `meshSettings` + `materialSettings` + a
|
|
290
|
+
* `config` of `{ planeSize, planeSegments }`. Recognised by the absence of
|
|
291
|
+
* `waveModel`, which every new config has.
|
|
292
|
+
*
|
|
293
|
+
* The plane it was authored with decides the host. The default was 10 000, so
|
|
294
|
+
* every existing scene becomes the world ocean — which is what those scenes
|
|
295
|
+
* look like today. A small plane was somebody placing a pond, and becomes one.
|
|
296
|
+
*/
|
|
297
|
+
function fromLegacy(raw) {
|
|
298
|
+
const mesh = isRecord(raw.meshSettings) ? raw.meshSettings : {};
|
|
299
|
+
const material = isRecord(raw.materialSettings) ? raw.materialSettings : {};
|
|
300
|
+
const legacyConfig = isRecord(raw.config) ? raw.config : {};
|
|
301
|
+
const variantName = typeof material.materialVariant === 'string' ? material.materialVariant : 'Ocean';
|
|
302
|
+
const variant = LEGACY_VARIANTS[variantName] ?? LEGACY_VARIANTS.Ocean;
|
|
303
|
+
const planeSize = Array.isArray(legacyConfig.planeSize) ? Number(legacyConfig.planeSize[0]) : 10000;
|
|
304
|
+
const host = Number.isFinite(planeSize) && planeSize < 2000 ? 'object' : 'world';
|
|
305
|
+
const position = Array.isArray(mesh.position) ? mesh.position : [0, 0, 0];
|
|
306
|
+
const level = Number(position[1]);
|
|
307
|
+
const base = OCEAN_DEFAULTS[variant.waterType];
|
|
308
|
+
return {
|
|
309
|
+
...base,
|
|
310
|
+
...(host === 'object' ? OBJECT_HOST_OVERRIDES : {}),
|
|
311
|
+
...variant.settings,
|
|
312
|
+
type: 'ocean',
|
|
313
|
+
waterType: variant.waterType,
|
|
314
|
+
host,
|
|
315
|
+
enabled: mesh.visible !== false,
|
|
316
|
+
seaLevel: Number.isFinite(level) ? level : 0,
|
|
317
|
+
size: host === 'object' && Number.isFinite(planeSize) ? [planeSize, planeSize] : base.size,
|
|
318
|
+
preset: variantName in LEGACY_VARIANTS ? variantName : '',
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* Surface block merged over its type's defaults, or null when there is nothing
|
|
323
|
+
* to render. Unlike the terrain, a legacy blob is mapped rather than dropped —
|
|
324
|
+
* see the note above.
|
|
325
|
+
*/
|
|
326
|
+
export function normalizeOcean(raw, whole) {
|
|
327
|
+
if (!isRecord(raw)) {
|
|
328
|
+
// No config block. If the surrounding blob is the retired shape, it is a
|
|
329
|
+
// real ocean that predates this system; map it.
|
|
330
|
+
if (isRecord(whole) && (isRecord(whole.materialSettings) || isRecord(whole.meshSettings))) {
|
|
331
|
+
return fromLegacy(whole);
|
|
332
|
+
}
|
|
333
|
+
return null;
|
|
334
|
+
}
|
|
335
|
+
if (typeof raw.waveModel !== 'string' && isRecord(whole) && isRecord(whole.materialSettings)) {
|
|
336
|
+
return fromLegacy(whole);
|
|
337
|
+
}
|
|
338
|
+
const waterType = WATER_TYPES.includes(raw.waterType)
|
|
339
|
+
? raw.waterType
|
|
340
|
+
: 'sea';
|
|
341
|
+
const host = WATER_HOSTS.includes(raw.host)
|
|
342
|
+
? raw.host
|
|
343
|
+
: 'world';
|
|
344
|
+
return {
|
|
345
|
+
...OCEAN_DEFAULTS[waterType],
|
|
346
|
+
...(host === 'object' ? OBJECT_HOST_OVERRIDES : {}),
|
|
347
|
+
...raw,
|
|
348
|
+
type: 'ocean',
|
|
349
|
+
waterType,
|
|
350
|
+
host,
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
export function normalizeOceanQuality(raw) {
|
|
354
|
+
return { ...defaultOceanQuality, ...(isRecord(raw) ? raw : {}) };
|
|
355
|
+
}
|
|
356
|
+
/** A whole settings blob, from a project of any age. */
|
|
357
|
+
export function normalizeOceanSettings(raw) {
|
|
358
|
+
const source = isRecord(raw) ? raw : {};
|
|
359
|
+
const config = normalizeOcean(source.config, source);
|
|
360
|
+
const settings = {
|
|
361
|
+
id: typeof source.id === 'string' ? source.id : defaultOceanWaterSettings.id,
|
|
362
|
+
type: 'ocean',
|
|
363
|
+
config: config ?? { ...defaultSeaConfig, enabled: false },
|
|
364
|
+
quality: normalizeOceanQuality(source.quality),
|
|
365
|
+
};
|
|
366
|
+
if (settings.config.host === 'object') {
|
|
367
|
+
const mesh = isRecord(source.meshSettings) ? source.meshSettings : {};
|
|
368
|
+
settings.meshSettings = {
|
|
369
|
+
visible: mesh.visible !== false,
|
|
370
|
+
position: (Array.isArray(mesh.position) ? mesh.position : [0, settings.config.seaLevel, 0]),
|
|
371
|
+
rotation: (Array.isArray(mesh.rotation) ? mesh.rotation : [0, 0, 0]),
|
|
372
|
+
scale: (Array.isArray(mesh.scale) ? mesh.scale : [1, 1, 1]),
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
if (source.animations)
|
|
376
|
+
settings.animations = source.animations;
|
|
377
|
+
if (source.mouseMove)
|
|
378
|
+
settings.mouseMove = source.mouseMove;
|
|
379
|
+
return settings;
|
|
380
|
+
}
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Config shapes for the procedural terrain system that lives in this package.
|
|
3
|
+
*
|
|
4
|
+
* Declared locally rather than in `@3driseai/3drise-core`, alongside
|
|
5
|
+
* `cloudConfigs.ts` and `gridConfigs.ts`, because the material and the renderer
|
|
6
|
+
* are here and nothing outside the viewer needs to construct these by hand.
|
|
7
|
+
*
|
|
8
|
+
* Core's `TerrainSettings` is the retired flat shape (`visible` +
|
|
9
|
+
* `displacementScale`) and is deliberately left alone: a saved project still
|
|
10
|
+
* carries it, and `normalizeTerrain` below is what turns one into nothing rather
|
|
11
|
+
* than into a mountain range the scene was never authored with.
|
|
12
|
+
*
|
|
13
|
+
* A terrain is ONE landform model with per-type shaping, not four renderers —
|
|
14
|
+
* the same way three of the four cloud types share one marcher. What separates
|
|
15
|
+
* mountains from dunes is the operator applied to the fBm and the numbers around
|
|
16
|
+
* it, so the type is a config field the shader branches on.
|
|
17
|
+
*/
|
|
18
|
+
/** The four landforms the height function shapes. */
|
|
19
|
+
export type TerrainType = 'mountains' | 'dunes' | 'hills' | 'canyon';
|
|
20
|
+
/** Fields every terrain shares, whatever its landform. */
|
|
21
|
+
export interface TerrainSurfaceConfig {
|
|
22
|
+
enabled: boolean;
|
|
23
|
+
/** Peak height above `seaLevel`, in world units. Also the denominator for
|
|
24
|
+
* every height-keyed splat threshold, so raising it does not re-shuffle the
|
|
25
|
+
* snow line. */
|
|
26
|
+
elevation: number;
|
|
27
|
+
/** World Y the terrain is built around. The clipmap sits here when the height
|
|
28
|
+
* field returns zero, so this is where a placed object meets flat ground. */
|
|
29
|
+
seaLevel: number;
|
|
30
|
+
/** Horizontal size of the primary landform, in world units. The single knob
|
|
31
|
+
* that decides whether this reads as a mountain range or a gravel pile. */
|
|
32
|
+
featureSize: number;
|
|
33
|
+
/** fBm octave count. Each one doubles frequency, so 8 spans a 256:1 range of
|
|
34
|
+
* detail; past ~10 the extra octaves are below the finest clipmap cell and
|
|
35
|
+
* only cost. Distant rings drop octaves automatically. */
|
|
36
|
+
octaves: number;
|
|
37
|
+
/** Frequency multiplier per octave. 2.0 is the textbook value; slightly above
|
|
38
|
+
* it (2.02-2.15) breaks the grid alignment that otherwise shows as a faint
|
|
39
|
+
* square lattice on large flat areas. */
|
|
40
|
+
lacunarity: number;
|
|
41
|
+
/** Amplitude multiplier per octave. Below 0.5 the terrain goes smooth and
|
|
42
|
+
* rolling; above it, jagged and fractal-looking. */
|
|
43
|
+
gain: number;
|
|
44
|
+
/** 0 gives rounded billow hills, 1 gives knife ridges. The single strongest
|
|
45
|
+
* cue for "mountain" versus "dune field". */
|
|
46
|
+
ridgeSharpness: number;
|
|
47
|
+
/** Domain warp amount, as a fraction of `featureSize`. This is what stops fBm
|
|
48
|
+
* looking like fBm: it bends ridge lines into the curved, branching shapes
|
|
49
|
+
* real drainage produces. Zero gives the obvious noise-blob silhouette. */
|
|
50
|
+
warpStrength: number;
|
|
51
|
+
/** Scale of the warp field relative to `featureSize`. Above ~1 the warp is
|
|
52
|
+
* slower than the terrain and it drifts rather than bends. */
|
|
53
|
+
warpSize: number;
|
|
54
|
+
/** Derivative damping. Octaves are attenuated where the accumulated slope is
|
|
55
|
+
* already steep, which flattens valley floors and sharpens flanks — the
|
|
56
|
+
* cheapest approximation of erosion there is, and the difference between
|
|
57
|
+
* "noise" and "landscape". */
|
|
58
|
+
erosion: number;
|
|
59
|
+
/** Number of strata steps. 0 is off. Canyon country is sedimentary, and the
|
|
60
|
+
* horizontal banding is most of what makes a mesa read as a mesa. */
|
|
61
|
+
terraces: number;
|
|
62
|
+
/** How hard a terrace edge is. 0 is a smooth ramp, 1 a near-vertical riser. */
|
|
63
|
+
terraceSharpness: number;
|
|
64
|
+
/** Orientation of the dune crests and the prevailing ridge grain, in degrees.
|
|
65
|
+
* Dunes are transverse to the wind, so this is a wind bearing. */
|
|
66
|
+
bearing: number;
|
|
67
|
+
/** Crest-to-crest distance of the dune train, in world units. */
|
|
68
|
+
duneWavelength: number;
|
|
69
|
+
/** Lee-slope steepening. Real dunes are asymmetric — a long windward ramp and
|
|
70
|
+
* a short slip face at the angle of repose. At 0 they are sine waves. */
|
|
71
|
+
duneAsymmetry: number;
|
|
72
|
+
/** Fraction of the height range flattened into mesa tops. */
|
|
73
|
+
plateau: number;
|
|
74
|
+
/** Depth of the incised channel network, as a fraction of `elevation`. */
|
|
75
|
+
valleyDepth: number;
|
|
76
|
+
/** Width of the incision. Narrow cuts slot canyons; wide ones cut broad washes. */
|
|
77
|
+
valleyWidth: number;
|
|
78
|
+
/** Ground at the bottom of the height range. */
|
|
79
|
+
lowColor: string;
|
|
80
|
+
/** Ground at mid height. */
|
|
81
|
+
midColor: string;
|
|
82
|
+
/** Exposed rock, splatted by slope rather than by height — which is the whole
|
|
83
|
+
* trick: rock appears wherever the surface is too steep to hold anything,
|
|
84
|
+
* at any altitude, so cliffs read as cliffs. */
|
|
85
|
+
rockColor: string;
|
|
86
|
+
/** Snow, salt or bleached stone at the top of the range. */
|
|
87
|
+
peakColor: string;
|
|
88
|
+
/** Slope (0 flat, 1 vertical) at which rock starts showing through. */
|
|
89
|
+
slopeRockStart: number;
|
|
90
|
+
/** Slope at which the surface is bare rock. */
|
|
91
|
+
slopeRockEnd: number;
|
|
92
|
+
/** Height fraction where the peak layer begins. */
|
|
93
|
+
peakLevel: number;
|
|
94
|
+
/** Width of the peak transition, in height fractions. A hard snow line is
|
|
95
|
+
* physically right for temperature but reads as a decal; ~0.1 is convincing. */
|
|
96
|
+
peakBlend: number;
|
|
97
|
+
/** Peak coverage lost per unit slope. Snow does not sit on a vertical face,
|
|
98
|
+
* and this is what keeps a summit from looking dipped in paint. */
|
|
99
|
+
peakSlopeFalloff: number;
|
|
100
|
+
/** Large-scale albedo break-up. Without it a splat layer is one flat colour
|
|
101
|
+
* across kilometres and the eye reads it as untextured. */
|
|
102
|
+
macroVariation: number;
|
|
103
|
+
/** Size of that variation, in world units. */
|
|
104
|
+
macroSize: number;
|
|
105
|
+
/** Strength of the high-frequency normal detail added in the fragment stage —
|
|
106
|
+
* bumps far below the mesh resolution. */
|
|
107
|
+
detailStrength: number;
|
|
108
|
+
/** Size of that detail, in world units. */
|
|
109
|
+
detailSize: number;
|
|
110
|
+
roughness: number;
|
|
111
|
+
/** Specular strength. Rock is nearly matte; wet sand and snow are not. */
|
|
112
|
+
specular: number;
|
|
113
|
+
/** Sky fill. Terrain is lit by the whole dome, not only the sun, and freezing
|
|
114
|
+
* this is what makes a night landscape glow. */
|
|
115
|
+
ambient: number;
|
|
116
|
+
/** Ground-bounce fill on downward-facing surfaces, tinted by the low colour. */
|
|
117
|
+
bounce: number;
|
|
118
|
+
/** Strength of the analytic self-shadow marched down the sun vector. This is
|
|
119
|
+
* what puts a mountain's shadow in its own valley, at any scale, with no
|
|
120
|
+
* shadow-map resolution to run out of. */
|
|
121
|
+
sunShadow: number;
|
|
122
|
+
/** Penumbra width of that shadow. Larger reads as a hazy day. */
|
|
123
|
+
shadowSoftness: number;
|
|
124
|
+
/** Rate distant terrain fades into the sky it is seen through. The main cue
|
|
125
|
+
* for how large the landscape reads, and the reason a horizon looks like a
|
|
126
|
+
* horizon rather than a cut-out. */
|
|
127
|
+
aerialPerspective: number;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* The terrain, as stored.
|
|
131
|
+
*
|
|
132
|
+
* `type` is 'terrain' — the OBJECT type — with the landform kept separately in
|
|
133
|
+
* `terrainType`, exactly as the clouds keep `deckType` apart from `type`.
|
|
134
|
+
* Collapsing the two would make the terrain invisible to anything that routes on
|
|
135
|
+
* object type.
|
|
136
|
+
*/
|
|
137
|
+
export type TerrainConfig = TerrainSurfaceConfig & {
|
|
138
|
+
type: 'terrain';
|
|
139
|
+
terrainType: TerrainType;
|
|
140
|
+
/** Name of the preset the numbers came from, or '' once any of them is edited.
|
|
141
|
+
* Purely a UI bookmark — the renderer never reads it. */
|
|
142
|
+
preset?: string;
|
|
143
|
+
};
|
|
144
|
+
/** Cost and extent knobs. */
|
|
145
|
+
export interface TerrainQualityConfig {
|
|
146
|
+
/** Clipmap ring count. Each ring doubles its cell size, so the visible radius
|
|
147
|
+
* is roughly `cellSize * segments * 2^(levels-1)`: 9 levels of 192 segments at
|
|
148
|
+
* 2 m reaches ~98 km, which is past where haze has dissolved the ground.
|
|
149
|
+
*
|
|
150
|
+
* There is no adaptive scaling of the pyramid, deliberately. Tying the cell
|
|
151
|
+
* size to camera altitude sounds right and is not: a clipmap triangle already
|
|
152
|
+
* subtends a constant angle whatever the scale, so scaling buys nothing in
|
|
153
|
+
* detail, and scaling by height above SEA LEVEL — the only height available
|
|
154
|
+
* without reading the field back off the GPU — coarsens a camera that is
|
|
155
|
+
* standing on a mountain rather than flying over one. Extra levels are cheap;
|
|
156
|
+
* a wrong guess about altitude is not. */
|
|
157
|
+
levels: number;
|
|
158
|
+
/** Grid resolution per ring side. Vertex cost is `levels * segments^2 * 0.75`,
|
|
159
|
+
* since every ring above the first is hollow. */
|
|
160
|
+
segments: number;
|
|
161
|
+
/** Finest cell, in world units, at the camera. */
|
|
162
|
+
cellSize: number;
|
|
163
|
+
/** 1/(2R). Drops the surface away with the square of distance so the terrain
|
|
164
|
+
* meets a real horizon instead of running flat to the far plane. Zero gives a
|
|
165
|
+
* flat world, which at these extents looks wrong long before it looks flat. */
|
|
166
|
+
curvature: number;
|
|
167
|
+
/** Steps in the analytic sun-shadow march, at the camera. Falls to four as the
|
|
168
|
+
* shadow fades out with distance. */
|
|
169
|
+
shadowSteps: number;
|
|
170
|
+
/** Distance over which the analytic self-shadow fades to nothing.
|
|
171
|
+
*
|
|
172
|
+
* The march is the most expensive thing the renderer does and past a few
|
|
173
|
+
* kilometres it buys nothing — haze has already taken the contrast out of the
|
|
174
|
+
* ground and a ridge shadow is a couple of pixels wide. Cutting it here drops
|
|
175
|
+
* the outer clipmap rings, two thirds of all vertices, out of the march
|
|
176
|
+
* entirely. */
|
|
177
|
+
shadowDistance: number;
|
|
178
|
+
/** Distance over which fragment-stage detail fades out. Beyond it the surface
|
|
179
|
+
* is shaded from the mesh normal alone, which removes far-field shimmer and
|
|
180
|
+
* buys back most of its own cost. */
|
|
181
|
+
detailFadeDistance: number;
|
|
182
|
+
/** Receive the scene's directional shadow map, so objects cast onto terrain.
|
|
183
|
+
* Terrain-on-terrain shadowing is analytic and unaffected by this. */
|
|
184
|
+
receiveShadows: boolean;
|
|
185
|
+
/** Radiance scale, so terrain sits at the same exposure as the sky and clouds
|
|
186
|
+
* whether or not the cloud composite is the thing tonemapping the frame. */
|
|
187
|
+
exposure: number;
|
|
188
|
+
wireframe: boolean;
|
|
189
|
+
}
|
|
190
|
+
export declare const defaultMountainsConfig: TerrainConfig;
|
|
191
|
+
export declare const defaultHillsConfig: TerrainConfig;
|
|
192
|
+
export declare const defaultDunesConfig: TerrainConfig;
|
|
193
|
+
export declare const defaultCanyonConfig: TerrainConfig;
|
|
194
|
+
export declare const defaultTerrainQuality: TerrainQualityConfig;
|
|
195
|
+
/** Per-type defaults, for the controller's type switcher. */
|
|
196
|
+
export declare const TERRAIN_DEFAULTS: Record<TerrainType, TerrainConfig>;
|
|
197
|
+
export type TerrainPropertyGroup = 'form' | 'surface' | 'lighting' | 'quality';
|
|
198
|
+
/** Everything the controller needs to build a row and everything the AI context
|
|
199
|
+
* builder needs to know what a knob does and where it is safe. The runtime never
|
|
200
|
+
* reads this — defaults live in the config objects above. */
|
|
201
|
+
export interface TerrainPropertySchema {
|
|
202
|
+
key: string;
|
|
203
|
+
label: string;
|
|
204
|
+
group: TerrainPropertyGroup;
|
|
205
|
+
min?: number;
|
|
206
|
+
max?: number;
|
|
207
|
+
step?: number;
|
|
208
|
+
unit?: string;
|
|
209
|
+
description: string;
|
|
210
|
+
advanced?: boolean;
|
|
211
|
+
/** Only show for these terrain types. Absent means all. */
|
|
212
|
+
types?: TerrainType[];
|
|
213
|
+
}
|
|
214
|
+
export declare const TERRAIN_SCHEMA: TerrainPropertySchema[];
|
|
215
|
+
export declare const TERRAIN_QUALITY_SCHEMA: TerrainPropertySchema[];
|
|
216
|
+
/**
|
|
217
|
+
* A terrain, as stored.
|
|
218
|
+
*
|
|
219
|
+
* Named `ProceduralTerrainSettings` because core already exports a
|
|
220
|
+
* `TerrainSettings` — the retired flat shape — and a saved project may still
|
|
221
|
+
* carry one. Same reason `VolumetricCloudsSettings` is not `CloudsSettings`.
|
|
222
|
+
*
|
|
223
|
+
* There is deliberately no `meshSettings` and no `materialSettings`: the clipmap
|
|
224
|
+
* follows the camera so it has no transform to edit, and the material is not
|
|
225
|
+
* swappable, so the Transform and Material tabs do not apply.
|
|
226
|
+
*/
|
|
227
|
+
export interface ProceduralTerrainSettings {
|
|
228
|
+
id: string;
|
|
229
|
+
type: 'terrain';
|
|
230
|
+
/** The landform. Named `config` to match the house shape for an object's
|
|
231
|
+
* editable block. */
|
|
232
|
+
config: TerrainConfig;
|
|
233
|
+
quality: TerrainQualityConfig;
|
|
234
|
+
}
|
|
235
|
+
export declare const defaultProceduralTerrainSettings: ProceduralTerrainSettings;
|
|
236
|
+
/**
|
|
237
|
+
* Surface block merged over its type's defaults, or null when there is nothing to
|
|
238
|
+
* render — including the retired flat shape, which has no `config` and must draw
|
|
239
|
+
* nothing rather than a landscape the project was never authored with.
|
|
240
|
+
*
|
|
241
|
+
* An unknown or missing `terrainType` falls back to hills rather than rendering
|
|
242
|
+
* nothing: a scene that says `enabled: true` should show ground.
|
|
243
|
+
*/
|
|
244
|
+
export declare function normalizeTerrain(raw: unknown): TerrainConfig | null;
|
|
245
|
+
export declare function normalizeTerrainQuality(raw: unknown): TerrainQualityConfig;
|
|
246
|
+
/**
|
|
247
|
+
* A whole settings blob, from a project of any age. The flat legacy shape has no
|
|
248
|
+
* `config`, so it normalises to a disabled terrain rather than to a default one.
|
|
249
|
+
*/
|
|
250
|
+
export declare function normalizeTerrainSettings(raw: unknown): ProceduralTerrainSettings;
|
|
251
|
+
//# sourceMappingURL=terrainConfigs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terrainConfigs.d.ts","sourceRoot":"","sources":["../../src/types/terrainConfigs.ts"],"names":[],"mappings":"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"}
|