Spaces:
Runtime error
Runtime error
| """ | |
| 3D mesh viewer for GLB/glTF. Returns HTML for use with st.components.v1.html(). | |
| Uses Google's <model-viewer> web component with base64-embedded GLB. | |
| """ | |
| import base64 | |
| from pathlib import Path | |
| # Embedding very large GLBs can make the page slow; warn above this size (bytes) | |
| MAX_EMBED_BYTES = 15 * 1024 * 1024 # 15 MB | |
| def mesh_viewer_html(glb_path: str | Path | None = None, glb_bytes: bytes | None = None, height_px: int = 480) -> str: | |
| """ | |
| Build HTML for an interactive 3D mesh viewer (model-viewer). | |
| Provide either glb_path (file path) or glb_bytes (raw GLB). Prefers path if both given. | |
| Returns HTML string. If no valid input or file too large, returns a short error HTML. | |
| """ | |
| data_uri: str | None = None | |
| if glb_path: | |
| p = Path(glb_path) | |
| if p.is_file() and p.suffix.lower() in (".glb", ".gltf"): | |
| try: | |
| raw = p.read_bytes() | |
| except Exception: | |
| raw = b"" | |
| else: | |
| raw = b"" | |
| elif glb_bytes: | |
| raw = glb_bytes | |
| else: | |
| raw = b"" | |
| if not raw or len(raw) < 4: | |
| return ( | |
| "<p style='padding:1em;color:#888;'>No GLB loaded. Upload a .glb file or choose one from outputs.</p>" | |
| ) | |
| if len(raw) > MAX_EMBED_BYTES: | |
| return ( | |
| f"<p style='padding:1em;color:#c66;'>Mesh is too large to embed in viewer ({len(raw) / 1024 / 1024:.1f} MB). " | |
| "Use a local viewer or a smaller mesh.</p>" | |
| ) | |
| b64 = base64.b64encode(raw).decode("utf-8") | |
| data_uri = f"data:model/gltf-binary;base64,{b64}" | |
| # model-viewer from unpkg; use module script | |
| return f"""<!DOCTYPE html> | |
| <html> | |
| <head> | |
| <meta charset="utf-8"> | |
| <script type="module" src="https://unpkg.com/@google/model-viewer@3.4.0/dist/model-viewer.min.js"></script> | |
| <style> | |
| model-viewer {{ width: 100%; height: {height_px}px; background: #1a1a1a; }} | |
| </style> | |
| </head> | |
| <body> | |
| <model-viewer | |
| src="{data_uri}" | |
| alt="3D mesh" | |
| camera-controls | |
| auto-rotate | |
| shadow-intensity="0.6" | |
| exposure="0.8" | |
| style="width:100%; height:{height_px}px;" | |
| ></model-viewer> | |
| </body> | |
| </html>""" | |