91 lines
3.0 KiB
JavaScript
91 lines
3.0 KiB
JavaScript
import * as THREE from 'three';
|
|
import { state } from '../state.js';
|
|
import { updateScreenEffect } from '../scene/magic-mirror.js'
|
|
import sceneFeatureManager from '../scene/SceneFeatureManager.js';
|
|
|
|
function updateCamera() {
|
|
const globalTime = Date.now() * 0.0001;
|
|
const lookAtTime = Date.now() * 0.0002;
|
|
|
|
const camAmplitude = 1.0;
|
|
const lookAmplitude = 8.0;
|
|
|
|
// Base Camera Position in front of the TV
|
|
const baseX = 0;
|
|
const baseY = 1.6;
|
|
const baseZ = -10.0;
|
|
|
|
// Base LookAt target (Center of the screen)
|
|
const baseTargetX = 0;
|
|
const baseTargetY = 1.6;
|
|
const baseTargetZ = -30.0;
|
|
|
|
// Camera Position Offsets (Drift)
|
|
const camOffsetX = Math.sin(globalTime * 3.1) * camAmplitude;
|
|
const camOffsetY = Math.cos(globalTime * 2.5) * camAmplitude * 0.1;
|
|
const camOffsetZ = Math.cos(globalTime * 3.2) * camAmplitude;
|
|
|
|
state.camera.position.x = baseX + camOffsetX;
|
|
state.camera.position.y = baseY + camOffsetY;
|
|
state.camera.position.z = baseZ + camOffsetZ;
|
|
|
|
// LookAt Target Offsets (Subtle Gaze Shift)
|
|
const lookOffsetX = Math.sin(lookAtTime * 1.5) * lookAmplitude;
|
|
const lookOffsetZ = Math.cos(lookAtTime * 2.5) * lookAmplitude;
|
|
const lookOffsetY = Math.cos(lookAtTime * 1.2) * lookAmplitude * 0.5;
|
|
|
|
// Apply lookAt to the subtly shifted target
|
|
state.camera.lookAt(baseTargetX + lookOffsetX, baseTargetY + lookOffsetY, baseTargetZ + lookOffsetZ);
|
|
}
|
|
|
|
function updateScreenLight() {
|
|
if (state.isVideoLoaded && state.screenLight.intensity > 0) {
|
|
const pulseTarget = state.originalScreenIntensity + (Math.random() - 0.5) * state.screenIntensityPulse;
|
|
state.screenLight.intensity = THREE.MathUtils.lerp(state.screenLight.intensity, pulseTarget, 0.1);
|
|
|
|
const lightTime = Date.now() * 0.0001;
|
|
const radius = 0.01;
|
|
const centerX = 0;
|
|
const centerY = 1.5;
|
|
|
|
state.screenLight.position.x = centerX + Math.cos(lightTime) * radius;
|
|
state.screenLight.position.y = centerY + Math.sin(lightTime * 1.5) * radius * 0.5; // Slightly different freq for Y
|
|
}
|
|
}
|
|
|
|
function updateShaderTime() {
|
|
if (state.tvScreen && state.tvScreen.material.uniforms && state.tvScreen.material.uniforms.u_time) {
|
|
state.tvScreen.material.uniforms.u_time.value = state.clock.getElapsedTime();
|
|
}
|
|
}
|
|
|
|
function updateVideo() {
|
|
if (state.videoTexture) {
|
|
state.videoTexture.needsUpdate = true;
|
|
}
|
|
}
|
|
|
|
|
|
// --- Animation Loop ---
|
|
export function animate() {
|
|
requestAnimationFrame(animate);
|
|
|
|
const deltaTime = 1;
|
|
sceneFeatureManager.update(deltaTime);
|
|
state.effectsManager.update();
|
|
updateCamera();
|
|
updateScreenLight();
|
|
updateVideo();
|
|
updateShaderTime();
|
|
updateScreenEffect();
|
|
|
|
// RENDER!
|
|
state.renderer.render(state.scene, state.camera);
|
|
}
|
|
|
|
// --- Window Resize Handler ---
|
|
export function onWindowResize() {
|
|
state.camera.aspect = window.innerWidth / window.innerHeight;
|
|
state.camera.updateProjectionMatrix();
|
|
state.renderer.setSize(window.innerWidth, window.innerHeight);
|
|
} |