چگونه یک مش سهبعدی را بهصورت برنامهنویسی در TypeScript بسازیم
Aspose.3D FOSS برای TypeScript به شما امکان میدهد که هندسه 3D را بهصورت کامل در کد بسازید بدون اینکه فایلی را بارگذاری کنید. شما موقعیتهای vertex را بهعنوان control points تعریف میکنید، سطوح polygon را بر اساس ایندکس مشخص میکنید و عناصر اختیاری vertex مانند normals، UVs یا vertex colors را اضافه میکنید. نتیجه میتواند در هر فرمت قابل نوشتن ذخیره شود: 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
}
}مرحله ۲: ایجاد یک صحنه و گره
یک Scene بالاترین سطحِ کانتینر است. تمام هندسه باید به یک Node داخل درخت صحنه متصل شود:
import { Scene } from '@aspose/3d';
const scene = new Scene();
const node = scene.rootNode.createChildNode('triangle');createChildNode(name) یک گره نامگذاریشده ایجاد میکند و آن را بهعنوان فرزند گرهٔ فعلی وصل میسازد. شیء Node بازگرداندهشده جایی است که در گام ۷ مش را به آن پیوست خواهید کرد.
مرحله ۳: ایجاد یک شی مش
Mesh موقعیتهای راس و تعاریف چندضلعی را نگه میدارد. یک مورد با نام اختیاری بسازید:
import { Mesh } from '@aspose/3d/entities';
const mesh = new Mesh('triangle');مش خالی شروع میشود: هیچ رئوس و هیچ سطحی وجود ندارد. شما آنها را در مراحل بعدی اضافه میکنید.
مرحله ۴: افزودن نقاط کنترل (رئوس)
نقاط کنترل موقعیتهای راس در فضای محلی هستند. مقادیر 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‑گونها را هنگام خروجیگیری مثلثبندی میکند.
مرحله ۶: افزودن نرمالهای راس
نرمالها کیفیت رندرینگ را بهبود میبخشند. از 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 به معنای این است که آرایه دادهها بهصورت مستقیم توسط شاخص راس چندضلعی ایندکس میشود.
مرحله ۷: مش را پیوست کنید و به 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مشکلات رایج
| Issue | Cause | Fix |
|---|---|---|
mesh.controlPoints.length پس از push برابر 0 است | مش توسط هیچ نودی ارجاع داده نشده | قبل از اختصاص node.entity، push کنید؛ ترتیب مهم نیست، اما مرجع را بررسی کنید |
| صادرات هندسه خالی تولید میکند | node.entity اختصاص داده نشده | قبل از فراخوانی scene.save()، اطمینان حاصل کنید node.entity = mesh انجام شده است |
| عدم تطابق تعداد نرمالها | آرایهای که به setData() پاس داده میشود کوتاهتر از controlPoints است | هنگام استفاده از MappingMode.CONTROL_POINT، برای هر نقطه کنترل یک ورودی FVector3 اضافه کنید |
| نمایشگر glTF مش سیاه نشان میدهد | نرمالها به سمت داخل جهتدار هستند | ترتیب winding را در 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 یک مقدار برای هر جفت چندضلعی‑راس ذخیره میکند که امکان داشتن نرمالهای متفاوت در همان راس زمانی که به چند چندضلعی تعلق دارد (لبههای سخت) را میدهد.
آیا قبل از ذخیرهسازی به STL باید مش را مثلثبندی کنم؟
خیر. کتابخانه بهصورت خودکار مثلثبندی را هنگام خروجی گرفتن به فرمتهایی که به مثلثها نیاز دارند، انجام میدهد. میتوانید چهارضلعیها و n‑گونها را در مش تعریف کنید و مستقیماً به STL ذخیره کنید.
چگونه مختصات UV را اضافه کنم؟
Use mesh.createElementUV(TextureMapping.Diffuse, MappingMode.CONTROL_POINT, ReferenceMode.DIRECT) برای ایجاد یک VertexElementUV، سپس setData([...]) را با یک آرایه از مقادیر FVector2 یا FVector3 صدا بزنید — یک مقدار برای هر نقطه کنترل. متد دریافتکننده data یک کپی برمیگرداند؛ مستقیم به آن push نکنید.
آیا میتوانم چندین مش را در یک صحنه بسازم؟
بله. چندین گره را زیر scene.rootNode ایجاد کنید و یک Mesh جداگانه به ویژگی entity هر گره اختصاص دهید.