วิธีสร้างเมช 3 มิติด้วย Aspose.3D ใน Python
Aspose.3D FOSS for Python ให้คุณสร้างเรขาคณิต 3 มิติทั้งหมดด้วยโค้ด: ไม่ต้องใช้เครื่องมือโมเดลภายนอก คุณสร้าง Mesh, เติมข้อมูลตำแหน่งเวอร์เท็กซ์ (control_points) และการกำหนดหน้าตา (polygons), แนบแอตทริบิวต์เวอร์เท็กซ์เพิ่มเติมเช่นนอร์มัล, แล้วบันทึกฉากเป็นรูปแบบที่รองรับใดก็ได้.
คู่มือแบบขั้นตอนต่อขั้นตอน
ขั้นตอนที่ 1: ติดตั้งแพคเกจ
ติดตั้ง 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.
ขั้นตอนที่ 2: สร้างฉากและโหนด
เมชทุกอันต้องอยู่ภายในกราฟฉาก สร้าง Scene และเพิ่ม Node ที่มีชื่อเพื่อเก็บเมช:
from aspose.threed import Scene
scene = Scene()
node = scene.root_node.create_child_node("triangle")ชื่อโหนดถูกเก็บไว้ในไฟล์ที่ส่งออกและเป็นประโยชน์สำหรับการดีบักและการดึงข้อมูลในภายหลังผ่าน node.get_child("triangle").
ขั้นตอนที่ 3: สร้าง Mesh Object
สร้างอินสแตนซ์ Mesh พร้อมชื่ออธิบายที่เป็นตัวเลือก:
from aspose.threed.entities import Mesh
mesh = Mesh("triangle")เมชเริ่มต้นเป็นค่าว่าง: ไม่มีจุดยอด, ไม่มีโพลิกอน. คุณเติมข้อมูลในขั้นตอนต่อไปนี้.
ขั้นตอนที่ 4: เพิ่มจุดควบคุม (จุดยอด)
จุดควบคุมคือตำแหน่งของเวอร์เท็กซ์ แต่ละเวอร์เท็กซ์จะถูกจัดเก็บเป็น Vector4(x, y, z, w) ซึ่ง w=1 บ่งบอกถึงจุดในพื้นที่ 3 มิติ:
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)}")Important: mesh.control_points คืนค่า สำเนา ของรายการเวอร์เท็กซ์ภายใน (getter ทำงานโดยเรียก list(self._control_points)). การเรียก mesh.control_points.append(v) จะเพิ่มเข้าไปในสำเนา ไม่ได้เพิ่มในเมช ดังนั้นเวอร์เท็กซ์จะถูกละทิ้งโดยไม่มีการแจ้งเตือน. ควรใช้ mesh._control_points.append(v) เสมอเพื่อเพิ่มเวอร์เท็กซ์. การเข้าถึงสถานะส่วนตัวผ่าน _control_points เป็นวิธีแก้ปัญหาที่เป็นที่รู้จัก; อินเทอร์เฟซอาจเปลี่ยนแปลงในเวอร์ชันอนาคตของไลบรารี.
ขั้นตอนที่ 5: สร้างหน้าตาโพลิกอน
กำหนดโทโพโลยีของหน้าโดยใช้ดัชนีเวอร์เท็กซ์. ส่งดัชนีเวอร์เท็กซ์ไปยัง create_polygon(). ดัชนีสามตัวสร้างสามเหลี่ยม; ดัชนีสี่ตัวสร้างควอด:
##Triangle: connect vertices 0 → 1 → 2
mesh.create_polygon(0, 1, 2)
print(f"Polygon count: {mesh.polygon_count}")สำหรับ quad mesh คุณจะต้องส่งดัชนีสี่ค่า: mesh.create_polygon(0, 1, 2, 3).
ดัชนีต้องเป็นตำแหน่งที่ถูกต้องใน control_points (เริ่มจาก 0, อยู่ในช่วง) การจัดลำดับการม้วนเป็นแบบทวนเข็มนาฬิกาสำหรับเวกเตอร์ปกติที่หันออกด้านนอก.
ขั้นตอนที่ 6: เพิ่มเวอร์เทกซ์นอร์ม
เวอร์เท็กซ์นอร์มัลถูกจัดเก็บเป็น 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 หมายถึงหนึ่ง normal ต่อ vertex. ReferenceMode.DIRECT หมายถึงข้อมูล normal จะถูกอ่านในลำดับเดียวกับ control points (ไม่มี index buffer เพิ่มเติม).
เวกเตอร์ปกติใช้ FVector4(x, y, z, w) กับ w=0 เพื่อบ่งบอกทิศทางแทนตำแหน่ง FVector4 เป็นเวกเตอร์ float แบบความแม่นยำเดี่ยว; ข้อมูลแอตทริบิวต์เวอร์เท็กซ์ในคลาสย่อย VertexElementFVector ใช้ประเภทนี้.
ขั้นตอนที่ 7: แนบ Mesh ไปยัง Node และบันทึก
เพิ่มเมชลงในโหนด แล้วบันทึกฉาก:
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")ปัญหาทั่วไป
| Issue | Resolution |
|---|---|
IndexError in create_polygon | ตรวจสอบว่าดัชนีทั้งหมดอยู่ภายใน range(len(mesh.control_points)). ดัชนีเริ่มจาก 0. |
| Mesh exports with zero vertices | mesh.control_points.append(...) ลบจุดยอดโดยเงียบ ๆ เนื่องจากคุณสมบัตินี้คืนค่ากลับเป็นสำเนา. ใช้ mesh._control_points.append(...) แทน. |
| Normals count does not match vertex count | เมื่อใช้ MappingMode.CONTROL_POINT + ReferenceMode.DIRECT, normals.data ต้องมีรายการจำนวน len(control_points) รายการเท่านั้น. |
| Mesh missing from saved file | ยืนยันว่า node.add_entity(mesh) ถูกเรียกก่อน scene.save(). Mesh ที่ไม่ได้แนบกับโหนดใดจะไม่ถูกส่งออก. |
| Wrong winding order (face appears invisible) | ลำดับจุดยอดแบบทวนเข็มนาฬิกาจะสร้าง Normal ที่หันออกด้านนอก. กลับลำดับดัชนีใน create_polygon เพื่อสลับทิศ. |
polygon_count returns 0 | polygon_count อ่านรายการเดียวกับ polygons. หากไม่ได้เรียก create_polygon รายการจะว่างเปล่า. |
| Normals appear incorrect in viewer | ตรวจสอบให้แน่ใจว่าเวกเตอร์ Normal ทั้งหมดมีความยาวเป็นหน่วย. คำนวณด้วย n / abs(n) หรือส่งค่าที่ทำ Normal แล้วล่วงหน้า. |
คำถามที่พบบ่อย
ความแตกต่างระหว่าง 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 อยู่ในสล็อตเทกซ์เจอร์ใด.
เมชต้องการนอร์มอลเพื่อการส่งออกที่ถูกต้องหรือไม่?
ไม่. Normals เป็นตัวเลือกเสริม. หากละเว้น, โปรแกรมดูส่วนใหญ่จะคำนวณ per-face normals จาก polygon winding order. การเพิ่ม per-vertex normals อย่างชัดเจนทำให้การแรเงานุ่มขึ้น.
ฉันสามารถเพิ่มเมชหลายอันในโหนดเดียวได้หรือไม่?
ใช่. เรียก node.add_entity(mesh) หลายครั้ง. แต่ละครั้งที่เรียกจะเพิ่มเอนทิตีใหม่ลงใน node.entities. บางรูปแบบอาจทำให้หลายเอนทิตีถูกรวมเป็นหนึ่งเดียวเมื่อส่งออก.
ฉันจะทำให้เมชที่มีหลายประเภทของโพลิกอนเป็นสามเหลี่ยมอย่างไร?
เรียก mesh.triangulate() เพื่อแปลงควอดและ N‑gon ทั้งหมดเป็นสามเหลี่ยมในที่เดียวกัน ซึ่งเป็นประโยชน์ก่อนบันทึกเป็นรูปแบบที่รองรับเฉพาะสามเหลี่ยมเท่านั้น.