故障排除指南

本页涵盖在 TypeScript 和 Node.js 项目中使用 @aspose/3d 时最常见的错误,提供根本原因解释和已验证的修复方案。


模块解析错误

Error: Cannot find module '@aspose/3d/formats/obj'

根本原因: TypeScript 的模块解析策略不支持 Node.js 风格的子路径导出(exportspackage.json 中),除非将 moduleResolution 设置为 nodenode16

Fix: 将 moduleResolution 设置为 "node" 在你的 tsconfig.json 中:

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "commonjs",
    "moduleResolution": "node",
    "esModuleInterop": true,
    "strict": true
  }
}

如果您使用 TypeScript 5.x 并配合 "module": "node16""module": "nodenext",请使用 "moduleResolution": "node16" 进行匹配。


SyntaxError: Cannot use import statement in a module

Root cause: 编译后的 JavaScript 正在使用 require() 语义运行,但输出包含 ES 模块 import 语法;当 module 设置为 es2020esnext 时会出现这种情况,但 Node.js 运行时期望的是 CommonJS。

Fix: 使用 "module": "commonjs"tsconfig.json 中,并直接使用 node 运行已编译的 .js 文件:

{
  "compilerOptions": {
    "module": "commonjs",
    "outDir": "./dist"
  }
}

然后编译并运行:

npx tsc
node dist/main.js

Error: Cannot find module '@aspose/3d'

根本原因: 未安装该软件包,或 node_modules 已过时。

修复:

npm install @aspose/3d

验证安装:

node -e "const { Scene } = require('@aspose/3d'); console.log('OK', new Scene().constructor.name);"

加载后空场景

场景加载,但rootNode.childNodes为空

根本原因 (1):文件格式将所有几何体直接放在 rootNode.entity 上,而不是作为子节点。这在单网格 STL 文件中很常见。

诊断:

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

const scene = new Scene();
scene.open('model.stl');

// Check rootNode directly
if (scene.rootNode.entity) {
    console.log(`Root entity: ${scene.rootNode.entity.constructor.name}`);
}
console.log(`Child count: ${scene.rootNode.childNodes.length}`);

修复: 遍历应从 scene.rootNode 本身开始,而不仅仅是它的子节点:

function visit(node: any): void {
    if (node.entity instanceof Mesh) {
        const m = node.entity as Mesh;
        console.log(`Mesh: ${m.controlPoints.length} vertices`);
    }
    for (const child of node.childNodes) {
        visit(child);
    }
}
visit(scene.rootNode);

根本原因 (2): 文件路径错误或文件为零字节。调用 open() 前,请检查文件是否存在且非空。

import * as fs from 'fs';

const path = 'model.obj';
if (!fs.existsSync(path)) throw new Error(`File not found: ${path}`);
const stat = fs.statSync(path);
if (stat.size === 0) throw new Error(`File is empty: ${path}`);

加载 OBJ 后材料列表为空

根本原因:在 ObjLoadOptions 中,材质加载默认被禁用。该库在加载几何体时未读取 .mtl 辅助文件。

修复: 设置 enableMaterials = true:

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

const scene = new Scene();
const opts = new ObjLoadOptions();
opts.enableMaterials = true;
scene.open('model.obj', opts);

还请确保 .mtl 文件与 .obj 文件位于同一目录,因为库会相对于 .obj 路径解析它。


格式和 I/O 错误

openFromBuffer 抛出未识别的格式错误

根本原因: 缓冲区内容不是可识别的二进制格式,或缓冲区已损坏(被截断、编码错误,或使用 base64 而非原始字节)。

诊断:

const buffer = fs.readFileSync('model.glb');
console.log('Buffer size:', buffer.length, 'bytes');
console.log('First 4 bytes (hex):', buffer.slice(0, 4).toString('hex'));
// GLB magic: 676c5446 ("glTF")
// STL binary starts with 80 bytes of header; no fixed magic
// OBJ is text: openFromBuffer may not detect format

修复:对于基于文本的格式(OBJ、COLLADA),传递相应的选项类以提示格式:

import { ObjLoadOptions } from '@aspose/3d/formats/obj';
scene.openFromBuffer(buffer, new ObjLoadOptions());

输出的 GLB 在 3D 查看器中以 JSON 打开

根本原因: GltfSaveOptions.binaryMode 默认是 false,即使输出文件名是 .glb,也会生成 .gltf JSON 输出。

修复: 明确设置 binaryMode = true:

import { GltfSaveOptions } from '@aspose/3d/formats/gltf';

const opts = new GltfSaveOptions();
opts.binaryMode = true;
scene.save('output.glb', opts);

STL 输出在切片软件中没有颜色或材质数据

根本原因: STL 格式在其标准规范中不支持材质或颜色。支持颜色的切片软件使用的专有扩展不受 @aspose/3d 支持。

修复: 导出为 3MF,而不是其他格式,因为它支持颜色和材质元数据:

scene.save('output.3mf');

TypeScript 编译错误

Property 'controlPoints' does not exist on type 'Entity'

Root cause: Entity 是基类;Mesh 是具有几何属性的具体类型。访问网格特定成员之前,需要一个 instanceof 检查。

修复:

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

if (node.entity instanceof Mesh) {
    const mesh = node.entity as Mesh;
    console.log(mesh.controlPoints.length);
}

Type 'null' is not assignable to type 'Node'

Root cause: getChildNode() 返回 Node | null。TypeScript 严格模式要求您处理 null 情况。

修复:

const child = node.getChildNode('wheel');
if (!child) throw new Error('Node "wheel" not found');
// child is now Node, not null

Cannot find name 'GltfSaveOptions'

Root cause: GltfSaveOptions 位于子路径模块 @aspose/3d/formats/gltf,而不是包根目录。

修复:从子路径导入:

import { GltfSaveOptions } from '@aspose/3d/formats/gltf';

内存和性能问题

处理大型 FBX 文件时内存耗尽

Root cause: 非常大的 FBX 文件(>200 MB)会分配大量堆内存。Node.js 在 64 位系统上的默认堆约为 1.5 GB,但对于多场景文件可能不足。

修复: 增加 Node.js 堆大小:

node --max-old-space-size=8192 dist/convert.js

当内存受限时,请顺序处理文件,而不是并行处理:

for (const file of files) {
    const scene = new Scene();
    scene.open(file);
    scene.save(file.replace('.fbx', '.glb'));
    // scene goes out of scope; GC can reclaim
}

另请参阅

 中文