كيفية تحميل نماذج ثلاثية الأبعاد في TypeScript
حزمة @aspose/3d توفر لتطبيقات TypeScript و Node.js واجهة برمجة تطبيقات بسيطة لفتح ملفات المشاهد ثلاثية الأبعاد. 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: افتح ملفًا ثلاثي الأبعاد باستخدام 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 ميغابايت)، تأكد من أن عملية 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.
أين يُتوقع وجود ملف .mtl عند تحميل OBJ؟
بشكل افتراضي، يبحث المحلل عن ملف .mtl المشار إليه داخل OBJ (توجيه mtllib) بالنسبة إلى دليل ملف OBJ. تأكد من أن كلا الملفين في نفس المجلد.