You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

194 lines
7.8 KiB

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=90, 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 main():
start = time.time()
get_printsize_url = 'https://mp.api.suwa3d.com/api/printOrder/info'
upload_obj_volume_url = 'https://mp.api.suwa3d.com/api/physical/add' # ?pid=1&order_id=1&faces=1&volume=1
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')
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')
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]
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}')
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'))
headcount = res.json()['data']['headcount']
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=80)
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 -- <orderId>")
sys.exit(1)
orderId = sys.argv[sys.argv.index("--") + 1]
main()