import fs from "fs"; import path from "path"; import { spawnSync } from "child_process"; import { MODEL_CONVERTER } from "../../paths.js"; // 格式映射 const FORMAT_EXT = { collada: ".dae", stp: ".stp", obj: ".obj", objnomtl: ".obj", stl: ".stl", stlb: ".stl", ply: ".ply", plyb: ".ply", "3ds": ".3ds", gltf2: ".gltf", glb2: ".glb", assbin: ".assbin", assxml: ".assxml", x3d: ".x3d", fbx: ".fbx", fbxa: ".fbx", "3mf": ".3mf", pbrt: ".pbrt", assjson: ".json" }; // 缓存 let importExts = null; let exportFormats = null; // 获取支持的导入格式 export const getImportExtensions = () => { if (!importExts) { const r = spawnSync(MODEL_CONVERTER, ["listext"], { encoding: "utf8" }); if (!r.stdout) throw new Error("无法获取支持的导入格式,请检查 model_converter.exe 是否存在"); importExts = r.stdout.trim().split(";").map(e => e.replace("*", "").toLowerCase()); } return importExts; }; // 获取支持的导出格式 export const getExportFormats = () => { if (!exportFormats) { const r = spawnSync(MODEL_CONVERTER, ["listexport"], { encoding: "utf8" }); if (!r.stdout) throw new Error("无法获取支持的导出格式,请检查 model_converter.exe 是否存在"); exportFormats = r.stdout.trim().split(/\r?\n/).filter(Boolean); } return exportFormats; }; // 转换文件 export const convert = async (inputFile, outputFile, format, cwd = process.cwd()) => { const r = spawnSync(MODEL_CONVERTER, ["export", inputFile, outputFile, `-f${format}`], { encoding: "utf8", cwd }); if (r.status !== 0) throw new Error(r.stderr || r.stdout || "转换失败"); return outputFile; }; // 获取输出文件扩展名 const getOutputExt = (format) => { return FORMAT_EXT[format] || "." + format; }; // 处理单个文件 export const processFile = async (file, config) => { const cwd = process.cwd(); const { dir, name } = path.parse(file); const outputExt = getOutputExt(config.outputFormat); const outputFile = path.join(dir || "", `${name}${outputExt}`); const absolutePath = path.join(cwd, file); if (!fs.existsSync(absolutePath)) { return { ok: false, file, reason: "文件不存在" }; } await convert(file, outputFile, config.outputFormat, cwd); return { ok: true, file, output: outputFile }; };