leLab / src /lib /meshLoaders.ts
jurmy24's picture
initial commit
9d3c32a
import {
LoadingManager,
MeshPhongMaterial,
Mesh,
Color,
Object3D,
Group,
BoxGeometry,
} from "three";
import { STLLoader } from "three/examples/jsm/loaders/STLLoader.js";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
import { ColladaLoader } from "three/examples/jsm/loaders/ColladaLoader.js";
import { OBJLoader } from "three/examples/jsm/loaders/OBJLoader.js";
/**
* Loads mesh files of different formats
* @param path The path to the mesh file
* @param manager The THREE.js loading manager
* @param done Callback function when loading is complete
*/
export const loadMeshFile = (
path: string,
manager: LoadingManager,
done: (result: Object3D | Group | Mesh | null, err?: Error) => void
) => {
// First try to get extension from the original path
let ext = path.split(/\./g).pop()?.toLowerCase();
// If the URL is a blob URL with a fragment containing the extension, use that
if (path.startsWith("blob:") && path.includes("#.")) {
const fragmentExt = path.split("#.").pop();
if (fragmentExt) {
ext = fragmentExt.toLowerCase();
}
}
// If we can't determine extension, try to check Content-Type
if (!ext) {
console.error(`Could not determine file extension for: ${path}`);
done(null, new Error(`Unsupported file format: ${path}`));
return;
}
switch (ext) {
case "gltf":
case "glb":
new GLTFLoader(manager).load(
path,
(result) => done(result.scene),
null,
(err) => done(null, err as Error)
);
break;
case "obj":
new OBJLoader(manager).load(
path,
(result) => done(result),
null,
(err) => done(null, err as Error)
);
break;
case "dae":
new ColladaLoader(manager).load(
path,
(result) => done(result.scene),
null,
(err) => done(null, err as Error)
);
break;
case "stl":
console.log(`🔧 Loading STL file: ${path}`);
new STLLoader(manager).load(
path,
(result) => {
console.log(`✅ STL loaded successfully: ${path}`);
const material = new MeshPhongMaterial();
const mesh = new Mesh(result, material);
done(mesh);
},
(progress) => {
console.log(`📊 STL loading progress: ${path}`, progress);
},
(err) => {
console.error(`❌ STL loading failed: ${path}`, err);
// Create a fallback basic geometry when STL fails to load
console.log(`🔄 Creating fallback geometry for: ${path}`);
const fallbackGeometry = new BoxGeometry(0.05, 0.05, 0.05); // Small 5cm cube
const fallbackMaterial = new MeshPhongMaterial({
color: 0xff6b35, // Orange color to indicate it's a fallback
transparent: true,
opacity: 0.7,
});
const fallbackMesh = new Mesh(fallbackGeometry, fallbackMaterial);
done(fallbackMesh);
}
);
break;
default:
done(null, new Error(`Unsupported file format: ${ext}`));
}
};
/**
* Creates a color in THREE.js format from a CSS color string
* @param color The CSS color string
* @returns A THREE.js Color
*/
export const createColor = (color: string): Color => {
return new Color(color);
};