使用 3D 内容的 Node.js 开发者经常需要在不同格式之间进行转换:设计工具导出 OBJ,网页渲染器需要 GLB,3D 打印机要求 STL,制造流水线使用 3MF。使用统一且一致的 API 处理这些转换可以减少流水线中的外部工具数量,并将转换逻辑保留在应用代码中,便于测试和版本管理。.

@aspose/3d package (v24.12.0, MIT license) 提供了一个 TypeScript 优先的 API,用于在 Node.js 中读取和写入所有主流 3D 格式。本指南将演示最常见的转换工作流。.

安装

npm install @aspose/3d

要求:Node.js 18、20 或 22;TypeScript 5.0 或更高版本。唯一的运行时依赖是 xmldom.

支持的格式

下表列出了本指南涉及的格式及其读取/写入支持情况。.

格式扩展名读取写入备注
Wavefront OBJ.obj仅导入;读取 .mtl 材质文件
glTF 2.0 (JSON).gltf标准 Web 交付格式
glTF 2.0 (二进制).glb自包含,推荐用于网页
STL(ASCII/二进制).stl标准 3D 打印格式
3MF.3mf具有丰富元数据的制造格式
FBX.fbx否*否*导入/导出器已存在,但未接通格式自动检测;无法通过 scene.open()
COLLADA.dae基于 XML 的交换格式

注意:: OBJ 仅限导入(canExport: false)。要将 OBJ 内容转换为其他格式,请使用 scene.open() 并保存为受支持的导出格式,例如 glTF、STL 或 3MF。.

OBJ 转 GLB(网页交付)

将 OBJ 转换为二进制 glTF(GLB)是最常见的网页工作流。GLB 是一个自包含的二进制包:纹理、几何体和元数据都在同一个文件中,这使得它在 HTTP 传输以及 Three.js、Babylon.js 和 model-viewer 的直接加载时都非常高效。.

import { Scene } from '@aspose/3d';

function convertObjToGlb(inputPath: string, outputPath: string): void {
  const scene = new Scene();
  scene.open(inputPath);
  scene.save(outputPath);  // extension '.glb' selects binary GLB format
  console.log(`Converted ${inputPath} -> ${outputPath}`);
}

convertObjToGlb('model.obj', 'model.glb');

输出格式会根据文件扩展名推断。使用 .glb 用于二进制 GLB 或 .gltf 用于单独的 JSON + .bin 布局。.

OBJ 转 STL:为 3D 打印准备模型

STL 是 FDM 和 SLA 3D 打印的通用语言。PrusaSlicer、Bambu Studio 和 Chitubox 等切片软件都支持 STL。将 OBJ 转换为 STL 非常直接,因为两种格式都存储三角网格。.

import { Scene } from '@aspose/3d';

function convertObjToStl(inputPath: string, outputPath: string): void {
  const scene = new Scene();
  scene.open(inputPath);
  scene.save(outputPath);  // extension '.stl' selects STL format
  console.log(`STL written to ${outputPath}`);
}

convertObjToStl('part.obj', 'part.stl');

STL 不存储颜色、材质或 UV 数据。如果你的 OBJ 文件使用材质组,这些信息在导出时会被丢弃。若需保留颜色的打印格式,可考虑使用 3MF(见下文)。.

STL 转 glTF:从扫描仪或 CAD 输出到网页

结构光扫描仪和参数化 CAD 导出器通常输出 STL。将其转换为 glTF 可使几何体在基于网页的查看器和 AR 平台中直接访问,无需服务器端渲染步骤。.

import { Scene } from '@aspose/3d';

function convertStlToGltf(inputPath: string, outputPath: string): void {
  const scene = new Scene();
  scene.open(inputPath);
  // extension '.gltf' saves as JSON + .bin sidecar
  scene.save(outputPath);
  console.log(`glTF written to ${outputPath}`);
}

convertStlToGltf('scan_output.stl', 'scan_output.gltf');

因为 STL 不包含材质或纹理信息,生成的 glTF 文件将仅包含几何体。如果需要,您可以在加载后以编程方式将材质附加到场景节点上。.

3MF to glTF (Manufacturing to Visualization)

3D 制造格式(3MF)在增材制造工作流中越来越常用,因为它在几何体的同时存储颜色、材质、组件树和打印元数据。将 3MF 转换为 glTF 可在 Web 工具中实现后续可视化,同时保留场景结构。.

import { Scene } from '@aspose/3d';

function convert3mfToGlb(inputPath: string, outputPath: string): void {
  const scene = new Scene();
  scene.open(inputPath);
  scene.save(outputPath);  // extension '.glb' selects binary GLB format
  console.log(`3MF -> GLB: ${outputPath}`);
}

convert3mfToGlb('assembly.3mf', 'assembly.glb');

3MF files often contain multi-component assemblies. The scene graph produced by scene.open() 在…中保留组件层次结构 scene.rootNode.childNodes,,因此您可以在保存之前检查或操作各个部分。.

批量转换

在处理文件目录时,将每个转换包装在一个 try/catch 以防单个损坏的文件导致整个批次中止。.

import { Scene } from '@aspose/3d';
import { readdirSync } from 'fs';
import { join, basename, extname } from 'path';

interface ConversionResult {
  input: string;
  output: string;
  success: boolean;
  error?: string;
}

function batchConvertToGlb(
  inputDir: string,
  outputDir: string,
  extensions: string[] = ['.obj', '.stl', '.3mf', '.dae']  // .fbx excluded: format auto-detection not wired
): ConversionResult[] {
  const results: ConversionResult[] = [];

  const files = readdirSync(inputDir).filter((f) =>
    extensions.includes(extname(f).toLowerCase())
  );

  for (const file of files) {
    const inputPath = join(inputDir, file);
    const outputPath = join(outputDir, basename(file, extname(file)) + '.glb');

    try {
      const scene = new Scene();
      scene.open(inputPath);
      scene.save(outputPath);  // extension '.glb' infers GLB format
      results.push({ input: inputPath, output: outputPath, success: true });
    } catch (err) {
      const message = err instanceof Error ? err.message : String(err);
      results.push({ input: inputPath, output: outputPath, success: false, error: message });
      console.error(`Failed to convert ${file}: ${message}`);
    }
  }

  const succeeded = results.filter((r) => r.success).length;
  console.log(`Batch complete: ${succeeded}/${results.length} files converted.`);
  return results;
}

// Usage
batchConvertToGlb('./input', './output');

上述模式从输入目录读取每个受支持的文件扩展名,转换为 GLB,并记录任何失败而不中止循环。返回的数组 ConversionResult 对象可用于报告或重试逻辑。.

结论

@aspose/3d 覆盖了 Node.js TypeScript 应用程序中完整的格式转换需求,采用一致的两步 API:: scene.open() 用于加载,, scene.save() 用于写入。关键约束是,虽然存在 FBX 导入器和导出器类,但尚未接通格式自动检测,因此无法通过 scene.open().

欲了解更多关于 Scene, Node,,以及 Mesh 在这些示例中使用的类,请参阅本文档中的类参考页面。.