چگونه یک مش سهبعدی با Aspose.3D در Python بسازیم
Aspose.3D FOSS برای Python به شما امکان میدهد که هندسهٔ 3D را بهصورت کامل با کد بسازید: نیازی به ابزار مدلسازی خارجی نیست. شما یک Mesh,، آن را با موقعیتهای راس (control_points) و تعاریف سطح (polygons)، ویژگیهای راس اختیاری مانند نرمالها را الصاق کنید، سپس صحنه را به هر فرمت پشتیبانیشده ذخیره کنید.
راهنمای گام به گام
گام ۱: نصب بسته
نصب Aspose.3D FOSS از PyPI. نیازی به افزونههای بومی یا زنجیره ابزار کامپایلر نیست.
pip install aspose-3d-fossنصب را تأیید کنید:
from aspose.threed import Scene
print("Aspose.3D FOSS ready")نسخههای پشتیبانیشده Python: 3.7، 3.8، 3.9، 3.10، 3.11، 3.12.
مرحله ۲: ایجاد یک Scene و یک Node
هر مش باید داخل یک گراف صحنه قرار گیرد. یک Scene و یک Node با نام برای نگهداری مش ایجاد کنید:
from aspose.threed import Scene
scene = Scene()
node = scene.root_node.create_child_node("triangle")نام گره در فایل صادر شده حفظ میشود و برای اشکالزدایی و بازیابی بعدی از طریق node.get_child("triangle").
مرحله ۳: ایجاد یک شیء Mesh
یک نمونه از Mesh با یک نام توصیفی اختیاری:
from aspose.threed.entities import Mesh
mesh = Mesh("triangle")Mesh در ابتدا خالی است: هیچ راسی، هیچ پلیگونی وجود ندارد. شما آن را در مراحل بعدی پر میکنید.
مرحله ۴: افزودن Control Points (راسها)
نقاط کنترل موقعیتهای راسها هستند. هر راس به صورت یک Vector4(x, y, z, w) که w=1 یک نقطه در فضای سهبعدی را نشان میدهد:
from aspose.threed.utilities import Vector4
##Vertex 0: origin
# Note: control_points returns a copy of the internal vertex list.
# Appending to the returned copy discards the vertex silently.
# Use _control_points to mutate the backing list directly.
# This is a known library limitation — a public add_control_point() API is not yet available.
mesh._control_points.append(Vector4(0.0, 0.0, 0.0, 1.0))
##Vertex 1: 1 unit along X
mesh._control_points.append(Vector4(1.0, 0.0, 0.0, 1.0))
##Vertex 2: apex
mesh._control_points.append(Vector4(0.5, 1.0, 0.0, 1.0))
print(f"Vertices added: {len(mesh.control_points)}")مهم: mesh.control_points یک مقدار را برمیگرداند کپی از فهرست داخلی راسها (متد getter اجرا میکند list(self._control_points)). فراخوانی mesh.control_points.append(v) به کپی اضافه میکند، نه به مش، بنابراین راس بهصورت ساکت حذف میشود. همیشه از mesh._control_points.append(v) برای افزودن رئوس. دسترسی به وضعیت خصوصی از طریق _control_points یک راهحل شناختهشده است؛ این رابط ممکن است در نسخهٔ آیندهٔ کتابخانه تغییر کند.
مرحله ۵: ایجاد سطوح Polygon
توپولوژی سطح را با استفاده از vertex indices تعریف کنید. vertex indices را به create_polygon().سه ایندکس یک مثلث تولید میکند؛ چهار ایندکس یک quad تولید میکند:
##Triangle: connect vertices 0 → 1 → 2
mesh.create_polygon(0, 1, 2)
print(f"Polygon count: {mesh.polygon_count}")برای یک مش quad، شما باید چهار ایندکس را پاس کنید: mesh.create_polygon(0, 1, 2, 3).
ایندکسها باید موقعیتهای معتبر در control_points (صفر-مبنا، در محدوده). ترتیب پیچش به صورت پادساعتگرد برای نرمالهای جهتدار به سمت بیرون است.
مرحله ۶: افزودن نرمالهای راس
نرمالهای رئوس به عنوان یک VertexElement به مش متصل هستند. از mesh.create_element() با VertexElementType.NORMAL, MappingMode.CONTROL_POINT,، و ReferenceMode.DIRECT:
from aspose.threed.entities import VertexElementType, MappingMode, ReferenceMode, VertexElementNormal
from aspose.threed.utilities import Vector4, FVector4
##Create the normal element (returns VertexElementNormal, a VertexElementFVector subclass)
normals: VertexElementNormal = mesh.create_element(
VertexElementType.NORMAL,
MappingMode.CONTROL_POINT,
ReferenceMode.DIRECT
)
##One normal per vertex: all pointing out of the XY plane (0, 0, 1)
normals.set_data([
FVector4(0, 0, 1, 0), # vertex 0
FVector4(0, 0, 1, 0), # vertex 1
FVector4(0, 0, 1, 0), # vertex 2
])
print("Normal layer attached.")MappingMode.CONTROL_POINT به معنای یک نرمال برای هر راس است. ReferenceMode.DIRECT به این معنی است که دادههای نرمال به همان ترتیب نقاط کنترل خوانده میشوند (بدون بافر ایندکس اضافی).
بردارهای نرمال از FVector4(x, y, z, w) با w=0 برای نشان دادن جهت به جای موقعیت. FVector4 یک بردار شناور تکدقت است؛ دادههای ویژگی راس در VertexElementFVector زیرکلاسها از این نوع استفاده میکنند.
مرحله ۷: اتصال مش به گره و ذخیرهسازی
مش را به گره اضافه کنید، سپس صحنه را ذخیره کنید:
node.add_entity(mesh)
scene.save("triangle.gltf")
print("Saved triangle.gltf")اسکریپت کامل کارآمد (تمام مراحل ترکیب شده):
from aspose.threed import Scene
from aspose.threed.entities import Mesh, VertexElementType, MappingMode, ReferenceMode, VertexElementNormal
from aspose.threed.utilities import Vector3, Vector4, FVector4
scene = Scene()
node = scene.root_node.create_child_node("triangle")
mesh = Mesh("triangle")
##Add 3 vertices (x, y, z, w)
# Use _control_points to mutate the backing list directly (control_points returns a copy)
mesh._control_points.append(Vector4(0.0, 0.0, 0.0, 1.0))
mesh._control_points.append(Vector4(1.0, 0.0, 0.0, 1.0))
mesh._control_points.append(Vector4(0.5, 1.0, 0.0, 1.0))
##Create a triangle polygon
mesh.create_polygon(0, 1, 2)
##Add normals (create_element returns VertexElementNormal, a VertexElementFVector subclass)
normals: VertexElementNormal = mesh.create_element(VertexElementType.NORMAL, MappingMode.CONTROL_POINT, ReferenceMode.DIRECT)
normals.set_data([
FVector4(0, 0, 1, 0),
FVector4(0, 0, 1, 0),
FVector4(0, 0, 1, 0),
])
node.add_entity(mesh)
scene.save("triangle.gltf")مشکلات رایج
| مسئله | راهحل |
|---|---|
IndexError در create_polygon | اطمینان حاصل کنید که همهٔ ایندکسها درون range(len(mesh.control_points)). ایندکسها صفر‑پایه هستند. |
| صادرات مش با صفر راس | mesh.control_points.append(...) بهصورت ساکت رئوس را حذف میکند زیرا ویژگی یک کپی برمیگرداند. از mesh._control_points.append(...) بهجای آن. |
| تعداد نرمالها با تعداد رئوس مطابقت ندارد | هنگام استفاده از MappingMode.CONTROL_POINT + ReferenceMode.DIRECT, normals.data باید دقیقاً داشته باشد len(control_points) ورودیها. |
| Mesh در فایل ذخیرهشده موجود نیست | تأیید کنید که node.add_entity(mesh) قبلاً فراخوانی شده بود scene.save(). Meshی که به هیچ گرهای متصل نیست صادر نمیشود. |
| ترتیب پیچش نادرست (face نامرئی به نظر میرسد) | ترتیب راسها به صورت پادساعتگرد نرمالی به سمت بیرون تولید میکند. ترتیب ایندکس را در create_polygon برای معکوس کردن آن. |
polygon_count 0 برمیگرداند | polygon_count فهرست یکسان را همانطور که polygons. اگر create_polygon فراخوانی نشد، لیست خالی است. |
| نرمالها در نمایشگر نادرست به نظر میرسند | اطمینان حاصل کنید که تمام بردارهای نرمال طول واحد دارند. محاسبه کنید با n / abs(n) یا مقادیر پیشنرمالشده را عبور دهید. |
سوالات متداول
تفاوت بین چیست Vector3 و Vector4 برای نقاط کنترل؟?
control_points ذخیره میکند Vector4 اشیاء. این w مولفه مختصات همگن است: استفاده کنید w=1 برای موقعیتهای راس و w=0 برای بردارهای جهت مانند نرمالها. Vector3 برای تبدیلها (ترجمه، مقیاس) استفاده میشود اما برای ذخیرهسازی هندسه نیست.
آیا میتوانم مشی با چهارضلعیها بهجای مثلثها بسازم؟?
بله. فراخوانی کنید mesh.create_polygon(0, 1, 2, 3) با چهار ایندکس برای تعریف یک چهارضلعی. برخی از فرمتهای ذخیرهسازی (STL، 3MF) به مثلثها نیاز دارند و بهصورت خودکار چهارضلعیها را مثلثبندی میکنند. glTF و COLLADA چهارضلعیها را حفظ میکنند.
چگونه میتوانم مختصات UV اضافه کنم؟?
استفاده کنید mesh.create_element_uv(TextureMapping.DIFFUSE, MappingMode.POLYGON_VERTEX) برای ایجاد یک VertexElementUV برای کانال دیفیوز، سپس محتویات آن را پر کنید data فهرست با Vector4 ورودیها. مختصات UV از x و y; z و w معمولاً 0 هستند. اولین آرگومان باید یک TextureMapping ثابت (مثلاً،., TextureMapping.DIFFUSE) شناسایی میکند که لایه UV به کدام اسلات بافت تعلق دارد.
آیا مش برای خروجی صحیح به نرمالها نیاز دارد؟?
نه. نرمالها اختیاری هستند. اگر حذف شوند، اکثر نمایشگرها نرمالهای هر سطح را بر اساس ترتیب چرخش چندضلعی محاسبه میکنند. افزودن نرمالهای صریح برای هر راس، سایهزنی نرمتری ایجاد میکند.
آیا میتوانم چندین مش را به یک گره اضافه کنم؟?
بله. فراخوانی node.add_entity(mesh) چندین بار. هر فراخوانی یک موجودیت جدید به node.entities. برخی فرمتها ممکن است چندین موجودیت را در هنگام خروجی به یک تبدیل کنند.
چگونه میتوانم یک مش با انواع چندضلعیهای ترکیبی را مثلثبندی کنم؟?
فراخوانی mesh.triangulate() تا تمام چهارضلعیها و N‑گونها را بهصورت درجا به مثلث تبدیل کند. این کار قبل از ذخیرهسازی به فرمتهایی که فقط از مثلث پشتیبانی میکنند مفید است.