目录
glb缩放
缩放并把中心点移动到原点
python
import os
import trimesh
import glob
def move_to_zero(mesh):
mesh.apply_translation(-mesh.centroid)
print(f"模型中心点: {mesh.centroid}")
def scale_to_target_mm(input_path, output_path, target_mm):
mesh = trimesh.load(input_path)
# 获取当前最大边长(米)
bounds = mesh.bounds
current_size = bounds[1] - bounds[0]
current_max_m = max(current_size)
# 目标尺寸(米)
target_m = target_mm #/ 1000
# 计算缩放因子
scale_factor = target_m / current_max_m
print(f"当前最大边长: {current_max_m:.3f} 米 ({current_max_m:.1f} mm)")
print(f"目标边长: {target_mm} mm")
print(f"缩放因子: {scale_factor}")
# 应用缩放
mesh.apply_scale(scale_factor)
move_to_zero(mesh)
mesh.export(output_path, file_type='glb')
# 验证
new_bounds = mesh.bounds
new_size = new_bounds[1] - new_bounds[0]
print(f"缩放后最大边长: {max(new_size) :.1f} mm")
return scale_factor
if __name__ == "__main__":
input_dir=r'E:\project\3d_label\three-bvh-csg-main\examples\kakou_m'
output_dir=r'E:\project\3d_label\three-bvh-csg-main\examples\kakou_s'
os.makedirs(output_dir, exist_ok=True)
glb_files = glob.glob(os.path.join(input_dir, "*.glb"))
glb_files.extend(glob.glob(os.path.join(input_dir, "*.GLB")))
print(f"找到 {len(glb_files)} 个 GLB 文件")
for i, input_path in enumerate(glb_files, 1):
filename = os.path.basename(input_path)
output_path = os.path.join(output_dir, filename)
scale_to_target_mm(input_path=input_path, output_path=output_path, target_mm=8)
trimesh转换
python
import trimesh
import numpy as np
import os
def analyze_and_convert_stl_to_glb(input_path, output_path=None, scale_factor=1.0, apply_scale=True):
if not os.path.exists(input_path):
print(f"错误:文件不存在 - {input_path}")
return None
print(f"读取 STL 文件: {os.path.basename(input_path)}")
print("=" * 60)
try:
mesh = trimesh.load_mesh(input_path, process=False) # process=False 保留原始数据
print("✓ 文件加载成功")
except Exception as e:
print(f"✗ 加载失败: {e}")
return None
# ========== 打印模型参数 ==========
print("\n【模型基本参数】")
print("-" * 40)
# 顶点和面信息
vertices_count = len(mesh.vertices)
faces_count = len(mesh.faces)
print(f"顶点数: {vertices_count:,}")
print(f"三角形面数: {faces_count:,}")
# 包围盒尺寸
bounds = mesh.bounds
min_bound = bounds[0]
max_bound = bounds[1]
size = max_bound - min_bound
print(f"\n【包围盒尺寸】")
print(f" 宽度 (X轴): {size[0]:.4f} 米 ({size[0] * 1000:.2f} mm)")
print(f" 高度 (Y轴): {size[1]:.4f} 米 ({size[1] * 1000:.2f} mm)")
print(f" 深度 (Z轴): {size[2]:.4f} 米 ({size[2] * 1000:.2f} mm)")
print(f" 最长边: {max(size):.4f} 米 ({max(size) * 1000:.2f} mm)")
# 包围盒范围
print(f"\n【包围盒范围】")
print(f" X: [{min_bound[0]:.4f}, {max_bound[0]:.4f}] 米")
print(f" Y: [{min_bound[1]:.4f}, {max_bound[1]:.4f}] 米")
print(f" Z: [{min_bound[2]:.4f}, {max_bound[2]:.4f}] 米")
# 中心点
center = mesh.centroid
print(f"\n【质心/中心点】")
print(f" ({center[0]:.4f}, {center[1]:.4f}, {center[2]:.4f}) 米")
# 体积和表面积
try:
volume = mesh.volume
area = mesh.area
print(f"\n【几何属性】")
print(f" 体积: {volume:.6f} 立方米 ({volume * 1e6:.2f} 立方厘米)")
print(f" 表面积: {area:.6f} 平方米 ({area * 1e4:.2f} 平方厘米)")
except:
print(f"\n【几何属性】")
print(f" 体积: 无法计算(网格可能不封闭)")
print(f" 表面积: 无法计算")
# 判断是否为流形
is_watertight = mesh.is_watertight
print(f"\n【网格质量】")
print(f" 是否为水密/流形: {'是 ✓' if is_watertight else '否 ✗'}")
if not is_watertight:
# 检查边界边数
try:
edges = mesh.edges_unique
boundary_edges = sum(1 for e in edges if len(mesh.edge_adjacencies[e[0], e[1]] if hasattr(mesh, 'edge_adjacencies') else 0) < 2)
print(f" 边界边数: {boundary_edges}")
except:
pass
# ========== 缩放处理 ==========
if apply_scale and scale_factor != 1.0:
print(f"\n【缩放处理】")
print(f" 缩放因子: {scale_factor}")
mesh.apply_scale(scale_factor)
# 打印缩放后的尺寸
new_bounds = mesh.bounds
new_size = new_bounds[1] - new_bounds[0]
print(f" 缩放后尺寸: {new_size[0]:.4f} × {new_size[1]:.4f} × {new_size[2]:.4f} 米")
print(f" 缩放后最大边长: {max(new_size) * 1000:.2f} mm")
# ========== 导出 GLB ==========
if output_path is None:
base_name = os.path.splitext(input_path)[0]
output_path = base_name + ".glb"
try:
mesh.export(output_path, file_type='glb')
print(f"\n【导出完成】")
print(f" 输出文件: {output_path}")
print(f" 文件大小: {os.path.getsize(output_path) / 1024:.2f} KB")
print("=" * 60)
return mesh
except Exception as e:
print(f"\n✗ 导出失败: {e}")
return None
def batch_convert_stl_to_glb(input_dir, output_dir=None, scale_factor=1.0):
import glob
# 查找所有 STL 文件
stl_files = glob.glob(os.path.join(input_dir, "*.stl"))
stl_files.extend(glob.glob(os.path.join(input_dir, "*.STL")))
if not stl_files:
print(f"错误:在目录 {input_dir} 中没有找到 STL 文件")
return
print(f"\n找到 {len(stl_files)} 个 STL 文件")
print("=" * 60)
# 创建输出目录
if output_dir and not os.path.exists(output_dir):
os.makedirs(output_dir)
success_count = 0
fail_count = 0
for i, input_file in enumerate(stl_files, 1):
print(f"\n[{i}/{len(stl_files)}] 处理: {os.path.basename(input_file)}")
if output_dir:
output_file = os.path.join(output_dir, os.path.splitext(os.path.basename(input_file))[0] + ".glb")
else:
output_file = os.path.splitext(input_file)[0] + ".glb"
try:
mesh = trimesh.load_mesh(input_file, process=False)
if scale_factor != 1.0:
mesh.apply_scale(scale_factor)
mesh.export(output_file, file_type='glb')
# 打印尺寸
size = mesh.bounds[1] - mesh.bounds[0]
print(f" ✓ 成功 | 尺寸: {max(size) * 1000:.1f}mm | 输出: {os.path.basename(output_file)}")
success_count += 1
except Exception as e:
print(f" ✗ 失败: {e}")
fail_count += 1
print("\n" + "=" * 60)
print(f"批量转换完成!")
print(f"成功: {success_count} 个")
print(f"失败: {fail_count} 个")
print("=" * 60)
# ========== 使用示例 ==========
if __name__ == "__main__":
# 单个文件转换
INPUT_STL = r"E:\soft\qiuxing2.stl" # 修改为你的 STL 文件路径
# 方式2:缩放后转换(例如:米转毫米,缩放 0.001)
analyze_and_convert_stl_to_glb(INPUT_STL, scale_factor=0.001)
# 方式3:指定输出路径并缩放
# OUTPUT_GLB = r"C:\path\to\output\model.glb"
# analyze_and_convert_stl_to_glb(INPUT_STL, OUTPUT_GLB, scale_factor=0.001)
# 批量转换目录中的所有 STL
# batch_convert_stl_to_glb(
# input_dir=r"C:\path\to\stl_files",
# output_dir=r"C:\path\to\glb_output",
# scale_factor=0.001 # 米转毫米
# )
# 如果只是查看模型参数不导出
if os.path.exists(INPUT_STL):
analyze_and_convert_stl_to_glb(INPUT_STL, scale_factor=1.0)
else:
print(f"请修改 INPUT_STL 变量为你的 STL 文件路径")
print("\n使用方法:")
print(" 1. 修改 INPUT_STL = '你的模型.stl'")
print(" 2. 运行脚本")
print("\n可选参数:")
print(" - scale_factor=0.001 : 米转毫米")
print(" - scale_factor=25.4 : 英寸转毫米")