Как да заредим 3D модели в TypeScript
Пакетът @aspose/3d предоставя на TypeScript и Node.js приложения прост API за отваряне на 3D сценични файлове. Scene е коренният обект: извикайте scene.open() с път към файла и незадължителни опции за зареждане, специфични за формата, след което обходете scene.rootNode, за да получите достъп до геометрия, материали и трансформации.
Ръководство стъпка по стъпка
Стъпка 1: Инсталирайте @aspose/3d чрез npm
Добавете пакета към вашия проект. Не са необходими нативни бинарни файлове или специфични за платформата инструменти за изграждане; само Node.js 18 или по‑нов.
npm install @aspose/3dЗа TypeScript проекти типови дефиниции се доставят заедно с пакета:
##tsconfig.json: minimum required settings
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"strict": true
}
}Стъпка 2: Импортиране на сцена и специфични за формата опции
Всеки формат разкрива свой собствен клас за зареждане и обект с опции под подпът. Импортирайте само това, което ви е необходимо:
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: Отворете 3D файл, използвайки scene.open()
Създайте инстанция на Scene, след което извикайте scene.open() с пътя към файла и незадължителен обект за опции за зареждане. Извикването е синхронно.
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
Когато ентитетът на възела е Mesh, можете да прочетете суровите контролни точки (върхове) от масива controlPoints. Всеки елемент е 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.material) {
console.log(`Material on "${node.name}": ${node.material.constructor.name}`);
}
}Общи проблеми и решения
Грешка: Не може да се намери модулът ‘@aspose/3d/formats/obj’
Подпътеките за формати изискват пакетни експорти на Node.js 12.7+. Уверете се, че използвате Node.js 18 или по-нов. Ако използвате TypeScript, задайте "moduleResolution": "node16" или "bundler" в tsconfig.json.
scene.rootNode.childNodes е празен след open()
Някои OBJ файлове използват нестандартни крайни знаци на реда или нямат завършващ нов ред. Проверете дали файлът е валиден OBJ, като го отворите в текстов редактор. Също така се уверете, че сте предали ObjLoadOptions и не общ LoadOptions: опциите, специфични за формата, са необходими за правилно разпределяне.
масивът controlPoints има нулева дължина
Мрежата може да е заредена, но да не съдържа геометрия (например празна група в OBJ). Използвайте mesh.polygonCount, за да проверите преди да итерирате върховете.
Използването на памет е високо при големи файлове
Зареждането от буфер с scene.openFromBuffer() не намалява пиковото използване на памет: целият файл трябва да бъде анализиран. За големи файлове (> 100 MB) уверете се, че процесът Node.js разполага с достатъчен heap: 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.
Къде се очаква .mtl файлът при зареждане на OBJ?
По подразбиране парсерът търси файла .mtl, посочен вътре в OBJ (директива mtllib), относително към директорията на OBJ файла. Уверете се, че и двата файла са в една и съща папка.