【Blender】Blender 基础:导入&导出

发布于:2025-06-09 ⋅ 阅读:(47) ⋅ 点赞:(0)

引言

Blender 是一款强大的开源 3D 建模与渲染工具,在实际项目中,我们往往需要与外部工具或平台对接三维数据。这使得“导入”和“导出”成为 Blender 使用中的基本且关键的环节。

本文将系统讲解 Blender 中模型的导入与导出流程,覆盖支持的常见格式、注意事项以及适配不同平台的实践建议。


一、Blender 支持的主要格式

操作 常见格式 用途
导入 .obj.fbx.gltf/.glb.dae.stl 从 CAD、Maya、3ds Max、Unity 等迁移
导出 .fbx.gltf/.glb.obj.stl 用于游戏引擎、Web 显示、3D 打印

✅ 推荐使用 .glb.gltf 格式导出,用于 Web 和实时场景,支持贴图、动画、材质完整性强。


二、模型导入流程

Blender 中导入模型操作简单,但在实际工作中仍有几个关键细节需要注意:

  1. 确认单位和坐标系

    • Blender 默认单位为米,Z轴朝上;
    • 某些格式(如 FBX)可能使用厘米、Y轴朝上。
  2. 集合自动命名机制

    • Blender 会以文件名创建集合(Collection);
    • 子对象可能会被自动重命名(如重复 Mesh 名称)。
  3. 贴图路径处理

    • 如果路径是相对的,需保持贴图与模型结构一致;
    • 外部贴图缺失会导致材质白模。
  4. 动画数据载入

    • 格式如 FBX、GLTF 会同时载入骨骼与动画轨迹;
    • 可在时间轴中直接预览。

三、模型导出逻辑

在导出模型时,我们需要明确目标平台的要求,比如是否需要压缩、是否保留动画、贴图格式等。

(一)导出前准备:

  • 应用变换(Apply All Transforms)

    • 保证模型位置、旋转、缩放一致性;
  • 合并对象(如有需要)

    • 合并子部件为整体模型,避免碎片;
  • 清理材质槽与无用数据块

    • 精简模型数据结构。

(二)导出选项控制(以 glTF 为例):

选项 说明
导出格式 .glb(二进制)或 .gltf(JSON + Bin + 图片)
压缩方式 支持 Draco 压缩(减少顶点数据体积)
材质设置 保留 Base Color、Metallic、Roughness、法线贴图等
动画设置 可勾选导出动作(Action)与骨骼结构

四、平台适配建议

不同应用场景,对模型导出有不同的要求:

应用场景 推荐格式 关键配置
WebGL / Three.js / Cesium .glb(含 Draco) 保留贴图、压缩顶点数据
Unity / Unreal Engine .fbx 应用变换,保留骨骼动画
3D 打印 .stl / .obj 删除材质,闭合网格,检查法线
医学三维重建 .glb / .obj 精简材质结构,保留关键模型结构

五、常见问题与排查建议

问题 原因 建议
导入后模型尺寸异常 单位不一致 检查单位设置,统一为米
模型显示为纯白 材质或贴图未绑定 检查贴图路径,确认贴图存在
对象名称混乱 自动重命名 导入后手动重命名或脚本统一命名
动画丢失 未导出动画轨迹 导出前确认勾选动画选项
导出文件过大 面数多、贴图大 结合简化模型和压缩贴图处理

六、使用Python代码批量导入glb(并保留原文件命名)

import bpy
import os
import glob

def import_gltf_strict_named(filepath: str):
    """导入一个 glb 文件,将顶层对象命名为文件名,并放入同名集合"""
    filename = os.path.splitext(os.path.basename(filepath))[0]

    # 记录导入前所有对象
    existing_objects = set(bpy.data.objects)

    # 执行导入
    bpy.ops.import_scene.gltf(filepath=filepath)

    # 记录导入后新增对象
    imported_objects = [obj for obj in bpy.data.objects if obj not in existing_objects]

    # 获取场景中刚导入的顶级对象
    root_objects = [obj for obj in imported_objects if obj.parent is None]

    # 创建集合(名字与文件名相同)
    new_col = bpy.data.collections.new(filename)
    bpy.context.scene.collection.children.link(new_col)

    # 将所有导入对象放入新集合,清理原集合引用
    for obj in imported_objects:
        for col in obj.users_collection:
            col.objects.unlink(obj)
        new_col.objects.link(obj)

    # 如果只有一个顶层对象(比如是个 Group),重命名它
    if len(root_objects) == 1:
        obj = root_objects[0]
        if obj.name != filename and not bpy.data.objects.get(filename):
            obj.name = filename
    else:
        # 如果有多个顶层对象,可以创建一个空的根对象命名
        parent = bpy.data.objects.new(filename, None)
        new_col.objects.link(parent)
        for obj in root_objects:
            obj.parent = parent

    print(f"✅ 已导入并命名:{filename}")


def batch_import_glb_strict(folder_path: str):
    files = glob.glob(os.path.join(folder_path, "*.glb")) + \
            glob.glob(os.path.join(folder_path, "*.gltf"))

    print(f"发现 {len(files)} 个模型文件")

    for i, file in enumerate(files):
        print(f"[{i+1}/{len(files)}] 正在处理:{file}")
        import_gltf_strict_named(file)

       # 执行导入
       # 这里修改导出地址
folder_path = r"F:\project\"
batch_import_glb_strict(folder_path)

七、使用Python代码批量导出glb

import bpy
import os

# 设置导出目录
export_dir = "G:\\new\\models"  # 修改为你自己的导出路径

# 创建导出目录(如果不存在)
if not os.path.exists(export_dir):
    os.makedirs(export_dir)

# 取消所有选择
bpy.ops.object.select_all(action='DESELECT')

# 获取所有要导出的对象(例如:位于指定 Collection 中)
objects_to_export = bpy.context.scene.objects  # 或用:bpy.data.collections['YourCollection'].objects

for obj in objects_to_export:
    if obj.type == 'MESH':
        # 仅选择当前对象
        bpy.ops.object.select_all(action='DESELECT')
        obj.select_set(True)
        bpy.context.view_layer.objects.active = obj

        # 设置导出路径和文件名
        export_path = os.path.join(export_dir, f"{obj.name}.glb")

        # 导出为 glTF/glb 文件
        bpy.ops.export_scene.gltf(
            filepath=export_path,
            use_selection=True,
            export_format='GLB',  # 改为 'GLTF_SEPARATE' 可导出 .gltf + .bin + textures
            export_apply=True
        )

print("批量导出完成!")