如何在 Python 中保存 3D 场景

如何在 Python 中保存 3D 场景

Aspose.3D FOSS for Python 允许您使用单个 Scene.save() 调用将 Scene 保存为任何受支持的输出格式。 当您传递文件路径时,格式检测是自动的;对于二进制输出或纹理嵌入等高级选项,您需要提供特定格式的保存选项对象。

分步指南

步骤 1:安装软件包

从 PyPI 安装 Aspose.3D FOSS。无需本地库。

pip install aspose-3d-foss

支持的 Python 版本:3.7、3.8、3.9、3.10、3.11、3.12。


步骤 2:导入所需类

至少需要 Scene。仅在需要非默认行为时才导入特定格式的导出器或保存选项类。

from aspose.threed import Scene

针对特定格式的选项:

from aspose.threed.formats.gltf import GltfSaveOptions, GltfExporter
from aspose.threed.formats.stl import StlFormat, StlSaveOptions
from aspose.threed.formats.fbx import FbxExporter, FbxSaveOptions
from aspose.threed.formats.collada import ColladaExporter, ColladaSaveOptions

步骤 3:加载场景

使用 Scene.from_file() 从磁盘加载现有场景。库会根据文件扩展名自动检测源格式。若要从头构建场景,请参阅 如何在 Python 中构建网格

# Load from an existing file — format auto-detected from extension
scene = Scene.from_file("input.obj")

或者,通过 Scene.open() 使用显式选项打开场景:

from aspose.threed import Scene

scene = Scene()
scene.open("input.fbx")

步骤 4:保存为 STL

使用 Scene.save() 并提供 .stl 路径。默认输出为 ASCII STL。若要写入二进制 STL(文件更小,无人类可读的头部),请使用 StlSaveOptions

# ASCII STL — format detected from the .stl extension
scene.save("output.stl")

# Binary STL — smaller file size
from aspose.threed.formats.stl import StlFormat, StlSaveOptions

stl_format = StlFormat()
options = stl_format.create_save_options()
options.binary_mode = True
scene.save("output_binary.stl", options)

步骤 5:保存为 glTF 或 GLB

GLTF 2.0 文件可以使用 GltfExporterGltfSaveOptions 导出。将 binary_mode = True 设置为生成自包含的 .glb 二进制包;将 binary_mode = False 设置为 JSON 基础的 .gltf 格式。

import io
from aspose.threed.formats.gltf import GltfExporter, GltfSaveOptions

# Text glTF
options = GltfSaveOptions()
options.binary_mode = False
options.file_name = "output.gltf"

exporter = GltfExporter()
with open("output.gltf", "wb") as f:
    stream = io.BytesIO()
    exporter.export(scene, stream, options)
    f.write(stream.getvalue())

# Binary GLB
options_glb = GltfSaveOptions()
options_glb.binary_mode = True
options_glb.file_name = "output.glb"

stream_glb = io.BytesIO()
exporter.export(scene, stream_glb, options_glb)
with open("output.glb", "wb") as f:
    f.write(stream_glb.getvalue())

步骤 6:保存为 FBX

FBX 场景通过 FbxExporter 导出。使用 FbxSaveOptions 可启用压缩或将纹理嵌入输出文件中。

from aspose.threed.formats.fbx import FbxExporter, FbxSaveOptions

options = FbxSaveOptions()
options.enable_compression = True
options.embed_textures = False  # keep textures as separate files

exporter = FbxExporter()
exporter.save(scene, "output.fbx", options)

步骤 7:保存为 OBJ 或 Collada(DAE)

对于 OBJ 和 Collada,请直接将文件路径传递给 Scene.save()。库会根据扩展名检测格式。

# OBJ — format auto-detected from .obj extension
scene.save("output.obj")

# Collada DAE — with material and coordinate-system options
from aspose.threed.formats.collada import ColladaExporter, ColladaSaveOptions

options = ColladaSaveOptions()
options.enable_materials = True
options.flip_coordinate_system = False
options.indented = True

exporter = ColladaExporter()
exporter.export(scene, open("output.dae", "wb"), options)

常见问题及解决方案

scene.save() 后的空输出文件
这通常意味着场景的根节点没有带有几何体的子节点。请确认在调用 save 之前,每个网格节点已附加到 scene.root_node。在构建场景后检查 len(scene.root_node.child_nodes)

AttributeError 在构建网格几何时
Mesh 类将顶点存储为内部控制点列表。有关详细的网格构建模式,请参阅 如何在 Python 中构建网格 文章,其中涵盖多边形创建、顶点元素和 UV 数据。

GLB 输出大于预期
Binary GLB 会将所有几何体和纹理数据内联。如果 GltfSaveOptions.flip_tex_coord_v 设置为 True,则会包含额外的坐标翻转过程。若不需要 V 轴纹理翻转,请将其设置为 False

FBX 导入/导出往返丢失材质
FBX 材质导出受 FbxSaveOptions.export_legacy_material_properties 控制。将其设置为 True 可写入第三方工具可读取的标准 FBX 材质块。

Collada DAE 不包含材质
在导出之前设置 ColladaSaveOptions.enable_materials = True(默认是 False)。

常见问题

Aspose.3D FOSS for Python 能导出哪些格式?

该库支持导出为:STL、glTF 2.0(文本和二进制 GLB)、FBX、OBJ、Collada(DAE)和 3MF。格式检测在您将文件路径字符串传递给 Scene.save() 时是自动的;库会读取扩展名以选择正确的导出器。

是否有避免写入磁盘的流式导出 API?

是的。GltfExporter.export(scene, stream, options) 写入任何 io.BytesIO 或类似文件的对象。您可以直接将内存缓冲区传递给 Web 响应或进一步处理,而无需触及文件系统。

我如何将场景从一种格式转换为另一种格式?

使用 Scene.from_file("input.fbx") 加载场景,并使用 scene.save("output.gltf") 保存。库会处理内存中的转换;无需中间文件。

我可以将多个子场景保存到不同的文件吗?

访问 scene.sub_scenes 以遍历每个子场景,创建一个新的 Scene 对象,附加相关节点,并对每个调用 save()

Scene.save() 是否会在不提示的情况下覆盖现有文件?

是的。该库在目标文件已存在时不会抛出错误;它会覆盖该文件。如果需要防止意外覆盖,请在代码中添加文件存在性检查。

另请参阅

 中文