如何在 TypeScript 中加载 3D 模型
该 @aspose/3d package 为 TypeScript 和 Node.js 应用程序提供了一个用于打开 3D 场景文件的简洁 API。. Scene 是根对象:调用 scene.open() 使用文件路径和可选的特定格式加载选项,然后遍历 scene.rootNode 以访问几何体、材质和变换。.
分步指南
步骤 1:通过 npm 安装 @aspose/3d
将该包添加到项目中。无需本机二进制文件或平台特定的构建工具;仅需 Node.js 18 或更高版本。.
npm install @aspose/3d对于 TypeScript 项目,类型定义已随包一起提供::
##tsconfig.json: minimum required settings
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"strict": true
}
}步骤 2:导入 Scene 和特定格式的选项
每种格式在子路径下公开各自的加载器类和选项对象。仅导入所需的部分::
import { Scene } from '@aspose/3d';
import { ObjLoadOptions } from '@aspose/3d/formats/obj';其他格式的使用模式相同::
import { GltfLoadOptions } from '@aspose/3d/formats/gltf';
import { FbxLoadOptions } from '@aspose/3d/formats/fbx';
import { StlLoadOptions } from '@aspose/3d/formats/stl';步骤 3:使用 scene.open() 打开 3D 文件
创建一个 Scene 实例,然后调用 scene.open() 使用文件路径和可选的 load-options 对象。此调用是同步的。.
import { Scene } from '@aspose/3d';
import { ObjLoadOptions } from '@aspose/3d/formats/obj';
const scene = new Scene();
const options = new ObjLoadOptions();
options.enableMaterials = true;
scene.open('model.obj', options);
console.log('Scene loaded successfully');从一个 Buffer 已在内存中的(在无服务器或流式场景中很有用)::
import * as fs from 'fs';
import { Scene } from '@aspose/3d';
import { ObjLoadOptions } from '@aspose/3d/formats/obj';
const buffer = fs.readFileSync('model.obj');
const scene = new Scene();
scene.openFromBuffer(buffer, new ObjLoadOptions());步骤 4:遍历场景节点
场景图是以 scene.rootNode.为根的树。每个 Node 可以包含子节点和可选的 entity (网格、相机、灯光等)。.
import { Scene } from '@aspose/3d';
import { ObjLoadOptions } from '@aspose/3d/formats/obj';
const scene = new Scene();
scene.open('model.obj', new ObjLoadOptions());
function visitNode(node: any, depth: number = 0): void {
const indent = ' '.repeat(depth);
console.log(`${indent}Node: ${node.name}`);
if (node.entity) {
console.log(`${indent} Entity type: ${node.entity.constructor.name}`);
}
for (const child of node.childNodes) {
visitNode(child, depth + 1);
}
}
visitNode(scene.rootNode);步骤 5:通过 controlPoints 访问网格顶点数据
当节点的实体是 a Mesh,,您可以从 the 读取原始控制点(顶点) controlPoints 数组。每个条目是 a Vector4 带有 x, y, z,,并且 w 组件。.
import { Scene } from '@aspose/3d';
import { ObjLoadOptions } from '@aspose/3d/formats/obj';
const scene = new Scene();
scene.open('model.obj', new ObjLoadOptions());
for (const node of scene.rootNode.childNodes) {
if (!node.entity) continue;
const entity = node.entity;
// Check if the entity is a Mesh by duck-typing controlPoints
if ('controlPoints' in entity) {
const mesh = entity as any;
console.log(`Mesh "${node.name}": ${mesh.controlPoints.length} vertices`);
// Print first three vertices
for (let i = 0; i < Math.min(3, mesh.controlPoints.length); i++) {
const v = mesh.controlPoints[i];
console.log(` v[${i}]: x=${v.x.toFixed(4)}, y=${v.y.toFixed(4)}, z=${v.z.toFixed(4)}`);
}
}
}步骤 6:配置 ObjLoadOptions 以加载材质
ObjLoadOptions 公开属性以控制伴随的 .mtl 材质文件和纹理的解析方式。.
import { Scene } from '@aspose/3d';
import { ObjLoadOptions } from '@aspose/3d/formats/obj';
const options = new ObjLoadOptions();
options.enableMaterials = true; // parse .mtl file if present
const scene = new Scene();
scene.open('model.obj', options);
// Inspect materials attached to nodes
for (const node of scene.rootNode.childNodes) {
if (node.entity && node.entity.material) {
console.log(`Material on "${node.name}": ${node.entity.material.constructor.name}`);
}
}常见问题及解决方案
错误:找不到模块 ‘@aspose/3d/formats/obj’ 格式子路径需要 Node.js 12.7+ 的包导出。确保您使用的是 Node.js 18 或更高版本。如果使用 TypeScript,请设置 "moduleResolution": "node16" 或 "bundler" 在 tsconfig.json.
在调用 open() 后,scene.rootNode.childNodes 为空 某些 OBJ 文件使用非标准的行结束符或缺少结尾换行符。通过在文本编辑器中打开来验证该文件是有效的 OBJ。还请确认您传入了 ObjLoadOptions 而不是通用的 LoadOptions: 特定格式的选项是正确分发所必需的。.
controlPoints 数组的长度为零 网格可能已加载,但不包含几何体(例如,OBJ 中的空组)。使用 mesh.polygonCount 在迭代顶点之前进行检查。.
大文件的内存使用率很高 使用 Load-from-buffer 与 scene.openFromBuffer() 不会降低峰值内存:必须解析整个文件。对于大文件(> 100 MB),请确保您的 Node.js 进程拥有足够的堆内存:: node --max-old-space-size=4096 yourScript.js.
类型错误:’entity’ 的类型为 ‘unknown’ 该 entity 属性的类型定义过于宽泛。请强制转换为 any 或到特定的类(Mesh, Camera,,等等)取决于您在场景中期望的内容。.
常见问题 (FAQ)
使用 scene.open() 可以加载哪些格式?? OBJ、glTF 2.0(.gltf + .bin)、GLB、STL、3MF、FBX 和 COLLADA(.dae)均受支持用于导入。传入相应的 *LoadOptions 每种格式的类。.
我可以在不指定选项的情况下加载文件吗?? 是的。. scene.open('model.glb') 对于不需要特殊配置的格式,可以在不提供选项的情况下工作。建议对 OBJ 传入选项,因为材质分辨率取决于 enableMaterials.
加载是异步执行的吗?? 不是。. scene.open() 和 scene.openFromBuffer() 是同步的。将它们包装在工作线程中或 setImmediate 如果您需要保持事件循环的响应性。.
是否支持 OBJ 导出?? 是的。OBJ 导出通过以下方式支持: scene.save('output.obj').。该 .mtl 材质文件会自动写入到与 .obj 文件一起。.
加载 OBJ 时,.mtl 文件预期位于何处?? 默认情况下,解析器会查找 .mtl 在 OBJ 中引用的文件(mtllib 指令)相对于 OBJ 文件所在的目录。确保两个文件位于同一文件夹中。.