102 lines
3.7 KiB
Python
102 lines
3.7 KiB
Python
import trimesh
|
|
import numpy as np
|
|
import shutil
|
|
import os
|
|
|
|
def load_obj(file_path):
|
|
"""Carrega um arquivo OBJ usando trimesh e retorna a primeira malha encontrada."""
|
|
scene = trimesh.load(file_path, file_type='obj')
|
|
if isinstance(scene, trimesh.Scene):
|
|
# Se for uma cena, extrair a primeira malha
|
|
mesh = trimesh.util.concatenate(scene.dump())
|
|
else:
|
|
mesh = scene
|
|
return mesh
|
|
|
|
def simplify_mesh(mesh, reduction_factor=0.5):
|
|
"""Reduz o número de triângulos da malha."""
|
|
target_faces = int(len(mesh.faces) * reduction_factor)
|
|
simplified_mesh = mesh.simplify_quadric_decimation(target_faces)
|
|
return simplified_mesh
|
|
|
|
def save_obj_with_materials(mesh, input_obj_path, output_obj_path):
|
|
"""Salva a malha em formato OBJ mantendo as referências aos materiais."""
|
|
# Exportar a malha simplificada para um arquivo OBJ temporário
|
|
temp_obj_path = output_obj_path + '.temp.obj'
|
|
mesh.export(temp_obj_path)
|
|
|
|
# Ler o conteúdo do arquivo OBJ original
|
|
with open(input_obj_path, 'r') as file:
|
|
original_lines = file.readlines()
|
|
|
|
# Ler o conteúdo do arquivo OBJ simplificado temporário
|
|
with open(temp_obj_path, 'r') as file:
|
|
simplified_lines = file.readlines()
|
|
|
|
# Encontrar a linha que referencia o arquivo MTL no original
|
|
mtl_line = None
|
|
for line in original_lines:
|
|
if line.startswith('mtllib'):
|
|
mtl_line = line
|
|
break
|
|
|
|
# Adicionar a linha do MTL no início do arquivo simplificado
|
|
if mtl_line:
|
|
simplified_lines.insert(0, mtl_line)
|
|
|
|
# Preservar as linhas usemtl e associar com as faces
|
|
usemtl_lines = []
|
|
for i, line in enumerate(original_lines):
|
|
if line.startswith('usemtl'):
|
|
usemtl_lines.append((i, line))
|
|
|
|
# Inserir as linhas usemtl antes das faces correspondentes
|
|
face_indices = [i for i, line in enumerate(simplified_lines) if line.startswith('f ')]
|
|
for face_index in face_indices:
|
|
for usemtl_index, usemtl_line in usemtl_lines:
|
|
if usemtl_index < face_index:
|
|
simplified_lines.insert(face_index, usemtl_line)
|
|
break
|
|
|
|
# Salvar o arquivo OBJ final com a referência ao MTL
|
|
with open(output_obj_path, 'w') as file:
|
|
file.writelines(simplified_lines)
|
|
|
|
# Remover o arquivo temporário
|
|
os.remove(temp_obj_path)
|
|
|
|
def copy_mtl_file(input_obj_path, output_obj_path):
|
|
"""Copia o arquivo MTL associado ao OBJ."""
|
|
with open(input_obj_path, 'r') as file:
|
|
lines = file.readlines()
|
|
for line in lines:
|
|
if line.startswith('mtllib'):
|
|
mtl_file = line.split()[1]
|
|
input_mtl_path = os.path.join(os.path.dirname(input_obj_path), mtl_file)
|
|
output_mtl_path = os.path.join(os.path.dirname(output_obj_path), mtl_file)
|
|
shutil.copy(input_mtl_path, output_mtl_path)
|
|
break
|
|
|
|
def simplify_obj_mesh(input_obj_path, output_obj_path, reduction_factor=0.5):
|
|
"""Simplifica a malha de um arquivo OBJ e mantém a referência ao MTL."""
|
|
# Carregar a malha do arquivo OBJ
|
|
mesh = load_obj(input_obj_path)
|
|
|
|
# Simplificar a malha
|
|
simplified_mesh = simplify_mesh(mesh, reduction_factor)
|
|
|
|
# Salvar a malha simplificada em formato OBJ mantendo as referências aos materiais
|
|
save_obj_with_materials(simplified_mesh, input_obj_path, output_obj_path)
|
|
|
|
# Copiar o arquivo MTL associado
|
|
copy_mtl_file(input_obj_path, output_obj_path)
|
|
|
|
# Caminhos dos arquivos
|
|
input_obj_file = 'Mont.obj'
|
|
output_obj_file = 'Mont_simplificado.obj'
|
|
|
|
# Fator de redução (0.5 para reduzir pela metade)
|
|
reduction_factor = 0.05
|
|
|
|
# Simplificar a malha
|
|
simplify_obj_mesh(input_obj_file, output_obj_file, reduction_factor) |