From fd1de8c3d0f26086ce77b9e80907bed0659d64ba Mon Sep 17 00:00:00 2001 From: dongchangxi <458593490@qq.com> Date: Fri, 5 Dec 2025 10:27:43 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=87=E7=89=87=E4=B8=8B=E8=BD=BD=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- script/factory_sliceing_v2/main.py | 2 +- script/factory_sliceing_v2/utils/funcs.py | 38 ++++++++-- .../utils/small_machine_transform.py | 76 +++++++++++++++++-- 3 files changed, 104 insertions(+), 12 deletions(-) diff --git a/script/factory_sliceing_v2/main.py b/script/factory_sliceing_v2/main.py index 808d5b0..f7006de 100644 --- a/script/factory_sliceing_v2/main.py +++ b/script/factory_sliceing_v2/main.py @@ -117,7 +117,7 @@ def main(work_dir=None): def testMain(): global currentDir currentDir = "/Users/dcx/code/make2/script/factory_sliceing_v2/tempData" - versionId = '10158' #'10153 10158' + versionId = '10153' #'10153 10158' print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} 正在处理版次ID={versionId}') res = step1(versionId) print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())} 处理完成,res={res}') diff --git a/script/factory_sliceing_v2/utils/funcs.py b/script/factory_sliceing_v2/utils/funcs.py index a3fda72..a5df218 100644 --- a/script/factory_sliceing_v2/utils/funcs.py +++ b/script/factory_sliceing_v2/utils/funcs.py @@ -324,6 +324,22 @@ def _process_single_item(v, arrDownloadPath, dirNewName, dirPath, isSmallMachine # 将 homo_matrix 转换为 JSON 字符串 homo_matrix_json = json.dumps(homo_matrix) + # 检查必要文件是否存在 + if not blender_bin_path or not os.path.exists(blender_bin_path): + error_msg = f"Blender 可执行文件不存在: {blender_bin_path}" + log(error_msg) + return False, error_msg + + if not os.path.exists(transform_script_path): + error_msg = f"转换脚本文件不存在: {transform_script_path}" + log(error_msg) + return False, error_msg + + if not os.path.exists(objsLocal): + error_msg = f"OBJ 文件不存在: {objsLocal}" + log(error_msg) + return False, error_msg + # 构建命令参数列表(使用列表形式,避免 shell 转义问题) cmd = [ blender_bin_path, @@ -334,10 +350,14 @@ def _process_single_item(v, arrDownloadPath, dirNewName, dirPath, isSmallMachine f'--objPathName={objsLocal}', f'--trans={homo_matrix_json}' ] - - log(f"执行 Blender 命令: {' '.join(cmd[:4])} ... (参数已隐藏)") + log(f"准备执行 Blender 命令") + log(f" Blender路径: {blender_bin_path}") + log(f" 脚本路径: {transform_script_path}") + log(f" OBJ文件: {objsLocal}") + log(f" 完整命令: {' '.join(cmd[:4])} ... (参数已隐藏)") try: + log(f"开始执行 Blender 转换命令...") # 使用 subprocess 执行命令,捕获输出和错误 # 在 Windows 上,Blender 输出可能是 UTF-8,需要指定编码并处理错误 result = subprocess.run( @@ -350,17 +370,23 @@ def _process_single_item(v, arrDownloadPath, dirNewName, dirPath, isSmallMachine check=False # 不自动抛出异常,手动检查返回码 ) + log(f"Blender 命令执行完成, 返回码: {result.returncode}") + + # 无论成功失败都输出详细信息 + if result.stdout: + log(f"Blender stdout 输出: {result.stdout}") + if result.stderr: + log(f"Blender stderr 输出: {result.stderr}") + if result.returncode != 0: error_output = result.stderr if result.stderr else result.stdout - error_msg = f"调用blender 执行 python 文件失败, error={result.returncode}, fileName={fileName}" + error_msg = f"调用blender 执行 python 文件失败, 返回码={result.returncode}, fileName={fileName}" if error_output: - error_msg += f", 错误信息: {error_output[:500]}" # 限制错误信息长度 + error_msg += f", 错误信息: {error_output[:10000000]}" # 增加错误信息长度限制 log(error_msg) return False, error_msg log(f"调用blender 执行 python 文件成功, fileName={fileName}") - if result.stdout: - log(f"Blender 输出: {result.stdout[:200]}") # 记录部分输出用于调试 except subprocess.TimeoutExpired: error_msg = f"调用blender 执行超时(超过5分钟), fileName={fileName}" diff --git a/script/factory_sliceing_v2/utils/small_machine_transform.py b/script/factory_sliceing_v2/utils/small_machine_transform.py index d5c18ef..d5e548e 100644 --- a/script/factory_sliceing_v2/utils/small_machine_transform.py +++ b/script/factory_sliceing_v2/utils/small_machine_transform.py @@ -1,6 +1,7 @@ import os,time,sys,argparse import numpy as np import json +import warnings def findBpyModule(): @@ -17,11 +18,55 @@ def custom_mesh_transform(vertices, transform_matrix): 返回: 变换后的顶点数组 (N, 3) """ + # 验证变换矩阵 + transform_matrix = np.array(transform_matrix, dtype=np.float64) + + # 检查矩阵形状 + if transform_matrix.shape != (4, 4): + raise ValueError(f"变换矩阵必须是 4x4 矩阵,当前形状: {transform_matrix.shape}") + + # 检查矩阵中是否包含无效值(NaN 或 Inf) + if np.any(np.isnan(transform_matrix)) or np.any(np.isinf(transform_matrix)): + invalid_count = np.sum(np.isnan(transform_matrix)) + np.sum(np.isinf(transform_matrix)) + raise ValueError(f"变换矩阵包含无效值 (NaN/Inf): {invalid_count} 个无效元素\n矩阵:\n{transform_matrix}") + + # 检查矩阵行列式(对于齐次变换矩阵,最后一行应该是 [0, 0, 0, 1]) + # 如果矩阵接近奇异,行列式会接近0 + det = np.linalg.det(transform_matrix[:3, :3]) # 只检查3x3旋转/缩放部分 + if abs(det) < 1e-10: + print(f"警告: 变换矩阵的3x3部分行列式接近0 (det={det:.2e}),可能导致数值不稳定") + + # 检查最后一行是否为 [0, 0, 0, 1](齐次变换矩阵的标准形式) + last_row = transform_matrix[3, :] + if not np.allclose(last_row, [0, 0, 0, 1], atol=1e-6): + print(f"警告: 变换矩阵最后一行不是标准形式 [0,0,0,1],而是: {last_row}") + # 1. 顶点转齐次坐标 (N, 3) → (N, 4) homogeneous_vertices = np.hstack((vertices, np.ones((vertices.shape[0], 1)))) # 2. 应用变换矩阵:矩阵乘法 (4x4) * (4xN) → (4xN) - transformed_homogeneous = transform_matrix @ homogeneous_vertices.T + # 捕获警告并检查结果 + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always") # 捕获所有警告 + transformed_homogeneous = transform_matrix @ homogeneous_vertices.T + + # 如果有警告,记录详细信息 + if w: + warning_msgs = [str(warning.message) for warning in w] + print(f"警告: 矩阵乘法过程中出现 {len(w)} 个警告:") + for msg in warning_msgs: + print(f" - {msg}") + print(f"变换矩阵:\n{transform_matrix}") + print(f"矩阵包含 NaN: {np.any(np.isnan(transform_matrix))}") + print(f"矩阵包含 Inf: {np.any(np.isinf(transform_matrix))}") + if not np.any(np.isnan(transform_matrix)) and not np.any(np.isinf(transform_matrix)): + print(f"矩阵最大值: {np.nanmax(transform_matrix):.6e}") + print(f"矩阵最小值: {np.nanmin(transform_matrix):.6e}") + + # 检查结果是否包含无效值 + if np.any(np.isnan(transformed_homogeneous)) or np.any(np.isinf(transformed_homogeneous)): + invalid_count = np.sum(np.isnan(transformed_homogeneous)) + np.sum(np.isinf(transformed_homogeneous)) + raise ValueError(f"变换后的顶点包含无效值 (NaN/Inf): {invalid_count} 个无效元素") # 3. 转回非齐次坐标 (3xN) → (N, 3) transformed_vertices = transformed_homogeneous[:3, :].T @@ -48,8 +93,9 @@ def transform_save(obj_path,homo_matrix): # log("错误: bpy 模块不可用。此函数只能在 Blender 环境中运行。") # log("请使用 Blender 的 Python 解释器运行此脚本,或通过 Blender 命令行运行。") # raise ImportError("bpy 模块不可用。此函数只能在 Blender 环境中运行。") - + print("开始转换数据") obj_name = obj_path.split("/")[-1] + print(f"obj_name={obj_name}") # 清除场景 bpy.ops.object.select_all(action='SELECT') bpy.ops.object.delete(use_global=False) @@ -74,8 +120,28 @@ def transform_save(obj_path,homo_matrix): mesh_data.vertices.foreach_get('co', original_vertices) original_vertices = original_vertices.reshape(-1, 3) - transformed_vertices = custom_mesh_transform(original_vertices, reconstructed_matrix) - + try: + transformed_vertices = custom_mesh_transform(original_vertices, reconstructed_matrix) + + # 验证转换后的顶点是否有效 + if np.any(np.isnan(transformed_vertices)) or np.any(np.isinf(transformed_vertices)): + invalid_count = np.sum(np.isnan(transformed_vertices)) + np.sum(np.isinf(transformed_vertices)) + error_msg = f"错误: 转换后的顶点包含无效值 (NaN/Inf): {invalid_count} 个无效元素, obj_name={obj_name}" + print(error_msg) + print(f"变换矩阵:\n{reconstructed_matrix}") + raise ValueError(error_msg) + + print(f"转换成功: {len(transformed_vertices)} 个顶点") + print(f"顶点坐标范围: X[{transformed_vertices[:, 0].min():.2f}, {transformed_vertices[:, 0].max():.2f}], " + f"Y[{transformed_vertices[:, 1].min():.2f}, {transformed_vertices[:, 1].max():.2f}], " + f"Z[{transformed_vertices[:, 2].min():.2f}, {transformed_vertices[:, 2].max():.2f}]") + + except Exception as e: + error_msg = f"转换顶点时发生错误, obj_name={obj_name}, error={str(e)}" + print(error_msg) + print(f"变换矩阵:\n{reconstructed_matrix}") + raise + offset = np.array([-380, -345, 0]) transformed_vertices += offset print(f"已对模型 {obj_name} 应用偏移: {offset}") @@ -123,5 +189,5 @@ if __name__ == "__main__": except json.JSONDecodeError as e: print(f"错误: 无法解析 trans 参数为 JSON: {e}") sys.exit(1) - + print("进入转换方法") transform_save(args.objPathName, homo_matrix) \ No newline at end of file