You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
102 lines
4.2 KiB
102 lines
4.2 KiB
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 = '#fff';
|
|
ctx.fillRect(0, 0, 512, 512);
|
|
finalTexture = new THREE.CanvasTexture(canvas);
|
|
}
|
|
|
|
finalTexture.flipY = false;
|
|
|
|
processObject(gltf.scene, finalTexture);
|
|
}, undefined, function (error) {
|
|
reject(error);
|
|
});
|
|
}
|
|
});
|
|
}
|
|
}
|