@3driseai/3drise-viewer 0.1.39 → 0.1.41
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/animationsV2/ClipsRuntime.d.ts +30 -0
- package/dist/animationsV2/ClipsRuntime.d.ts.map +1 -1
- package/dist/animationsV2/ClipsRuntime.js +185 -14
- package/dist/animationsV2/clipUtils.d.ts +15 -0
- package/dist/animationsV2/clipUtils.d.ts.map +1 -1
- package/dist/animationsV2/clipUtils.js +39 -2
- package/dist/animationsV2/normalize.d.ts.map +1 -1
- package/dist/animationsV2/normalize.js +4 -0
- package/dist/animationsV2/types.d.ts +12 -0
- package/dist/animationsV2/types.d.ts.map +1 -1
- package/dist/api/sceneHandle.d.ts +40 -3
- package/dist/api/sceneHandle.d.ts.map +1 -1
- package/dist/api/sceneHandle.js +40 -0
- package/dist/components/AnimatedObject.d.ts.map +1 -1
- package/dist/components/AnimatedObject.js +6 -2
- package/dist/components/EnabledContext.d.ts +12 -0
- package/dist/components/EnabledContext.d.ts.map +1 -0
- package/dist/components/EnabledContext.js +12 -0
- package/dist/components/GalleryObject.d.ts +13 -0
- package/dist/components/GalleryObject.d.ts.map +1 -0
- package/dist/components/GalleryObject.js +46 -0
- package/dist/components/ImageObject.d.ts +9 -0
- package/dist/components/ImageObject.d.ts.map +1 -0
- package/dist/components/ImageObject.js +26 -0
- package/dist/components/ObjectNode.d.ts.map +1 -1
- package/dist/components/ObjectNode.js +17 -6
- package/dist/components/ObjectsRenderer.d.ts.map +1 -1
- package/dist/components/ObjectsRenderer.js +9 -0
- package/dist/components/ProjectLoader.d.ts +2 -0
- package/dist/components/ProjectLoader.d.ts.map +1 -1
- package/dist/components/ProjectLoader.js +2 -2
- package/dist/components/SceneBuilder.d.ts +10 -0
- package/dist/components/SceneBuilder.d.ts.map +1 -1
- package/dist/components/SceneBuilder.js +3 -2
- package/dist/components/gallery/BasicCarouselGallery.d.ts +18 -0
- package/dist/components/gallery/BasicCarouselGallery.d.ts.map +1 -0
- package/dist/components/gallery/BasicCarouselGallery.js +9 -0
- package/dist/components/gallery/ContourLinesGallery.d.ts +18 -0
- package/dist/components/gallery/ContourLinesGallery.d.ts.map +1 -0
- package/dist/components/gallery/ContourLinesGallery.js +9 -0
- package/dist/components/gallery/DepthLayersGallery.d.ts +18 -0
- package/dist/components/gallery/DepthLayersGallery.d.ts.map +1 -0
- package/dist/components/gallery/DepthLayersGallery.js +9 -0
- package/dist/components/gallery/EngravingGallery.d.ts +18 -0
- package/dist/components/gallery/EngravingGallery.d.ts.map +1 -0
- package/dist/components/gallery/EngravingGallery.js +9 -0
- package/dist/components/gallery/FlowLinesGallery.d.ts +18 -0
- package/dist/components/gallery/FlowLinesGallery.d.ts.map +1 -0
- package/dist/components/gallery/FlowLinesGallery.js +9 -0
- package/dist/components/gallery/FoldGallery.d.ts +18 -0
- package/dist/components/gallery/FoldGallery.d.ts.map +1 -0
- package/dist/components/gallery/FoldGallery.js +9 -0
- package/dist/components/gallery/GlassPanesGallery.d.ts +18 -0
- package/dist/components/gallery/GlassPanesGallery.d.ts.map +1 -0
- package/dist/components/gallery/GlassPanesGallery.js +9 -0
- package/dist/components/gallery/HaloGallery.d.ts +18 -0
- package/dist/components/gallery/HaloGallery.d.ts.map +1 -0
- package/dist/components/gallery/HaloGallery.js +9 -0
- package/dist/components/gallery/LightThreadsGallery.d.ts +18 -0
- package/dist/components/gallery/LightThreadsGallery.d.ts.map +1 -0
- package/dist/components/gallery/LightThreadsGallery.js +9 -0
- package/dist/components/gallery/LoomGallery.d.ts +18 -0
- package/dist/components/gallery/LoomGallery.d.ts.map +1 -0
- package/dist/components/gallery/LoomGallery.js +9 -0
- package/dist/components/gallery/PaperLanternsGallery.d.ts +18 -0
- package/dist/components/gallery/PaperLanternsGallery.d.ts.map +1 -0
- package/dist/components/gallery/PaperLanternsGallery.js +9 -0
- package/dist/components/gallery/ParticleShiftGallery.d.ts +18 -0
- package/dist/components/gallery/ParticleShiftGallery.d.ts.map +1 -0
- package/dist/components/gallery/ParticleShiftGallery.js +9 -0
- package/dist/components/gallery/PinscreenGallery.d.ts +18 -0
- package/dist/components/gallery/PinscreenGallery.d.ts.map +1 -0
- package/dist/components/gallery/PinscreenGallery.js +9 -0
- package/dist/components/gallery/PopUpGallery.d.ts +18 -0
- package/dist/components/gallery/PopUpGallery.d.ts.map +1 -0
- package/dist/components/gallery/PopUpGallery.js +9 -0
- package/dist/components/gallery/PrismSplitGallery.d.ts +18 -0
- package/dist/components/gallery/PrismSplitGallery.d.ts.map +1 -0
- package/dist/components/gallery/PrismSplitGallery.js +9 -0
- package/dist/components/gallery/RidgelinesGallery.d.ts +18 -0
- package/dist/components/gallery/RidgelinesGallery.d.ts.map +1 -0
- package/dist/components/gallery/RidgelinesGallery.js +9 -0
- package/dist/components/gallery/ShadowBoxGallery.d.ts +18 -0
- package/dist/components/gallery/ShadowBoxGallery.d.ts.map +1 -0
- package/dist/components/gallery/ShadowBoxGallery.js +9 -0
- package/dist/components/gallery/SilkGallery.d.ts +18 -0
- package/dist/components/gallery/SilkGallery.d.ts.map +1 -0
- package/dist/components/gallery/SilkGallery.js +9 -0
- package/dist/components/gallery/SlatsGallery.d.ts +18 -0
- package/dist/components/gallery/SlatsGallery.d.ts.map +1 -0
- package/dist/components/gallery/SlatsGallery.js +9 -0
- package/dist/components/gallery/StrataGallery.d.ts +18 -0
- package/dist/components/gallery/StrataGallery.d.ts.map +1 -0
- package/dist/components/gallery/StrataGallery.js +9 -0
- package/dist/components/gallery/TerracesGallery.d.ts +18 -0
- package/dist/components/gallery/TerracesGallery.d.ts.map +1 -0
- package/dist/components/gallery/TerracesGallery.js +9 -0
- package/dist/components/gallery/WireReliefGallery.d.ts +18 -0
- package/dist/components/gallery/WireReliefGallery.d.ts.map +1 -0
- package/dist/components/gallery/WireReliefGallery.js +9 -0
- package/dist/components/gallery/index.d.ts +46 -0
- package/dist/components/gallery/index.d.ts.map +1 -0
- package/dist/components/gallery/index.js +22 -0
- package/dist/components/gallery/kit/GalleryVariant.d.ts +68 -0
- package/dist/components/gallery/kit/GalleryVariant.d.ts.map +1 -0
- package/dist/components/gallery/kit/GalleryVariant.js +231 -0
- package/dist/components/gallery/kit/feeds.d.ts +7 -0
- package/dist/components/gallery/kit/feeds.d.ts.map +1 -0
- package/dist/components/gallery/kit/feeds.js +83 -0
- package/dist/components/gallery/kit/galleryKit.d.ts +118 -0
- package/dist/components/gallery/kit/galleryKit.d.ts.map +1 -0
- package/dist/components/gallery/kit/galleryKit.js +298 -0
- package/dist/components/gallery/kit/lookBase.d.ts +157 -0
- package/dist/components/gallery/kit/lookBase.d.ts.map +1 -0
- package/dist/components/gallery/kit/lookBase.js +211 -0
- package/dist/components/gallery/kit/pictures.d.ts +14 -0
- package/dist/components/gallery/kit/pictures.d.ts.map +1 -0
- package/dist/components/gallery/kit/pictures.js +81 -0
- package/dist/components/gallery/looks/basicCarousel.d.ts +177 -0
- package/dist/components/gallery/looks/basicCarousel.d.ts.map +1 -0
- package/dist/components/gallery/looks/basicCarousel.js +315 -0
- package/dist/components/gallery/looks/contourLines.d.ts +153 -0
- package/dist/components/gallery/looks/contourLines.d.ts.map +1 -0
- package/dist/components/gallery/looks/contourLines.js +91 -0
- package/dist/components/gallery/looks/depthLayers.d.ts +155 -0
- package/dist/components/gallery/looks/depthLayers.d.ts.map +1 -0
- package/dist/components/gallery/looks/depthLayers.js +87 -0
- package/dist/components/gallery/looks/engraving.d.ts +162 -0
- package/dist/components/gallery/looks/engraving.d.ts.map +1 -0
- package/dist/components/gallery/looks/engraving.js +96 -0
- package/dist/components/gallery/looks/flowLines.d.ts +180 -0
- package/dist/components/gallery/looks/flowLines.d.ts.map +1 -0
- package/dist/components/gallery/looks/flowLines.js +113 -0
- package/dist/components/gallery/looks/fold.d.ts +209 -0
- package/dist/components/gallery/looks/fold.d.ts.map +1 -0
- package/dist/components/gallery/looks/fold.js +155 -0
- package/dist/components/gallery/looks/glassPanes.d.ts +133 -0
- package/dist/components/gallery/looks/glassPanes.d.ts.map +1 -0
- package/dist/components/gallery/looks/glassPanes.js +208 -0
- package/dist/components/gallery/looks/halo.d.ts +100 -0
- package/dist/components/gallery/looks/halo.d.ts.map +1 -0
- package/dist/components/gallery/looks/halo.js +119 -0
- package/dist/components/gallery/looks/lightThreads.d.ts +199 -0
- package/dist/components/gallery/looks/lightThreads.d.ts.map +1 -0
- package/dist/components/gallery/looks/lightThreads.js +246 -0
- package/dist/components/gallery/looks/loom.d.ts +238 -0
- package/dist/components/gallery/looks/loom.d.ts.map +1 -0
- package/dist/components/gallery/looks/loom.js +256 -0
- package/dist/components/gallery/looks/paperLanterns.d.ts +181 -0
- package/dist/components/gallery/looks/paperLanterns.d.ts.map +1 -0
- package/dist/components/gallery/looks/paperLanterns.js +399 -0
- package/dist/components/gallery/looks/particleShift.d.ts +193 -0
- package/dist/components/gallery/looks/particleShift.d.ts.map +1 -0
- package/dist/components/gallery/looks/particleShift.js +282 -0
- package/dist/components/gallery/looks/pinscreen.d.ts +175 -0
- package/dist/components/gallery/looks/pinscreen.d.ts.map +1 -0
- package/dist/components/gallery/looks/pinscreen.js +96 -0
- package/dist/components/gallery/looks/popUp.d.ts +206 -0
- package/dist/components/gallery/looks/popUp.d.ts.map +1 -0
- package/dist/components/gallery/looks/popUp.js +132 -0
- package/dist/components/gallery/looks/prismSplit.d.ts +151 -0
- package/dist/components/gallery/looks/prismSplit.d.ts.map +1 -0
- package/dist/components/gallery/looks/prismSplit.js +84 -0
- package/dist/components/gallery/looks/ridgelines.d.ts +179 -0
- package/dist/components/gallery/looks/ridgelines.d.ts.map +1 -0
- package/dist/components/gallery/looks/ridgelines.js +111 -0
- package/dist/components/gallery/looks/shadowBox.d.ts +152 -0
- package/dist/components/gallery/looks/shadowBox.d.ts.map +1 -0
- package/dist/components/gallery/looks/shadowBox.js +82 -0
- package/dist/components/gallery/looks/silk.d.ts +140 -0
- package/dist/components/gallery/looks/silk.d.ts.map +1 -0
- package/dist/components/gallery/looks/silk.js +346 -0
- package/dist/components/gallery/looks/slats.d.ts +176 -0
- package/dist/components/gallery/looks/slats.d.ts.map +1 -0
- package/dist/components/gallery/looks/slats.js +93 -0
- package/dist/components/gallery/looks/strata.d.ts +172 -0
- package/dist/components/gallery/looks/strata.d.ts.map +1 -0
- package/dist/components/gallery/looks/strata.js +88 -0
- package/dist/components/gallery/looks/terraces.d.ts +168 -0
- package/dist/components/gallery/looks/terraces.d.ts.map +1 -0
- package/dist/components/gallery/looks/terraces.js +91 -0
- package/dist/components/gallery/looks/wireRelief.d.ts +153 -0
- package/dist/components/gallery/looks/wireRelief.d.ts.map +1 -0
- package/dist/components/gallery/looks/wireRelief.js +128 -0
- package/dist/components/image/ContourImage.d.ts +7 -0
- package/dist/components/image/ContourImage.d.ts.map +1 -0
- package/dist/components/image/ContourImage.js +6 -0
- package/dist/components/image/EngravingImage.d.ts +7 -0
- package/dist/components/image/EngravingImage.d.ts.map +1 -0
- package/dist/components/image/EngravingImage.js +6 -0
- package/dist/components/image/FrostImage.d.ts +7 -0
- package/dist/components/image/FrostImage.d.ts.map +1 -0
- package/dist/components/image/FrostImage.js +6 -0
- package/dist/components/image/LenticularImage.d.ts +7 -0
- package/dist/components/image/LenticularImage.d.ts.map +1 -0
- package/dist/components/image/LenticularImage.js +6 -0
- package/dist/components/image/PinscreenImage.d.ts +7 -0
- package/dist/components/image/PinscreenImage.d.ts.map +1 -0
- package/dist/components/image/PinscreenImage.js +6 -0
- package/dist/components/image/PrismImage.d.ts +7 -0
- package/dist/components/image/PrismImage.d.ts.map +1 -0
- package/dist/components/image/PrismImage.js +6 -0
- package/dist/components/image/ProjectorImage.d.ts +7 -0
- package/dist/components/image/ProjectorImage.d.ts.map +1 -0
- package/dist/components/image/ProjectorImage.js +6 -0
- package/dist/components/image/ReliefImage.d.ts +7 -0
- package/dist/components/image/ReliefImage.d.ts.map +1 -0
- package/dist/components/image/ReliefImage.js +6 -0
- package/dist/components/image/RollImage.d.ts +7 -0
- package/dist/components/image/RollImage.d.ts.map +1 -0
- package/dist/components/image/RollImage.js +6 -0
- package/dist/components/image/ShardsImage.d.ts +126 -0
- package/dist/components/image/ShardsImage.d.ts.map +1 -0
- package/dist/components/image/ShardsImage.js +470 -0
- package/dist/components/image/core/contour.d.ts +126 -0
- package/dist/components/image/core/contour.d.ts.map +1 -0
- package/dist/components/image/core/contour.js +123 -0
- package/dist/components/image/core/engraving.d.ts +135 -0
- package/dist/components/image/core/engraving.d.ts.map +1 -0
- package/dist/components/image/core/engraving.js +163 -0
- package/dist/components/image/core/frost.d.ts +126 -0
- package/dist/components/image/core/frost.d.ts.map +1 -0
- package/dist/components/image/core/frost.js +156 -0
- package/dist/components/image/core/imageCore.d.ts +110 -0
- package/dist/components/image/core/imageCore.d.ts.map +1 -0
- package/dist/components/image/core/imageCore.js +269 -0
- package/dist/components/image/core/lenticular.d.ts +129 -0
- package/dist/components/image/core/lenticular.d.ts.map +1 -0
- package/dist/components/image/core/lenticular.js +132 -0
- package/dist/components/image/core/pinscreen.d.ts +126 -0
- package/dist/components/image/core/pinscreen.d.ts.map +1 -0
- package/dist/components/image/core/pinscreen.js +147 -0
- package/dist/components/image/core/prism.d.ts +120 -0
- package/dist/components/image/core/prism.d.ts.map +1 -0
- package/dist/components/image/core/prism.js +164 -0
- package/dist/components/image/core/projector.d.ts +135 -0
- package/dist/components/image/core/projector.d.ts.map +1 -0
- package/dist/components/image/core/projector.js +225 -0
- package/dist/components/image/core/relief.d.ts +111 -0
- package/dist/components/image/core/relief.d.ts.map +1 -0
- package/dist/components/image/core/relief.js +94 -0
- package/dist/components/image/core/roll.d.ts +114 -0
- package/dist/components/image/core/roll.d.ts.map +1 -0
- package/dist/components/image/core/roll.js +116 -0
- package/dist/components/image/imageVariant.d.ts +46 -0
- package/dist/components/image/imageVariant.d.ts.map +1 -0
- package/dist/components/image/imageVariant.js +128 -0
- package/dist/components/image/index.d.ts +22 -0
- package/dist/components/image/index.d.ts.map +1 -0
- package/dist/components/image/index.js +10 -0
- package/dist/components/image/pictureCycle.d.ts +15 -0
- package/dist/components/image/pictureCycle.d.ts.map +1 -0
- package/dist/components/image/pictureCycle.js +82 -0
- package/dist/components/index.d.ts +4 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +4 -0
- package/dist/components/volumetricClouds/VolumetricCloudsPass.d.ts +9 -7
- package/dist/components/volumetricClouds/VolumetricCloudsPass.d.ts.map +1 -1
- package/dist/components/volumetricClouds/VolumetricCloudsPass.js +39 -27
- package/dist/constants.d.ts +1 -1
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +18 -5
- package/dist/galleryRuntime.d.ts +57 -0
- package/dist/galleryRuntime.d.ts.map +1 -0
- package/dist/galleryRuntime.js +105 -0
- package/dist/hooks/useConfigLive.d.ts +1 -1
- package/dist/hooks/useConfigLive.d.ts.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/keyPad/KeyPadControls.d.ts +16 -0
- package/dist/keyPad/KeyPadControls.d.ts.map +1 -0
- package/dist/keyPad/KeyPadControls.js +176 -0
- package/dist/keyPad/index.d.ts +16 -0
- package/dist/keyPad/index.d.ts.map +1 -0
- package/dist/keyPad/index.js +8 -0
- package/dist/keyPad/keyBindings.d.ts +43 -0
- package/dist/keyPad/keyBindings.d.ts.map +1 -0
- package/dist/keyPad/keyBindings.js +92 -0
- package/dist/keyPad/keyPadAnimation.d.ts +28 -0
- package/dist/keyPad/keyPadAnimation.d.ts.map +1 -0
- package/dist/keyPad/keyPadAnimation.js +131 -0
- package/dist/keyPad/keyPadMotion.d.ts +68 -0
- package/dist/keyPad/keyPadMotion.d.ts.map +1 -0
- package/dist/keyPad/keyPadMotion.js +283 -0
- package/dist/keyPad/keyPadStore.d.ts +25 -0
- package/dist/keyPad/keyPadStore.d.ts.map +1 -0
- package/dist/keyPad/keyPadStore.js +63 -0
- package/dist/keyPad/types.d.ts +23 -0
- package/dist/keyPad/types.d.ts.map +1 -0
- package/dist/keyPad/types.js +9 -0
- package/dist/operations/catalogue/motionTrail.d.ts.map +1 -1
- package/dist/operations/catalogue/motionTrail.js +8 -1
- package/dist/operations/catalogue/visibility.d.ts.map +1 -1
- package/dist/operations/catalogue/visibility.js +23 -1
- package/dist/shaders/clouds/CloudResolveMaterial.d.ts +2 -1
- package/dist/shaders/clouds/CloudResolveMaterial.d.ts.map +1 -1
- package/dist/shaders/clouds/CloudResolveMaterial.js +37 -12
- package/dist/shaders/clouds/CloudVolumeMaterial.d.ts +4 -0
- package/dist/shaders/clouds/CloudVolumeMaterial.d.ts.map +1 -1
- package/dist/shaders/clouds/CloudVolumeMaterial.js +15 -3
- package/dist/triggers/kinds/gallery.d.ts +2 -0
- package/dist/triggers/kinds/gallery.d.ts.map +1 -0
- package/dist/triggers/kinds/gallery.js +39 -0
- package/dist/triggers/kinds/index.d.ts +1 -0
- package/dist/triggers/kinds/index.d.ts.map +1 -1
- package/dist/triggers/kinds/index.js +1 -0
- package/dist/ui/UiAnchorUpdater.d.ts.map +1 -1
- package/dist/ui/UiAnchorUpdater.js +2 -1
- package/dist/utils/cursorPicking.d.ts.map +1 -1
- package/dist/utils/cursorPicking.js +2 -1
- package/dist/utils/shownInScene.d.ts +13 -0
- package/dist/utils/shownInScene.d.ts.map +1 -0
- package/dist/utils/shownInScene.js +16 -0
- package/package.json +2 -2
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
// The approved lab module, verbatim but for its import paths and the lab's picture loader (Claude outputs/gallery-lab/
|
|
2
|
+
// lanterns.mjs). Plain JS-shaped code (the viewer compiles non-strict); typed at its one door, kit/GalleryVariant.tsx. Its own DEFAULTS only fill knobs the
|
|
3
|
+
// core defaults (DEFAULT_GALLERY_OBJECTS.paperLanterns) do not carry; its own autoplay is never used.
|
|
4
|
+
// lanterns — a gallery variant for 3drise (type 'gallery', config.type 'lanterns').
|
|
5
|
+
//
|
|
6
|
+
// A string of paper lanterns, one picture printed around each. The rope is a
|
|
7
|
+
// catenary between two posts; every lantern hangs from it on a cord and is a real
|
|
8
|
+
// pendulum (θ'' = −(g/l) sin θ − c θ' + wind), with a torsion twist about its
|
|
9
|
+
// cord, so the set never sits still: a breeze drifts through, and a tug on the
|
|
10
|
+
// rope (next / prev / a drag) runs a wave of swings down the line. One number
|
|
11
|
+
// drives the set — the scroll position `s` on a damped spring — each lantern's
|
|
12
|
+
// place on the rope is its offset from `s`; the lantern at the front hangs lower
|
|
13
|
+
// on its cord, nearer the viewer, and is LIT: a real point light burns inside
|
|
14
|
+
// it — the paper glows from the
|
|
15
|
+
// inside with the picture's own colours, and the rim shows the translucency of
|
|
16
|
+
// paper. The others glow softly. Pictures wrap the front half of each lantern
|
|
17
|
+
// (paper tone on the back), with bamboo rings top and bottom. Cursor: `breeze`
|
|
18
|
+
// — the cursor's motion is wind on the lanterns it passes; `glow` — the lantern
|
|
19
|
+
// under the cursor brightens. Nothing is drawn at the cursor.
|
|
20
|
+
import * as THREE from 'three';
|
|
21
|
+
import { withLean } from '../kit/galleryKit.js';
|
|
22
|
+
export const catalog = {
|
|
23
|
+
key: 'lanterns',
|
|
24
|
+
name: 'Paper Lanterns',
|
|
25
|
+
description: 'A string of paper lanterns with the pictures printed around them, each a swinging pendulum on a catenary rope; the front one hangs lower and glows from inside, a tug on the rope on every change. Use for festivals, night markets, warm showcases.',
|
|
26
|
+
tags: ['gallery', 'lanterns', 'pendulum', 'rope', 'light', 'night', 'navigation', 'interactive'],
|
|
27
|
+
camera: { position: [0.4, -0.1, 6.2], target: [0, 0.05, 0] },
|
|
28
|
+
};
|
|
29
|
+
export const DEFAULTS = {
|
|
30
|
+
type: 'lanterns',
|
|
31
|
+
enabled: true, lean: 1,
|
|
32
|
+
imageUrls: [],
|
|
33
|
+
autoplay: 0,
|
|
34
|
+
intensity: 1, // the lit lantern's lamp
|
|
35
|
+
opacity: 1,
|
|
36
|
+
// --- structural ---
|
|
37
|
+
aspect: 1.4, // picture aspect; the lantern's size follows (circumference-half × height)
|
|
38
|
+
radius: 0.42, // lantern radius
|
|
39
|
+
// --- the string ---
|
|
40
|
+
spacing: 1.35, // distance between lanterns, in diameters
|
|
41
|
+
sag: 0.35, // how much the rope hangs between the posts
|
|
42
|
+
span: 7, // the posts' distance (the rope's length across)
|
|
43
|
+
cord: 0.45, // cord length from rope to lantern
|
|
44
|
+
focusDrop: 0.55, // how much lower the front lantern hangs
|
|
45
|
+
focusLift: 0.9, // how far it comes toward the viewer
|
|
46
|
+
visible: 2.6, // lanterns each side before they fade
|
|
47
|
+
// --- motion ---
|
|
48
|
+
stiffness: 40, damping: 9, throwing: 0.15,
|
|
49
|
+
gravity: 9.8, // pendulum
|
|
50
|
+
swingDamping: 0.7,
|
|
51
|
+
wind: 0.5, // the breeze
|
|
52
|
+
tug: 1, // the swing a change sends down the rope
|
|
53
|
+
// --- light ---
|
|
54
|
+
glow: 0.35, // the unlit lanterns' inner glow
|
|
55
|
+
lamp: 1, // the lit one's inner glow
|
|
56
|
+
lampColor: '#ffb86b',
|
|
57
|
+
paperColor: '#f0dcc0',
|
|
58
|
+
rimColor: '#ffd9a6',
|
|
59
|
+
ringColor: '#3a2a1c',
|
|
60
|
+
// --- pointer ---
|
|
61
|
+
pointerMode: 'breeze',
|
|
62
|
+
pointerStrength: 1,
|
|
63
|
+
pointerRadius: 1.2,
|
|
64
|
+
pointerColor: '#ffe6c2',
|
|
65
|
+
};
|
|
66
|
+
export const STRUCTURAL = ['imageUrls', 'aspect', 'radius'];
|
|
67
|
+
export const POINTER_MODES = ['breeze', 'glow'];
|
|
68
|
+
export const GUI = [
|
|
69
|
+
{ key: 'lean', min: 0, max: 3, step: 0.01, tip: 'The gallery turns toward the cursor' },
|
|
70
|
+
{ key: 'aspect', min: 0.6, max: 2.5, step: 0.01 }, { key: 'radius', min: 0.2, max: 0.8, step: 0.01 },
|
|
71
|
+
{ key: 'spacing', min: 1, max: 3, step: 0.01 }, { key: 'sag', min: 0, max: 1.5, step: 0.01 }, { key: 'span', min: 3, max: 14, step: 0.1 }, { key: 'cord', min: 0.1, max: 1.5, step: 0.01 },
|
|
72
|
+
{ key: 'focusDrop', min: 0, max: 1.5, step: 0.01 }, { key: 'focusLift', min: 0, max: 2, step: 0.01 }, { key: 'visible', min: 1, max: 6, step: 0.1 },
|
|
73
|
+
{ key: 'stiffness', min: 5, max: 150, step: 1 }, { key: 'damping', min: 2, max: 30, step: 0.1 }, { key: 'throwing', min: 0, max: 0.5, step: 0.01 },
|
|
74
|
+
{ key: 'gravity', min: 1, max: 30, step: 0.1 }, { key: 'swingDamping', min: 0, max: 4, step: 0.01 }, { key: 'wind', min: 0, max: 2, step: 0.01 }, { key: 'tug', min: 0, max: 3, step: 0.01 },
|
|
75
|
+
{ key: 'glow', min: 0, max: 1, step: 0.01 }, { key: 'lamp', min: 0, max: 2, step: 0.01 },
|
|
76
|
+
{ key: 'autoplay', min: 0, max: 20, step: 0.5 },
|
|
77
|
+
{ key: 'pointerMode', options: ['none', ...POINTER_MODES] }, { key: 'pointerStrength', min: 0, max: 3, step: 0.01 }, { key: 'pointerRadius', min: 0.2, max: 4, step: 0.01 },
|
|
78
|
+
{ key: 'intensity', min: 0, max: 3, step: 0.01 }, { key: 'opacity', min: 0, max: 1, step: 0.01 },
|
|
79
|
+
{ key: 'lampColor', color: true }, { key: 'paperColor', color: true }, { key: 'rimColor', color: true }, { key: 'ringColor', color: true }, { key: 'pointerColor', color: true },
|
|
80
|
+
];
|
|
81
|
+
export const PRESETS = [
|
|
82
|
+
{ name: 'Night market', description: 'The default: a warm string, a gentle breeze.', patch: {} },
|
|
83
|
+
{ name: 'Still air', description: 'No wind, slow heavy swings, a long rope.', patch: { wind: 0.05, swingDamping: 0.35, gravity: 6, span: 10, sag: 0.6, spacing: 1.6 } },
|
|
84
|
+
{ name: 'Storm', description: 'Gusts, fast swings, lanterns close together.', patch: { wind: 1.8, swingDamping: 0.5, gravity: 14, spacing: 1.1, sag: 0.5, tug: 2 } },
|
|
85
|
+
{ name: 'Gallery wall', description: 'Taut rope, no sag, dim neighbours, a bright front.', patch: { sag: 0.02, wind: 0.15, glow: 0.12, lamp: 1.4, focusDrop: 0.8, focusLift: 1.2, spacing: 1.3 } },
|
|
86
|
+
];
|
|
87
|
+
const col = (c) => new THREE.Color(c);
|
|
88
|
+
const smooth = (a, b, x) => { const t = Math.min(1, Math.max(0, (x - a) / (b - a))); return t * t * (3 - 2 * t); };
|
|
89
|
+
function mulberry32(a) { return function () { a |= 0; a = (a + 0x6D2B79F5) | 0; let t = Math.imul(a ^ (a >>> 15), 1 | a); t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t; return ((t ^ (t >>> 14)) >>> 0) / 4294967296; }; }
|
|
90
|
+
export function createUniforms() {
|
|
91
|
+
return {
|
|
92
|
+
uTex: { value: null },
|
|
93
|
+
uGlow: { value: 0.35 }, uLamp: { value: 1 }, uIntensity: { value: 1 }, uOpacity: { value: 1 },
|
|
94
|
+
uLampColor: { value: col('#ffb86b') }, uPaperColor: { value: col('#f0dcc0') }, uRimColor: { value: col('#ffd9a6') }, uPointerColor: { value: col('#ffe6c2') },
|
|
95
|
+
uTime: { value: 0 },
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
export function applyConfig(u, c) {
|
|
99
|
+
const set = (k, v) => { if (v === undefined)
|
|
100
|
+
return; if (u[k].value && u[k].value.isColor) {
|
|
101
|
+
if (v.isColor)
|
|
102
|
+
u[k].value.copy(v);
|
|
103
|
+
else
|
|
104
|
+
u[k].value.set(v);
|
|
105
|
+
}
|
|
106
|
+
else
|
|
107
|
+
u[k].value = v; };
|
|
108
|
+
set('uGlow', c.glow);
|
|
109
|
+
set('uLamp', c.lamp);
|
|
110
|
+
set('uIntensity', c.intensity);
|
|
111
|
+
set('uOpacity', c.opacity);
|
|
112
|
+
set('uLampColor', c.lampColor);
|
|
113
|
+
set('uPaperColor', c.paperColor);
|
|
114
|
+
set('uRimColor', c.rimColor);
|
|
115
|
+
set('uPointerColor', c.pointerColor);
|
|
116
|
+
}
|
|
117
|
+
const fragHead = /* glsl */ `
|
|
118
|
+
layout(location = 0) out highp vec4 pc_fragColor;
|
|
119
|
+
#define gl_FragColor pc_fragColor
|
|
120
|
+
`;
|
|
121
|
+
const vert = /* glsl */ `
|
|
122
|
+
attribute float aIdx;
|
|
123
|
+
attribute vec4 aState; // lit (0..1), alpha, hover, phase
|
|
124
|
+
varying vec2 vUv; varying float vLayer; varying vec4 vState; varying vec3 vN; varying vec3 vV; varying vec3 vL;
|
|
125
|
+
void main(){
|
|
126
|
+
vUv = uv; vLayer = aIdx; vState = aState;
|
|
127
|
+
vec4 wp = instanceMatrix * vec4(position, 1.0);
|
|
128
|
+
vec4 mv = modelViewMatrix * wp;
|
|
129
|
+
vN = normalize(normalMatrix * mat3(instanceMatrix) * normal);
|
|
130
|
+
vV = -mv.xyz; vL = position; // lantern-local: the lamp sits at the centre
|
|
131
|
+
gl_Position = projectionMatrix * mv;
|
|
132
|
+
}
|
|
133
|
+
`;
|
|
134
|
+
const frag = /* glsl */ `
|
|
135
|
+
${fragHead}
|
|
136
|
+
precision highp sampler2DArray;
|
|
137
|
+
uniform sampler2DArray uTex;
|
|
138
|
+
uniform float uGlow, uLamp, uIntensity, uOpacity, uTime;
|
|
139
|
+
uniform vec3 uLampColor, uPaperColor, uRimColor, uPointerColor;
|
|
140
|
+
varying vec2 vUv; varying float vLayer; varying vec4 vState; varying vec3 vN; varying vec3 vV; varying vec3 vL;
|
|
141
|
+
void main(){
|
|
142
|
+
float lit = vState.x, alpha = vState.y, hover = vState.z;
|
|
143
|
+
// the picture wraps the front half (u 0.25..0.75 of the cylinder); paper on the back
|
|
144
|
+
float ux = fract(vUv.x + 0.5); // the cylinder's seam is at the back
|
|
145
|
+
float front = smoothstep(0.22, 0.27, ux) * (1.0 - smoothstep(0.73, 0.78, ux));
|
|
146
|
+
vec2 puv = vec2((ux - 0.25) * 2.0, vUv.y);
|
|
147
|
+
vec3 pic = texture(uTex, vec3(clamp(puv, 0.0, 1.0), vLayer)).rgb;
|
|
148
|
+
vec3 paper = uPaperColor * (0.96 + 0.04 * sin(vUv.x * 220.0)); // the paper's ribs
|
|
149
|
+
vec3 base = mix(paper, pic, front);
|
|
150
|
+
// light from inside: the lamp at the centre, brightest at mid height, falling to the rings
|
|
151
|
+
float inner = mix(uGlow, uLamp * uIntensity, lit);
|
|
152
|
+
float mid = 1.0 - 0.6 * pow(abs(vUv.y - 0.5) * 2.0, 2.0);
|
|
153
|
+
float flicker = 1.0 + lit * 0.05 * sin(uTime * 17.0 + vState.w * 10.0) * sin(uTime * 5.3);
|
|
154
|
+
vec3 N = normalize(vN); vec3 V = normalize(vV);
|
|
155
|
+
float ndv = abs(dot(N, V));
|
|
156
|
+
// translucent paper: light leaks most where we look through the paper at a grazing angle
|
|
157
|
+
float rim = pow(1.0 - ndv, 2.5);
|
|
158
|
+
vec3 c = base * (0.14 + inner * mid * flicker * 0.8) + uLampColor * inner * rim * 0.35 + uRimColor * rim * 0.06;
|
|
159
|
+
c += uPointerColor * hover * 0.25;
|
|
160
|
+
// the paper's weave against the light
|
|
161
|
+
c *= 0.975 + 0.025 * sin(vUv.x * 300.0) * sin(vUv.y * 120.0);
|
|
162
|
+
float a = alpha * uOpacity;
|
|
163
|
+
if (a < 0.003) discard;
|
|
164
|
+
gl_FragColor = vec4(c * a, a);
|
|
165
|
+
#include <tonemapping_fragment>
|
|
166
|
+
#include <colorspace_fragment>
|
|
167
|
+
}
|
|
168
|
+
`;
|
|
169
|
+
const haloVert = /* glsl */ `
|
|
170
|
+
varying vec2 vQ;
|
|
171
|
+
uniform vec3 uHaloPos; uniform float uHaloSize;
|
|
172
|
+
void main(){ vQ = position.xy; vec4 mv = modelViewMatrix * vec4(uHaloPos, 1.0); mv.xy += position.xy * uHaloSize; gl_Position = projectionMatrix * mv; }
|
|
173
|
+
`;
|
|
174
|
+
const haloFrag = /* glsl */ `
|
|
175
|
+
${fragHead}
|
|
176
|
+
uniform vec3 uLampColor; uniform float uHalo, uOpacity;
|
|
177
|
+
varying vec2 vQ;
|
|
178
|
+
void main(){ float r = length(vQ); float g = exp(-r * r * 4.0) * (1.0 - smoothstep(0.7, 1.0, r)); gl_FragColor = vec4(uLampColor * g * uHalo * 0.35 * uOpacity, 0.0);
|
|
179
|
+
#include <tonemapping_fragment>
|
|
180
|
+
#include <colorspace_fragment> }
|
|
181
|
+
`;
|
|
182
|
+
// ---------------------------------------------------------------- images: cover-fit array texture
|
|
183
|
+
// ---------------------------------------------------------------- build
|
|
184
|
+
export function build(u, c) { return withLean(buildGallery(u, c), c); }
|
|
185
|
+
function buildGallery(u, c) {
|
|
186
|
+
const MAX = 32;
|
|
187
|
+
const r = c.radius, h = (Math.PI * r) / c.aspect; // the picture spans the front half-circumference
|
|
188
|
+
const geo = new THREE.CylinderGeometry(r, r, h, 48, 1, true);
|
|
189
|
+
const aIdx = new Float32Array(MAX);
|
|
190
|
+
for (let i = 0; i < MAX; i++)
|
|
191
|
+
aIdx[i] = i;
|
|
192
|
+
geo.setAttribute('aIdx', new THREE.InstancedBufferAttribute(aIdx, 1));
|
|
193
|
+
const state = new Float32Array(MAX * 4);
|
|
194
|
+
const aState = new THREE.InstancedBufferAttribute(state, 4);
|
|
195
|
+
aState.setUsage(THREE.DynamicDrawUsage);
|
|
196
|
+
geo.setAttribute('aState', aState);
|
|
197
|
+
const mat = new THREE.ShaderMaterial({ uniforms: u, vertexShader: vert, fragmentShader: frag, glslVersion: THREE.GLSL3, side: THREE.DoubleSide, transparent: true, depthWrite: true, premultipliedAlpha: true });
|
|
198
|
+
const lanterns = new THREE.InstancedMesh(geo, mat, MAX);
|
|
199
|
+
lanterns.count = 0;
|
|
200
|
+
lanterns.frustumCulled = false;
|
|
201
|
+
lanterns.userData.pick = 'lanterns';
|
|
202
|
+
// bamboo rings: two per lantern, one instanced mesh
|
|
203
|
+
const ringGeo = new THREE.TorusGeometry(r * 1.02, r * 0.045, 8, 40);
|
|
204
|
+
const ringMat = new THREE.MeshStandardMaterial({ color: c.ringColor, roughness: 0.8, metalness: 0.05 });
|
|
205
|
+
const rings = new THREE.InstancedMesh(ringGeo, ringMat, MAX * 2);
|
|
206
|
+
rings.count = 0;
|
|
207
|
+
rings.frustumCulled = false;
|
|
208
|
+
rings.raycast = () => { };
|
|
209
|
+
// the rope (a catenary) and the cords
|
|
210
|
+
const ropeMat = new THREE.LineBasicMaterial({ color: '#5a4a3a', transparent: true, opacity: 0.9 });
|
|
211
|
+
const ropeGeo = new THREE.BufferGeometry();
|
|
212
|
+
ropeGeo.setAttribute('position', new THREE.BufferAttribute(new Float32Array(64 * 3), 3));
|
|
213
|
+
const rope = new THREE.Line(ropeGeo, ropeMat);
|
|
214
|
+
const cordGeo = new THREE.BufferGeometry();
|
|
215
|
+
cordGeo.setAttribute('position', new THREE.BufferAttribute(new Float32Array(MAX * 2 * 3), 3));
|
|
216
|
+
const cords = new THREE.LineSegments(cordGeo, ropeMat);
|
|
217
|
+
// the lit lantern: a real point light inside it, and a soft halo
|
|
218
|
+
const haloU = { uHaloPos: { value: new THREE.Vector3() }, uHaloSize: { value: r * 3.2 }, uHalo: { value: 1 }, uLampColor: u.uLampColor, uOpacity: u.uOpacity };
|
|
219
|
+
const halo = new THREE.Mesh(new THREE.PlaneGeometry(2, 2), new THREE.ShaderMaterial({ uniforms: haloU, vertexShader: haloVert, fragmentShader: haloFrag, glslVersion: THREE.GLSL3, transparent: true, depthWrite: false, blending: THREE.AdditiveBlending, premultipliedAlpha: true }));
|
|
220
|
+
halo.frustumCulled = false;
|
|
221
|
+
halo.raycast = () => { };
|
|
222
|
+
halo.renderOrder = 4;
|
|
223
|
+
rope.raycast = () => { };
|
|
224
|
+
cords.raycast = () => { }; // only the lanterns take clicks
|
|
225
|
+
const object = new THREE.Group();
|
|
226
|
+
object.add(rope, cords, rings, lanterns, halo);
|
|
227
|
+
const rnd = mulberry32(5);
|
|
228
|
+
const st = {
|
|
229
|
+
cfg: { ...c }, count: 0, s: 0, v: 0, target: 0, dragging: false, dragS0: 0, dragX0: 0, lastDx: 0,
|
|
230
|
+
th: new Float32Array(MAX), om: new Float32Array(MAX), // pendulum angle (swing in z) and its rate
|
|
231
|
+
tw: new Float32Array(MAX), tv: new Float32Array(MAX), // torsion twist about the cord
|
|
232
|
+
phase: new Float32Array(MAX).map(() => rnd() * 6.283), hoverT: new Float32Array(MAX), hover: -1,
|
|
233
|
+
time: 0, autoT: 0, pointer: null, prevPointer: null, tugQueue: [], gust: 0, gustT: 0,
|
|
234
|
+
};
|
|
235
|
+
const M = new THREE.Matrix4(), P = new THREE.Vector3(), Q = new THREE.Quaternion(), S = new THREE.Vector3(), E = new THREE.Euler();
|
|
236
|
+
const wrap = (d, n) => n > 1 ? ((d + n / 2) % n + n) % n - n / 2 : d;
|
|
237
|
+
function layout(dt) {
|
|
238
|
+
const k = st.cfg, n = st.count;
|
|
239
|
+
if (!n)
|
|
240
|
+
return;
|
|
241
|
+
const pitch = 2 * r * k.spacing;
|
|
242
|
+
const ropeTop = 0.9; // rope height (gallery units) at the posts
|
|
243
|
+
const rp = ropeGeo.attributes.position.array;
|
|
244
|
+
for (let i = 0; i < 64; i++) {
|
|
245
|
+
const x = -k.span / 2 + (i / 63) * k.span;
|
|
246
|
+
rp[i * 3] = x;
|
|
247
|
+
rp[i * 3 + 1] = ropeTop - k.sag * (1 - (x * x) / (k.span * k.span / 4));
|
|
248
|
+
rp[i * 3 + 2] = 0;
|
|
249
|
+
}
|
|
250
|
+
ropeGeo.attributes.position.needsUpdate = true;
|
|
251
|
+
const cp = cordGeo.attributes.position.array;
|
|
252
|
+
let litPos = null;
|
|
253
|
+
for (let i = 0; i < n; i++) {
|
|
254
|
+
const d = wrap(i - st.s, n);
|
|
255
|
+
const ad = Math.abs(d);
|
|
256
|
+
const focus = 1 - smooth(0, 0.9, ad);
|
|
257
|
+
const x = d * pitch;
|
|
258
|
+
const ry = ropeTop - k.sag * Math.max(0, 1 - (x * x) / (k.span * k.span / 4));
|
|
259
|
+
const L = k.cord + k.focusDrop * focus; // cord length: the front one hangs lower
|
|
260
|
+
// pendulum: swing angle th about the rope (x axis): the lantern swings in z; twist about the cord
|
|
261
|
+
const th = st.th[i], tw = st.tw[i];
|
|
262
|
+
const bx = x, by = ry - L * Math.cos(th) - h / 2, bz = L * Math.sin(th) + k.focusLift * focus;
|
|
263
|
+
P.set(bx, by, bz);
|
|
264
|
+
E.set(th, tw, 0, 'XYZ');
|
|
265
|
+
Q.setFromEuler(E);
|
|
266
|
+
S.set(1, 1, 1);
|
|
267
|
+
M.compose(P, Q, S);
|
|
268
|
+
lanterns.setMatrixAt(i, M);
|
|
269
|
+
// rings at the top and bottom of the lantern, in its frame
|
|
270
|
+
const top = new THREE.Vector3(0, h / 2, 0).applyQuaternion(Q).add(P), bot = new THREE.Vector3(0, -h / 2, 0).applyQuaternion(Q).add(P);
|
|
271
|
+
const RQ = Q.clone().multiply(new THREE.Quaternion().setFromEuler(new THREE.Euler(Math.PI / 2, 0, 0)));
|
|
272
|
+
M.compose(top, RQ, S);
|
|
273
|
+
rings.setMatrixAt(i * 2, M);
|
|
274
|
+
M.compose(bot, RQ, S);
|
|
275
|
+
rings.setMatrixAt(i * 2 + 1, M);
|
|
276
|
+
cp.set([x, ry, 0, top.x, top.y, top.z], i * 6);
|
|
277
|
+
const alpha = (1 - smooth(k.visible - 0.7, k.visible, ad)) * (Math.abs(x) < k.span / 2 - r ? 1 : 0);
|
|
278
|
+
state[i * 4] = focus;
|
|
279
|
+
state[i * 4 + 1] = alpha;
|
|
280
|
+
state[i * 4 + 2] = st.hoverT[i];
|
|
281
|
+
state[i * 4 + 3] = st.phase[i];
|
|
282
|
+
if (focus > 0) {
|
|
283
|
+
if (!litPos) {
|
|
284
|
+
litPos = new THREE.Vector3();
|
|
285
|
+
litPos.w = 0;
|
|
286
|
+
}
|
|
287
|
+
litPos.addScaledVector(P, focus);
|
|
288
|
+
litPos.w += focus;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
for (let i = n; i < MAX; i++)
|
|
292
|
+
cp.set([0, 0, 0, 0, 0, 0], i * 6);
|
|
293
|
+
lanterns.count = n;
|
|
294
|
+
rings.count = n * 2;
|
|
295
|
+
cordGeo.setDrawRange(0, n * 2);
|
|
296
|
+
lanterns.computeBoundingSphere(); // the lanterns move every frame: keep the click test's bounds current
|
|
297
|
+
lanterns.instanceMatrix.needsUpdate = true;
|
|
298
|
+
rings.instanceMatrix.needsUpdate = true;
|
|
299
|
+
aState.needsUpdate = true;
|
|
300
|
+
cordGeo.attributes.position.needsUpdate = true;
|
|
301
|
+
if (litPos && litPos.w > 0) {
|
|
302
|
+
litPos.multiplyScalar(1 / litPos.w);
|
|
303
|
+
haloU.uHaloPos.value.copy(litPos);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
const controls = {
|
|
307
|
+
next() { st.target = Math.round(st.target) + 1; st.autoT = 0; tug(+1); },
|
|
308
|
+
prev() { st.target = Math.round(st.target) - 1; st.autoT = 0; tug(-1); },
|
|
309
|
+
goTo(i) { const n = st.count; if (!n)
|
|
310
|
+
return; const cur = ((Math.round(st.s) % n) + n) % n; const dd = wrap(i - cur, n); st.target = Math.round(st.s) + dd; st.autoT = 0; tug(Math.sign(dd) || 1); },
|
|
311
|
+
jump(i) { st.s = st.target = i; st.v = 0; },
|
|
312
|
+
get index() { const n = st.count; return n ? ((Math.round(st.s) % n) + n) % n : 0; },
|
|
313
|
+
get count() { return st.count; },
|
|
314
|
+
get busy() { return Math.abs(st.target - st.s) > 0.02; },
|
|
315
|
+
setTexture(tex, count) { if (u.uTex.value)
|
|
316
|
+
u.uTex.value.dispose(); u.uTex.value = tex; st.count = Math.min(count, MAX); layout(0); },
|
|
317
|
+
dragBegin(x) { st.dragging = true; st.dragS0 = st.s; st.dragX0 = x; st.v = 0; },
|
|
318
|
+
dragMove(x) { if (!st.dragging)
|
|
319
|
+
return; const ns = st.dragS0 - (x - st.dragX0) / (2 * r * st.cfg.spacing); st.lastDx = ns - st.s; st.s = ns; },
|
|
320
|
+
dragEnd(dt) { if (!st.dragging)
|
|
321
|
+
return; st.dragging = false; st.v = st.lastDx / Math.max(dt, 1 / 120); st.target = Math.round(st.s + st.v * st.cfg.throwing); tug(Math.sign(st.v) || 1); },
|
|
322
|
+
get dragging() { return st.dragging; },
|
|
323
|
+
hover(i) { st.hover = i; },
|
|
324
|
+
};
|
|
325
|
+
/** a tug on the rope: an impulse that runs down the line, delayed by distance from the front */
|
|
326
|
+
function tug(dir) { st.tugQueue.push({ t: 0, dir }); }
|
|
327
|
+
object.userData.gallery = controls;
|
|
328
|
+
return {
|
|
329
|
+
object, controls, lanterns, materials: [mat, ringMat, ropeMat, halo.material],
|
|
330
|
+
/** The picture under a click / the cursor: the lantern hit (a visible one), or undefined. */
|
|
331
|
+
pickPicture(hit) { const i = hit.object === lanterns ? hit.instanceId : undefined; return i !== undefined && i < st.count && state[i * 4 + 1] > 0.05 ? i : undefined; },
|
|
332
|
+
apply(cfg) { Object.assign(st.cfg, cfg); applyConfig(u, cfg); if (cfg.ringColor)
|
|
333
|
+
ringMat.color.set(cfg.ringColor); },
|
|
334
|
+
/** pointer: { x, y } on the z = 0 plane in gallery units, or null */
|
|
335
|
+
update(dt, pointer) {
|
|
336
|
+
dt = Math.min(dt, 0.05);
|
|
337
|
+
st.time += dt;
|
|
338
|
+
u.uTime.value = st.time;
|
|
339
|
+
const k = st.cfg, n = st.count;
|
|
340
|
+
if (!st.dragging) {
|
|
341
|
+
const sub = 4, hh = dt / sub;
|
|
342
|
+
for (let q = 0; q < sub; q++) {
|
|
343
|
+
st.v += (k.stiffness * (st.target - st.s) - k.damping * st.v) * hh;
|
|
344
|
+
st.s += st.v * hh;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
if (k.autoplay > 0 && n > 1 && !pointer && !st.dragging) {
|
|
348
|
+
st.autoT += dt;
|
|
349
|
+
if (st.autoT >= k.autoplay)
|
|
350
|
+
controls.next();
|
|
351
|
+
}
|
|
352
|
+
// the breeze: a slow gust field plus the cursor's wake
|
|
353
|
+
st.gustT += dt;
|
|
354
|
+
if (st.gustT > 3 + rnd() * 4) {
|
|
355
|
+
st.gustT = 0;
|
|
356
|
+
st.gust = (rnd() - 0.3) * k.wind;
|
|
357
|
+
}
|
|
358
|
+
const breeze = k.wind * (0.6 * Math.sin(st.time * 0.37) * Math.sin(st.time * 0.11 + 1.3) + 0.4 * Math.sin(st.time * 0.9)) + st.gust * Math.exp(-st.gustT * 0.8);
|
|
359
|
+
let cursorWind = 0, cx = 0;
|
|
360
|
+
if (pointer && st.prevPointer && k.pointerMode === 'breeze') {
|
|
361
|
+
cursorWind = (pointer.x - st.prevPointer.x) / dt * 0.35 * k.pointerStrength;
|
|
362
|
+
cx = pointer.x;
|
|
363
|
+
}
|
|
364
|
+
st.prevPointer = pointer ? { ...pointer } : null;
|
|
365
|
+
// pendulums (semi-implicit Euler), with the tugs running down the rope
|
|
366
|
+
for (const tq of st.tugQueue)
|
|
367
|
+
tq.t += dt;
|
|
368
|
+
const pitch = 2 * r * k.spacing;
|
|
369
|
+
for (let i = 0; i < n; i++) {
|
|
370
|
+
const d = wrap(i - st.s, n);
|
|
371
|
+
const L = k.cord + k.focusDrop * (1 - smooth(0, 0.9, Math.abs(d)));
|
|
372
|
+
let F = breeze * 0.9 * (0.7 + 0.3 * Math.sin(st.phase[i] + st.time * 0.5));
|
|
373
|
+
if (cursorWind)
|
|
374
|
+
F += cursorWind * Math.exp(-Math.pow((d * pitch - cx) / k.pointerRadius, 2));
|
|
375
|
+
for (const tq of st.tugQueue) {
|
|
376
|
+
const arrive = Math.abs(d) * 0.09;
|
|
377
|
+
const dtq = tq.t - arrive;
|
|
378
|
+
if (dtq > 0 && dtq < 0.25)
|
|
379
|
+
F += tq.dir * k.tug * 6.0 * Math.sin(dtq / 0.25 * Math.PI);
|
|
380
|
+
}
|
|
381
|
+
// the scroll itself drags the lanterns through the air (rope acceleration)
|
|
382
|
+
F -= st.v * 0.6;
|
|
383
|
+
const acc = -(k.gravity / Math.max(0.1, L)) * Math.sin(st.th[i]) - k.swingDamping * st.om[i] + F;
|
|
384
|
+
st.om[i] += acc * dt;
|
|
385
|
+
st.th[i] += st.om[i] * dt;
|
|
386
|
+
const tacc = -12 * st.tw[i] - 1.5 * st.tv[i] + F * 0.15 * Math.sin(st.phase[i] * 3.0);
|
|
387
|
+
st.tv[i] += tacc * dt;
|
|
388
|
+
st.tw[i] += st.tv[i] * dt;
|
|
389
|
+
st.hoverT[i] += (((st.hover === i && k.pointerMode === 'glow') ? 1 : 0) - st.hoverT[i]) * (1 - Math.exp(-dt * 8));
|
|
390
|
+
}
|
|
391
|
+
st.tugQueue = st.tugQueue.filter((tq) => tq.t < 4);
|
|
392
|
+
// the lit lantern's lamp: the real light follows the front lantern
|
|
393
|
+
haloU.uHalo.value = k.lamp * k.intensity;
|
|
394
|
+
layout(dt);
|
|
395
|
+
},
|
|
396
|
+
dispose() { geo.dispose(); ringGeo.dispose(); ropeGeo.dispose(); cordGeo.dispose(); halo.geometry.dispose(); mat.dispose(); ringMat.dispose(); ropeMat.dispose(); halo.material.dispose(); if (u.uTex.value)
|
|
397
|
+
u.uTex.value.dispose(); },
|
|
398
|
+
};
|
|
399
|
+
}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import * as THREE from 'three';
|
|
2
|
+
export declare const catalog: {
|
|
3
|
+
key: string;
|
|
4
|
+
name: string;
|
|
5
|
+
camera: {
|
|
6
|
+
position: number[];
|
|
7
|
+
target: number[];
|
|
8
|
+
};
|
|
9
|
+
description: string;
|
|
10
|
+
tags: string[];
|
|
11
|
+
};
|
|
12
|
+
export declare const DEFAULTS: {
|
|
13
|
+
type: string;
|
|
14
|
+
enabled: boolean;
|
|
15
|
+
lean: number;
|
|
16
|
+
imageUrls: any[];
|
|
17
|
+
autoplay: number;
|
|
18
|
+
intensity: number;
|
|
19
|
+
opacity: number;
|
|
20
|
+
aspect: number;
|
|
21
|
+
width: number;
|
|
22
|
+
grains: number;
|
|
23
|
+
layout: string;
|
|
24
|
+
spacing: number;
|
|
25
|
+
depth: number;
|
|
26
|
+
visible: number;
|
|
27
|
+
shape: number;
|
|
28
|
+
stiffness: number;
|
|
29
|
+
damping: number;
|
|
30
|
+
throwing: number;
|
|
31
|
+
changeTime: number;
|
|
32
|
+
wave: number;
|
|
33
|
+
slant: number;
|
|
34
|
+
lift: number;
|
|
35
|
+
particleSize: number;
|
|
36
|
+
faded: number;
|
|
37
|
+
grain: number;
|
|
38
|
+
pointerMode: string;
|
|
39
|
+
pointerStrength: number;
|
|
40
|
+
pointerRadius: number;
|
|
41
|
+
};
|
|
42
|
+
export declare const STRUCTURAL: string[];
|
|
43
|
+
export declare const POINTER_MODES: string[];
|
|
44
|
+
export declare const GUI: ({
|
|
45
|
+
key: string;
|
|
46
|
+
options: string[];
|
|
47
|
+
tip: string;
|
|
48
|
+
min?: undefined;
|
|
49
|
+
max?: undefined;
|
|
50
|
+
step?: undefined;
|
|
51
|
+
} | {
|
|
52
|
+
key: string;
|
|
53
|
+
min: number;
|
|
54
|
+
max: number;
|
|
55
|
+
step: number;
|
|
56
|
+
tip: string;
|
|
57
|
+
options?: undefined;
|
|
58
|
+
} | {
|
|
59
|
+
key: string;
|
|
60
|
+
min: number;
|
|
61
|
+
max: number;
|
|
62
|
+
step: number;
|
|
63
|
+
options?: undefined;
|
|
64
|
+
} | {
|
|
65
|
+
key: string;
|
|
66
|
+
options: string[];
|
|
67
|
+
min?: undefined;
|
|
68
|
+
max?: undefined;
|
|
69
|
+
step?: undefined;
|
|
70
|
+
})[];
|
|
71
|
+
export declare const PRESETS: ({
|
|
72
|
+
name: string;
|
|
73
|
+
description: string;
|
|
74
|
+
patch: {
|
|
75
|
+
wave?: undefined;
|
|
76
|
+
lift?: undefined;
|
|
77
|
+
changeTime?: undefined;
|
|
78
|
+
particleSize?: undefined;
|
|
79
|
+
grains?: undefined;
|
|
80
|
+
slant?: undefined;
|
|
81
|
+
};
|
|
82
|
+
} | {
|
|
83
|
+
name: string;
|
|
84
|
+
description: string;
|
|
85
|
+
patch: {
|
|
86
|
+
wave: number;
|
|
87
|
+
lift: number;
|
|
88
|
+
changeTime: number;
|
|
89
|
+
particleSize?: undefined;
|
|
90
|
+
grains?: undefined;
|
|
91
|
+
slant?: undefined;
|
|
92
|
+
};
|
|
93
|
+
} | {
|
|
94
|
+
name: string;
|
|
95
|
+
description: string;
|
|
96
|
+
patch: {
|
|
97
|
+
particleSize: number;
|
|
98
|
+
grains: number;
|
|
99
|
+
wave: number;
|
|
100
|
+
slant: number;
|
|
101
|
+
lift?: undefined;
|
|
102
|
+
changeTime?: undefined;
|
|
103
|
+
};
|
|
104
|
+
})[];
|
|
105
|
+
export declare function createUniforms(): {
|
|
106
|
+
uTex: {
|
|
107
|
+
value: any;
|
|
108
|
+
};
|
|
109
|
+
uS: {
|
|
110
|
+
value: number;
|
|
111
|
+
};
|
|
112
|
+
uCount: {
|
|
113
|
+
value: number;
|
|
114
|
+
};
|
|
115
|
+
uTime: {
|
|
116
|
+
value: number;
|
|
117
|
+
};
|
|
118
|
+
uAct: {
|
|
119
|
+
value: Float32Array<ArrayBuffer>;
|
|
120
|
+
};
|
|
121
|
+
uSpacing: {
|
|
122
|
+
value: number;
|
|
123
|
+
};
|
|
124
|
+
uDepth: {
|
|
125
|
+
value: number;
|
|
126
|
+
};
|
|
127
|
+
uVisible: {
|
|
128
|
+
value: number;
|
|
129
|
+
};
|
|
130
|
+
uWave: {
|
|
131
|
+
value: number;
|
|
132
|
+
};
|
|
133
|
+
uSlant: {
|
|
134
|
+
value: number;
|
|
135
|
+
};
|
|
136
|
+
uLift: {
|
|
137
|
+
value: number;
|
|
138
|
+
};
|
|
139
|
+
uSize: {
|
|
140
|
+
value: number;
|
|
141
|
+
};
|
|
142
|
+
uFaded: {
|
|
143
|
+
value: number;
|
|
144
|
+
};
|
|
145
|
+
uGrain: {
|
|
146
|
+
value: number;
|
|
147
|
+
};
|
|
148
|
+
uIntensity: {
|
|
149
|
+
value: number;
|
|
150
|
+
};
|
|
151
|
+
uOpacity: {
|
|
152
|
+
value: number;
|
|
153
|
+
};
|
|
154
|
+
uW: {
|
|
155
|
+
value: number;
|
|
156
|
+
};
|
|
157
|
+
uH: {
|
|
158
|
+
value: number;
|
|
159
|
+
};
|
|
160
|
+
uGx: {
|
|
161
|
+
value: number;
|
|
162
|
+
};
|
|
163
|
+
uGy: {
|
|
164
|
+
value: number;
|
|
165
|
+
};
|
|
166
|
+
uDpr: {
|
|
167
|
+
value: number;
|
|
168
|
+
};
|
|
169
|
+
uVh: {
|
|
170
|
+
value: number;
|
|
171
|
+
};
|
|
172
|
+
uPointer: {
|
|
173
|
+
value: THREE.Vector3;
|
|
174
|
+
};
|
|
175
|
+
uPointerActive: {
|
|
176
|
+
value: number;
|
|
177
|
+
};
|
|
178
|
+
uPointerMode: {
|
|
179
|
+
value: number;
|
|
180
|
+
};
|
|
181
|
+
uPointerStrength: {
|
|
182
|
+
value: number;
|
|
183
|
+
};
|
|
184
|
+
uPointerRadius: {
|
|
185
|
+
value: number;
|
|
186
|
+
};
|
|
187
|
+
uPlace: {
|
|
188
|
+
value: THREE.Matrix4[];
|
|
189
|
+
};
|
|
190
|
+
};
|
|
191
|
+
export declare function applyConfig(u: any, c: any): void;
|
|
192
|
+
export declare function build(u: any, c: any): any;
|
|
193
|
+
//# sourceMappingURL=particleShift.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"particleShift.d.ts","sourceRoot":"","sources":["../../../../src/components/gallery/looks/particleShift.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,eAAO,MAAM,OAAO;;;;;;;;;CAEiF,CAAC;AAEtG,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAQpB,CAAC;AACF,eAAO,MAAM,UAAU,UAA6C,CAAC;AACrE,eAAO,MAAM,aAAa,UAAY,CAAC;AACvC,eAAO,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;IAUf,CAAC;AACF,eAAO,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAInB,CAAC;AAEF,wBAAgB,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAU7B;AACD,wBAAgB,WAAW,CAAC,CAAC,KAAA,EAAE,CAAC,KAAA,QAM/B;AA4HD,wBAAgB,KAAK,CAAC,CAAC,KAAA,EAAE,CAAC,KAAA,OAA6C"}
|