File size: 3,332 Bytes
9d3c32a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
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);
};