-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfix_obj.py
More file actions
94 lines (78 loc) · 3.5 KB
/
Copy pathfix_obj.py
File metadata and controls
94 lines (78 loc) · 3.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
import trimesh
import numpy as np
# Load the broken mesh
mesh_path = "broken-obj/997.obj"
mesh = trimesh.load(mesh_path)
print(f"Original mesh has {len(mesh.edges_unique)} unique edges")
# More detailed boundary edge analysis
boundary_edges = np.sum(mesh.edges_unique_length == 1)
print(f"Boundary edges: {boundary_edges}")
# Try alternative methods to detect boundary edges
# Method A: Look at face connectivity directly
face_count_per_edge = np.bincount(mesh.edges_sorted.flatten(), minlength=len(mesh.vertices))
boundary_vertices = np.where(face_count_per_edge == 1)[0]
print(f"Potential boundary vertices: {len(boundary_vertices)}")
# Method B: Check for edges with only one adjacent face using edges_sorted and edges_face
if hasattr(mesh, 'edges_sorted') and hasattr(mesh, 'edges_face'):
edges_sorted = mesh.edges_sorted
edges_face = mesh.edges_face
# If edges_face is 1D, reshape it to match edges_sorted
if len(edges_face.shape) == 1 and len(edges_sorted) * 2 == len(edges_face):
edges_face = edges_face.reshape(-1, 2)
# Check for edges with -1 in edges_face (indicating no second face)
if np.any(edges_face == -1):
boundary_count = np.sum(edges_face == -1)
print(f"Found {boundary_count} potential boundaries using edges_face == -1")
# Check for topological issues
if hasattr(mesh, 'is_watertight'):
print(f"Is mesh watertight: {mesh.is_watertight}")
if hasattr(mesh, 'euler_number'):
print(f"Euler number: {mesh.euler_number}")
# Method 1: Clean up the mesh
# First make a copy
clean_mesh = mesh.copy()
# Merge duplicate vertices
clean_mesh.merge_vertices()
# Remove degenerate faces
clean_mesh.remove_degenerate_faces()
# Remove unreferenced vertices
clean_mesh.remove_unreferenced_vertices()
# Fix normals
clean_mesh.fix_normals()
# Check boundary count after clean-up
clean_boundary = np.sum(clean_mesh.edges_unique_length == 1)
print(f"After clean-up, boundary edges: {clean_boundary}")
# Method 2: Fill holes
# Already have a clean mesh to work with
# holes_filled = clean_mesh.fill_holes()
# print(f"Holes filled: {holes_filled}")
# filled_boundary = np.sum(clean_mesh.edges_unique_length == 1)
# print(f"After filling holes, boundary edges: {filled_boundary}")
# Export using different methods to see if it helps
# Method 1: Default export
clean_mesh.export("clean_997.obj", include_texture=False)
print(f"Saved clean mesh to clean_997.obj")
# Method 2: Export with different options
try:
# Try different export parameters
watertight_mesh = clean_mesh.copy()
# Make the mesh watertight if possible
if not watertight_mesh.is_watertight:
print("Attempting to make mesh watertight...")
# More aggressive merging
watertight_mesh.merge_vertices()
# Fill any remaining holes
watertight_mesh.fill_holes()
watertight_mesh.fix_normals()
# Check if watertight mesh has boundary edges
watertight_boundary = np.sum(watertight_mesh.edges_unique_length == 1)
print(f"Final mesh boundary edges: {watertight_boundary}")
print(f"Is watertight: {watertight_mesh.is_watertight}")
# Save the repaired mesh
watertight_mesh.export("fixed_997_ascii.obj", include_texture=False, ascii=True,
include_normals=True, include_color=False)
print(f"Saved ASCII version to fixed_997_ascii.obj")
except TypeError:
# If the parameters aren't supported in this trimesh version
watertight_mesh.export("fixed_997_ascii.obj")
print(f"Saved alternate mesh format to fixed_997_ascii.obj")