Untitled
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'; import { Scene, PerspectiveCamera, PCFSoftShadowMap, AnimationMixer, Clock, MeshBasicMaterial, DoubleSide, // Remove the second instance here TextureLoader, // Remove the second instance here LinearMipMapLinearFilter, ReinhardToneMapping, LoopOnce, Fog, FogExp2, } from 'three'; import { setupRenderer } from '../helpers/RendererHelper.js'; import gsap from 'gsap'; import ScrollTrigger from 'gsap/ScrollTrigger'; gsap.registerPlugin(ScrollTrigger); const loader = new GLTFLoader(); const clock = new Clock(); let scene, camera, renderer, mixer, action; let duration = 0; // Load the alpha texture const textureLoader = new TextureLoader(); // Load the PNG image for HDRI (using as an environment map) const hdriTexturePath = './src/assets/hdri.png'; // Replace with the path to your PNG image const hdriTexture = textureLoader.load(hdriTexturePath); const monsteraAlphaTexturePath = './src/models/Monstera Plant_AlphaMain.png'; // Replace with the path to your alpha texture const monsteraAlphaTexture = textureLoader.load(monsteraAlphaTexturePath); const otherPlantAlphaTexturePath = './src/models/OtherPlant_Alpha.png'; // Replace with the path to your alpha texture const otherPlantAlphaTexture = textureLoader.load(otherPlantAlphaTexturePath); const scrunchieAlphaTexturePath = './src/models/Scrunchie Box Alpha.png'; // Replace with the path to your alpha texture const scrunchieAlphaTexture = textureLoader.load(scrunchieAlphaTexturePath); export function setupScene(canvas) { // Accept canvas as a parameter scene = new Scene(); // ADD FOG const fogColor = 0x505050; const fogNear = 5; const fogFar = 200; scene.fog = new Fog(fogColor, fogNear, fogFar); console.log(scene.fog); // Set up a fallback camera (in case no GLTF camera exists) camera = new PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 500, ); camera.near = 0.1; camera.far = 500; camera.updateProjectionMatrix(); // Set up renderer renderer = setupRenderer(canvas); renderer.setSize(window.innerWidth, window.innerHeight); renderer.setPixelRatio(window.devicePixelRatio); renderer.toneMapping = ReinhardToneMapping; renderer.toneMappingExposure = 6.0; // renderer.useLegacyLights = true; renderer.shadowMap.enabled = true; renderer.shadowMap.type = PCFSoftShadowMap; renderer.sortObjects = true; // Apply the PNG as environment map scene.background = hdriTexture; scene.environment = hdriTexture; // Load the GLTF model loadModel(); } function loadModel() { loader.load('./src/models/VRworld.glb', (gltf) => { const model = gltf.scene; model.traverse((child) => { if (child.isMesh) { const bakedMaterial = new MeshBasicMaterial({ map: child.material.map, // Apply the baked texture color: 0xffffff, // Keep white to avoid altering the texture colors side: DoubleSide, // Turn off backface culling fog: true, }); child.material = bakedMaterial; child.castShadow = true; child.receiveShadow = true; child.material.transparent = true; child.material.side = DoubleSide; child.material.depthWrite = true; child.material.depthTest = true; child.material.specular = null; // Ensure mipmaps are generated for textures if (child.material.map) { child.material.map.generateMipmaps = true; child.material.map.minFilter = LinearMipMapLinearFilter; } if (['Monstera_Plant001', 'Monstera_Plant'].includes(child.name)) { child.material.transparent = true; child.material.alphaMap = monsteraAlphaTexture; // Flip the alpha texture 180 degrees monsteraAlphaTexture.repeat.set(1, -1); // Flip horizontally and vertically monsteraAlphaTexture.offset.set(0, 1); // Adjust the offset so the flip appears correctly child.material.alphaMap.needsUpdate = true; } if (['Other_Plant'].includes(child.name)) { child.material.transparent = true; child.material.alphaMap = otherPlantAlphaTexture; otherPlantAlphaTexture.repeat.set(1, -1); // Flip horizontally and vertically otherPlantAlphaTexture.offset.set(0, 1); // Adjust the offset so the flip appears correctly child.material.alphaMap.needsUpdate = true; } if ( [ 'PillowCase_Box', 'PillowCaseCover', 'PillowSilkCover', 'Text001', ].includes(child.name) ) { if (child.material) { child.material.emissiveIntensity = 0.1; } } if ( [ 'Scrunchie_Box', 'Scrunchie_Box001', 'Scrunchie_Box002', 'Scrunchie_Box004', 'Scrunchie_Box003', ].includes(child.name) ) { child.material.transparent = true; child.material.alphaMap = scrunchieAlphaTexture; // Flip the alpha texture 180 degrees scrunchieAlphaTexture.repeat.set(1, -1); // Flip horizontally and vertically scrunchieAlphaTexture.offset.set(0, 1); // Adjust the offset so the flip appears correctly child.material.alphaMap.needsUpdate = true; } } }); scene.add(model); if (gltf.cameras && gltf.cameras.length > 0) { camera = gltf.cameras[0]; } mixer = new AnimationMixer(model); const animations = gltf.animations; if (animations.length > 0) { animations.forEach((animation) => { const action = mixer.clipAction(animation); action.play(); // Play each animation action.loop = LoopOnce; action.clampWhenFinished = true; }); duration = animations[0].duration; enableScrollWheelControl(); } animate(); }); } function enableScrollWheelControl() { let scrollSpeed = 0.005; // Adjust this for sensitivity let currentAnimationTime = 0; window.addEventListener('wheel', (event) => { if (!mixer || !duration) return; // Update animation time based on scroll direction and speed currentAnimationTime += event.deltaY * scrollSpeed; currentAnimationTime = Math.max( 0, Math.min(duration, currentAnimationTime), ); // Clamp to animation duration // Manually update the animation mixer to reflect the scroll-based time mixer.setTime(currentAnimationTime); }); } function updateCameraFromAnimation(animationTime) { if (!mixer || !mixer._actions.length) return; // Ensure there are actions in the mixer const animationAction = mixer._actions[0]; // Get the first action if (!animationAction || !animationAction.getClip()) return; // Ensure there is a valid action const animationClip = animationAction.getClip(); // Get the clip if (!animationClip) return; // Check for camera-related tracks in the animation const cameraTracks = animationClip.tracks.filter((track) => track.name.startsWith('Camera'), ); if (cameraTracks.length === 0) { console.warn('No camera tracks found in the animation'); return; } cameraTracks.forEach((track) => { // Handle position updates if (track.name.endsWith('.position')) { const position = track.interpolate(animationTime); camera.position.set(position[0], position[1], position[2]); } camera.near = 0.1; camera.updateProjectionMatrix(); // Handle rotation updates (quaternion) if (track.name.endsWith('.quaternion')) { const quaternion = track.getValueAt(animationTime); camera.quaternion.set( quaternion[0], quaternion[1], quaternion[2], quaternion[3], ); } }); } function animate() { requestAnimationFrame(animate); const delta = clock.getDelta(); if (mixer) { mixer.update(delta); } renderer.render(scene, camera); }
Leave a Comment