วิธีแปลงโมเดล 3 มิติใน Python

วิธีแปลงโมเดล 3 มิติใน Python

การแปลงรูปแบบด้วย Aspose.3D FOSS for Python เป็นกระบวนการสองขั้นตอน: โหลดเข้าสู่วัตถุ Scene แล้วบันทึกเป็นรูปแบบผลลัพธ์ที่ต้องการ เนื่องจากเรขาคณิตทั้งหมดถูกเก็บไว้ในตัวแทนในหน่วยความจำร่วมกัน ไม่จำเป็นต้องมีขั้นตอนกลางที่เฉพาะเจาะจงต่อรูปแบบ ส่วนต่อไปนี้แสดงการแปลงที่พบบ่อยที่สุดพร้อมโค้ดที่ทำงานได้

คู่มือแบบขั้นตอนต่อขั้นตอน

ขั้นตอนที่ 1: ติดตั้งแพคเกจ

pip install aspose-3d-foss

ไม่จำเป็นต้องใช้ไลบรารีระบบ, คอมไพเลอร์ หรือการพึ่งพา runtime เพิ่มเติมใดๆ


ขั้นตอนที่ 2: โหลดโมเดลต้นฉบับ

ใช้ Scene.from_file() สำหรับกรณีที่ง่ายที่สุด: รูปแบบจะถูกตรวจจับโดยอัตโนมัติจากส่วนขยายของไฟล์:

from aspose.threed import Scene

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

สำหรับไฟล์ OBJ ที่คุณต้องการควบคุมระบบพิกัดหรือการโหลดวัสดุ ให้ใช้ scene.open() พร้อมกับ ObjLoadOptions:

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

options = ObjLoadOptions()
options.flip_coordinate_system = True  # Convert to Z-up if needed
options.enable_materials = True        # Load the accompanying .mtl file
options.normalize_normal = True

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

ทั้งสองวิธีสร้างอ็อบเจ็กต์ Scene ที่เหมือนกันสำหรับขั้นตอนการบันทึกต่อไป


ขั้นตอนที่ 3: ตรวจสอบฉากที่โหลดแล้ว

ก่อนทำการแปลง ควรตรวจสอบว่าเรขาคณิตโหลดอย่างถูกต้องหรือไม่ ไฟล์หาย ฟีเจอร์ FBX ที่ไม่รองรับ หรือปัญหาเส้นทางกับไฟล์ .mtl ทั้งหมดนี้อาจทำให้ฉากว่างเปล่า.

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

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

mesh_count = 0
total_vertices = 0

def count_meshes(node) -> None:
    global mesh_count, total_vertices
    for entity in node.entities:
        if isinstance(entity, Mesh):
            mesh_count += 1
            total_vertices += len(entity.control_points)
    for child in node.child_nodes:
        count_meshes(child)

count_meshes(scene.root_node)
print(f"Loaded {mesh_count} mesh(es), {total_vertices} total vertices")

if mesh_count == 0:
    raise ValueError("Scene contains no geometry: check the source file path and format")

ขั้นตอนที่ 4: บันทึกเป็นรูปแบบเป้าหมาย

เรียก scene.save() พร้อมเส้นทางเอาต์พุต. ส่งอ็อบเจ็กต์ตัวเลือกการบันทึกที่เฉพาะรูปแบบเพื่อควบคุมการออกเป็นไบนารีหรือ ASCII, แกนพิกัด, และการบีบอัด.

OBJ เป็น STL (ไบนารี)

from aspose.threed import Scene
from aspose.threed.formats import StlSaveOptions

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

save_opts = StlSaveOptions()
##StlSaveOptions defaults to binary output, which is more compact.

scene.save("model.stl", save_opts)
print("Saved model.stl")

OBJ เป็น glTF 2.0

from aspose.threed import Scene
from aspose.threed.formats import GltfSaveOptions

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

save_opts = GltfSaveOptions()

scene.save("model.gltf", save_opts)
print("Saved model.gltf")

เพื่อบันทึกเป็นไฟล์ไบนารี GLB ที่รวมทุกอย่างไว้ในตัวเองแทน .gltf + บัฟเฟอร์ภายนอก ให้เปลี่ยนส่วนขยายของผลลัพธ์เป็น .glb:

scene.save("model.glb", save_opts)

OBJ เป็น 3MF

from aspose.threed import Scene
from aspose.threed.formats import ThreeMfSaveOptions

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

save_opts = ThreeMfSaveOptions()

scene.save("model.3mf", save_opts)
print("Saved model.3mf")

STL เป็น glTF 2.0

รูปแบบเดียวกันใช้ได้โดยไม่คำนึงถึงรูปแบบของแหล่งข้อมูล:

from aspose.threed import Scene
from aspose.threed.formats import GltfSaveOptions

scene = Scene.from_file("input.stl")
scene.save("output.gltf", GltfSaveOptions())
print("Saved output.gltf")

ขั้นตอนที่ 5: ตรวจสอบผลลัพธ์

หลังจากบันทึกแล้ว ให้ยืนยันว่าไฟล์ผลลัพธ์มีอยู่และมีขนาดไม่เป็นศูนย์ สำหรับการตรวจสอบที่ละเอียดขึ้น ให้โหลดไฟล์ใหม่และเปรียบเทียบจำนวนเมช:

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

output_path = "model.stl"

##Basic file-system check
size = os.path.getsize(output_path)
print(f"Output file size: {size} bytes")
if size == 0:
    raise RuntimeError("Output file is empty: save may have failed silently")

##Round-trip verification: reload and count geometry
def _iter_nodes(node):
    yield node
    for child in node.child_nodes:
        yield from _iter_nodes(child)

reloaded = Scene.from_file(output_path)
mesh_count = sum(
    1
    for node in _iter_nodes(reloaded.root_node)
    for entity in node.entities
    if isinstance(entity, Mesh)
)
print(f"Round-trip check: {mesh_count} mesh(es) in output")

ปัญหาทั่วไปและการแก้ไข

ไฟล์ผลลัพธ์ถูกสร้างแล้วแต่ไม่มีเรขาคณิต

ไฟล์ต้นทางอาจโหลดมาโดยไม่มีเมชเลย เพิ่มขั้นตอนการตรวจสอบจากขั้นตอนที่ 3 ก่อนบันทึก นอกจากนี้ให้ตรวจสอบให้แน่ใจว่านามสกุลไฟล์ตรงกับรูปแบบจริง; Aspose.3D ใช้นามสกุลเพื่อเลือกตัวแยกวิเคราะห์.

ผลลัพธ์ glTF ขาดเทกเจอร์

Aspose.3D FOSS ส่งต่อเรขาคณิตและคุณสมบัติวัตถุผ่านการแปลง หากไฟล์ OBJ ต้นทางอ้างอิงไฟล์รูปภาพภายนอกใน .mtl ไฟล์รูปภาพเหล่านั้นจะไม่ถูกคัดลอกโดยอัตโนมัติพร้อมกับ .gltf คัดลอกรูปภาพเทกเจอร์ไปยังไดเรกทอรีผลลัพธ์ด้วยตนเองหลังจากบันทึก.

ผลลัพธ์ STL แสดงด้านใน‑นอก (ปกติของหน้าเปลี่ยนทิศ)

STL ไม่ได้บรรจุข้อมูลเมตาดาต้าลำดับการม้วน หากเวกเตอร์ปกติที่ส่งออกถูกกลับด้าน ให้ตั้งค่าตัวเลือก StlSaveOptions หากมี หรือพลิกระบบพิกัดระหว่างการโหลด: ObjLoadOptions.flip_coordinate_system = True.

ValueError: unsupported format ขณะบันทึก

ตรวจสอบให้แน่ใจว่าการต่อท้ายไฟล์ผลลัพธ์เป็นหนึ่งใน .obj, .stl, .gltf, .glb, .dae, .3mf. ส่วนต่อท้ายไฟล์เป็นตัวพิมพ์ใหญ่‑เล็กที่แตกต่างกันบน Linux.

ไฟล์ขนาดใหญ่มากทำให้การแปลงช้า

Aspose.3D FOSS ประมวลผลเรขาคณิตในหน่วยความจำ. สำหรับไฟล์ที่มีหลายล้านโพลิกอน ให้ตรวจสอบว่ามี RAM เพียงพอ. ขณะนี้ไม่มี API สำหรับการเขียนแบบสตรีมมิ่ง.


คำถามที่พบบ่อย (FAQ)

ฉันสามารถแปลงไฟล์โดยไม่ต้องบันทึกลงดิสก์ก่อนหรือไม่?

ใช่ ทั้ง scene.open() และ scene.save() ยอมรับอ็อบเจ็กต์ที่คล้ายไฟล์แบบไบนารีเพิ่มเติมจากเส้นทางไฟล์ ส่งผ่านอ็อบเจ็กต์ใดก็ได้ที่ทำตาม read() สำหรับการโหลดหรือ write() สำหรับการบันทึก:

import io
from aspose.threed import Scene

# Load from an in-memory buffer
data = open('model.obj', 'rb').read()
scene = Scene()
scene.open(io.BytesIO(data))

# Save to an in-memory buffer
buf = io.BytesIO()
scene.save(buf)

FBX รองรับเป็นรูปแบบแหล่งที่มาสำหรับการแปลงหรือไม่?

การทำโทเคนของ FBX ได้รับการดำเนินการบางส่วน แต่ตัวพาร์เซอร์ยังไม่สมบูรณ์ การป้อนข้อมูล FBX อาจทำให้ฉากไม่สมบูรณ์ ใช้ OBJ, STL, glTF, COLLADA หรือ 3MF เป็นรูปแบบแหล่งที่เชื่อถือได้

วัสดุจะคงอยู่หลังการแปลง OBJ เป็น glTF หรือไม่?

คุณสมบัติพื้นฐานของวัสดุ Phong/Lambert (สีกระจาย) จะถูกส่งต่อผ่านโมเดล Scene และเขียนลงในบล็อกวัสดุของ glTF พารามิเตอร์เชดเดอร์เชิงกระบวนการหรือแบบกำหนดเองที่ไม่สามารถแสดงในโมเดลวัสดุของ glTF จะถูกละทิ้ง.

ฉันสามารถแปลงหลายไฟล์ในลูปได้หรือไม่?

ใช่. แต่ละการเรียก Scene.from_file() จะสร้างอ็อบเจ็กต์อิสระ ดังนั้นการวนลูปผ่านรายการของเส้นทางจึงทำได้อย่างตรงไปตรงมา:

from pathlib import Path
from aspose.threed import Scene
from aspose.threed.formats import StlSaveOptions

source_dir = Path("input")
output_dir = Path("output")
output_dir.mkdir(exist_ok=True)

opts = StlSaveOptions()
for obj_file in source_dir.glob("*.obj"):
    scene = Scene.from_file(str(obj_file))
    out_path = output_dir / obj_file.with_suffix(".stl").name
    scene.save(str(out_path), opts)
    print(f"Converted {obj_file.name} -> {out_path.name}")

การแปลงจะคงลำดับชั้นของซีน (โหนดพาเรนท์/ชิลด์) ไว้หรือไม่?

ใช่. โครงสร้างต้นไม้ของโหนดจะถูกเก็บรักษาตามที่รูปแบบเป้าหมายอนุญาต รูปแบบเช่น STL เก็บเฉพาะเรขาคณิตแบบแบนโดยไม่มีโครงสร้างโหนด; โครงสร้างลำดับชั้นจะถูกทำให้แบนเมื่อบันทึก รูปแบบเช่น glTF และ COLLADA จะรักษาโครงสร้างลำดับชั้นเต็มรูปแบบ.

 ภาษาไทย