from math import radians import sys, os, time, bpy, requests, json, bmesh sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) import platform if platform.system() == 'Windows': sys.path.append('e:\\libs\\') else: sys.path.append('/data/deploy/make3d/make2/libs/') import config 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 get_headcount(pid): res = requests.get(config.urls['get_printinfo_url'], params={'id': pid}) print('get_printsize_url:', res.url) print('res:', res.text) if res.status_code != 200: print('获取人数失败,程序退出') exit(1) res = json.loads(res.text) return res['data']['headcount'] 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 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 getPSRotation(pid): get_ps_rotation_url = 'https://mp.api.suwa3d.com/api/takephotoOrder/angle' res = requests.get(get_ps_rotation_url, params={'pid': pid}) res = json.loads(res.text) rotation = (radians(0), radians(0), radians(int(res['data']))) return rotation def main(): start = time.time() workdir = 'e:\\' 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.wm.read_homefile() # bpy.context.scene.unit_settings.scale_length = 0.001 bpy.context.scene.unit_settings.length_unit = 'CENTIMETERS' bpy.context.scene.unit_settings.mass_unit = 'GRAMS' 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(align_mode='OPT_1', relative_to='OPT_2', align_axis={'Z'}) 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) rotation = getPSRotation(pid) print('rotation:', rotation) obj.rotation_euler = rotation print('rotate obj time:', diff_minutes_and_seconds(start)) # resize object scale = 90 / obj.dimensions.z obj.scale = (scale, scale, scale) bpy.ops.object.origin_set(type='ORIGIN_CENTER_OF_VOLUME', center='MEDIAN') bpy.context.object.location[0] = 0 bpy.context.object.location[1] = 0 bpy.ops.object.transform_apply(location=True, rotation=True, scale=True) # bpy.ops.wm.save_as_mainfile(filepath=f'{workdir}{pid}\\output\{pid}_4.blend') 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') # 生成数字模型 headcount = get_headcount(pid) faces_dest = 120000 * headcount # 减面 faces_current = len(obj.data.polygons) bpy.ops.object.modifier_add(type='DECIMATE') bpy.context.object.modifiers["Decimate"].ratio = faces_dest / faces_current bpy.ops.object.modifier_apply(modifier="Decimate") bpy.ops.export_scene.gltf(filepath=os.path.join(workdir, pid, 'output', f'{pid}_decimate.glb'), export_format='GLB', export_apply=True, export_jpeg_quality=75, export_draco_mesh_compression_enable=False) config.oss_bucket.put_object_from_file(f'glbs/3d/{pid}.glb', os.path.join(workdir, pid, 'output', f'{pid}_decimate.glb')) print('免费体验3d相册已生成,上传glb文件:', f'glbs/3d/{pid}.glb 完成') # 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()