نحوه بارگذاری مدل‌های سه‌بعدی در Python

نحوه بارگذاری مدل‌های سه‌بعدی در Python

Aspose.3D FOSS برای Python یک API ساده برای باز کردن فایل‌های 3D بدون هیچ وابستگی بومی فراهم می‌کند. پس از بارگذاری یک فایل به یک Scene شیء، می‌توانید سلسله‌مراتبی گره‌ها را پیمایش کنید و داده‌های هندسی خام هر مش در صحنه را بخوانید.

راهنمای گام به گام

گام ۱: نصب بسته

نصب Aspose.3D FOSS از PyPI. هیچ کتابخانه سیستمی اضافی مورد نیاز نیست.

pip install aspose-3d-foss

نسخه‌های پشتیبانی‌شده Python: 3.7، 3.8، 3.9، 3.10، 3.11، 3.12.


گام ۲: وارد کردن کلاس Scene

کلاس Scene کلاس، محفظه سطح بالای تمام داده‌های 3D است. آن را به همراه هر کلاس گزینه‌بارگذاری که نیاز دارید وارد کنید.

from aspose.threed import Scene
from aspose.threed.formats import ObjLoadOptions

تمام کلاس‌های عمومی زیر aspose.threed یا زیرپکیج‌های آن (aspose.threed.entities, aspose.threed.formats, aspose.threed.utilities).


گام ۳: بارگذاری یک فایل

از متد استاتیک Scene.from_file() برای باز کردن هر فرمت پشتیبانی‌شده استفاده کنید. کتابخانه فرمت را به‌صورت خودکار از پسوند فایل تشخیص می‌دهد.

##Automatic format detection
scene = Scene.from_file("model.obj")

به‌جای آن، یک Scene نمونه ایجاد کنید و فراخوانی کنید open(); مفید است وقتی می‌خواهید گزینه‌های بارگذاری را پاس کنید یا خطاها را به‌صورت صریح مدیریت کنید:

scene = Scene()
scene.open("model.obj")

هر دو روش از فایل‌های OBJ، STL (دودویی و ASCII)، glTF 2.0 / GLB، COLLADA (DAE) و 3MF پشتیبانی می‌کنند.


گام ۴: پیمایش گره‌های Scene

یک صحنه بارگذاری‌شده یک درخت از Node اشیائی که ریشه در scene.root_node. به‌صورت بازگشتی تکرار کنید تا تمام گره‌ها را پیدا کنید:

from aspose.threed import Scene, Node

scene = Scene.from_file("model.obj")

def walk(node: Node, depth: int = 0) -> None:
    indent = "  " * depth
    print(f"{indent}Node: {node.name!r}")
    for child in node.child_nodes:
        walk(child, depth + 1)

walk(scene.root_node)

هر Node می‌تواند صفر یا بیشتر داشته باشد Entity اشیاء (مش‌ها، دوربین‌ها، نورها). بررسی کنید node.entities تا ببینید چه چیزی پیوست شده است.


مرحلهٔ 5: دسترسی به داده‌های راس و چندضلعی

موجودیت یک گره را به Mesh و نقاط کنترل آن (موقعیت‌های راس) و چندضلعی‌ها (فهرست‌های ایندکس سطح) را بخوانید:

from aspose.threed import Scene
from aspose.threed.entities import Mesh

scene = Scene.from_file("model.obj")

for node in scene.root_node.child_nodes:
    for entity in node.entities:
        if isinstance(entity, Mesh):
            mesh: Mesh = entity
            print(f"Mesh '{node.name}': "
                  f"{len(mesh.control_points)} vertices, "
                  f"{len(mesh.polygons)} polygons")

            # First vertex position
            if mesh.control_points:
                v = mesh.control_points[0]
                print(f"  First vertex: ({v.x:.4f}, {v.y:.4f}, {v.z:.4f})")

            # First polygon face (list of control-point indices)
            if mesh.polygons:
                print(f"  First polygon: {mesh.polygons[0]}")

mesh.control_points یک لیست از Vector4 اشیاء؛; x, y, z موقعیت و w مختصات همگن است (معمولاً 1.0).

mesh.polygons یک لیست از لیست‌های اعداد صحیح است که در آن هر لیست داخلی مجموعهٔ مرتب‌شده‌ای از شاخص‌های نقاط کنترل برای یک فیس است.


مرحلهٔ 6: اعمال گزینه‌های بارگذاری مخصوص فرمت

برای کنترل دقیق بر نحوهٔ تفسیر یک فایل OBJ، یک ObjLoadOptions نمونه را به scene.open():

from aspose.threed import Scene
from aspose.threed.formats import ObjLoadOptions

options = ObjLoadOptions()
options.flip_coordinate_system = True   # Convert right-hand Y-up to Z-up
options.scale = 0.01                    # Convert centimetres to metres
options.enable_materials = True         # Load .mtl material file
options.normalize_normal = True         # Normalize all normals to unit length

scene = Scene()
scene.open("model.obj", options)

برای فایل‌های STL، کلاس معادل است StlLoadOptions. برای glTF، از GltfLoadOptions. ببینید the مرجع API برای یک فهرست کامل.


مشکلات رایج و راه‌حل‌ها

خطای FileNotFoundError هنگام فراخوانی Scene.from_file()

مسیر باید مطلق باشد یا نسبت به دایرکتوری کاری در زمان اجرا به‌درستی نسبی باشد. از pathlib.Path برای ساخت مسیرهای قابل اعتماد:

from pathlib import Path
from aspose.threed import Scene

path = Path(__file__).parent / "assets" / "model.obj"
scene = Scene.from_file(str(path))

mesh.polygons پس از بارگذاری یک فایل STL خالی است

فایل‌های STL مثلث‌ها را به‌صورت فیس‌ت‌های خام ذخیره می‌کنند، نه یک مش ایندکس‌شده. پس از بارگذاری، چندضلعی‌ها از آن فیس‌ت‌ها ترکیب می‌شوند. اگر polygons خالی به‌نظر می‌رسد، بررسی کنید len(mesh.control_points); اگر تعداد مضربی از ۳ باشد، هندسه به‌صورت بدون ایندکس ذخیره می‌شود و هر سه‌گانه متوالی رئوس یک مثلث را تشکیل می‌دهد.

عدم تطابق سیستم مختصات (مدل به‌نظر می‌رسد چرخیده یا آینه‌ای باشد)

ابزارهای مختلف از قراردادهای متفاوتی استفاده می‌کنند (Y‑up در مقابل Z‑up، دست چپ در مقابل دست راست). تنظیم کنید ObjLoadOptions.flip_coordinate_system = True یا یک چرخش به ریشه گرهٔ Transform پس از بارگذاری.

AttributeError: 'NoneType' object has no attribute 'polygons'

فهرست موجودیت‌های یک گره ممکن است شامل موجودیت‌های غیر مش (دوربین‌ها، نورها) باشد. همیشه با isinstance(entity, Mesh) قبل از تبدیل.


سوالات متداول (FAQ)

کدام فرمت‌های 3D را می‌توانم بارگذاری کنم؟?

OBJ (Wavefront)، STL (دودویی و متنی)، glTF 2.0 / GLB، COLLADA (DAE) و 3MF. توکنیزاسیون فایل FBX به‌صورت جزئی پشتیبانی می‌شود اما تجزیه کامل هنوز تکمیل نشده است.

آیا بارگذاری یک فایل OBJ همچنین .mtl ماتریال؟?

بله، وقتی ObjLoadOptions.enable_materials = True (پیش‌فرض). کتابخانه به دنبال .mtl فایل در همان دایرکتوری که .obj فایل. اگر the .mtl وجود ندارد، هندسه همچنان بارگذاری می‌شود و یک هشدار صادر می‌گردد.

آیا می‌توانم به‌جای مسیر، فایلی را از یک جریان بایت بارگذاری کنم؟?

بله. scene.open() هر شیء شبیه‌فایلی را که دارای یک .read() متد علاوه بر یک رشته مسیر فایل می‌پذیرد. یک جریان باینری باز (به عنوان مثال،., io.BytesIO) به‌صورت مستقیم. Scene.from_file() فقط یک رشته مسیر فایل را می‌پذیرد.

چگونه می‌توانم نرمال‌های سطح را دریافت کنم؟?

پس از بارگذاری، بررسی کنید mesh.get_element(VertexElementType.NORMAL). این یک VertexElementNormal که data فهرست شامل یک بردار نرمال برای هر مرجع است که بر اساس mapping_mode و reference_mode.

from aspose.threed.entities import Mesh, VertexElementType

normals = mesh.get_element(VertexElementType.NORMAL)
if normals:
    print(normals.data[0])  # First normal vector

آیا کتابخانه برای بارگذاری همزمان چندین فایل thread‑safe است؟?

هر Scene شیء مستقل است. بارگذاری فایل‌های جداگانه به‌صورت جداگانه Scene نمونه‌ها از رشته‌های جداگانه ایمن هستند به‌شرط این‌که یک Scene در میان رشته‌ها بدون قفل‌گذاری خارجی.

 فارسی