music-video-gen/party-cathedral/src/scene/light-ball.js
2025-11-21 23:07:31 +01:00

72 lines
2.6 KiB
JavaScript

import * as THREE from 'three';
import { state } from '../state.js';
import { SceneFeature } from './SceneFeature.js';
import sceneFeatureManager from './SceneFeatureManager.js';
// --- Dimensions from room-walls.js for positioning ---
const naveWidth = 12;
const naveHeight = 15;
const length = 40;
export class LightBall extends SceneFeature {
constructor() {
super();
this.lightBalls = [];
sceneFeatureManager.register(this);
}
init() {
// --- Ball Properties ---
const ballRadius = 0.4;
const lightIntensity = 5.0;
const lightColors = [0xff0000, 0x00ff00, 0x0000ff, 0xffff00, 0x00ffff]; // Red, Green, Blue, Yellow
lightColors.forEach(color => {
// --- Create the Ball ---
const ballGeometry = new THREE.SphereGeometry(ballRadius, 32, 32);
const ballMaterial = new THREE.MeshBasicMaterial({ color: color, emissive: color, emissiveIntensity: 1.0 });
const ball = new THREE.Mesh(ballGeometry, ballMaterial);
ball.castShadow = false;
ball.receiveShadow = false;
// --- Create the Light ---
const light = new THREE.PointLight(color, lightIntensity, length / 1.5);
light.shadow.mapSize.width = 1024;
light.shadow.mapSize.height = 1024;
light.shadow.camera.near = 0.1;
light.shadow.camera.far = 200;
// --- Initial Position ---
ball.position.set(
(Math.random() - 0.5) * naveWidth,
naveHeight * 0.6 + Math.random() * 4,
(Math.random() - 0.5) * length * 0.8
);
light.position.copy(ball.position);
state.scene.add(ball);
state.scene.add(light);
this.lightBalls.push({
mesh: ball,
light: light,
driftSpeed: 0.2 + Math.random() * 0.2,
driftAmplitude: 4.0 + Math.random() * 4.0,
offset: Math.random() * Math.PI * 6,
});
});
}
update(deltaTime) {
const time = state.clock.getElapsedTime();
this.lightBalls.forEach(lb => {
const { mesh, light, driftSpeed, offset } = lb;
mesh.position.x = Math.sin(time * driftSpeed + offset) * naveWidth/2 * 0.8;
mesh.position.y = 10 + Math.cos(time * driftSpeed * 1.3 + offset) * naveHeight/2 * 0.6;
mesh.position.z = Math.cos(time * driftSpeed * 0.7 + offset) * length/2 * 0.8;
light.position.copy(mesh.position);
});
}
}
new LightBall();