كيفية بناء شبكة ثلاثية الأبعاد برمجياً باستخدام TypeScript

كيفية بناء شبكة ثلاثية الأبعاد برمجياً باستخدام TypeScript

يتيح لك Aspose.3D FOSS for TypeScript بناء هندسة ثلاثية الأبعاد بالكامل في الشيفرة دون تحميل أي ملف. تقوم بتعريف مواضع الرؤوس كنقاط تحكم، وتحديد وجوه المضلعات بواسطة الفهرس، وإرفاق عناصر الرؤوس الاختيارية مثل normals، UVs، أو ألوان الرؤوس. يمكن حفظ النتيجة بأي تنسيق قابل للكتابة: glTF، GLB، STL، FBX، أو COLLADA.

المتطلبات المسبقة

  • Node.js 18 أو أحدث
  • TypeScript 5.0 أو أحدث
  • @aspose/3d مثبت (انظر الخطوة 1)

دليل خطوة بخطوة

الخطوة 1: تثبيت @aspose/3d

npm install @aspose/3d

لا يلزم أي إضافات أصلية أو مكتبات نظام. الحزمة تتضمن تعريفات نوع TypeScript.

الحد الأدنى tsconfig.json:

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "commonjs",
    "moduleResolution": "node",
    "esModuleInterop": true,
    "strict": true
  }
}

الخطوة 2: إنشاء مشهد وعقدة

A Scene هو الحاوي الأعلى مستوى. يجب إرفاق جميع الهندسة إلى Node داخل شجرة المشهد:

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

const scene = new Scene();
const node = scene.rootNode.createChildNode('triangle');

createChildNode(name) ينشئ عقدة مسماة ويربطها كطفل للعقدة الحالية. الكائن Node المعاد هو المكان الذي ستُرفق فيه الشبكة في الخطوة 7.


الخطوة 3: إنشاء كائن شبكة

Mesh يحتوي على مواضع الرؤوس وتعريفات المضلع. أنشئ واحدًا مع اسم اختياري:

import { Mesh } from '@aspose/3d/entities';

const mesh = new Mesh('triangle');

تبدأ الشبكة فارغة: لا توجد رؤوس ولا وجوه. تقوم بإضافتها في الخطوات التالية.


الخطوة 4: إضافة نقاط التحكم (الرؤوس)

نقاط التحكم هي مواضع الرؤوس في الفضاء المحلي. ادفع قيم Vector4 إلى mesh.controlPoints. المكوّن الرابع (w) هو 1 للمواقع:

import { Vector4 } from '@aspose/3d/utilities';

mesh.controlPoints.push(new Vector4(0.0, 0.0, 0.0, 1.0)); // index 0
mesh.controlPoints.push(new Vector4(1.0, 0.0, 0.0, 1.0)); // index 1
mesh.controlPoints.push(new Vector4(0.5, 1.0, 0.0, 1.0)); // index 2

تُشير إلى هذه المواقع باستخدام الفهرس القائم على الصفر عند تعريف وجوه المضلع.


الخطوة 5: إنشاء أوجه مضلع

createPolygon() يحدد وجهًا عن طريق سرد مؤشرات الرؤوس بالترتيب. ثلاثة مؤشرات تُكوّن مثلثًا:

mesh.createPolygon(0, 1, 2);

يمكنك أيضًا تعريف رباعيات (أربعة مؤشرات) أو مضلعات عشوائية للتنسيقات التي تدعمها. بالنسبة إلى glTF، ستقوم المكتبة تلقائيًا بتحويل الرباعيات والـ n‑gons إلى مثلثات عند التصدير.


الخطوة 6: إضافة Vertex Normals

تحسّن المتجهات العادية جودة العرض. استخدم mesh.createElement() لإنشاء VertexElementNormal، جمع المتجهات العادية في مصفوفة، ثم استدعِ setData() لتخزينها. تُعيد الدالة data نسخة دفاعية — إضافة عناصر إليها لا تأثير لها. استخدم FVector3 (عدد عائم بدقة مفردة) لبيانات العادية، وليس Vector4.

import { VertexElementNormal } from '@aspose/3d/entities';
import { VertexElementType, MappingMode, ReferenceMode } from '@aspose/3d/entities';
import { FVector3 } from '@aspose/3d/utilities';

const normals = mesh.createElement(
    VertexElementType.NORMAL,
    MappingMode.CONTROL_POINT,
    ReferenceMode.DIRECT
) as VertexElementNormal;

// Build the normal array, then call setData() — do NOT push to normals.data
normals.setData([
    new FVector3(0, 0, 1), // normal for vertex 0 (pointing +Z)
    new FVector3(0, 0, 1), // normal for vertex 1
    new FVector3(0, 0, 1), // normal for vertex 2
]);

MappingMode.CONTROL_POINT يعني واحد عادي لكل رأس. ReferenceMode.DIRECT يعني أن مصفوفة البيانات مفهرسة مباشرةً بواسطة فهرس رأس المضلع.


الخطوة 7: إرفاق الشبكة وحفظ إلى glTF

قم بتعيين الشبكة إلى العقدة عبر node.entity، ثم احفظ المشهد:

import { GltfSaveOptions, GltfFormat } from '@aspose/3d/formats/gltf';

node.entity = mesh;

const saveOpts = new GltfSaveOptions();
scene.save('triangle.gltf', GltfFormat.getInstance(), saveOpts);
console.log('Triangle mesh saved to triangle.gltf');

لإنتاج ملف .glb واحد مكتمل ذاتيًا بدلاً من ذلك، اضبط saveOpts.binaryMode = true وغيّر امتداد ملف الإخراج إلى .glb.

مثال كامل

النص التالي هو البرنامج الكامل الذي يجمع جميع الخطوات السابقة:

import { Scene } from '@aspose/3d';
import { Mesh, VertexElementNormal } from '@aspose/3d/entities';
import { VertexElementType, MappingMode, ReferenceMode } from '@aspose/3d/entities';
import { Vector4, FVector3 } from '@aspose/3d/utilities';
import { GltfSaveOptions, GltfFormat } from '@aspose/3d/formats/gltf';

const scene = new Scene();
const node = scene.rootNode.createChildNode('triangle');

const mesh = new Mesh('triangle');

mesh.controlPoints.push(new Vector4(0.0, 0.0, 0.0, 1.0));
mesh.controlPoints.push(new Vector4(1.0, 0.0, 0.0, 1.0));
mesh.controlPoints.push(new Vector4(0.5, 1.0, 0.0, 1.0));

mesh.createPolygon(0, 1, 2);

const normals = mesh.createElement(
    VertexElementType.NORMAL,
    MappingMode.CONTROL_POINT,
    ReferenceMode.DIRECT
) as VertexElementNormal;

// setData() is the correct API — normals.data returns a defensive copy; pushing to it has no effect
normals.setData([
    new FVector3(0, 0, 1),
    new FVector3(0, 0, 1),
    new FVector3(0, 0, 1),
]);

node.entity = mesh;

const saveOpts = new GltfSaveOptions();
scene.save('triangle.gltf', GltfFormat.getInstance(), saveOpts);
console.log('Triangle mesh saved to triangle.gltf');

تشغيل باستخدام ts-node:

npx ts-node triangle.ts

مشكلات شائعة

المشكلةالسببالإصلاح
mesh.controlPoints.length يساوي 0 بعد الدفعالشبكة غير مُشار إليها من قبل أي عقدةادفع قبل تعيين node.entity؛ الترتيب لا يهم، لكن تحقق من المرجع
التصدير ينتج هندسة فارغةnode.entity غير مُعينتأكد من node.entity = mesh قبل استدعاء scene.save()
عدم تطابق عدد المتجهات العاديةالمصفوفة الممررة إلى setData() أقصر من controlPointsأضف إدخال FVector3 واحد لكل نقطة تحكم عند استخدام MappingMode.CONTROL_POINT
عارض glTF يظهر شبكة سوداءالمتجهات العادية تشير إلى الداخلاعكس ترتيب الالتفاف في createPolygon (مثلاً، 0, 2, 1) أو عكس متجهات العادية
TypeScript: خاصية ’normals.data’ غير موجودةمسار الاستيراد خاطئاستورد VertexElementNormal من @aspose/3d/entities، وليس من جذر @aspose/3d

الأسئلة المتكررة

هل يمكنني إنشاء رباعيات بدلاً من المثلثات؟ نعم. مرّر أربعة مؤشرات إلى createPolygon(0, 1, 2, 3). تقوم المكتبة بتحويل الرباعيات إلى مثلثات أثناء التصدير إلى الصيغ التي تتطلب مثلثات (glTF, STL).

ما الفرق بين MappingMode.CONTROL_POINT و MappingMode.POLYGON_VERTEX؟
CONTROL_POINT يخزن قيمة واحدة لكل رأس فريد. POLYGON_VERTEX يخزن قيمة واحدة لكل زوج مضلع‑رأس، مما يسمح بـ normals مختلفة عند نفس الرأس عندما يكون جزءًا من مضلعات متعددة (hard edges).

هل أحتاج إلى تحويل الشبكة إلى مثلثات قبل حفظها كـ STL؟
لا. تتعامل المكتبة مع تحويل المثلثات تلقائيًا عند التصدير إلى الصيغ التي تتطلب مثلثات. يمكنك تعريف رباعيات وأشكال متعددة الأضلاع في الشبكة وحفظها كـ STL مباشرة.

كيف أضيف إحداثيات UV؟
استخدم mesh.createElementUV(TextureMapping.Diffuse, MappingMode.CONTROL_POINT, ReferenceMode.DIRECT) لإنشاء VertexElementUV، ثم استدعِ setData([...]) مع مصفوفة من قيم FVector2 أو FVector3 — قيمة واحدة لكل نقطة تحكم. المستخرج data getter يُعيد نسخة؛ لا تدفع إليه مباشرةً.

هل يمكنني بناء عدة شبكات في مشهد واحد؟
نعم. أنشئ عدة عقد تحت scene.rootNode وعيّن Mesh منفصل لكل خاصية entity الخاصة بالعقدة.

انظر أيضًا

 العربية