Miguelpef commited on
Commit
7ce9c01
·
verified ·
1 Parent(s): a633317

Upload app, readme, requirements and example model

Browse files
Files changed (4) hide show
  1. README.md +28 -14
  2. modelo_optimizado.vox +0 -0
  3. requirements.txt +4 -0
  4. viewer.py +128 -0
README.md CHANGED
@@ -1,14 +1,28 @@
1
- ---
2
- title: Voxel Viewer
3
- emoji: 🌖
4
- colorFrom: red
5
- colorTo: yellow
6
- sdk: gradio
7
- sdk_version: 5.13.1
8
- app_file: app.py
9
- pinned: false
10
- license: mit
11
- short_description: Allows users to view and interact with 3D voxel models in .v
12
- ---
13
-
14
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Voxel Model Viewer
2
+
3
+ A web application built with Gradio that allows users to view and interact with 3D voxel models in .vox format.
4
+
5
+ ## Features
6
+
7
+ - Upload and view .vox files in 3D
8
+ - Interactive 3D visualization with rotation and zoom
9
+ - Dark theme interface for better contrast
10
+ - Support for colored voxels using the model's palette
11
+
12
+ ## Usage
13
+
14
+ 1. Upload a .vox file using the file upload interface
15
+ 2. The model will be displayed in an interactive 3D viewer
16
+ 3. Use mouse controls to rotate and zoom the model
17
+
18
+ ## Technical Details
19
+
20
+ This application uses:
21
+ - Gradio for the web interface
22
+ - PyVox for parsing .vox files
23
+ - Plotly for 3D visualization
24
+ - NumPy for array operations
25
+
26
+ ## Example
27
+
28
+ An example .vox file (modelo_optimizado.vox) is included in the repository for testing purposes.
modelo_optimizado.vox ADDED
Binary file (51.5 kB). View file
 
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ gradio>=4.0.0
2
+ numpy>=1.24.0
3
+ plotly>=5.18.0
4
+ pyvox>=1.0.0
viewer.py ADDED
@@ -0,0 +1,128 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import numpy as np
3
+ import plotly.graph_objects as go
4
+ from pyvox.models import Vox
5
+ from pyvox.writer import VoxWriter
6
+ from pyvox.parser import VoxParser
7
+
8
+ def load_vox_model(file_path):
9
+ """Load and parse a .vox file"""
10
+ try:
11
+ print(f"Attempting to parse vox file: {file_path}")
12
+ model = VoxParser(file_path).parse()
13
+ print(f"Model parsed successfully")
14
+
15
+ voxels = model.to_dense()
16
+ print(f"Voxel array shape: {voxels.shape}")
17
+ print(f"Number of non-zero voxels: {np.count_nonzero(voxels)}")
18
+ print(f"Palette size: {len(model.palette)}")
19
+
20
+ if np.count_nonzero(voxels) == 0:
21
+ print("Warning: No voxels found in the model")
22
+ return None, None
23
+
24
+ return voxels, model.palette
25
+ except Exception as e:
26
+ print(f"Error in load_vox_model: {str(e)}")
27
+ return None, None
28
+
29
+ def create_3d_scatter(voxels, palette):
30
+ """Create a 3D scatter plot from voxel data"""
31
+ # Get coordinates and color indices of non-zero voxels
32
+ x, y, z = np.nonzero(voxels)
33
+ color_indices = voxels[x, y, z] - 1 # Subtract 1 since palette indices in .vox start at 1
34
+
35
+ # Apply rotation to orient the model correctly
36
+ # Negate y coordinate to flip the model upright and rotate z to face forward
37
+ y = -y
38
+ temp_z = z.copy()
39
+ z = -temp_z # Negate z to make the model face forward
40
+
41
+ # Convert palette indices to RGB colors using direct palette indexing
42
+ rgb_colors = [f'rgb({int(palette[c][0])}, {int(palette[c][1])}, {int(palette[c][2])})'
43
+ if c < len(palette) else 'rgb(255, 255, 255)' for c in color_indices]
44
+
45
+ # Create 3D scatter plot with improved voxel representation
46
+ fig = go.Figure(data=[go.Scatter3d(
47
+ x=x, y=y, z=z,
48
+ mode='markers',
49
+ marker=dict(
50
+ size=6, # Reduced size for better visualization
51
+ color=rgb_colors,
52
+ opacity=1.0,
53
+ symbol='square', # Using square symbol (supported by Plotly)
54
+ line=dict(width=0), # Remove border lines completely
55
+ sizemode='diameter', # Fixed size regardless of zoom
56
+ sizeref=1.0 # Reference scale for consistent size
57
+ )
58
+ )])
59
+
60
+ # Calculate center and range for better camera positioning
61
+ center_x = (x.max() + x.min()) / 2
62
+ center_y = (y.max() + y.min()) / 2
63
+ center_z = (z.max() + z.min()) / 2
64
+ max_range = max(x.max() - x.min(), y.max() - y.min(), z.max() - z.min())
65
+
66
+ # Update layout for better visualization
67
+ fig.update_layout(
68
+ scene=dict(
69
+ aspectmode='cube', # Force cubic aspect ratio
70
+ camera=dict(
71
+ up=dict(x=0, y=1, z=0),
72
+ center=dict(x=0, y=0, z=0),
73
+ eye=dict(x=1.5, y=0.9, z=0.9) # Adjusted camera position for a closer view while maintaining angle
74
+ ),
75
+ xaxis=dict(range=[center_x - max_range/1.5, center_x + max_range/1.5], showgrid=True, gridwidth=1, gridcolor='rgba(128, 128, 128, 0.2)'),
76
+ yaxis=dict(range=[center_y - max_range/1.5, center_y + max_range/1.5], showgrid=True, gridwidth=1, gridcolor='rgba(128, 128, 128, 0.2)'),
77
+ zaxis=dict(range=[center_z - max_range/1.5, center_z + max_range/1.5], showgrid=True, gridwidth=1, gridcolor='rgba(128, 128, 128, 0.2)')
78
+ ),
79
+ margin=dict(l=0, r=0, t=0, b=0),
80
+ showlegend=False,
81
+ template='plotly_dark', # Dark theme for better contrast
82
+ paper_bgcolor='rgba(0,0,0,1)', # Pure black background
83
+ plot_bgcolor='rgba(0,0,0,1)'
84
+ )
85
+
86
+ return fig
87
+
88
+ def display_vox_model(vox_file):
89
+ """Main function to display the voxel model"""
90
+ try:
91
+ # Load the vox model
92
+ if not vox_file:
93
+ return "Please upload a .vox file"
94
+
95
+ if not vox_file.name.endswith('.vox'):
96
+ return "Please upload a valid .vox file"
97
+
98
+ print(f"Loading vox file: {vox_file.name}")
99
+ voxels, palette = load_vox_model(vox_file.name)
100
+
101
+ if voxels is None or palette is None:
102
+ return "Error: Could not load voxel data from file"
103
+
104
+ if voxels.size == 0:
105
+ return "Error: No voxels found in the model"
106
+
107
+ print(f"Model loaded successfully. Shape: {voxels.shape}, Palette size: {len(palette)}")
108
+
109
+ # Create the 3D visualization
110
+ fig = create_3d_scatter(voxels, palette)
111
+
112
+ return fig
113
+ except Exception as e:
114
+ print(f"Error details: {str(e)}")
115
+ return f"Error loading model: {str(e)}"
116
+
117
+ # Create Gradio interface
118
+ interface = gr.Interface(
119
+ fn=display_vox_model,
120
+ inputs=gr.File(label="Upload .vox file"),
121
+ outputs=gr.Plot(label="3D Voxel Model"),
122
+ title="Voxel Model Viewer",
123
+ description="Upload a .vox file to view the 3D voxelized model.",
124
+ examples=[["modelo_optimizado.vox"]]
125
+ )
126
+
127
+ if __name__ == "__main__":
128
+ interface.launch()