@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.
- 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/CustomPrimitive.js +1 -1
- 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/GeometryShape.d.ts.map +1 -1
- package/dist/components/GeometryShape.js +19 -3
- 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 +11 -9
- 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/ParticlesR3f.d.ts.map +1 -1
- package/dist/components/ParticlesR3f.js +63 -12
- package/dist/components/PointCloud.d.ts.map +1 -1
- package/dist/components/PointCloud.js +50 -10
- 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 +1 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +15 -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/useMaterialApplication.d.ts.map +1 -1
- package/dist/hooks/useMaterialApplication.js +2 -3
- package/dist/hooks/useMaterialOptions.d.ts +2 -2
- package/dist/hooks/useMaterialOptions.d.ts.map +1 -1
- package/dist/hooks/useMaterialOptions.js +13 -31
- package/dist/hooks/useObjectEdges.d.ts.map +1 -1
- package/dist/hooks/useObjectEdges.js +3 -49
- 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/pointsMaterialOwnership.d.ts +9 -0
- package/dist/utils/pointsMaterialOwnership.d.ts.map +1 -0
- package/dist/utils/pointsMaterialOwnership.js +14 -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,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 @@
|
|
|
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"}
|