Untitled
unknown
plain_text
a year ago
8.3 kB
6
Indexable
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);
}
Editor is loading...
Leave a Comment