import * as THREE from 'three'; import { GLTFLoader } from 'three/examples/jsm/Addons.js'; import { DRACOLoader } from 'three/examples/jsm/Addons.js'; import { createCustomJitterMaterial } from './materials/CustomJitterMaterial'; import { TextureLoader } from 'three'; export class ModelLoader { constructor() { } loadDRACOModelURL(modelURL, textureURL, scale) { return new Promise((resolve, reject) => { const loader = new GLTFLoader(); const dracoLoader = new DRACOLoader(); dracoLoader.setDecoderPath('/draco/'); loader.setDRACOLoader(dracoLoader); const applyMaterial = (object, texture) => { object.traverse((child) => { if (child.isMesh) { texture.encoding = THREE.sRGBEncoding; texture.needsUpdate = true; child.material = createCustomJitterMaterial(100, texture); } }); }; const processObject = (object, texture) => { object.scale.copy(scale); const box = new THREE.Box3().setFromObject(object); const height = box.max.y - box.min.y; object.position.y = height / 2; object.position.x = 0; applyMaterial(object, texture); resolve(object); }; if (textureURL) { const textureLoader = new TextureLoader(); textureLoader.load(textureURL, function (baseTexture) { baseTexture.flipY = false; const canvas = document.createElement('canvas'); const context = canvas.getContext('2d'); canvas.width = baseTexture.image.width; canvas.height = baseTexture.image.height; context.drawImage(baseTexture.image, 0, 0); const drawableTexture = new THREE.CanvasTexture(canvas); drawableTexture.flipY = false; loader.load(modelURL, function (gltf) { processObject(gltf.scene, drawableTexture); }, undefined, function (error) { reject(error); }); }, undefined, function (error) { reject(error); }); } else { loader.load(modelURL, function (gltf) { let extractedTexture = null; gltf.scene.traverse((child) => { if (child.isMesh && child.material && child.material.map) { if (!extractedTexture) { extractedTexture = child.material.map; } } }); let finalTexture; if (extractedTexture && extractedTexture.image) { // The texture from the GLTF is valid, make it a drawable CanvasTexture const canvas = document.createElement('canvas'); const context = canvas.getContext('2d'); canvas.width = extractedTexture.image.width; canvas.height = extractedTexture.image.height; context.drawImage(extractedTexture.image, 0, 0); finalTexture = new THREE.CanvasTexture(canvas); } else { // fallback: create a white texture const canvas = document.createElement('canvas'); canvas.width = 1024; canvas.height = 1024; const ctx = canvas.getContext('2d'); ctx.fillStyle = '#0044ffff'; ctx.fillRect(0, 0, 1024, 1024); finalTexture = new THREE.CanvasTexture(canvas); } finalTexture.flipY = false; processObject(gltf.scene, finalTexture); }, undefined, function (error) { reject(error); }); } }); } }