evoneural/evoneuralIn3D-app
0
1"""23D mesh viewer for GLB/glTF. Returns HTML for use with st.components.v1.html().3Uses Google's <model-viewer> web component with base64-embedded GLB.4"""5 6import base647from pathlib import Path8 9# Embedding very large GLBs can make the page slow; warn above this size (bytes)10MAX_EMBED_BYTES = 15 * 1024 * 1024 # 15 MB11 12 13def mesh_viewer_html(glb_path: str | Path | None = None, glb_bytes: bytes | None = None, height_px: int = 480) -> str:14 """15 Build HTML for an interactive 3D mesh viewer (model-viewer).16 Provide either glb_path (file path) or glb_bytes (raw GLB). Prefers path if both given.17 Returns HTML string. If no valid input or file too large, returns a short error HTML.18 """19 data_uri: str | None = None20 if glb_path:21 p = Path(glb_path)22 if p.is_file() and p.suffix.lower() in (".glb", ".gltf"):23 try:24 raw = p.read_bytes()25 except Exception:26 raw = b""27 else:28 raw = b""29 elif glb_bytes:30 raw = glb_bytes31 else:32 raw = b""33 34 if not raw or len(raw) < 4:35 return (36 "<p style='padding:1em;color:#888;'>No GLB loaded. Upload a .glb file or choose one from outputs.</p>"37 )38 39 if len(raw) > MAX_EMBED_BYTES:40 return (41 f"<p style='padding:1em;color:#c66;'>Mesh is too large to embed in viewer ({len(raw) / 1024 / 1024:.1f} MB). "42 "Use a local viewer or a smaller mesh.</p>"43 )44 45 b64 = base64.b64encode(raw).decode("utf-8")46 data_uri = f"data:model/gltf-binary;base64,{b64}"47 48 # model-viewer from unpkg; use module script49 return f"""<!DOCTYPE html>50<html>51<head>52 <meta charset="utf-8">53 <script type="module" src="https://unpkg.com/@google/model-viewer@3.4.0/dist/model-viewer.min.js"></script>54 <style>55 model-viewer {{ width: 100%; height: {height_px}px; background: #1a1a1a; }}56 </style>57</head>58<body>59 <model-viewer60 src="{data_uri}"61 alt="3D mesh"62 camera-controls63 auto-rotate64 shadow-intensity="0.6"65 exposure="0.8"66 style="width:100%; height:{height_px}px;"67 ></model-viewer>68</body>69</html>"""70 