@3driseai/3drise-viewer 0.1.40 → 0.1.42
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.map +1 -1
- package/dist/animationsV2/ClipsRuntime.js +9 -5
- package/dist/animationsV2/clipUtils.d.ts +9 -0
- package/dist/animationsV2/clipUtils.d.ts.map +1 -1
- package/dist/animationsV2/clipUtils.js +11 -2
- package/dist/animationsV2/normalize.d.ts.map +1 -1
- package/dist/animationsV2/normalize.js +2 -0
- package/dist/animationsV2/types.d.ts +4 -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/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 +11 -5
- 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.map +1 -1
- package/dist/constants.js +2 -0
- 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/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/UiLayers.d.ts +17 -1
- package/dist/ui/UiLayers.d.ts.map +1 -1
- package/dist/ui/UiLayers.js +76 -3
- package/dist/ui/index.d.ts +2 -2
- package/dist/ui/index.d.ts.map +1 -1
- package/dist/ui/index.js +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
// The approved lab module, verbatim but for its import paths and the lab's picture loader (Claude outputs/gallery-lab/
|
|
2
|
+
// silk.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.silk) do not carry; its own autoplay is never used.
|
|
4
|
+
// silk — every picture is a sheet of cloth hanging from a rail: a mass-spring cloth (Verlet, pinned along
|
|
5
|
+
// the top, structural + shear + bend constraints) in a breeze. Light goes through the fabric: a key light
|
|
6
|
+
// lights the front, and where it falls on the back the picture shows through as a warm translucency, the
|
|
7
|
+
// folds shading themselves. Change: the outgoing sheet is let go at the rail and falls out of frame in a
|
|
8
|
+
// slow billow; the incoming one drops from the rail and swings into stillness. Neighbours hang at depth.
|
|
9
|
+
import * as THREE from 'three';
|
|
10
|
+
import { fragHead, col, smooth, mulberry32, createScroll, sliceTextures, withLean } from '../kit/galleryKit.js';
|
|
11
|
+
import { createLayout, LAYOUT_GUI, LAYOUT_KEYS } from '../kit/galleryKit.js';
|
|
12
|
+
export const catalog = { key: 'silk', name: 'Silk', camera: { position: [0.2, -0.1, 5.4], target: [0, -0.1, 0] },
|
|
13
|
+
description: 'Pictures printed on sheets of silk hanging from a rail, each a cloth simulation in a breeze lit by the scene with a silk sheen; a change lets the sheet fall and drops the next from the rail. Use for fashion, textiles, soft and elegant showcases.',
|
|
14
|
+
tags: ['gallery', 'silk', 'cloth', 'fabric', 'translucency', 'navigation', 'interactive'] };
|
|
15
|
+
export const DEFAULTS = {
|
|
16
|
+
type: 'silk', enabled: true, lean: 1, imageUrls: [], autoplay: 0, intensity: 1, opacity: 1,
|
|
17
|
+
aspect: 1.4, width: 2.2, resolution: 22, // structural
|
|
18
|
+
layout: 'row', spacing: 1.3, depth: 0.9, visible: 2.2, shape: 1, dim: 0.22,
|
|
19
|
+
stiffness: 30, damping: 8, throwing: 0.12,
|
|
20
|
+
wind: 0.35, gravity: 9, drag: 0.985, iterations: 6, fallTime: 2.2,
|
|
21
|
+
sheen: 0.6,
|
|
22
|
+
pointerMode: 'breath', pointerStrength: 1, pointerRadius: 0.8, pointerColor: '#ffd9a6',
|
|
23
|
+
};
|
|
24
|
+
export const STRUCTURAL = ['imageUrls', 'aspect', 'width', 'resolution'];
|
|
25
|
+
export const POINTER_MODES = ['breath', 'touch'];
|
|
26
|
+
export const GUI = [
|
|
27
|
+
{ key: 'lean', min: 0, max: 3, step: 0.01, tip: 'The gallery turns toward the cursor' },
|
|
28
|
+
{ key: 'aspect', min: 0.6, max: 2.5, step: 0.01 }, { key: 'width', min: 1, max: 4, step: 0.01 }, { key: 'resolution', min: 8, max: 40, step: 1 },
|
|
29
|
+
...LAYOUT_GUI, { key: 'dim', min: 0, max: 1, step: 0.01 },
|
|
30
|
+
{ key: 'stiffness', min: 5, max: 120, step: 1 }, { key: 'damping', min: 2, max: 30, step: 0.1 },
|
|
31
|
+
{ key: 'wind', min: 0, max: 3, step: 0.01 }, { key: 'gravity', min: 1, max: 30, step: 0.1 }, { key: 'drag', min: 0.9, max: 0.999, step: 0.001 }, { key: 'iterations', min: 1, max: 12, step: 1 }, { key: 'fallTime', min: 0.5, max: 6, step: 0.1 },
|
|
32
|
+
{ key: 'sheen', min: 0, max: 1, step: 0.01 },
|
|
33
|
+
{ key: 'autoplay', min: 0, max: 20, step: 0.5 },
|
|
34
|
+
{ key: 'pointerMode', options: ['none', ...POINTER_MODES] }, { key: 'pointerStrength', min: 0, max: 3, step: 0.01 }, { key: 'pointerRadius', min: 0.2, max: 3, step: 0.01 },
|
|
35
|
+
{ key: 'intensity', min: 0, max: 3, step: 0.01 }, { key: 'opacity', min: 0, max: 1, step: 0.01 },
|
|
36
|
+
{ key: 'pointerColor', color: true },
|
|
37
|
+
];
|
|
38
|
+
export const PRESETS = [
|
|
39
|
+
{ name: 'Breeze', description: 'The default.', patch: {} },
|
|
40
|
+
{ name: 'Still', description: 'No wind: heavy sheets, slow falls.', patch: { wind: 0.05, gravity: 6, fallTime: 3.5, } },
|
|
41
|
+
{ name: 'Gale', description: 'Strong wind, light fabric.', patch: { wind: 2.2, gravity: 7, drag: 0.992 } },
|
|
42
|
+
];
|
|
43
|
+
export function createUniforms() {
|
|
44
|
+
return {
|
|
45
|
+
uTex: { value: null }, uKey: { value: new THREE.Vector3(0.5, 0.6, 0.8).normalize() }, uKeyColor: { value: col('#fff2e0') }, uBackColor: { value: col('#ffd3a8') },
|
|
46
|
+
uTrans: { value: 0.7 }, uSheen: { value: 0.5 }, uIntensity: { value: 1 }, uOpacity: { value: 1 }, uPointerColor: { value: col('#ffd9a6') },
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
export function applyConfig(u, c) {
|
|
50
|
+
const set = (k, v) => { if (v === undefined)
|
|
51
|
+
return; if (u[k].value && u[k].value.isColor) {
|
|
52
|
+
if (v.isColor)
|
|
53
|
+
u[k].value.copy(v);
|
|
54
|
+
else
|
|
55
|
+
u[k].value.set(v);
|
|
56
|
+
}
|
|
57
|
+
else
|
|
58
|
+
u[k].value = v; };
|
|
59
|
+
set('uTrans', c.translucency);
|
|
60
|
+
set('uSheen', c.sheen);
|
|
61
|
+
set('uIntensity', c.intensity);
|
|
62
|
+
set('uOpacity', c.opacity);
|
|
63
|
+
set('uKeyColor', c.keyColor);
|
|
64
|
+
set('uBackColor', c.backColor);
|
|
65
|
+
set('uPointerColor', c.pointerColor);
|
|
66
|
+
if (c.keyAngle !== undefined) {
|
|
67
|
+
const a = c.keyAngle * Math.PI / 180;
|
|
68
|
+
u.uKey.value.set(Math.sin(a) * 0.8, 0.55, Math.cos(a) * 0.8).normalize();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
const vert = /* glsl */ `
|
|
72
|
+
varying vec2 vUv; varying vec3 vN; varying vec3 vV; varying vec3 vW;
|
|
73
|
+
void main(){ vUv = uv; vN = normalize(normalMatrix * normal); vec4 mv = modelViewMatrix * vec4(position, 1.0); vV = -mv.xyz; vW = (modelMatrix * vec4(position, 1.0)).xyz; gl_Position = projectionMatrix * mv; }
|
|
74
|
+
`;
|
|
75
|
+
const frag = /* glsl */ `
|
|
76
|
+
${fragHead}
|
|
77
|
+
precision highp sampler2DArray;
|
|
78
|
+
uniform sampler2DArray uTex; uniform float uLayer, uDimK, uFade, uTrans, uSheen, uIntensity, uOpacity, uHover;
|
|
79
|
+
uniform vec3 uKey, uKeyColor, uBackColor, uPointerColor;
|
|
80
|
+
varying vec2 vUv; varying vec3 vN; varying vec3 vV;
|
|
81
|
+
void main(){
|
|
82
|
+
vec3 pic = texture(uTex, vec3(vUv, uLayer)).rgb;
|
|
83
|
+
vec3 N = normalize(vN); if (!gl_FrontFacing) N = -N;
|
|
84
|
+
vec3 V = normalize(vV); vec3 L = normalize((viewMatrix * vec4(uKey, 0.0)).xyz);
|
|
85
|
+
float ndl = dot(N, L);
|
|
86
|
+
float front = max(ndl, 0.0);
|
|
87
|
+
float back = max(-ndl, 0.0); // light on the far side: comes through the weave
|
|
88
|
+
float wrapL = 0.5 + 0.5 * ndl;
|
|
89
|
+
vec3 diffuse = pic * (0.12 + 0.95 * front) * uKeyColor;
|
|
90
|
+
vec3 through = pic * uBackColor * back * uTrans * 0.9;
|
|
91
|
+
// silk sheen: an anisotropic-ish highlight along the hang direction, soft
|
|
92
|
+
vec3 Hh = normalize(L + V); float spec = pow(max(dot(N, Hh), 0.0), 24.0) * uSheen * 0.35;
|
|
93
|
+
vec3 c = (diffuse + through + uKeyColor * spec + pic * wrapL * 0.08) * uDimK;
|
|
94
|
+
c += uPointerColor * uHover * 0.2;
|
|
95
|
+
float a = uOpacity * uFade;
|
|
96
|
+
if (a < 0.003) discard;
|
|
97
|
+
gl_FragColor = vec4(c * uIntensity * a, a);
|
|
98
|
+
#include <tonemapping_fragment>
|
|
99
|
+
#include <colorspace_fragment>
|
|
100
|
+
}
|
|
101
|
+
`;
|
|
102
|
+
// ---------------------------------------------------------------- the cloth
|
|
103
|
+
function makeCloth(W, H, nx, ny) {
|
|
104
|
+
const n = nx * ny;
|
|
105
|
+
const pos = new Float32Array(n * 3), prev = new Float32Array(n * 3), pin = new Uint8Array(n);
|
|
106
|
+
const rest = []; // constraints: [a, b, length]
|
|
107
|
+
const idx = (i, j) => j * nx + i;
|
|
108
|
+
for (let j = 0; j < ny; j++)
|
|
109
|
+
for (let i = 0; i < nx; i++) {
|
|
110
|
+
const k = idx(i, j) * 3;
|
|
111
|
+
pos[k] = (i / (nx - 1) - 0.5) * W;
|
|
112
|
+
pos[k + 1] = H / 2 - (j / (ny - 1)) * H;
|
|
113
|
+
pos[k + 2] = 0;
|
|
114
|
+
if (j === 0)
|
|
115
|
+
pin[idx(i, j)] = 1;
|
|
116
|
+
}
|
|
117
|
+
prev.set(pos);
|
|
118
|
+
const add = (a, b) => { const d = Math.hypot(pos[a * 3] - pos[b * 3], pos[a * 3 + 1] - pos[b * 3 + 1], pos[a * 3 + 2] - pos[b * 3 + 2]); rest.push(a, b, d); };
|
|
119
|
+
for (let j = 0; j < ny; j++)
|
|
120
|
+
for (let i = 0; i < nx; i++) {
|
|
121
|
+
if (i + 1 < nx)
|
|
122
|
+
add(idx(i, j), idx(i + 1, j));
|
|
123
|
+
if (j + 1 < ny)
|
|
124
|
+
add(idx(i, j), idx(i, j + 1));
|
|
125
|
+
if (i + 1 < nx && j + 1 < ny) {
|
|
126
|
+
add(idx(i, j), idx(i + 1, j + 1));
|
|
127
|
+
add(idx(i + 1, j), idx(i, j + 1));
|
|
128
|
+
}
|
|
129
|
+
if (i + 2 < nx)
|
|
130
|
+
add(idx(i, j), idx(i + 2, j));
|
|
131
|
+
if (j + 2 < ny)
|
|
132
|
+
add(idx(i, j), idx(i, j + 2));
|
|
133
|
+
}
|
|
134
|
+
const geo = new THREE.BufferGeometry();
|
|
135
|
+
geo.setAttribute('position', new THREE.BufferAttribute(pos, 3).setUsage(THREE.DynamicDrawUsage));
|
|
136
|
+
const uvs = new Float32Array(n * 2);
|
|
137
|
+
for (let j = 0; j < ny; j++)
|
|
138
|
+
for (let i = 0; i < nx; i++) {
|
|
139
|
+
uvs[idx(i, j) * 2] = i / (nx - 1);
|
|
140
|
+
uvs[idx(i, j) * 2 + 1] = 1 - j / (ny - 1);
|
|
141
|
+
}
|
|
142
|
+
geo.setAttribute('uv', new THREE.BufferAttribute(uvs, 2));
|
|
143
|
+
const index = [];
|
|
144
|
+
for (let j = 0; j < ny - 1; j++)
|
|
145
|
+
for (let i = 0; i < nx - 1; i++) {
|
|
146
|
+
const a = idx(i, j), b = idx(i + 1, j), c = idx(i, j + 1), d = idx(i + 1, j + 1);
|
|
147
|
+
index.push(a, c, b, b, c, d);
|
|
148
|
+
}
|
|
149
|
+
geo.setIndex(index);
|
|
150
|
+
geo.computeVertexNormals();
|
|
151
|
+
return { geo, pos, prev, pin, rest: new Float32Array(rest), n, nx, ny, W, H };
|
|
152
|
+
}
|
|
153
|
+
function stepCloth(cl, dt, g, wind, drag, iters, extraForce, pinM, pinned) {
|
|
154
|
+
const me = pinM.elements;
|
|
155
|
+
const { pos, prev, pin, rest, n } = cl;
|
|
156
|
+
const dt2 = dt * dt;
|
|
157
|
+
for (let i = 0; i < n; i++) {
|
|
158
|
+
const k = i * 3;
|
|
159
|
+
if (pinned && pin[i]) {
|
|
160
|
+
const lx = (i / (cl.nx - 1) - 0.5) * cl.W, ly = cl.H / 2 + 0.02;
|
|
161
|
+
pos[k] = me[0] * lx + me[4] * ly + me[12];
|
|
162
|
+
pos[k + 1] = me[1] * lx + me[5] * ly + me[13];
|
|
163
|
+
pos[k + 2] = me[2] * lx + me[6] * ly + me[14];
|
|
164
|
+
prev[k] = pos[k];
|
|
165
|
+
prev[k + 1] = pos[k + 1];
|
|
166
|
+
prev[k + 2] = pos[k + 2];
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
const x = pos[k], y = pos[k + 1], z = pos[k + 2];
|
|
170
|
+
let fx = 0, fy = -g, fz = 0;
|
|
171
|
+
const w = wind(x, y, z, i);
|
|
172
|
+
fx += w[0];
|
|
173
|
+
fy += w[1];
|
|
174
|
+
fz += w[2];
|
|
175
|
+
if (extraForce) {
|
|
176
|
+
const e = extraForce(x, y, z);
|
|
177
|
+
fx += e[0];
|
|
178
|
+
fy += e[1];
|
|
179
|
+
fz += e[2];
|
|
180
|
+
}
|
|
181
|
+
pos[k] = x + (x - prev[k]) * drag + fx * dt2;
|
|
182
|
+
pos[k + 1] = y + (y - prev[k + 1]) * drag + fy * dt2;
|
|
183
|
+
pos[k + 2] = z + (z - prev[k + 2]) * drag + fz * dt2;
|
|
184
|
+
prev[k] = x;
|
|
185
|
+
prev[k + 1] = y;
|
|
186
|
+
prev[k + 2] = z;
|
|
187
|
+
}
|
|
188
|
+
for (let it = 0; it < iters; it++)
|
|
189
|
+
for (let c = 0; c < rest.length; c += 3) {
|
|
190
|
+
const a = rest[c] * 3, b = rest[c + 1] * 3, L = rest[c + 2];
|
|
191
|
+
const dx = pos[b] - pos[a], dy = pos[b + 1] - pos[a + 1], dz = pos[b + 2] - pos[a + 2];
|
|
192
|
+
const d = Math.hypot(dx, dy, dz) || 1e-6;
|
|
193
|
+
const diff = (d - L) / d * 0.5;
|
|
194
|
+
const pa = pinned && pin[rest[c]], pb = pinned && pin[rest[c + 1]];
|
|
195
|
+
const wa = pa ? 0 : (pb ? 2 : 1), wb = pb ? 0 : (pa ? 2 : 1);
|
|
196
|
+
pos[a] += dx * diff * wa * 0.5;
|
|
197
|
+
pos[a + 1] += dy * diff * wa * 0.5;
|
|
198
|
+
pos[a + 2] += dz * diff * wa * 0.5;
|
|
199
|
+
pos[b] -= dx * diff * wb * 0.5;
|
|
200
|
+
pos[b + 1] -= dy * diff * wb * 0.5;
|
|
201
|
+
pos[b + 2] -= dz * diff * wb * 0.5;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
export function build(u, c) { return withLean(buildGallery(u, c), c); }
|
|
205
|
+
function buildGallery(u, c) {
|
|
206
|
+
const MAX = 32, W = c.width, H = W / c.aspect, nx = Math.max(6, c.resolution | 0), ny = Math.max(4, Math.round(nx / c.aspect));
|
|
207
|
+
const rnd = mulberry32(2);
|
|
208
|
+
const sheets = [];
|
|
209
|
+
const object = new THREE.Group();
|
|
210
|
+
const rail = new THREE.Mesh(new THREE.CylinderGeometry(0.015, 0.015, 1, 10), new THREE.MeshStandardMaterial({ color: '#8a8f9a', roughness: 0.4, metalness: 0.8 }));
|
|
211
|
+
rail.rotation.z = Math.PI / 2;
|
|
212
|
+
rail.visible = false;
|
|
213
|
+
object.add(rail);
|
|
214
|
+
const pick = new THREE.Mesh(new THREE.PlaneGeometry(W, H), new THREE.MeshBasicMaterial({ visible: false }));
|
|
215
|
+
object.add(pick);
|
|
216
|
+
for (let i = 0; i < MAX; i++) {
|
|
217
|
+
const cl = makeCloth(W, H, nx, ny);
|
|
218
|
+
// silk: lit by the scene (the studio's lights) — a soft diffuse print with a sheen along the folds
|
|
219
|
+
const mat = new THREE.MeshPhysicalMaterial({ color: '#ffffff', roughness: 0.62, metalness: 0, sheen: c.sheen, sheenRoughness: 0.35, sheenColor: new THREE.Color('#fff4e6'), side: THREE.DoubleSide, transparent: true });
|
|
220
|
+
const mesh = new THREE.Mesh(cl.geo, mat);
|
|
221
|
+
mesh.frustumCulled = false;
|
|
222
|
+
mesh.visible = false;
|
|
223
|
+
mesh.raycast = () => { };
|
|
224
|
+
mesh.castShadow = true;
|
|
225
|
+
mesh.receiveShadow = true;
|
|
226
|
+
object.add(mesh);
|
|
227
|
+
sheets.push({ cl, mesh, mat, falling: 0, phase: rnd() * 6.28, lastD: 99, offsetX: 0 });
|
|
228
|
+
}
|
|
229
|
+
const cfg = { ...c };
|
|
230
|
+
const scroll = createScroll(cfg, () => { });
|
|
231
|
+
scroll.st.pitch = W * c.spacing;
|
|
232
|
+
const st = { time: 0, prevIndex: 0, pointer: null, prevPointer: null, gust: 0, gustT: 0, tex: [] };
|
|
233
|
+
const controls = Object.assign(scroll.controls, {
|
|
234
|
+
setTexture(tex, count) { for (const t of st.tex ?? [])
|
|
235
|
+
t.dispose(); scroll.st.count = Math.min(count, MAX); [st.tex] = sliceTextures(tex, scroll.st.count); tex.dispose(); st.tex.forEach((t, i) => { sheets[i].mat.map = t; sheets[i].mat.needsUpdate = true; }); },
|
|
236
|
+
});
|
|
237
|
+
const jump = controls.jump;
|
|
238
|
+
controls.jump = (i) => { jump(i); for (const s of sheets)
|
|
239
|
+
s.lastD = 99; }; // a jump re-hangs too
|
|
240
|
+
object.userData.gallery = controls;
|
|
241
|
+
const railY = H / 2 + 0.02;
|
|
242
|
+
const layout = createLayout(W, H);
|
|
243
|
+
function resetSheet(s, M) {
|
|
244
|
+
const { pos, prev, n } = s.cl, me = M.elements;
|
|
245
|
+
for (let i = 0; i < n; i++) {
|
|
246
|
+
const k = i * 3;
|
|
247
|
+
const ci = i % s.cl.nx, cj = Math.floor(i / s.cl.nx);
|
|
248
|
+
const lx = (ci / (s.cl.nx - 1) - 0.5) * W, ly = H / 2 + 0.02 - (cj / (s.cl.ny - 1)) * H;
|
|
249
|
+
pos[k] = me[0] * lx + me[4] * ly + me[12];
|
|
250
|
+
pos[k + 1] = me[1] * lx + me[5] * ly + me[13];
|
|
251
|
+
pos[k + 2] = me[2] * lx + me[6] * ly + me[14];
|
|
252
|
+
prev[k] = pos[k];
|
|
253
|
+
prev[k + 1] = pos[k + 1];
|
|
254
|
+
prev[k + 2] = pos[k + 2];
|
|
255
|
+
}
|
|
256
|
+
s.falling = 0;
|
|
257
|
+
}
|
|
258
|
+
return {
|
|
259
|
+
object, controls, pickMesh: pick, materials: sheets.map(s => s.mat).concat(rail.material),
|
|
260
|
+
// a new layout (or any change of the places) re-hangs the sheets still in their new places
|
|
261
|
+
apply(k) { Object.assign(cfg, k); for (const s of sheets) {
|
|
262
|
+
s.mat.sheen = cfg.sheen;
|
|
263
|
+
if (LAYOUT_KEYS.some(q => k[q] !== undefined))
|
|
264
|
+
s.lastD = 99;
|
|
265
|
+
} scroll.st.pitch = W * cfg.spacing; },
|
|
266
|
+
update(dt, pointer) {
|
|
267
|
+
dt = Math.min(dt, 0.033);
|
|
268
|
+
st.time += dt;
|
|
269
|
+
scroll.step(dt, pointer);
|
|
270
|
+
const n = scroll.st.count, s0 = scroll.st.s, pitch = W * cfg.spacing;
|
|
271
|
+
st.gustT += dt;
|
|
272
|
+
if (st.gustT > 2.5 + rnd() * 3) {
|
|
273
|
+
st.gustT = 0;
|
|
274
|
+
st.gust = (rnd() - 0.4) * cfg.wind * 6;
|
|
275
|
+
}
|
|
276
|
+
const breezeZ = cfg.wind * (1.2 * Math.sin(st.time * 0.5) * Math.sin(st.time * 0.17 + 1.0) + 0.7 * Math.sin(st.time * 1.4)) + st.gust * Math.exp(-st.gustT * 0.9);
|
|
277
|
+
const idx = controls.index;
|
|
278
|
+
if (idx !== st.prevIndex) {
|
|
279
|
+
st.gustT = 0;
|
|
280
|
+
st.gust = (cfg.wind * 1.2 + 0.35) * Math.sign(scroll.st.v || 1);
|
|
281
|
+
st.prevIndex = idx;
|
|
282
|
+
} // the row's move stirs the air
|
|
283
|
+
// the cursor's breath / touch, in the z = 0 plane
|
|
284
|
+
let breathX = 0, breathV = 0;
|
|
285
|
+
if (pointer && st.prevPointer && cfg.pointerMode === 'breath') {
|
|
286
|
+
breathV = (pointer.x - st.prevPointer.x) / dt;
|
|
287
|
+
breathX = pointer.x;
|
|
288
|
+
}
|
|
289
|
+
st.prevPointer = pointer ? { ...pointer } : null;
|
|
290
|
+
const span = Math.min(n, 2 * cfg.visible + 1) * pitch;
|
|
291
|
+
rail.scale.set(1, span, 1);
|
|
292
|
+
rail.position.set(0, railY, 0);
|
|
293
|
+
for (let i = 0; i < n; i++) {
|
|
294
|
+
const s = sheets[i];
|
|
295
|
+
const { d, focus, fade } = layout.place(i, s0, n, cfg, s.place ?? (s.place = new THREE.Matrix4()));
|
|
296
|
+
const vis = fade > 0.002 || s.falling > 0;
|
|
297
|
+
s.mesh.visible = vis;
|
|
298
|
+
if (!vis) {
|
|
299
|
+
s.lastD = 99;
|
|
300
|
+
continue;
|
|
301
|
+
}
|
|
302
|
+
if (s.lastD === 99)
|
|
303
|
+
resetSheet(s, s.place); // just came into view: hang still
|
|
304
|
+
s.lastD = d;
|
|
305
|
+
const wind = (px, py, pz, k) => {
|
|
306
|
+
const f = (0.6 + 0.4 * Math.sin(px * 2.1 + st.time * 0.9 + s.phase)) * (1 - (py - (railY - H)) / H * 0.3);
|
|
307
|
+
let wz = breezeZ * f * 0.35, wx = 0;
|
|
308
|
+
if (breathV) {
|
|
309
|
+
const g = Math.exp(-Math.pow((px - breathX) / cfg.pointerRadius, 2));
|
|
310
|
+
wz += Math.abs(breathV) * 1.4 * g * cfg.pointerStrength;
|
|
311
|
+
wx += breathV * 0.4 * g * cfg.pointerStrength;
|
|
312
|
+
}
|
|
313
|
+
if (pointer && cfg.pointerMode === 'touch') {
|
|
314
|
+
const dx = px - pointer.x, dy = py - pointer.y;
|
|
315
|
+
const g = Math.exp(-(dx * dx + dy * dy) / (cfg.pointerRadius * cfg.pointerRadius * 0.3));
|
|
316
|
+
wz -= 9 * g * cfg.pointerStrength;
|
|
317
|
+
}
|
|
318
|
+
return [wx, 0, wz];
|
|
319
|
+
};
|
|
320
|
+
if (s.falling > 0) {
|
|
321
|
+
s.falling += dt / cfg.fallTime;
|
|
322
|
+
stepCloth(s.cl, dt, cfg.gravity * 0.5, wind, cfg.drag, cfg.iterations, null, s.place, false);
|
|
323
|
+
s.mat.opacity = cfg.opacity * (1 - smooth(0.35, 1, s.falling));
|
|
324
|
+
if (s.falling >= 1) {
|
|
325
|
+
s.falling = 0;
|
|
326
|
+
s.mesh.visible = false;
|
|
327
|
+
s.lastD = 99;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
else {
|
|
331
|
+
stepCloth(s.cl, dt, cfg.gravity, wind, cfg.drag, cfg.iterations, null, s.place, true);
|
|
332
|
+
s.mat.opacity = cfg.opacity * fade;
|
|
333
|
+
}
|
|
334
|
+
s.mat.color.setScalar((1 - cfg.dim * (1 - focus)) * cfg.intensity);
|
|
335
|
+
s.cl.geo.attributes.position.needsUpdate = true;
|
|
336
|
+
s.cl.geo.computeVertexNormals();
|
|
337
|
+
}
|
|
338
|
+
pick.position.x = 0;
|
|
339
|
+
},
|
|
340
|
+
dispose() { for (const s of sheets) {
|
|
341
|
+
s.cl.geo.dispose();
|
|
342
|
+
s.mat.dispose();
|
|
343
|
+
} rail.geometry.dispose(); rail.material.dispose(); pick.geometry.dispose(); for (const t of st.tex ?? [])
|
|
344
|
+
t.dispose(); },
|
|
345
|
+
};
|
|
346
|
+
}
|
|
@@ -0,0 +1,176 @@
|
|
|
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
|
+
aspect: number;
|
|
15
|
+
width: number;
|
|
16
|
+
slats: number;
|
|
17
|
+
turn: number;
|
|
18
|
+
thickness: number;
|
|
19
|
+
gap: number;
|
|
20
|
+
roughness: number;
|
|
21
|
+
metalness: number;
|
|
22
|
+
backColor: string;
|
|
23
|
+
changeTime: number;
|
|
24
|
+
wave: number;
|
|
25
|
+
slant: number;
|
|
26
|
+
dim: number;
|
|
27
|
+
pointerMode: string;
|
|
28
|
+
pointerRadius: number;
|
|
29
|
+
pointerTurn: number;
|
|
30
|
+
enabled: boolean;
|
|
31
|
+
lean: number;
|
|
32
|
+
imageUrls: any[];
|
|
33
|
+
autoplay: number;
|
|
34
|
+
intensity: number;
|
|
35
|
+
opacity: number;
|
|
36
|
+
layout: string;
|
|
37
|
+
spacing: number;
|
|
38
|
+
depth: number;
|
|
39
|
+
visible: number;
|
|
40
|
+
shape: number;
|
|
41
|
+
stiffness: number;
|
|
42
|
+
damping: number;
|
|
43
|
+
throwing: number;
|
|
44
|
+
pointerStrength: number;
|
|
45
|
+
};
|
|
46
|
+
export declare const STRUCTURAL: string[];
|
|
47
|
+
export declare const POINTER_MODES: string[];
|
|
48
|
+
export declare const GUI: ({
|
|
49
|
+
key: string;
|
|
50
|
+
options: string[];
|
|
51
|
+
tip: string;
|
|
52
|
+
min?: undefined;
|
|
53
|
+
max?: undefined;
|
|
54
|
+
step?: undefined;
|
|
55
|
+
} | {
|
|
56
|
+
key: string;
|
|
57
|
+
min: number;
|
|
58
|
+
max: number;
|
|
59
|
+
step: number;
|
|
60
|
+
} | {
|
|
61
|
+
key: string;
|
|
62
|
+
options: string[];
|
|
63
|
+
color?: undefined;
|
|
64
|
+
} | {
|
|
65
|
+
key: string;
|
|
66
|
+
color: boolean;
|
|
67
|
+
options?: undefined;
|
|
68
|
+
})[];
|
|
69
|
+
export declare const PRESETS: ({
|
|
70
|
+
name: string;
|
|
71
|
+
description: string;
|
|
72
|
+
patch: {
|
|
73
|
+
slats?: undefined;
|
|
74
|
+
thickness?: undefined;
|
|
75
|
+
changeTime?: undefined;
|
|
76
|
+
wave?: undefined;
|
|
77
|
+
gap?: undefined;
|
|
78
|
+
};
|
|
79
|
+
} | {
|
|
80
|
+
name: string;
|
|
81
|
+
description: string;
|
|
82
|
+
patch: {
|
|
83
|
+
slats: number;
|
|
84
|
+
thickness: number;
|
|
85
|
+
changeTime: number;
|
|
86
|
+
wave: number;
|
|
87
|
+
gap?: undefined;
|
|
88
|
+
};
|
|
89
|
+
} | {
|
|
90
|
+
name: string;
|
|
91
|
+
description: string;
|
|
92
|
+
patch: {
|
|
93
|
+
slats: number;
|
|
94
|
+
gap: number;
|
|
95
|
+
changeTime: number;
|
|
96
|
+
wave: number;
|
|
97
|
+
thickness?: undefined;
|
|
98
|
+
};
|
|
99
|
+
})[];
|
|
100
|
+
export declare function createUniforms(): {
|
|
101
|
+
uN: {
|
|
102
|
+
value: number;
|
|
103
|
+
};
|
|
104
|
+
uTurn: {
|
|
105
|
+
value: number;
|
|
106
|
+
};
|
|
107
|
+
uThick: {
|
|
108
|
+
value: number;
|
|
109
|
+
};
|
|
110
|
+
uGap: {
|
|
111
|
+
value: number;
|
|
112
|
+
};
|
|
113
|
+
uPTurn: {
|
|
114
|
+
value: number;
|
|
115
|
+
};
|
|
116
|
+
uBack: {
|
|
117
|
+
value: THREE.Color;
|
|
118
|
+
};
|
|
119
|
+
uTex: {
|
|
120
|
+
value: any;
|
|
121
|
+
};
|
|
122
|
+
uS: {
|
|
123
|
+
value: number;
|
|
124
|
+
};
|
|
125
|
+
uCount: {
|
|
126
|
+
value: number;
|
|
127
|
+
};
|
|
128
|
+
uTime: {
|
|
129
|
+
value: number;
|
|
130
|
+
};
|
|
131
|
+
uAct: {
|
|
132
|
+
value: Float32Array<ArrayBuffer>;
|
|
133
|
+
};
|
|
134
|
+
uW: {
|
|
135
|
+
value: number;
|
|
136
|
+
};
|
|
137
|
+
uH: {
|
|
138
|
+
value: number;
|
|
139
|
+
};
|
|
140
|
+
uWave: {
|
|
141
|
+
value: number;
|
|
142
|
+
};
|
|
143
|
+
uSlant: {
|
|
144
|
+
value: number;
|
|
145
|
+
};
|
|
146
|
+
uDim: {
|
|
147
|
+
value: number;
|
|
148
|
+
};
|
|
149
|
+
uIntensity: {
|
|
150
|
+
value: number;
|
|
151
|
+
};
|
|
152
|
+
uOpacity: {
|
|
153
|
+
value: number;
|
|
154
|
+
};
|
|
155
|
+
uPointer: {
|
|
156
|
+
value: THREE.Vector3;
|
|
157
|
+
};
|
|
158
|
+
uPointerActive: {
|
|
159
|
+
value: number;
|
|
160
|
+
};
|
|
161
|
+
uPointerMode: {
|
|
162
|
+
value: number;
|
|
163
|
+
};
|
|
164
|
+
uPointerStrength: {
|
|
165
|
+
value: number;
|
|
166
|
+
};
|
|
167
|
+
uPointerRadius: {
|
|
168
|
+
value: number;
|
|
169
|
+
};
|
|
170
|
+
uPlace: {
|
|
171
|
+
value: THREE.Matrix4[];
|
|
172
|
+
};
|
|
173
|
+
};
|
|
174
|
+
export declare function applyConfig(u: any, c: any): void;
|
|
175
|
+
export declare function build(u: any, c: any): any;
|
|
176
|
+
//# sourceMappingURL=slats.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slats.d.ts","sourceRoot":"","sources":["../../../../src/components/gallery/looks/slats.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,eAAO,MAAM,OAAO;;;;;;;;;CAE8D,CAAC;AAEnF,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAKpB,CAAC;AACF,eAAO,MAAM,UAAU,UAA4C,CAAC;AACpE,eAAO,MAAM,aAAa,UAAW,CAAC;AACtC,eAAO,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;IASf,CAAC;AACF,eAAO,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAInB,CAAC;AACF,wBAAgB,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAE7B;AACD,wBAAgB,WAAW,CAAC,CAAC,KAAA,EAAE,CAAC,KAAA,QAI/B;AA2BD,wBAAgB,KAAK,CAAC,CAAC,KAAA,EAAE,CAAC,KAAA,OAA6C"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
// The approved lab module, verbatim but for its import paths and the lab's picture loader (Claude outputs/gallery-lab/
|
|
2
|
+
// slats.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.slats) do not carry; its own autoplay is never used.
|
|
4
|
+
// slats — every picture is cut into thin vertical slats, each a real 3D strip turning about its own vertical axis,
|
|
5
|
+
// lit by the scene: the front of a slat carries its strip of the picture, its back and edges are plain. An inactive
|
|
6
|
+
// picture's slats stand nearly edge-on — a row of fine grey lines with the dark showing between them. When it
|
|
7
|
+
// becomes the active one a soft wave crosses it and the slats turn to face the viewer one after another, closing
|
|
8
|
+
// into the picture in full colour; leaving turns them back. The cursor turns the slats near it a little toward it.
|
|
9
|
+
// Scene-lit (standard material): the studio's lights catch the turning slats; the gallery adds none.
|
|
10
|
+
import * as THREE from 'three';
|
|
11
|
+
import { BASE_DEFAULTS, BASE_GUI_MOTION, BASE_GUI_TAIL, LAYOUT_GUI, baseUniforms, applyBase, instanced, litMaterial, makeGallery, withLean } from '../kit/lookBase.js';
|
|
12
|
+
export const catalog = { key: 'slats', name: 'Slats', camera: { position: [1.2, 0.3, 4.4], target: [0, 0, 0] },
|
|
13
|
+
description: 'Pictures cut into thin vertical slats lit by the scene: inactive ones stand nearly edge-on as fine grey lines, the active one turns its slats to face you in a soft wave, closing into the picture; the cursor turns the slats near it. Use for architecture, interiors and product showcases.',
|
|
14
|
+
tags: ['gallery', 'slats', 'louvres', 'turning', 'scene-lit', 'interactive'] };
|
|
15
|
+
export const DEFAULTS = {
|
|
16
|
+
...BASE_DEFAULTS, type: 'slats', aspect: 1.4, width: 2.2, slats: 36, // structural
|
|
17
|
+
turn: 82, thickness: 0.018, gap: 0.04, roughness: 0.5, metalness: 0.1, backColor: '#2a2c33',
|
|
18
|
+
changeTime: 1.8, wave: 0.45, slant: 0, dim: 0.45,
|
|
19
|
+
pointerMode: 'turn', pointerRadius: 0.5, pointerTurn: 22,
|
|
20
|
+
};
|
|
21
|
+
export const STRUCTURAL = ['imageUrls', 'aspect', 'width', 'slats'];
|
|
22
|
+
export const POINTER_MODES = ['turn'];
|
|
23
|
+
export const GUI = [
|
|
24
|
+
{ key: 'lean', min: 0, max: 3, step: 0.01, tip: 'The gallery turns toward the cursor' },
|
|
25
|
+
{ key: 'aspect', min: 0.6, max: 2.5, step: 0.01 }, { key: 'width', min: 1, max: 4, step: 0.01 }, { key: 'slats', min: 8, max: 120, step: 1, tip: 'Slats across a picture' },
|
|
26
|
+
...LAYOUT_GUI, ...BASE_GUI_MOTION,
|
|
27
|
+
{ key: 'turn', min: 0, max: 90, step: 1, tip: 'How far an inactive picture’s slats are turned (degrees)' },
|
|
28
|
+
{ key: 'thickness', min: 0.002, max: 0.08, step: 0.001, tip: 'Thickness of a slat' }, { key: 'gap', min: 0, max: 0.4, step: 0.005, tip: 'Gap between slats, as a share of a slat' },
|
|
29
|
+
{ key: 'roughness', min: 0, max: 1, step: 0.01 }, { key: 'metalness', min: 0, max: 1, step: 0.01 },
|
|
30
|
+
{ key: 'pointerMode', options: ['none', ...POINTER_MODES] }, ...BASE_GUI_TAIL, { key: 'pointerTurn', min: 0, max: 60, step: 1, tip: 'How far the cursor turns the slats (degrees)' },
|
|
31
|
+
{ key: 'backColor', color: true },
|
|
32
|
+
];
|
|
33
|
+
export const PRESETS = [
|
|
34
|
+
{ name: 'Slats', description: 'The default.', patch: {} },
|
|
35
|
+
{ name: 'Blinds', description: 'Many fine slats, a quick wave.', patch: { slats: 80, thickness: 0.006, changeTime: 1.2, wave: 0.3 } },
|
|
36
|
+
{ name: 'Panels', description: 'A few wide panels, slow.', patch: { slats: 12, gap: 0.08, changeTime: 2.8, wave: 0.6 } },
|
|
37
|
+
];
|
|
38
|
+
export function createUniforms() {
|
|
39
|
+
return { ...baseUniforms(), uN: { value: 36 }, uTurn: { value: 1.43 }, uThick: { value: 0.018 }, uGap: { value: 0.04 }, uPTurn: { value: 0.38 }, uBack: { value: new THREE.Color('#2a2c33') } };
|
|
40
|
+
}
|
|
41
|
+
export function applyConfig(u, c) {
|
|
42
|
+
const set = applyBase(u, c, POINTER_MODES);
|
|
43
|
+
set('uThick', c.thickness);
|
|
44
|
+
set('uGap', c.gap);
|
|
45
|
+
set('uBack', c.backColor);
|
|
46
|
+
if (c.turn !== undefined)
|
|
47
|
+
u.uTurn.value = c.turn * Math.PI / 180;
|
|
48
|
+
if (c.pointerTurn !== undefined)
|
|
49
|
+
u.uPTurn.value = c.pointerTurn * Math.PI / 180;
|
|
50
|
+
}
|
|
51
|
+
const vertex = {
|
|
52
|
+
head: /* glsl */ `uniform float uN, uTurn, uThick, uGap, uPTurn; varying vec2 vUv; varying float vImg; varying float vW; varying float vFront; varying float vAlpha;`,
|
|
53
|
+
body: /* glsl */ `
|
|
54
|
+
float img = aI.x, k = aI.y; float u0 = (k + 0.5) / uN;
|
|
55
|
+
float sw = uW / uN;
|
|
56
|
+
float cx = (u0 - 0.5) * uW;
|
|
57
|
+
float w = waveAt(actOf(img), vec2(u0, 0.5));
|
|
58
|
+
float m = maskAt(vec2(cx, 0.0));
|
|
59
|
+
float a = (1.0 - w) * uTurn + uPTurn * m * sign(uPointer.x - cx + 1e-4);
|
|
60
|
+
vec3 v = vec3(position.x * sw * (1.0 - uGap), position.y * uH, position.z * uThick);
|
|
61
|
+
float ca = cos(a), sa = sin(a);
|
|
62
|
+
gPos = vec3(cx + ca * v.x + sa * v.z, v.y, -sa * v.x + ca * v.z);
|
|
63
|
+
gNrm = vec3(ca * normal.x + sa * normal.z, normal.y, -sa * normal.x + ca * normal.z);
|
|
64
|
+
vUv = vec2(u0 + position.x / uN, position.y + 0.5);
|
|
65
|
+
vImg = img; vW = w; vFront = step(0.5, normal.z); vAlpha = fadeAt(img);
|
|
66
|
+
`,
|
|
67
|
+
};
|
|
68
|
+
const fragment = {
|
|
69
|
+
head: /* glsl */ `uniform vec3 uBack; varying vec2 vUv; varying float vImg; varying float vW; varying float vFront; varying float vAlpha;`,
|
|
70
|
+
body: /* glsl */ `
|
|
71
|
+
vec3 pic = texture(uTex, vec3(vUv, vImg)).rgb;
|
|
72
|
+
vec3 face = mix(fadedOf(pic) * 1.6, pic, vW);
|
|
73
|
+
diffuseColor.rgb = mix(uBack * mix(0.6, 1.0, uDim), face, vFront) * uIntensity;
|
|
74
|
+
diffuseColor.a *= vAlpha * uOpacity; if (diffuseColor.a < 0.01) discard;
|
|
75
|
+
`,
|
|
76
|
+
};
|
|
77
|
+
export function build(u, c) { return withLean(buildGallery(u, c), c); }
|
|
78
|
+
function buildGallery(u, c) {
|
|
79
|
+
const W = c.width, H = W / c.aspect, N = Math.max(2, c.slats | 0);
|
|
80
|
+
u.uN.value = N;
|
|
81
|
+
const geo = instanced(new THREE.BoxGeometry(1, 1, 1), N, () => [0, 0]);
|
|
82
|
+
const mat = litMaterial(u, 'slats', vertex, fragment, { roughness: c.roughness, metalness: c.metalness });
|
|
83
|
+
const mesh = new THREE.Mesh(geo, mat);
|
|
84
|
+
mesh.frustumCulled = false;
|
|
85
|
+
mesh.raycast = () => { };
|
|
86
|
+
mesh.receiveShadow = true;
|
|
87
|
+
const g = makeGallery(u, c, { W, H, meshes: [mesh], setCount: (n) => { geo.instanceCount = n * N; } });
|
|
88
|
+
const apply = g.apply;
|
|
89
|
+
g.apply = (k) => { apply(k); applyConfig(u, k); if (k.roughness !== undefined)
|
|
90
|
+
mat.roughness = k.roughness; if (k.metalness !== undefined)
|
|
91
|
+
mat.metalness = k.metalness; };
|
|
92
|
+
return g;
|
|
93
|
+
}
|