Spaces:
Sleeping
Sleeping
| import numpy as np | |
| from .palette import create_palette, PaletteMapper | |
| from .atlas import create_atlas | |
| from .mesh import apply_atlas | |
| __all__ = ["convert_meshes", "ConversionConfig", "ConversionResult"] | |
| class ConversionConfig: | |
| def __init__( | |
| self, | |
| atlas_size=16, | |
| face_sampling_ratio=0.1, | |
| simplify_details=True, | |
| detail_sensitivity=None, | |
| ): | |
| self.atlas_size = atlas_size | |
| self.face_sampling_ratio = face_sampling_ratio | |
| self.simplify_details = simplify_details | |
| self.detail_sensitivity = detail_sensitivity | |
| self.total_palette_colors = atlas_size * atlas_size | |
| class ConversionResult: | |
| def __init__(self, meshes, atlas, palette, scene_metadata=None): | |
| self.meshes = meshes | |
| self.atlas = atlas | |
| self.palette = palette | |
| self.scene_metadata = scene_metadata | |
| def convert_meshes( | |
| mesh_list, | |
| atlas_size=16, | |
| face_sampling_ratio=0.1, | |
| simplify_details=True, | |
| detail_sensitivity=None, | |
| scene_metadata=None, | |
| ): | |
| if not mesh_list: | |
| raise ValueError("No meshes provided") | |
| config = ConversionConfig( | |
| atlas_size, face_sampling_ratio, simplify_details, detail_sensitivity | |
| ) | |
| print( | |
| f"Processing {len(mesh_list)} mesh(es) with {config.total_palette_colors}-color palette" | |
| ) | |
| all_sampled_colors = [] | |
| meshes_with_valid_geometry = [] | |
| mesh_face_colors = {} | |
| for mesh_name, mesh_object in mesh_list: | |
| if mesh_object is None or len(mesh_object.faces) == 0: | |
| print(f"Skipping {mesh_name}: no valid geometry") | |
| continue | |
| print( | |
| f"Analyzing {mesh_name}: {len(mesh_object.faces)} faces, {len(mesh_object.vertices)} vertices" | |
| ) | |
| meshes_with_valid_geometry.append((mesh_name, mesh_object)) | |
| from .extraction.reader import get_face_colors | |
| face_colors = get_face_colors( | |
| mesh_object, | |
| simplify_details=config.simplify_details, | |
| detail_sensitivity=config.detail_sensitivity, | |
| ) | |
| mesh_face_colors[mesh_name] = face_colors | |
| from .extraction import sample_colors | |
| face_areas = mesh_object.area_faces if hasattr(mesh_object, "area_faces") else None | |
| sampled_colors = sample_colors(face_colors, config.face_sampling_ratio, face_areas) | |
| all_sampled_colors.extend(sampled_colors) | |
| if not meshes_with_valid_geometry: | |
| raise ValueError("No valid meshes found") | |
| combined_color_array = np.array(all_sampled_colors, dtype=np.uint8) | |
| print( | |
| f"Total sampled colors: {len(combined_color_array)} from {len(meshes_with_valid_geometry)} mesh(es)" | |
| ) | |
| quantized_palette = create_palette(combined_color_array, size=config.atlas_size) | |
| texture_atlas_image, color_to_uv_mapping = create_atlas( | |
| quantized_palette, size=config.atlas_size | |
| ) | |
| nearest_color_mapper = PaletteMapper(quantized_palette) | |
| atlas_applied_meshes = [] | |
| for mesh_name, mesh_object in meshes_with_valid_geometry: | |
| print(f"Applying atlas to {mesh_name}") | |
| mesh_with_atlas_texture = apply_atlas( | |
| mesh_object, texture_atlas_image, color_to_uv_mapping, nearest_color_mapper, | |
| face_colors=mesh_face_colors[mesh_name] | |
| ) | |
| atlas_applied_meshes.append((mesh_name, mesh_with_atlas_texture)) | |
| print(f"✓ Successfully processed {len(atlas_applied_meshes)} mesh(es)") | |
| return ConversionResult( | |
| atlas_applied_meshes, texture_atlas_image, quantized_palette, scene_metadata | |
| ) | |