From b793d7cfd574a1b9bba9838e2164f9e893eaeca6 Mon Sep 17 00:00:00 2001 From: dongchangxi <458593490@qq.com> Date: Tue, 18 Mar 2025 16:13:03 +0800 Subject: [PATCH] 111 --- blender/gray_fill_dm_code.py | 2 +- blender/gray_resize_model.py | 223 +++++++++++++++++++++++++++++++++++ gray_auto_convert3d.py | 34 ++++-- gray_no_resize.py | 12 +- 4 files changed, 251 insertions(+), 20 deletions(-) create mode 100644 blender/gray_resize_model.py diff --git a/blender/gray_fill_dm_code.py b/blender/gray_fill_dm_code.py index e028853..99e7844 100644 --- a/blender/gray_fill_dm_code.py +++ b/blender/gray_fill_dm_code.py @@ -751,7 +751,7 @@ def create_redis_connection(): """创建 Redis 连接,若连接失败则重试""" while True: try: - r = redis.Redis(host="106.14.158.208", password="kcV2000", port=6379, db=6) + r = redis.Redis(host="mark.api.suwa3d.com", password="kcV2000", port=6379, db=6) # 尝试进行一次操作,检查连接是否有效 r.ping() # ping 操作是一个简单的连接测试 print("Redis连接成功!") diff --git a/blender/gray_resize_model.py b/blender/gray_resize_model.py new file mode 100644 index 0000000..9d9b039 --- /dev/null +++ b/blender/gray_resize_model.py @@ -0,0 +1,223 @@ +from math import radians +import sys, platform, os, time, bpy, requests, json, bmesh, shutil +from PIL import Image +import platform +# if platform.system() == 'Windows': +# sys.path.append('e:\\libs\\') +# else: +# sys.path.append('/data/deploy/make3d/make2/libs/') +sys.path.append('/home/acprint/code/libs/') +import config, libs + +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 fix_link_texture(pid): + # 修改obj中的mtl文件为pid_original.mtl + path = os.path.join(workdir, 'print', f'{pid}_{orderId}') + filename = os.path.join(path, f'{pid}_original.obj') + + with open(filename, 'r') as f: + lines = f.readlines() + for i in range(len(lines)): + if lines[i].startswith('mtllib'): + lines[i] = f'mtllib {pid}_original.mtl\n' + break + with open(filename, 'w') as f: + f.writelines(lines) + + f.close() + + # 将pid.mtl文件复制为pid_original.mtl _decimate + shutil.copy(os.path.join(path, f'{pid}.mtl'), os.path.join(path, f'{pid}_original.mtl')) + shutil.copy(os.path.join(path, f'{pid}Tex1.jpg'), os.path.join(path, f'{pid}Tex1_decimate.jpg')) + texture_file = os.path.join(path, f'{pid}Tex1_decimate.jpg') + if os.path.exists(texture_file): + img = Image.open(texture_file) + img = img.resize((int(img.size[0] * 0.5), int(img.size[1] * 0.5))) + img.save(texture_file, quality=100, optimize=True) + print('resize texture file to 50% success') + # 修改pid_original.mtl文件中的贴图为pid_old.jpg + with open(os.path.join(path, f'{pid}_original.mtl'), 'r') as f: + lines = f.readlines() + for i in range(len(lines)): + if lines[i].startswith('map_Kd'): + lines[i] = f'map_Kd {pid}Tex1_decimate.jpg\n' + break + with open(os.path.join(path, f'{pid}_original.mtl'), 'w') as f: + f.writelines(lines) + + f.close() + +def imagePiex(filePath,piex): + # 打开图片 + image = Image.open(filePath) + # 设置新的最大宽度和高度 + max_size = (piex, piex) + # 保持宽高比缩放图片 + image.thumbnail(max_size) + # 保存调整后的图片 + image.save(filePath) + +def main(): + start = time.time() + + get_printsize_url = 'https://mp.gray.api.suwa3d.com/api/printOrder/infoByOrderId' + upload_obj_volume_url = 'https://mp.gray.api.suwa3d.com/api/physical/add' # ?pid=1&order_id=1&faces=1&volume=1 + + print(f'{get_printsize_url}?order_id={orderId}') + res = requests.get(f'{get_printsize_url}?id={orderId}') + print('获取打印尺寸:', res.text) + + if res.status_code == 200: + pid = res.json()['data']['pid'] + path = os.path.join(workdir, 'print', f'{pid}_{orderId}') + filename = os.path.join(path, f'{pid}.obj') + imagePath = os.path.join(path, f'{pid}Tex1.jpg') + bpy.ops.object.delete(use_global=False, confirm=False) + 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' + + print('正在处理:', filename) + bpy.ops.import_scene.obj(filepath=filename) + obj = bpy.context.selected_objects[0] + print('原始模型尺寸:', obj.dimensions) + bpy.ops.object.transform_apply(location=True, rotation=True, scale=True) + print('应用后模型尺寸:', obj.dimensions) + shutil.copy(filename, os.path.join(path, f'{pid}_original.obj')) + filename_original = os.path.join(path, f'{pid}_original.obj') + headcount = res.json()['data']['headcount'] + for f in res.json()['data']['fileList']: + + if "undefined" in f: + continue + + try: + height = float(f.split('_')[-2][:-2]) * 10 + except Exception as e: + print("eeee",e) + bpy.ops.wm.quit_blender() + return + + + + obj = bpy.context.selected_objects[0] + bpy.context.view_layer.objects.active = obj + print(f'{f}处理前{height}mm模型尺寸: {obj.dimensions}') + scale = height / obj.dimensions.z + obj.scale = (scale, scale, scale) + bpy.ops.object.transform_apply(scale=True) + print(f'{f}处理后{height}mm模型尺寸: {obj.dimensions}') + + if headcount == 1 and height <= 80: + pixs = 4096 + faces_dest = 125000 + if height <= 50: + pixs = 2048 + faces_dest = 63000 + print(f'减面到{faces_dest}') + faces_dest = faces_dest * 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") + # imagePiex(imagePath,pixs) + + bpy.ops.export_scene.obj(filepath=os.path.join(path, f'{pid}.obj')) + if os.path.exists(os.path.join(path, f)): + os.remove(os.path.join(path, f)) + os.rename(os.path.join(path, f'{pid}.obj'), os.path.join(path, f)) + config.oss_bucket.put_object_from_file(f'objs/print/{pid}/{f}', os.path.join(path, f)) + + + + # 重新加载模型,然后生成数字模型 + bpy.ops.object.delete(use_global=False, confirm=False) + fix_link_texture(pid) + bpy.ops.import_scene.obj(filepath=filename_original) + 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' + + obj = bpy.context.selected_objects[0] + bpy.context.view_layer.objects.active = obj + obj.select_set(True) + + scale = 90 / obj.dimensions.y + obj.scale = (scale, scale, scale) + bpy.ops.object.transform_apply(location=True, rotation=True, scale=True) + # if str(pid) == '120745': bpy.ops.wm.save_as_mainfile(filepath=os.path.join(path, f'{pid}_{orderId}.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') + tempWeight = obj_volume * 1.2 + faces = len(obj.data.polygons) + print('faces:', faces) + upload_res = requests.get(f'{upload_obj_volume_url}?pid={pid}&order_id={orderId}&faces={faces}&volume={obj_volume}&headcount={headcount}&weight={tempWeight}') + print('上传模型体积:', upload_res.text) + + # 生成数字模型 + + 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.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.export_scene.obj(filepath=os.path.join(path, f'{pid}_decimate.obj')) + bpy.ops.export_scene.gltf(filepath=os.path.join(path, f'{pid}_decimate.glb'), export_format='GLB', export_apply=True, export_jpeg_quality=100) + config.oss_bucket.put_object_from_file(f'glbs/3d/{pid}.glb', os.path.join(path, f'{pid}_decimate.glb')) + bpy.ops.wm.quit_blender() + + +if __name__ == '__main__': + if platform.system() == 'Windows': + workdir = 'E:\\' + else: + workdir = '/data/datasets/' + + if len(sys.argv) - (sys.argv.index("--") + 1) < 1: + print("Usage: blender -b -P resize_model.py -- ") + sys.exit(1) + orderId = sys.argv[sys.argv.index("--") + 1] + + main() diff --git a/gray_auto_convert3d.py b/gray_auto_convert3d.py index 0c05fce..681f0fe 100644 --- a/gray_auto_convert3d.py +++ b/gray_auto_convert3d.py @@ -63,21 +63,24 @@ def down_obj_fromoss(pid, print_type=1, order_id=None,download_flag="print_build prefix = f'objs/print/{pid}/' #根据order_id 获取文件在 oss 上的存储路径 if order_id is not None: - tempURL = "https://mp.gray.api.suwa3d.com/api/order/getOssSuffixByOrderId?orderId="+str(order_id) + tempURL = "https://mp.gray.api.suwa3d.com/api/order/getOssSuffixByOrderId?order_id="+str(order_id) + print(tempURL) res = requests.get(tempURL) + print(res.json()) resCode = res.json()['code'] if int(resCode) != 1000: return -1 print(res.text) if res.json()['data'] != "": - prefix = f'objs/print/{pid}/{res.json()["data"]}/{str(order_id)}/' - + prefix = f'objs/print/{pid}/{res.json()["data"]}/{str(order_id)}' + print(prefix) filelist = oss2.ObjectIteratorV2(oss_client, prefix=prefix) #判断是否有值,没有值的话就从老的路径再获取一次数据 - if len(filelist) == 0: + if len(list(filelist)) == 0: filelist = oss2.ObjectIteratorV2(oss_client, prefix=f'objs/print/{pid}/') - + else: + filelist = oss2.ObjectIteratorV2(oss_client, prefix=prefix) find = False @@ -205,7 +208,7 @@ def make3d4print_task(r): print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), 'redis连接异常,重新连接') print(e) time.sleep(5) - r = redis.Redis(host='106.14.158.208', password='kcV2000', port=6379, db=6) + r = redis.Redis(host='mark.api.suwa3d.com', password='kcV2000', port=6379, db=6) return orderId = None if tempOrderId == "0": @@ -226,7 +229,7 @@ def make3d4print_task(r): #根据 buy_type 判断 是否是冰箱贴 或者徽章 buyType = str(res['buy_type']) - if buyType == "2" or buyType == "3": + if buyType == "2" or buyType == "3" or buyType == "4": #塞入到no_resize 队列 r.lpush("model:noresize", orderId) return @@ -239,19 +242,24 @@ def make3d4print_task(r): #创建正在处理的文本内容 creatDoingLog(orderId) - print_type = res['print_type'] - digital_type = res['digital_type'] # 0: 只有手办 1: 只有数字模型 2: 手办+数字模型 + print_type = 1 + digital_type = 1 # 0: 只有手办 1: 只有数字模型 2: 手办+数字模型 print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), f'orderId:{orderId} pid:{pid} 生成待打印模型 start', ) isFindObj = False - down_obj_fromoss(pid, print_type, orderId,download_flag="print_build") + print("AAAAAAAAAAAAAAAAAA") + downloadRes = down_obj_fromoss(pid, print_type, orderId,download_flag="print_build") + print("downloadRes",downloadRes) + if downloadRes == -1: + print("下载错误") + return # 获取程序运行当前目录 - resize_py_path = os.path.join(os.getcwd(), 'blender', 'resize_model.py') + resize_py_path = os.path.join(os.getcwd(), 'blender', 'gray_resize_model.py') print(f'{blenderbin} -b -P {resize_py_path} -- {orderId}') os.system(f'{blenderbin} -b -P {resize_py_path} -- {orderId}') if not detect_obj4print(pid, orderId): print('obj文件生成异常,退出,重新执行') - restart_current_process("python auto_convert3d.py") + # restart_current_process("python gray_auto_convert3d.py") return print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), f'orderId:{orderId} pid:{pid} 生成待打印模型 end') @@ -325,7 +333,7 @@ def make3d4print_task(r): print(f"{pid}-已处理结束") - restart_current_process("python auto_convert3d.py") + # restart_current_process("python gray_auto_convert3d.py") def delete_files_in_directory(directory): diff --git a/gray_no_resize.py b/gray_no_resize.py index da77e3f..400a71d 100644 --- a/gray_no_resize.py +++ b/gray_no_resize.py @@ -13,7 +13,7 @@ def create_redis_connection(): """创建 Redis 连接,若连接失败则重试""" while True: try: - r = redis.Redis(host="106.14.158.208", password="kcV2000", port=6379, db=6) + r = redis.Redis(host="mark.api.suwa3d.com", password="kcV2000", port=6379, db=6) # 尝试进行一次操作,检查连接是否有效 r.ping() # ping 操作是一个简单的连接测试 print("Redis连接成功!") @@ -36,7 +36,7 @@ def main(r): #根据pid获取orderId def getPidFromOrderId(orderId): - getPidFromOrderId_url = 'https://mp.gray.api.suwa3d.com/api/printOrder/info' + getPidFromOrderId_url = 'https://mp.gray.api.suwa3d.com/api/printOrder/infoByOrderId' print(f'{getPidFromOrderId_url}?id={orderId}') res = requests.get(f'{getPidFromOrderId_url}?id={orderId}') resCode = res.json()['code'] @@ -58,16 +58,16 @@ def down_obj_fromoss(pid, print_type=1, order_id=None,download_flag="print_build prefix = f'objs/print/{pid}/' #根据order_id 获取文件在 oss 上的存储路径 if order_id is not None: - tempURL = "https://mp.gray.api.suwa3d.com/api/order/getOssSuffixByOrderId?orderId="+str(order_id) + tempURL = "https://mp.gray.api.suwa3d.com/api/order/getOssSuffixByOrderId?order_id="+str(order_id) res = requests.get(tempURL) resCode = res.json()['code'] if int(resCode) != 1000: return -1 print(res.text) if res.json()['data'] != "": - prefix = f'objs/print/{pid}/{res.json()["data"]}/{order_id}/' - + prefix = f'objs/print/{pid}/{res.json()["data"]}/{order_id}' + print(f"prefix ======= {prefix}") filelist = oss2.ObjectIteratorV2(oss_client, prefix=prefix) find = False findTex1Jpg = False @@ -171,7 +171,7 @@ def make3d4print_task(r): path = os.path.join(workdir, 'print', f'{pid}_{orderId}') #获取打印尺寸信息 - get_printsize_url = 'https://mp.gray.api.suwa3d.com/api/printOrder/info' + get_printsize_url = 'https://mp.gray.api.suwa3d.com/api/printOrder/infoByOrderId' res = requests.get(f'{get_printsize_url}?id={orderId}') print('获取打印尺寸:', res.text) objName = ""