Как да заредим 3D модели в TypeScript

Как да заредим 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 файла. Уверете се, че и двата файла са в една и съща папка.

Виж също

 Български