File size: 3,085 Bytes
6f62f26
 
 
 
 
 
fc41a87
6f62f26
 
 
 
fc41a87
6f62f26
 
 
 
 
 
fc41a87
6f62f26
 
 
 
 
 
 
 
 
 
9b2ee46
6f62f26
 
fc41a87
 
bf70016
516de62
bf70016
9b2ee46
fc41a87
f72b58c
bf70016
6f62f26
fc41a87
 
 
 
f72b58c
 
6f62f26
fc41a87
f72b58c
fc41a87
6f62f26
9b2ee46
6f62f26
 
 
 
 
 
 
 
 
 
 
2d1ede7
fc41a87
6f62f26
2d1ede7
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
import gradio as gr
import trimesh
import numpy as np
from PIL import Image
import tempfile

def apply_masked_texture(section):
    # Load the original mesh
    mesh = trimesh.load('train.glb', force='mesh')
    im = Image.open('rust_steel.png').convert('RGB')

    # Calculate the bounding box coordinates
    bounds = mesh.bounds
    min_bounds, max_bounds = bounds[0], bounds[1]
    mid_x = (max_bounds[0] + min_bounds[0]) / 2
    mid_y = (max_bounds[1] + min_bounds[1]) / 2
    mid_z = (max_bounds[2] + min_bounds[2]) / 2

    # Define sections with relevant indices
    sections = {
        'upper': np.where(mesh.vertices[:, 2] > mid_z)[0],
        'lower': np.where(mesh.vertices[:, 2] <= mid_z)[0],
        'middle': np.where((mesh.vertices[:, 0] >= min_bounds[0]) & (mesh.vertices[:, 0] <= max_bounds[0]) &
                           (mesh.vertices[:, 1] >= min_bounds[1]) & (mesh.vertices[:, 1] <= max_bounds[1]) &
                           (mesh.vertices[:, 2] >= min_bounds[2]) & (mesh.vertices[:, 2] <= max_bounds[2]))[0],
        'top': np.where(mesh.vertices[:, 1] > mid_y)[0],
        'right': np.where(mesh.vertices[:, 0] > mid_x)[0]
    }

    # Select the indices for the specified section
    selected_indices = sections[section]

    # Initialize UV mapping and retain original visuals for unselected vertices
    if mesh.visual.kind == 'texture' and mesh.visual.uv is not None:
        original_uv = mesh.visual.uv
    else:
        original_uv = np.random.rand(len(mesh.vertices), 2)

    # Create new UV coordinates only for the selected region
    new_uv = np.copy(original_uv)
    new_uv[selected_indices, :] = np.random.rand(len(selected_indices), 2)

    # Preserve the original colors and visuals for non-selected sections
    original_colors = mesh.visual.vertex_colors if mesh.visual.vertex_colors is not None else np.ones((len(mesh.vertices), 4)) * 255

    # Create a new material with the texture image
    material = trimesh.visual.texture.SimpleMaterial(image=im)
    new_visuals = trimesh.visual.TextureVisuals(uv=new_uv, material=material)

    # Create a new mesh with both original and updated visuals
    textured_mesh = trimesh.Trimesh(vertices=mesh.vertices, faces=mesh.faces, visual=new_visuals, validate=True, process=False)
    textured_mesh.visual.vertex_colors = original_colors  # Retain original vertex colors

    # Save the modified mesh to a temporary file for Gradio visualization
    temp_file = tempfile.NamedTemporaryFile(delete=False, suffix='.glb')
    textured_mesh.export(temp_file.name, file_type='glb')
    temp_file.close()
    return temp_file.name

with gr.Blocks() as app:
    gr.Markdown("### 3D Model Texture Application")
    original_model = gr.Model3D('train.glb', label="Original Model")
    modified_model = gr.Model3D(label="Textured Model")

    section_dropdown = gr.Dropdown(choices=['upper', 'lower', 'middle', 'top', 'right'], label="Select Section")
    button = gr.Button("Apply Texture to Section")
    button.click(apply_masked_texture, inputs=section_dropdown, outputs=modified_model)

app.launch()