@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
|
@@ -1,7 +1,22 @@
|
|
|
1
1
|
import type { ObjectReadyProps } from '../types/objectReady';
|
|
2
2
|
import * as THREE from 'three';
|
|
3
|
-
import type { TimeSettings,
|
|
4
|
-
import
|
|
3
|
+
import type { TimeSettings, SkySettings, FogSettings } from '@3driseai/3drise-core';
|
|
4
|
+
import type { VolumetricCloudsSettings } from '../types/cloudConfigs';
|
|
5
|
+
import React from 'react';
|
|
6
|
+
/**
|
|
7
|
+
* Sky, sun and everything lit by them.
|
|
8
|
+
*
|
|
9
|
+
* Pure and props-driven: it holds no store subscription of its own, so the same
|
|
10
|
+
* component serves the editor (through a thin connector that supplies the props
|
|
11
|
+
* from Redux) and a published scene (through EnvironmentManager, which reads
|
|
12
|
+
* them out of the saved project). There is deliberately no second copy of this
|
|
13
|
+
* file in the client — a divergence here shows up as an embed that renders
|
|
14
|
+
* differently from the editor it was authored in.
|
|
15
|
+
*
|
|
16
|
+
* It owns the per-frame tick of skySystemManager, which is the single source of
|
|
17
|
+
* truth for time of day. Everything below reads the manager rather than
|
|
18
|
+
* receiving a sun direction, so nothing has to be threaded through props.
|
|
19
|
+
*/
|
|
5
20
|
export interface SkySystemRef {
|
|
6
21
|
setTime: (hours: number, minutes?: number) => void;
|
|
7
22
|
getTime: () => Date;
|
|
@@ -11,6 +26,9 @@ export interface SkySystemRef {
|
|
|
11
26
|
export interface SkySystemProps extends ObjectReadyProps {
|
|
12
27
|
timeSettings: TimeSettings;
|
|
13
28
|
visible?: boolean;
|
|
29
|
+
/** True mounts the physical sun rig (skybox + lensflare + directional light);
|
|
30
|
+
* false mounts the analytic Preetham sky instead. They are alternatives, not
|
|
31
|
+
* layers — the sun rig draws its own background. */
|
|
14
32
|
sunSystemVisible?: boolean;
|
|
15
33
|
sunSize?: number;
|
|
16
34
|
moonSize?: number;
|
|
@@ -19,11 +37,14 @@ export interface SkySystemProps extends ObjectReadyProps {
|
|
|
19
37
|
castShadow?: boolean;
|
|
20
38
|
shadowMapSize?: number;
|
|
21
39
|
playerPosition?: THREE.Vector3;
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
40
|
+
/** Volumetric cloud layers. Optional because a host may prefer to mount
|
|
41
|
+
* CloudsGenerator itself as a sibling — the editor does, so a cloud slider
|
|
42
|
+
* cannot re-render the sun. Both positions put the pass in the same place
|
|
43
|
+
* in the tree. */
|
|
44
|
+
cloudsSettings?: VolumetricCloudsSettings;
|
|
25
45
|
skyControllerSettings?: SkySettings;
|
|
26
|
-
|
|
46
|
+
/** Optional for the same reason as cloudsSettings: the editor gives fog its
|
|
47
|
+
* own connector, the embed path passes it here. */
|
|
27
48
|
fogSettings?: FogSettings;
|
|
28
49
|
onTimeOfDayChange?: (timeOfDay: string, elapsedTime: number) => void;
|
|
29
50
|
onTimeUpdate?: (timeOfDay: number) => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SkySystem.d.ts","sourceRoot":"","sources":["../../src/components/SkySystem.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAE7D,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,KAAK,EAAE,YAAY,EAAE,
|
|
1
|
+
{"version":3,"file":"SkySystem.d.ts","sourceRoot":"","sources":["../../src/components/SkySystem.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAE7D,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpF,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AAOtE,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B;;;;;;;;;;;;;GAaG;AAEH,MAAM,WAAW,YAAY;IACzB,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACnD,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,YAAY,EAAE,MAAM,MAAM,CAAC;IAC3B,eAAe,EAAE,MAAM,KAAK,CAAC,OAAO,CAAC;CACxC;AAED,MAAM,WAAW,cAAe,SAAQ,gBAAgB;IACpD,YAAY,EAAE,YAAY,CAAC;IAC3B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;yDAEqD;IACrD,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC;IAC/B;;;uBAGmB;IACnB,cAAc,CAAC,EAAE,wBAAwB,CAAC;IAC1C,qBAAqB,CAAC,EAAE,WAAW,CAAC;IACpC;wDACoD;IACpD,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,iBAAiB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IACrE,YAAY,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;CAC9C;AAED,QAAA,MAAM,SAAS,qFAmHb,CAAC;AAGH,eAAe,SAAS,CAAC"}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useObjectReady } from '../hooks/useObjectReady.js';
|
|
3
3
|
import { useEffect, useLayoutEffect, useRef, forwardRef, useImperativeHandle } from 'react';
|
|
4
|
-
import * as THREE from 'three';
|
|
5
4
|
import { useFrame } from '@react-three/fiber';
|
|
6
5
|
import { skySystemManager } from '@3driseai/3drise-core';
|
|
7
6
|
import Skybox from './Skybox.js';
|
|
@@ -9,7 +8,8 @@ import Lensflare from './Lensflare.js';
|
|
|
9
8
|
import SunLight from './SunLight.js';
|
|
10
9
|
import SkyController from './SkyController.js';
|
|
11
10
|
import SceneFog from './SceneFog.js';
|
|
12
|
-
|
|
11
|
+
import CloudsGenerator from './CloudsGenerator.js';
|
|
12
|
+
const SkySystem = forwardRef(({ timeSettings, visible = true, sunSystemVisible = false, sunSize = 1, moonSize = 1, skyboxScale = 100000, sunIntensity = 1, castShadow = true, shadowMapSize = 2048, playerPosition, cloudsSettings, skyControllerSettings, fogSettings, onTimeOfDayChange, onTimeUpdate, onObjectReady, onObjectDispose, }, ref) => {
|
|
13
13
|
const previousTimeOfDayRef = useRef(null);
|
|
14
14
|
const rootRef = useRef(null);
|
|
15
15
|
const ready = { onObjectReady, onObjectDispose };
|
|
@@ -20,8 +20,9 @@ const SkySystem = forwardRef(({ timeSettings, visible = true, sunSystemVisible =
|
|
|
20
20
|
getTimeOfDay: () => skySystemManager.getTimeOfDay(),
|
|
21
21
|
getSunDirection: () => skySystemManager.getSunDirection(),
|
|
22
22
|
}));
|
|
23
|
-
// useLayoutEffect so the manager is registered before useFrame's first
|
|
24
|
-
//
|
|
23
|
+
// useLayoutEffect so the manager is registered before useFrame's first rAF
|
|
24
|
+
// callback — a regular useEffect runs after paint, and the first tick is
|
|
25
|
+
// dropped with manager.enabled still false.
|
|
25
26
|
useLayoutEffect(() => {
|
|
26
27
|
skySystemManager.setTimeSettings(timeSettings);
|
|
27
28
|
}, [timeSettings]);
|
|
@@ -44,7 +45,7 @@ const SkySystem = forwardRef(({ timeSettings, visible = true, sunSystemVisible =
|
|
|
44
45
|
});
|
|
45
46
|
if (!visible)
|
|
46
47
|
return null;
|
|
47
|
-
return (_jsxs("group", { ref: rootRef, children: [skyControllerSettings && !sunSystemVisible && (_jsx(SkyController, { settings: skyControllerSettings, timeSettings: timeSettings, scale: skyboxScale, ...ready })), sunSystemVisible && (_jsxs(_Fragment, { children: [_jsx(Skybox, { visible: true, scale: skyboxScale, sunSize: sunSize, moonSize: moonSize, timeSettings: timeSettings, ...ready }), _jsx(Lensflare, { visible: true, intensity: sunIntensity, timeSettings: timeSettings, ...ready }), _jsx(SunLight, { visible: true, timeSettings: timeSettings, targetPosition: playerPosition, intensity: sunIntensity, castShadow: castShadow, shadowMapSize: shadowMapSize, ...ready })] })), fogSettings &&
|
|
48
|
+
return (_jsxs("group", { ref: rootRef, children: [skyControllerSettings && !sunSystemVisible && (_jsx(SkyController, { settings: skyControllerSettings, timeSettings: timeSettings, scale: skyboxScale, ...ready })), sunSystemVisible && (_jsxs(_Fragment, { children: [_jsx(Skybox, { visible: true, scale: skyboxScale, sunSize: sunSize, moonSize: moonSize, timeSettings: timeSettings, ...ready }), _jsx(Lensflare, { visible: true, intensity: sunIntensity, timeSettings: timeSettings, ...ready }), _jsx(SunLight, { visible: true, timeSettings: timeSettings, targetPosition: playerPosition, intensity: sunIntensity, castShadow: castShadow, shadowMapSize: shadowMapSize, ...ready })] })), fogSettings && _jsx(SceneFog, { fog: fogSettings }), cloudsSettings && (_jsx(CloudsGenerator, { settings: cloudsSettings, skySettings: skyControllerSettings, timeSettings: timeSettings, sunIntensity: sunIntensity, ...ready }))] }));
|
|
48
49
|
});
|
|
49
50
|
SkySystem.displayName = 'SkySystem';
|
|
50
51
|
export default SkySystem;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SunLight.d.ts","sourceRoot":"","sources":["../../src/components/SunLight.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAE7D,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC1D,MAAM,WAAW,aAAc,SAAQ,gBAAgB;IACnD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,YAAY,EAAE,YAAY,CAAC;IAC3B,cAAc,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC;IAC/B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;CAC1B;
|
|
1
|
+
{"version":3,"file":"SunLight.d.ts","sourceRoot":"","sources":["../../src/components/SunLight.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAE7D,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC1D,MAAM,WAAW,aAAc,SAAQ,gBAAgB;IACnD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,YAAY,EAAE,YAAY,CAAC;IAC3B,cAAc,CAAC,EAAE,KAAK,CAAC,OAAO,CAAC;IAC/B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;CAC1B;AAiBD,QAAA,MAAM,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,aAAa,CA0CrC,CAAC;AACF,eAAe,QAAQ,CAAC"}
|
|
@@ -13,7 +13,10 @@ const SUNRISE = 6;
|
|
|
13
13
|
const SUNSET = 21;
|
|
14
14
|
const DARKNESS_START = 20.42;
|
|
15
15
|
const DARKNESS_END = 6.58;
|
|
16
|
-
|
|
16
|
+
/** Shared so the default does not hand a fresh Vector3 to the deps array on every
|
|
17
|
+
* render, which re-ran the reposition effect every time anything above re-rendered. */
|
|
18
|
+
const ORIGIN = new THREE.Vector3(0, 0, 0);
|
|
19
|
+
const SunLight = ({ visible = true, timeSettings, targetPosition = ORIGIN, shadowDistance = 300, intensity: intensityMultiplier = 1, castShadow = true, shadowMapSize = 2048, onObjectReady, onObjectDispose, }) => {
|
|
17
20
|
const lightRef = useRef(null);
|
|
18
21
|
useObjectReady(lightRef, { visible, timeSettings, intensity: intensityMultiplier, castShadow, shadowMapSize }, onObjectReady, onObjectDispose);
|
|
19
22
|
const colorRef = useRef(new THREE.Color(0xffe5b0));
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { SkySettings, TimeSettings } from '@3driseai/3drise-core';
|
|
3
|
+
import type { ObjectReadyProps } from '../types/objectReady';
|
|
4
|
+
import type { ProceduralTerrainSettings } from '../types/terrainConfigs';
|
|
5
|
+
export interface TerrainBuilderProps extends ObjectReadyProps {
|
|
6
|
+
/** Accepts a partial or older-shaped blob — including core's retired flat
|
|
7
|
+
* `TerrainSettings`, which has no `config` and normalises to nothing rather
|
|
8
|
+
* than to a landscape the project was never authored with. */
|
|
9
|
+
settings?: Partial<ProceduralTerrainSettings> | null;
|
|
10
|
+
skySettings?: SkySettings;
|
|
11
|
+
timeSettings?: TimeSettings;
|
|
12
|
+
/** Matches SkySystem's sunIntensity, so terrain brightens with the scene. */
|
|
13
|
+
sunIntensity?: number;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Picks the landform for the scene's ground.
|
|
17
|
+
*
|
|
18
|
+
* The counterpart to `CloudsGenerator`, and deliberately the same shape: switch
|
|
19
|
+
* on the model field, mount exactly one renderer, normalise each block against
|
|
20
|
+
* its own source so editing one cannot invalidate the other.
|
|
21
|
+
*
|
|
22
|
+
* Terrain is simpler than the sky in one respect — there is one landform, not a
|
|
23
|
+
* deck plus an independent ice layer — so there is no second branch to compose.
|
|
24
|
+
* It is harder in another: `quality` rebuilds every clipmap ring when its
|
|
25
|
+
* identity changes, which is why it is memoised separately and why the controller
|
|
26
|
+
* writes quality changes live rather than through Redux.
|
|
27
|
+
*/
|
|
28
|
+
declare const TerrainBuilder: React.FC<TerrainBuilderProps>;
|
|
29
|
+
export default TerrainBuilder;
|
|
30
|
+
//# sourceMappingURL=TerrainBuilder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TerrainBuilder.d.ts","sourceRoot":"","sources":["../../src/components/TerrainBuilder.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkB,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AAOzE,MAAM,WAAW,mBAAoB,SAAQ,gBAAgB;IACzD;;mEAE+D;IAC/D,QAAQ,CAAC,EAAE,OAAO,CAAC,yBAAyB,CAAC,GAAG,IAAI,CAAC;IACrD,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,6EAA6E;IAC7E,YAAY,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;;;;;;GAYG;AACH,QAAA,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CA+BjD,CAAC;AAEF,eAAe,cAAc,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo } from 'react';
|
|
3
|
+
import { normalizeTerrain, normalizeTerrainQuality } from '../types/terrainConfigs.js';
|
|
4
|
+
import Mountains from './terrain/Mountains.js';
|
|
5
|
+
import Dunes from './terrain/Dunes.js';
|
|
6
|
+
import Hills from './terrain/Hills.js';
|
|
7
|
+
import Canyon from './terrain/Canyon.js';
|
|
8
|
+
/**
|
|
9
|
+
* Picks the landform for the scene's ground.
|
|
10
|
+
*
|
|
11
|
+
* The counterpart to `CloudsGenerator`, and deliberately the same shape: switch
|
|
12
|
+
* on the model field, mount exactly one renderer, normalise each block against
|
|
13
|
+
* its own source so editing one cannot invalidate the other.
|
|
14
|
+
*
|
|
15
|
+
* Terrain is simpler than the sky in one respect — there is one landform, not a
|
|
16
|
+
* deck plus an independent ice layer — so there is no second branch to compose.
|
|
17
|
+
* It is harder in another: `quality` rebuilds every clipmap ring when its
|
|
18
|
+
* identity changes, which is why it is memoised separately and why the controller
|
|
19
|
+
* writes quality changes live rather than through Redux.
|
|
20
|
+
*/
|
|
21
|
+
const TerrainBuilder = ({ settings, skySettings, timeSettings, sunIntensity, onObjectReady, onObjectDispose, }) => {
|
|
22
|
+
const config = useMemo(() => normalizeTerrain(settings?.config), [settings?.config]);
|
|
23
|
+
const quality = useMemo(() => normalizeTerrainQuality(settings?.quality), [settings?.quality]);
|
|
24
|
+
if (!config?.enabled)
|
|
25
|
+
return null;
|
|
26
|
+
const shared = {
|
|
27
|
+
config,
|
|
28
|
+
quality,
|
|
29
|
+
skySettings,
|
|
30
|
+
timeSettings,
|
|
31
|
+
sunIntensity,
|
|
32
|
+
id: settings?.id,
|
|
33
|
+
onObjectReady,
|
|
34
|
+
onObjectDispose,
|
|
35
|
+
};
|
|
36
|
+
switch (config.terrainType) {
|
|
37
|
+
case 'mountains': return _jsx(Mountains, { ...shared });
|
|
38
|
+
case 'dunes': return _jsx(Dunes, { ...shared });
|
|
39
|
+
case 'canyon': return _jsx(Canyon, { ...shared });
|
|
40
|
+
case 'hills':
|
|
41
|
+
default: return _jsx(Hills, { ...shared });
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
export default TerrainBuilder;
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
export type { AnimatedObjectProps } from './AnimatedObject';
|
|
2
2
|
export type { BubblesProps } from './Bubbles';
|
|
3
3
|
export type { CloudsProps } from './Clouds';
|
|
4
|
+
export type { CloudsGeneratorProps } from './CloudsGenerator';
|
|
4
5
|
export type { EffectsGeneratorProps } from './EffectsGenerator';
|
|
5
|
-
export type { EnvironmentManagerProps } from './EnvironmentManager';
|
|
6
|
+
export type { EnvironmentManagerProps, ViewerEnvironmentConfig } from './EnvironmentManager';
|
|
7
|
+
export type { HdrEnvironmentProps } from './HdrEnvironment';
|
|
6
8
|
export type { OutlineMode, Point3 } from './extractOutline';
|
|
7
9
|
export type { FrameProps } from './Frame';
|
|
8
10
|
export type { FrameShapeType } from './FrameGeometry';
|
|
@@ -48,18 +50,22 @@ export type { StarsProps } from './Stars';
|
|
|
48
50
|
export type { SunCoreProps } from './SunCore';
|
|
49
51
|
export type { SunLightProps } from './SunLight';
|
|
50
52
|
export type { Text2DProps } from './Text2D';
|
|
53
|
+
export type { TerrainBuilderProps } from './TerrainBuilder';
|
|
54
|
+
export type { OceanBuilderProps } from './OceanBuilder';
|
|
51
55
|
export type { Text3DProps } from './Text3D';
|
|
52
56
|
export type { VolumePointsProps } from './VolumePoints';
|
|
53
57
|
export { AnimatedObject, default as AnimatedObjectDefault } from './AnimatedObject';
|
|
54
58
|
export { default as Bubbles } from './Bubbles';
|
|
55
59
|
export { CameraController, default as CameraControllerDefault } from './CameraController';
|
|
56
60
|
export { default as Clouds } from './Clouds';
|
|
61
|
+
export { default as CloudsGenerator } from './CloudsGenerator';
|
|
57
62
|
export { default as CreatedObject } from './CreatedObject';
|
|
58
63
|
export { default as CustomPrimitive } from './CustomPrimitive';
|
|
59
64
|
export { default as Earth } from './Earth';
|
|
60
65
|
export { default as EffectsGenerator } from './EffectsGenerator';
|
|
61
66
|
export { default as EffectsGroup } from './EffectsGroup';
|
|
62
67
|
export { default as EnvironmentManager } from './EnvironmentManager';
|
|
68
|
+
export { default as HdrEnvironment, isHdrActive } from './HdrEnvironment';
|
|
63
69
|
export { default as EnvironmentObject } from './EnvironmentObject';
|
|
64
70
|
export { default as Frame } from './Frame';
|
|
65
71
|
export { FrameGeometry } from './FrameGeometry';
|
|
@@ -119,11 +125,21 @@ export { default as Stars, generateStarsGeometry } from './Stars';
|
|
|
119
125
|
export { default as Sun } from './Sun';
|
|
120
126
|
export { default as SunCore } from './SunCore';
|
|
121
127
|
export { default as SunLight } from './SunLight';
|
|
128
|
+
export { default as TerrainBuilder } from './TerrainBuilder';
|
|
129
|
+
export { default as OceanBuilder } from './OceanBuilder';
|
|
122
130
|
export { default as Text2D } from './Text2D';
|
|
123
131
|
export { default as Text3D } from './Text3D';
|
|
124
132
|
export { VolumePoints } from './VolumePoints';
|
|
125
133
|
export { FitGroup, GeometryMesh, computeMode, contourSlices, evenScatter, meshVertices, plexus, surfaceScatter, symmetricScatter, useShapeGeometry as useGeometryShape, volumeFill, wireframe, } from './GeometryShape';
|
|
126
134
|
export { contour2D, edges3D } from './extractOutline';
|
|
127
135
|
export * from './cursor';
|
|
136
|
+
export * from './volumetricClouds';
|
|
137
|
+
export * from './terrain';
|
|
138
|
+
export * from './water';
|
|
128
139
|
export * from './effects';
|
|
140
|
+
export type { LandscapeBuilderProps } from './LandscapeBuilder';
|
|
141
|
+
export { default as LandscapeBuilder } from './LandscapeBuilder';
|
|
142
|
+
export type { LandscapeObjectProps } from './LandscapeObject';
|
|
143
|
+
export { default as LandscapeObject } from './LandscapeObject';
|
|
144
|
+
export * from './landscape';
|
|
129
145
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAIA,YAAY,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAC5D,YAAY,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC9C,YAAY,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC5C,YAAY,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAChE,YAAY,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAIA,YAAY,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAC5D,YAAY,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC9C,YAAY,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC5C,YAAY,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAC9D,YAAY,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAChE,YAAY,EAAE,uBAAuB,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAC7F,YAAY,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAC5D,YAAY,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC5D,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAG1C,YAAY,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtD,YAAY,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC5C,YAAY,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAC1D,YAAY,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACzD,YAAY,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC5C,YAAY,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACxD,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACtD,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACtD,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACtD,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,YAAY,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAC5D,YAAY,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACpD,YAAY,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC9C,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACtD,YAAY,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AACtE,YAAY,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAC1D,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACxD,YAAY,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC9C,YAAY,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAC1D,YAAY,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAChE,YAAY,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAC9D,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAEtD,YAAY,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AACpE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC1C,YAAY,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC9C,YAAY,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACxD,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACxD,YAAY,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACxC,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,YAAY,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACxD,YAAY,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAC1D,YAAY,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC5C,YAAY,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAC1D,YAAY,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC9C,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChE,YAAY,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAC1D,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC1C,YAAY,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC9C,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,YAAY,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC5C,YAAY,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAC5D,YAAY,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACxD,YAAY,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC5C,YAAY,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAGxD,OAAO,EAAE,cAAc,EAAE,OAAO,IAAI,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AACpF,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,OAAO,IAAI,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAC1F,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAC3D,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACjE,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AACrE,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC1E,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACnE,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAC3D,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACvE,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAC3D,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACjE,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,mBAAmB,EAAE,MAAM,QAAQ,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AACnE,OAAO,EAAE,WAAW,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AACtE,OAAO,EAAE,WAAW,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AACtE,OAAO,EAAE,WAAW,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AACtE,OAAO,EAAE,SAAS,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAChE,OAAO,EAAE,SAAS,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAChE,OAAO,EAAE,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAChE,OAAO,EAAE,WAAW,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AACtE,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAC3D,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AACrE,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,QAAQ,CAAC;AACzC,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAC3D,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,QAAQ,CAAC;AACzC,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAC3D,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAC3D,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAC3D,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,EAAE,OAAO,IAAI,GAAG,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,UAAU,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAO9C,OAAO,EACL,QAAQ,EACR,YAAY,EACZ,WAAW,EACX,aAAa,EACb,WAAW,EACX,YAAY,EACZ,MAAM,EACN,cAAc,EACd,gBAAgB,EAChB,gBAAgB,IAAI,gBAAgB,EACpC,UAAU,EACV,SAAS,GACV,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAGtD,cAAc,UAAU,CAAC;AACzB,cAAc,oBAAoB,CAAC;AACnC,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAI1B,YAAY,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAChE,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACjE,YAAY,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAC/D,cAAc,aAAa,CAAC"}
|
package/dist/components/index.js
CHANGED
|
@@ -5,12 +5,14 @@ export { AnimatedObject, default as AnimatedObjectDefault } from './AnimatedObje
|
|
|
5
5
|
export { default as Bubbles } from './Bubbles.js';
|
|
6
6
|
export { CameraController, default as CameraControllerDefault } from './CameraController.js';
|
|
7
7
|
export { default as Clouds } from './Clouds.js';
|
|
8
|
+
export { default as CloudsGenerator } from './CloudsGenerator.js';
|
|
8
9
|
export { default as CreatedObject } from './CreatedObject.js';
|
|
9
10
|
export { default as CustomPrimitive } from './CustomPrimitive.js';
|
|
10
11
|
export { default as Earth } from './Earth.js';
|
|
11
12
|
export { default as EffectsGenerator } from './EffectsGenerator.js';
|
|
12
13
|
export { default as EffectsGroup } from './EffectsGroup.js';
|
|
13
14
|
export { default as EnvironmentManager } from './EnvironmentManager.js';
|
|
15
|
+
export { default as HdrEnvironment, isHdrActive } from './HdrEnvironment.js';
|
|
14
16
|
export { default as EnvironmentObject } from './EnvironmentObject.js';
|
|
15
17
|
export { default as Frame } from './Frame.js';
|
|
16
18
|
export { FrameGeometry } from './FrameGeometry.js';
|
|
@@ -70,6 +72,8 @@ export { default as Stars, generateStarsGeometry } from './Stars.js';
|
|
|
70
72
|
export { default as Sun } from './Sun.js';
|
|
71
73
|
export { default as SunCore } from './SunCore.js';
|
|
72
74
|
export { default as SunLight } from './SunLight.js';
|
|
75
|
+
export { default as TerrainBuilder } from './TerrainBuilder.js';
|
|
76
|
+
export { default as OceanBuilder } from './OceanBuilder.js';
|
|
73
77
|
export { default as Text2D } from './Text2D.js';
|
|
74
78
|
export { default as Text3D } from './Text3D.js';
|
|
75
79
|
export { VolumePoints } from './VolumePoints.js';
|
|
@@ -82,4 +86,10 @@ export { FitGroup, GeometryMesh, computeMode, contourSlices, evenScatter, meshVe
|
|
|
82
86
|
export { contour2D, edges3D } from './extractOutline.js';
|
|
83
87
|
// ------------------------------------------------------------ sub-folders
|
|
84
88
|
export * from './cursor/index.js';
|
|
89
|
+
export * from './volumetricClouds/index.js';
|
|
90
|
+
export * from './terrain/index.js';
|
|
91
|
+
export * from './water/index.js';
|
|
85
92
|
export * from './effects/index.js';
|
|
93
|
+
export { default as LandscapeBuilder } from './LandscapeBuilder.js';
|
|
94
|
+
export { default as LandscapeObject } from './LandscapeObject.js';
|
|
95
|
+
export * from './landscape/index.js';
|
|
@@ -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;
|