from math import radians import sys, os, time, bpy, requests, json, bmesh def get_obj_version(filename): with open(filename, 'r') as f: for line in f: if line.startswith('# Engine version'): return float(line.split(' ')[-1][1:].strip()[:3]) exit(0) return None def delete_lines_in_file(filename, count): with open(filename, 'r') as f: lines = f.readlines() lines = lines[count:] with open(filename, 'w') as f: f.writelines(lines) def diff_minutes_and_seconds(start): hours = int((time.time() - start) / 3600) minutes = int((time.time() - start) / 60) seconds = int((time.time() - start) % 60) microseconds = int(int((time.time() - start) * 1000000) % 1000000 / 1000) return f'{hours}:{minutes}:{seconds}.{microseconds}' def getPSid(pid): get_psid_url = 'https://mp.api.suwa3d.com/api/customerP3dLog/photoStudio' res = requests.get(get_psid_url, params={'pid': pid}) res = json.loads(res.text) return str(res['data']) def bmesh_copy_from_object(obj, transform=True, triangulate=True, apply_modifiers=False): """Returns a transformed, triangulated copy of the mesh""" assert obj.type == 'MESH' if apply_modifiers and obj.modifiers: import bpy depsgraph = bpy.context.evaluated_depsgraph_get() obj_eval = obj.evaluated_get(depsgraph) me = obj_eval.to_mesh() bm = bmesh.new() bm.from_mesh(me) obj_eval.to_mesh_clear() else: me = obj.data if obj.mode == 'EDIT': bm_orig = bmesh.from_edit_mesh(me) bm = bm_orig.copy() else: bm = bmesh.new() bm.from_mesh(me) if transform: matrix = obj.matrix_world.copy() if not matrix.is_identity: bm.transform(matrix) matrix.translation.zero() if not matrix.is_identity: bm.normal_update() if triangulate: bmesh.ops.triangulate(bm, faces=bm.faces) return bm def main(): start = time.time() config = { '0': { 'rotation': (radians(0), radians(0), radians(0)), }, '1': { 'rotation': (radians(0), radians(0), radians(66)), }, '29': { 'rotation': (radians(0), radians(0), radians(180)), }, '45': { 'rotation': (radians(0), radians(0), radians(105)), }, '46': { 'rotation': (radians(0), radians(0), radians(-10)), }, '74': { 'rotation': (radians(0), radians(0), radians(110)), }, '75': { 'rotation': (radians(0), radians(0), radians(210)), }, } workdir = 'd:\\' if len(sys.argv) - (sys.argv.index("--") +1) < 1: print("Usage: blender -b -P autofix.py -- ") sys.exit(1) input_file = sys.argv[sys.argv.index("--") + 1] for pid in input_file.split(','): psid = getPSid(pid) bpy.ops.object.delete(use_global=False, confirm=False) filename = f'{workdir}{pid}\\output\{pid}.obj' print('正在处理:', filename) bpy.ops.import_scene.obj(filepath=filename) bpy.ops.object.align(relative_to='OPT_1', align_axis={'X'}) # bpy.ops.object.transform_apply(location=True, rotation=True, scale=True) print('import obj time:', diff_minutes_and_seconds(start)) # rotate obj obj = bpy.context.selected_objects[0] bpy.context.view_layer.objects.active = obj obj.select_set(True) if psid in config: obj.rotation_euler = config[psid]['rotation'] else: obj.rotation_euler = config['0']['rotation'] print('rotate obj time:', diff_minutes_and_seconds(start)) # bpy.ops.object.transform_apply(location=True, rotation=True, scale=True) # resize object obj_scale = 90 / obj.dimensions.z print('scale:', obj_scale) obj.scale = (obj_scale, obj_scale, obj_scale) bpy.ops.object.transform_apply(location=True, rotation=True, scale=True) bm = bmesh_copy_from_object(obj) obj_volume = round(bm.calc_volume() / 1000, 3) print('volume:', obj_volume) print('weight:', obj_volume * 1.2, 'g') faces = len(obj.data.polygons) print('faces:', faces) # save object bpy.ops.export_scene.obj(filepath=f'{workdir}{pid}\\output\{pid}.obj') # render scene to a file # bpy.context.scene.render.filepath = f'{workdir}{pid}_fixed.png' # bpy.ops.render.render(write_still=True, use_viewport=True) print('render time:', diff_minutes_and_seconds(start)) bpy.ops.wm.quit_blender() if __name__ == '__main__': main()