Cách tải mô hình 3D trong TypeScript

Cách tải mô hình 3D trong TypeScript

Gói @aspose/3d gói cung cấp cho các ứng dụng TypeScript và Node.js một API đơn giản để mở các tệp cảnh 3D. Scene là đối tượng gốc: gọi scene.open() với đường dẫn tệp và các tùy chọn tải định dạng tùy chọn, sau đó duyệt scene.rootNode để truy cập hình học, vật liệu và biến đổi.

Hướng Dẫn Từng Bước

Bước 1: Cài đặt @aspose/3d qua npm

Thêm gói vào dự án của bạn. Không cần binary gốc hay công cụ biên dịch đặc thù cho nền tảng; chỉ cần Node.js 18 trở lên.

npm install @aspose/3d

Đối với các dự án TypeScript, các định nghĩa kiểu được đóng gói cùng gói:

##tsconfig.json: minimum required settings
{
  "compilerOptions": {
    "target": "ES2020",
    "module": "commonjs",
    "strict": true
  }
}

Bước 2: Nhập Scene và các tùy chọn riêng cho định dạng

Mỗi định dạng cung cấp lớp loader và đối tượng tùy chọn riêng dưới một đường dẫn phụ. Chỉ nhập những gì bạn cần:

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

Đối với các định dạng khác, mẫu này là giống hệt:

import { GltfLoadOptions } from '@aspose/3d/formats/gltf';
import { FbxLoadOptions } from '@aspose/3d/formats/fbx';
import { StlLoadOptions } from '@aspose/3d/formats/stl';

Bước 3: Mở tệp 3D bằng scene.open()

Tạo một Scene đối tượng, sau đó gọi scene.open() với đường dẫn tệp và một đối tượng tùy chọn load-options. Lệnh gọi là đồng bộ.

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');

Để tải từ một Buffer đã có trong bộ nhớ (hữu ích trong các ngữ cảnh serverless hoặc streaming):

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());

Bước 4: Duyệt qua các node của cảnh

Đồ thị cảnh là một cây có gốc tại scene.rootNode. Mỗi Node có thể chứa các nút con và một tùy chọn entity (mesh, camera, light, v.v.).

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);

Bước 5: Truy cập dữ liệu đỉnh lưới qua controlPoints

Khi thực thể của một nút là một Mesh, bạn có thể đọc các điểm điều khiển thô (đỉnh) từ controlPoints mảng. Mỗi mục là một Vector4 với x, y, z, và w các thành phần.

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)}`);
        }
    }
}

Bước 6: Cấu hình ObjLoadOptions để tải vật liệu

ObjLoadOptions tiết lộ các thuộc tính để kiểm soát cách .mtl các tệp vật liệu và kết cấu được giải quyết.

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}`);
    }
}

Các vấn đề thường gặp và cách khắc phục

Lỗi: Không thể tìm thấy mô-đun ‘@aspose/3d/formats/obj’ Các đường dẫn phụ của định dạng yêu cầu xuất gói Node.js 12.7+. Đảm bảo bạn đang sử dụng Node.js 18 trở lên. Nếu dùng TypeScript, hãy đặt "moduleResolution": "node16" hoặc "bundler" trong tsconfig.json.

scene.rootNode.childNodes rỗng sau khi gọi open() Một số tệp OBJ sử dụng ký tự xuống dòng không chuẩn hoặc thiếu ký tự xuống dòng cuối cùng. Xác minh tệp là OBJ hợp lệ bằng cách mở nó trong trình soạn thảo văn bản. Cũng hãy chắc chắn rằng bạn đã truyền ObjLoadOptions và không phải một generic LoadOptions: các tùy chọn đặc thù cho định dạng là bắt buộc để phân phối đúng.

mảng controlPoints có độ dài bằng 0 Lưới có thể đã được tải nhưng không chứa hình học nào (ví dụ, một nhóm rỗng trong OBJ). Sử dụng mesh.polygonCount để kiểm tra trước khi lặp qua các đỉnh.

Việc sử dụng bộ nhớ cao đối với các tệp lớn Tải từ bộ đệm với scene.openFromBuffer() không giảm bộ nhớ tối đa: toàn bộ tệp phải được phân tích. Đối với các tệp lớn (> 100 MB), hãy đảm bảo quá trình Node.js của bạn có đủ heap: node --max-old-space-size=4096 yourScript.js.

Lỗi kiểu: ’entity’ có kiểu ‘unknown’ Cái entity thuộc tính được khai báo một cách chung chung. Ép sang any hoặc sang một lớp cụ thể (Mesh, Camera, v.v.) tùy thuộc vào những gì bạn mong đợi trong cảnh của mình.

Câu hỏi thường gặp (FAQ)

Các định dạng nào có thể được tải bằng scene.open()? OBJ, glTF 2.0 (.gltf + .bin), GLB, STL, 3MF, FBX và COLLADA (.dae) đều được hỗ trợ để nhập. Hãy truyền lớp tương ứng *LoadOptions cho mỗi định dạng.

Tôi có thể tải một tệp mà không chỉ định tùy chọn không? Có. scene.open('model.glb') hoạt động mà không cần tùy chọn cho các định dạng không yêu cầu cấu hình đặc biệt. Việc truyền tùy chọn được khuyến nghị cho OBJ vì độ phân giải vật liệu phụ thuộc vào enableMaterials.

Quá trình tải có chạy bất đồng bộ không? Không. scene.open()scene.openFromBuffer() đều đồng bộ. Đóng gói chúng trong một luồng worker hoặc setImmediate nếu bạn cần giữ vòng lặp sự kiện phản hồi.

Xuất OBJ có được hỗ trợ không? Có. Xuất OBJ được hỗ trợ qua scene.save('output.obj'). Tệp .mtl vật liệu được ghi tự động bên cạnh the .obj tệp.

Tệp .mtl được mong đợi ở đâu khi tải OBJ? Mặc định, parser tìm kiếm .mtl tệp được tham chiếu trong OBJ (mtllib directive) tương đối với thư mục của tệp OBJ. Đảm bảo cả hai tệp đều nằm trong cùng một thư mục.

Xem Thêm

 Tiếng Việt