Feature: Wall curtain behind stage
This commit is contained in:
parent
6566416ebd
commit
e6487de0a7
@ -17,6 +17,7 @@ import { RoseWindowLight } from './rose-window-light.js';
|
|||||||
import { RoseWindowLightshafts } from './rose-window-lightshafts.js';
|
import { RoseWindowLightshafts } from './rose-window-lightshafts.js';
|
||||||
import { StainedGlass } from './stained-glass-window.js';
|
import { StainedGlass } from './stained-glass-window.js';
|
||||||
import { MusicPlayer } from './music-player.js';
|
import { MusicPlayer } from './music-player.js';
|
||||||
|
import { WallCurtain } from './wall-curtain.js';
|
||||||
// Scene Features ^^^
|
// Scene Features ^^^
|
||||||
|
|
||||||
// --- Scene Modeling Function ---
|
// --- Scene Modeling Function ---
|
||||||
|
|||||||
90
party-cathedral/src/scene/wall-curtain.js
Normal file
90
party-cathedral/src/scene/wall-curtain.js
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
import * as THREE from 'three';
|
||||||
|
import { state } from '../state.js';
|
||||||
|
import { SceneFeature } from './SceneFeature.js';
|
||||||
|
import sceneFeatureManager from './SceneFeatureManager.js';
|
||||||
|
import curtainTextureUrl from '/textures/tapestry.png';
|
||||||
|
|
||||||
|
export class WallCurtain extends SceneFeature {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.curtains = [];
|
||||||
|
sceneFeatureManager.register(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
init() {
|
||||||
|
// --- Curtain Properties ---
|
||||||
|
const naveWidth = 12;
|
||||||
|
const naveHeight = 7;
|
||||||
|
const stageHeight = 1.5;
|
||||||
|
const curtainWidth = naveWidth; // Span the width of the nave
|
||||||
|
const curtainHeight = naveHeight - stageHeight; // Hang from the ceiling down to the stage
|
||||||
|
const segmentsX = 50; // More segments for a smoother wave
|
||||||
|
const segmentsY = 50;
|
||||||
|
|
||||||
|
// --- Texture ---
|
||||||
|
const texture = state.loader.load(curtainTextureUrl);
|
||||||
|
texture.wrapS = THREE.RepeatWrapping;
|
||||||
|
texture.wrapT = THREE.RepeatWrapping;
|
||||||
|
texture.repeat.set(5, 1); // Repeat the texture 5 times horizontally
|
||||||
|
|
||||||
|
// --- Material ---
|
||||||
|
const material = new THREE.MeshStandardMaterial({
|
||||||
|
map: texture,
|
||||||
|
side: THREE.DoubleSide,
|
||||||
|
roughness: 0.9,
|
||||||
|
metalness: 0.1,
|
||||||
|
});
|
||||||
|
|
||||||
|
// --- Create and Place Curtains ---
|
||||||
|
const createAndPlaceCurtain = (position, rotationY) => {
|
||||||
|
const geometry = new THREE.PlaneGeometry(curtainWidth, curtainHeight, segmentsX, segmentsY);
|
||||||
|
const originalPositions = geometry.attributes.position.clone();
|
||||||
|
const curtainMesh = new THREE.Mesh(geometry, material);
|
||||||
|
curtainMesh.position.copy(position);
|
||||||
|
curtainMesh.rotation.y = rotationY;
|
||||||
|
curtainMesh.castShadow = true;
|
||||||
|
curtainMesh.receiveShadow = true;
|
||||||
|
state.scene.add(curtainMesh);
|
||||||
|
|
||||||
|
this.curtains.push({
|
||||||
|
mesh: curtainMesh,
|
||||||
|
originalPositions: originalPositions,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Place a single large curtain behind the stage
|
||||||
|
const backWallZ = -20;
|
||||||
|
const curtainY = stageHeight + curtainHeight / 2;
|
||||||
|
const curtainPosition = new THREE.Vector3(0, curtainY, backWallZ + 0.1);
|
||||||
|
|
||||||
|
createAndPlaceCurtain(curtainPosition, 0); // No rotation needed
|
||||||
|
}
|
||||||
|
|
||||||
|
update(deltaTime) {
|
||||||
|
if (!this.waving) { return; }
|
||||||
|
const time = state.clock.getElapsedTime();
|
||||||
|
const waveSpeed = 1.5;
|
||||||
|
const waveFrequency = 0.5;
|
||||||
|
const waveAmplitude = 0.2;
|
||||||
|
|
||||||
|
this.curtains.forEach(curtain => {
|
||||||
|
const positions = curtain.mesh.geometry.attributes.position;
|
||||||
|
const originalPos = curtain.originalPositions;
|
||||||
|
|
||||||
|
for (let i = 0; i < positions.count; i++) {
|
||||||
|
const originalX = originalPos.getX(i);
|
||||||
|
// The wave now moves horizontally across the curtain
|
||||||
|
const zOffset = Math.sin(originalX * waveFrequency + time * waveSpeed) * waveAmplitude;
|
||||||
|
positions.setZ(i, originalPos.getZ(i) + zOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mark positions as needing an update
|
||||||
|
positions.needsUpdate = true;
|
||||||
|
|
||||||
|
// Recalculate normals for correct lighting on the waving surface
|
||||||
|
curtain.mesh.geometry.computeVertexNormals();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
new WallCurtain();
|
||||||
BIN
party-cathedral/textures/tapestry.png
Normal file
BIN
party-cathedral/textures/tapestry.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.5 MiB |
Loading…
Reference in New Issue
Block a user