# Mako: quick perspective looks (Workbench), exec'd in Blender. ENGINE / NAME / SHOTS / WIRE may be set before exec. # WIRE = True draws every mesh's edges over the shading (temporary wireframe copies, removed afterwards), to check the topology. import bpy, math, os from mathutils import Vector OUTD = os.path.join(r"D:\HADAL - The Descent\models\tender-mako", "previews") os.makedirs(OUTD, exist_ok=True) sc = bpy.context.scene eng = globals().get("ENGINE", "BLENDER_WORKBENCH") name = globals().get("NAME", "wb") wire = globals().get("WIRE", False) shots = globals().get("SHOTS", { "q_front_port": (Vector((6.2, -7.6, 3.2)), Vector((0, -0.2, 0.0)), 34), "q_rear_stbd": (Vector((-6.6, 7.4, 2.8)), Vector((0, 0.6, 0.0)), 34), "q_low_side": (Vector((8.0, -1.0, -1.8)), Vector((0, 0.4, -0.2)), 34), "q_top": (Vector((2.5, -1.0, 9.5)), Vector((0, 0.8, 0.2)), 40), "q_nose": (Vector((2.6, -5.4, 1.2)), Vector((0, -1.0, 0.2)), 34), "q_clips": (Vector((1.8, -2.2, 3.0)), Vector((0, -0.09, 1.05)), 40), "q_cockpit_noglass": (Vector((1.9, -3.4, 1.6)), Vector((0, -0.7, -0.1)), 32), }) temps = [] if wire: wc = bpy.data.collections.get("_wire") or bpy.data.collections.new("_wire") if wc.name not in sc.collection.children: sc.collection.children.link(wc) wm = bpy.data.materials.get("_wire_ink") or bpy.data.materials.new("_wire_ink") wm.diffuse_color = (0.02, 0.02, 0.03, 1) for o in bpy.data.collections["MAKO | Tender (exported)"].all_objects: if o.type != 'MESH' or o.name == "SM_Mako_Cabin": continue t = o.copy(); t.data = o.data.copy(); t.name = "_w_" + o.name t.data.materials.clear(); t.data.materials.append(wm) t.parent = None; t.matrix_world = o.matrix_world.copy() wc.objects.link(t) md = t.modifiers.new("w", 'WIREFRAME'); md.thickness = 0.0030; md.use_relative_offset = False; md.use_even_offset = False temps.append(t) sc.render.engine = eng if eng == 'BLENDER_WORKBENCH': sh = sc.display.shading sh.light = 'STUDIO'; sh.color_type = 'MATERIAL'; sh.show_object_outline = False; sh.show_cavity = not wire sh.cavity_type = 'BOTH' sc.render.film_transparent = False sc.render.image_settings.file_format = 'PNG'; sc.render.image_settings.color_mode = 'RGB' sc.render.resolution_x, sc.render.resolution_y, sc.render.resolution_percentage = (1800, 1000, 100) if wire else (1400, 800, 100) cam = bpy.data.objects.get("_pv_cam") if cam is None: cam = bpy.data.objects.new("_pv_cam", bpy.data.cameras.new("_pv_cam")) sc.collection.objects.link(cam) cam.data.type = 'PERSP' prev = sc.camera sc.camera = cam for o in bpy.data.objects: if o.name.startswith("UCX_"): o.hide_render = True done = [] glass_o = bpy.data.objects.get("SM_Mako_Glass") for nm, (loc, tgt, lens) in shots.items(): if glass_o is not None: # shots named *_noglass look into the cockpit with the glass hidden glass_o.hide_render = nm.endswith("noglass") cam.location = loc cam.rotation_euler = (tgt - loc).normalized().to_track_quat('-Z', 'Y').to_euler() cam.data.lens = lens sc.render.filepath = os.path.join(OUTD, "%s_%s.png" % (name, nm)) bpy.ops.render.render(write_still=True) done.append(sc.render.filepath) sc.camera = prev bpy.data.objects.remove(cam) for t in temps: me = t.data bpy.data.objects.remove(t) bpy.data.meshes.remove(me) if wire: bpy.data.collections.remove(wc) if wm.users == 0: bpy.data.materials.remove(wm) result = done