مشاهدة Graph
أ أ المشهد الرسمي هو نموذج البيانات الأساسية لـ Aspose.3D FOSS for Python. كل ملف 3D، سواء تم تحميلها من القرص أو تم بناءه في الذاكرة، يتم تمثيلها كشجرة من Node الأجسام التي تُدخل في Scene.root_node.يمكن لكل عقدة أن تحمل عقدات الطفل وواحدة أو أكثر. Entity الكائنات (المؤتمرات، الكاميرات والأضواء).فهم الرسم البياني للمشهد يمنحك الوصول المباشر إلى الهندسة والملفات والتحولات الفضائية لكل كائن في المشهد.
التثبيت و الإعداد
قم بتثبيت المكتبة من PyPI:
asposefoss/3d is not yet published — build from source until it ships. See the project README for build instructions.لا تتطلب التمديدات أو المجموعات أو حزم النظام الإضافية.للمبادئ التوجيهية الكاملة، انظر: دليل التثبيت.
الموضوع: مشاهدة فيلم Scene Graph Concepts
يلي الرسم البياني للمشهد في Aspose.3D FOSS سلسلة بسيطة من التخزين:
Scene
└── root_node (Node)
├── child_node_A (Node)
│ ├── entity: Mesh
│ └── transform: translation, rotation, scale
├── child_node_B (Node)
│ └── child_node_C (Node)
│ └── entity: Mesh
└── ...| الموضوع | دور |
|---|---|
Scene | الحاوية العليا - حوض root_node, asset_info, animation_clips,و ، و sub_scenes. |
Node | - اسم العقدة: لديه أحد الوالدين، صفر أو أكثر من الأطفال، الصفر أم أكثر الكيانات، ومكانية Transform. |
Entity | الجيومتر أو الكائن المسرحي المرفق إلى عقدة.أنواع الكيانات الشائعة: Mesh, Camera, Light. |
Transform | موقع الفضاء المحلي، والدورات، والمقياس لنوود.نتائج الفضائيات العالمية يتم قراءتها من global_transform. |
خطوة بخطوة: بناء الرسم البياني المشهد برمجة
الخطوة الأولى: إنشاء مشهد
و جديد Scene يبدأ دائماً بالخروج من الفراغ. root_node:
from aspose.threed import Scene
scene = Scene()
print(scene.root_node.name) # "" (empty string — root node has no name by default)
print(len(scene.root_node.child_nodes)) # 0Scene هو نقطة الدخول لكل شيء: تحميل الملفات، وتخزين المجلدات, إنشاء مقاطع الرسوم المتحركة, والوصول إلى شجرة العقد.
الخطوة 2: إنشاء أشرطة الأطفال
استخدام create_child_node(name) إضافة أسماء العقد إلى الشجرة:
from aspose.threed import Scene
scene = Scene()
parent = scene.root_node.create_child_node("parent")
child = parent.create_child_node("child")
print(parent.name) # "parent"
print(child.parent_node.name) # "parent"
print(len(scene.root_node.child_nodes)) # 1بدلاً من ذلك، قم بإنشاء نظام ثابت. Node و يضيفها صراحة:
from aspose.threed import Scene, Node
scene = Scene()
node = Node("standalone")
scene.root_node.add_child_node(node)كلا النهجين يحققان نفس النتيجة. create_child_node أكثر صرامة للبناء داخل الخط.
الخطوة 3: إنشاء كيان Mesh وربطه
أ أ Mesh أضف تعليق حول (control_points(وأما في الدنيا فهي تُعرف على التفكير)polygonsإنشاء واحد ، إضافة الهندسة الجيولوجية ، ثم ضعه إلى عقدة:
from aspose.threed import Scene, Node
from aspose.threed.entities import Mesh
from aspose.threed.utilities import Vector3, Vector4
scene = Scene()
parent = scene.root_node.create_child_node("parent")
child = parent.create_child_node("child")
##Create a quad mesh (four vertices, one polygon)
# Note: control_points returns a copy of the internal list; append to
# _control_points directly to actually add vertices. This is a known
# library limitation — a public add_control_point() API is not yet available.
mesh = Mesh("cube")
mesh._control_points.append(Vector4(0, 0, 0, 1))
mesh._control_points.append(Vector4(1, 0, 0, 1))
mesh._control_points.append(Vector4(1, 1, 0, 1))
mesh._control_points.append(Vector4(0, 1, 0, 1))
mesh.create_polygon(0, 1, 2, 3)
child.add_entity(mesh)
print(f"Mesh name: {mesh.name}")
print(f"Vertex count: {len(mesh.control_points)}")
print(f"Polygon count: {mesh.polygon_count}")Vector4(x, y, z, w) يقدم اتساقًا متجانسًّا.استخدام w=1 من أجل مواقف نقطة منتظمة.
create_polygon(*indices) يقبل المؤشرات العمودية ويسجل وجهًا واحدًّا في قائمة البوليغونات.تجاوز ثلاثة مؤشرات لثلاثة أجزاء، وأربعة لربع.
الخطوة 4: إعداد تحويلات النود
كل عقدة لديها Transform التي تسيطر على موقفها، والتوجه، وحجمها في الفضاء المحلي:
from aspose.threed.utilities import Vector3, Quaternion
##Translate the node 2 units along the X axis
child.transform.translation = Vector3(2.0, 0.0, 0.0)
##Scale the node to half its natural size
child.transform.scaling = Vector3(0.5, 0.5, 0.5)
##Rotate 45 degrees around the Y axis using Euler angles
child.transform.euler_angles = Vector3(0.0, 45.0, 0.0)التحولات متراكمة: موقع الفضاء العالمي في عقدة الطفل هو تكوين تحولها الخاص مع جميع التحويلات الأجداد. node.global_transform (مستحيل و لا يقرأ إلا ).
الخطوة 5: اجتياز المسرحية الرسوم المتكررة
تسير على الشجرة بأكملها من خلال التراجع عن طريق node.child_nodes:
def traverse(node, depth=0):
indent = " " * depth
entity_type = type(node.entity).__name__ if node.entity else "None"
print(f"{indent}{node.name} [{entity_type}]")
for child in node.child_nodes:
traverse(child, depth + 1)
traverse(scene.root_node)نموذج الخروج للمشهد الذي تم بناؤه أعلاه (اسم عقدة الجذر هو سلك فارغ):
[None]
parent [None]
child [Mesh]للمشاهد مع العديد من الكيانات لكل عقدة، إيترايت node.entities بدلاً من node.entity:
def traverse_full(node, depth=0):
indent = " " * depth
entity_names = [type(e).__name__ for e in node.entities] or ["None"]
print(f"{indent}{node.name} [{', '.join(entity_names)}]")
for child in node.child_nodes:
traverse_full(child, depth + 1)
traverse_full(scene.root_node)الخطوة 6: حفظ المشهد
قم بتوجيه مسار الملف إلى scene.save().تنزيل النموذج من ملحق الملف:
scene.save("scene.gltf") # JSON glTF 2.0
scene.save("scene.glb") # Binary GLB container
scene.save("scene.obj") # Wavefront OBJ
scene.save("scene.stl") # STLبالنسبة للخيارات المحددة للنموذج، قم بتقديم كائن خيارات التخزين كحجة ثانية:
from aspose.threed.formats import GltfSaveOptions
opts = GltfSaveOptions()
scene.save("scene.gltf", opts)نصائح وأفضل الممارسات
- اسم كل عقدة. إعطاء العقد أسماء ذات مغزى يجعل التفريغ عبرات أسهل بكثير ويضمن أن الأسماء يتم الحفاظ عليها في الملف المستورد.
- 1 ملعقة لكل عقدة. الحفاظ على الكيانات 1:1 مع العقد يسهل التحولات والتصادم الأسئلة.
- استخدام
create_child_nodeعن طريق اليد المرفقة. يضع الإشارة الأصلية تلقائيًا ويكون أقل عرضة للخطأ. - قراءة
global_transformبعد أن تم بناء الهرم. إن النتيجة الفضائية العالمية مستقرة فقط بمجرد أن يتم وضع جميع التحولات الأجدية. - لا تتحول الشجرة أثناء التجول. إضافة أو إزالة عقدة الطفل أثناء التآكل
child_nodesسوف تنتج سلوك غير متوقع. جمع العقدة أولا، ثم تعديل. - استخدام نقاط التحكم
Vector4,لا ، لاVector3. دائماً اجتازw=1- الموقف العادي للفيرتكس.;w=0يمثل اتجاه فيكتور (وليس نقطة). mesh.control_pointsإرجاع نسخة. وَالْمُتَّقِينَcontrol_pointsعودة الممتلكاتlist(self._control_points)- يرفع إلى القائمة التي تم إرجاعها لا يتغير المزيج.mesh._control_pointsهذا هو الحد المكتبي المعروف؛ API المتغيرات العامة لا يوجد بعد.
القضايا المشتركة
| مسألة | القرار |
|---|---|
AttributeError: 'NoneType' object has no attribute 'polygons' | الحراسة مع if node.entity is not None قبل الوصول إلى ممتلكات الكيان.مصدر بدون كيانات لديه entity = None. |
يظهر الماس في الأصل على الرغم من الإعدادات translation | transform.translation إذا كان النقطة الأم نفسها لديها تحويل غير الهوية ، فقد تختلف موقف العالم. global_transform. |
طفل يفتقر بعد scene.save() / تحميل | بعض تنسيقات (OBJ) تلمع الهرم.استخدم glTF أو COLLADA للحفاظ على شجرة العقد الكاملة. |
polygon_count 0 بعد mesh.create_polygon(...) | تأكد من أن المؤشرات الورقية قد انتقلت إلى create_polygon في المدى القصير (0 إلى len(control_points) - 1). |
Node.get_child(name) العودة None | اسم الحالة حساسة.تأكيد سلك الاسم الدقيق المستخدم في وقت إنشاء. |
| زيارات العقد في ترتيب غير متوقع | child_nodes إعادة الأطفال في أمر الإدراج (الطلب) add_child_node / create_child_node وَلَمْ يُدْرِكْهُ ) . |