Skip to content

Instantly share code, notes, and snippets.

@stoobit
Created January 8, 2026 21:26
Show Gist options
  • Select an option

  • Save stoobit/7899d64245bdfc86100f3cffc8b72069 to your computer and use it in GitHub Desktop.

Select an option

Save stoobit/7899d64245bdfc86100f3cffc8b72069 to your computer and use it in GitHub Desktop.
A python script that converts models generated by SAM-3D-Body to the USDZ file format using blender.
import bpy
import os
import math
import shutil
# --- CONFIGURATION ---
SOURCE_FOLDER = "/Users/name/.../models_original/"
EXPORT_FOLDER = "/Users/name/.../usdz/"
OBJECTS_TO_KEEP = ["HumanMesh"]
MATCH_LOOSELY = True
WRAPPER_ROTATION = (0, 180, 135)
TARGET_COLOR = (0.92, 0.92, 0.92, 1.0)
# ------------------------------
def clear_scene():
if bpy.context.active_object and bpy.context.active_object.mode == "EDIT":
bpy.ops.object.mode_set(mode="OBJECT")
bpy.ops.object.select_all(action="SELECT")
bpy.ops.object.delete()
for block in bpy.data.meshes:
if block.users == 0:
bpy.data.meshes.remove(block)
for block in bpy.data.armatures:
if block.users == 0:
bpy.data.armatures.remove(block)
for block in bpy.data.objects:
if block.users == 0:
bpy.data.objects.remove(block)
for block in bpy.data.materials:
if block.users == 0:
bpy.data.materials.remove(block)
def make_materials_solid_and_dark(obj):
"""Forces material to be Opaque and Darker"""
for slot in obj.material_slots:
mat = slot.material
if not mat:
continue
mat.blend_method = "OPAQUE"
if hasattr(mat, "shadow_method"):
mat.shadow_method = "OPAQUE"
mat.use_backface_culling = False
if getattr(mat, "use_nodes", False):
nodes = mat.node_tree.nodes
principled = next((n for n in nodes if n.type == "BSDF_PRINCIPLED"), None)
if principled:
if "Alpha" in principled.inputs:
principled.inputs["Alpha"].default_value = 1.0
if "Transmission" in principled.inputs:
principled.inputs["Transmission"].default_value = 0.0
if "Transmission Weight" in principled.inputs:
principled.inputs["Transmission Weight"].default_value = 0.0
color_input = None
if "Base Color" in principled.inputs:
color_input = principled.inputs["Base Color"]
elif "Color" in principled.inputs:
color_input = principled.inputs["Color"]
if color_input:
if not color_input.is_linked:
color_input.default_value = TARGET_COLOR
def process_files():
if os.path.exists(EXPORT_FOLDER):
shutil.rmtree(EXPORT_FOLDER)
os.makedirs(EXPORT_FOLDER)
files = [
f
for f in os.listdir(SOURCE_FOLDER)
if f.lower().endswith((".fbx", ".obj", ".glb", ".gltf"))
]
print(f"Found {len(files)} files to process...")
for filename in files:
filepath = os.path.join(SOURCE_FOLDER, filename)
clear_scene()
print(f"Processing: {filename}")
try:
if filename.lower().endswith(".fbx"):
bpy.ops.import_scene.fbx(filepath=filepath)
elif filename.lower().endswith(".obj"):
bpy.ops.import_scene.obj(filepath=filepath)
elif filename.lower().endswith((".glb", ".gltf")):
bpy.ops.import_scene.gltf(filepath=filepath)
except Exception as e:
print(f"Error importing {filename}: {e}")
continue
kept_objects = []
for obj in bpy.data.objects:
is_target = False
for keep_name in OBJECTS_TO_KEEP:
if MATCH_LOOSELY:
if obj.name.startswith(keep_name):
is_target = True
else:
if obj.name == keep_name:
is_target = True
if is_target:
kept_objects.append(obj)
bpy.ops.object.select_all(action="DESELECT")
for obj in bpy.data.objects:
if obj not in kept_objects:
obj.select_set(True)
bpy.ops.object.delete()
for obj in kept_objects:
if obj.type == "MESH":
make_materials_solid_and_dark(obj)
if kept_objects:
bpy.ops.object.empty_add(type="PLAIN_AXES", location=(0, 0, 0))
wrapper = bpy.context.active_object
for obj in kept_objects:
obj.select_set(True)
bpy.context.view_layer.objects.active = wrapper
bpy.ops.object.parent_set(type="OBJECT", keep_transform=True)
obj.select_set(False)
wrapper.rotation_mode = "XYZ"
wrapper.rotation_euler = (
math.radians(WRAPPER_ROTATION[0]),
math.radians(WRAPPER_ROTATION[1]),
math.radians(WRAPPER_ROTATION[2]),
)
# 5. EXPORT AS USDZ
file_root = os.path.splitext(filename)[0]
out_name = file_root + ".usdz"
out_path = os.path.join(EXPORT_FOLDER, out_name)
bpy.ops.object.select_all(action="SELECT")
bpy.ops.wm.usd_export(
filepath=out_path,
selected_objects_only=True,
export_materials=True,
relative_paths=True,
)
print(f" Saved to: {out_path}")
print("----- BATCH PROCESSING COMPLETE -----")
if __name__ == "__main__":
process_files()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment