import bpy, sys, math, mathutils src, outdir = sys.argv[-2], sys.argv[-1] bpy.ops.wm.read_factory_settings(use_empty=True) bpy.ops.import_scene.gltf(filepath=src) meshes = [o for o in bpy.data.objects if o.type == 'MESH'] # frame on the dominant mesh only — tiny helper meshes (attachment markers) inflate the bbox if len(meshes) > 1: meshes = [max(meshes, key=lambda o: len(o.data.vertices))] # bind pose: strip animation for o in bpy.data.objects: if o.animation_data: o.animation_data_clear() if o.type == 'ARMATURE': for pb in o.pose.bones: pb.location = (0,0,0); pb.rotation_quaternion = (1,0,0,0); pb.rotation_euler = (0,0,0); pb.scale = (1,1,1) bpy.context.view_layer.update() mn = mathutils.Vector((1e9,)*3); mx = mathutils.Vector((-1e9,)*3) for o in meshes: for v in o.bound_box: w = o.matrix_world @ mathutils.Vector(v) mn = mathutils.Vector(map(min, mn, w)); mx = mathutils.Vector(map(max, mx, w)) c = (mn + mx) / 2; h = (mx - mn).z; w_ = max((mx - mn).x, (mx - mn).y) sc = bpy.context.scene sc.render.engine = 'BLENDER_EEVEE' sc.render.resolution_x = 1024; sc.render.resolution_y = 1024 sc.render.film_transparent = True wld = bpy.data.worlds.new('w'); sc.world = wld; wld.use_nodes = True wld.node_tree.nodes['Background'].inputs[0].default_value = (1,1,1,1) wld.node_tree.nodes['Background'].inputs[1].default_value = 1.0 for name, dirv in (('front', mathutils.Vector((0,1,0))), ('back', mathutils.Vector((0,-1,0)))): cam = bpy.data.objects.new('cam_'+name, bpy.data.cameras.new('c')) cam.data.type = 'ORTHO'; cam.data.ortho_scale = h * 1.1 bpy.context.collection.objects.link(cam) cam.location = c - dirv * (h * 2) cam.rotation_euler = dirv.to_track_quat('-Z','Y').to_euler() sc.camera = cam sc.render.filepath = f"{outdir}/base_{name}.png" bpy.ops.render.render(write_still=True) print('rendered', name)