Files
animation/tools/handpose_render_objs.py
T

60 lines
2.6 KiB
Python
Raw Normal View History

"""Clay-render each OBJ in a directory, 3 angles, framed on its bbox.
Only files matching *_hand_*.obj are picked up, and outdir MUST be absolute — a relative
one makes Blender write outside the tree and silently produce nothing.
usage: blender --background --factory-startup --python render_objs.py -- objdir outdir [res] [dist]
res square render resolution in px (default 900)
dist camera distance as a multiple of the mesh radius (default 2.6; lower = tighter)"""
import bpy, sys, math, glob, os
from mathutils import Vector
argv = sys.argv[sys.argv.index("--") + 1:]
objdir, outdir = argv[0], argv[1]
RES = int(argv[2]) if len(argv) > 2 else 900
DIST = float(argv[3]) if len(argv) > 3 else 2.6
bpy.ops.wm.read_factory_settings(use_empty=True)
scn = bpy.context.scene
scn.render.engine = 'BLENDER_EEVEE' if bpy.app.version >= (4, 2) else 'BLENDER_EEVEE_NEXT'
scn.render.resolution_x = scn.render.resolution_y = RES
mat = bpy.data.materials.new("Clay")
mat.use_nodes = True
bsdf = mat.node_tree.nodes["Principled BSDF"]
bsdf.inputs["Base Color"].default_value = (0.72, 0.55, 0.45, 1.0)
bsdf.inputs["Roughness"].default_value = 0.65
for rot, energy in (((50, 0, 30), 3.0), ((-40, 0, -140), 1.2), ((10, 0, 180), 0.8)):
sun = bpy.data.objects.new("Sun", bpy.data.lights.new("Sun", 'SUN'))
sun.data.energy = energy
sun.rotation_euler = tuple(math.radians(a) for a in rot)
scn.collection.objects.link(sun)
cam = bpy.data.objects.new("Cam", bpy.data.cameras.new("Cam"))
cam.data.lens = 60
scn.collection.objects.link(cam)
scn.camera = cam
for path in sorted(glob.glob(os.path.join(objdir, "*_hand_*.obj"))):
bpy.ops.wm.obj_import(filepath=path)
obj = bpy.context.selected_objects[0]
obj.data.materials.clear()
obj.data.materials.append(mat)
for p in obj.data.polygons: p.use_smooth = True
bb = [obj.matrix_world @ Vector(c) for c in obj.bound_box]
ctr = sum(bb, Vector()) / 8
rad = max((v - ctr).length for v in bb)
tag = os.path.splitext(os.path.basename(path))[0]
# OBJ import is -Z forward +Y up by default: gltf Y-up mesh arrives Z-up in Blender
for label, direction in (("palm", Vector((0, -1, -0.25))),
("back", Vector((0, 1, 0.35))),
("side", Vector((-1, -0.3, 0.1)))):
d = direction.normalized()
cam.location = ctr - d * (rad * DIST)
cam.rotation_euler = d.to_track_quat('-Z', 'Y').to_euler()
scn.render.filepath = os.path.join(outdir, f"{tag}_{label}.png")
bpy.ops.render.render(write_still=True)
print("[objr] wrote", scn.render.filepath)
bpy.data.objects.remove(obj, do_unlink=True)
print("[objr] DONE")