evoneuralIn3D-app / scripts /mesh_viewer.py
manav0506's picture
Sync with main evoneural: quality options, mesh viewer, GLB fix, TripoSR in Dockerfile
0de805c
Raw
History Blame Contribute Delete
2.15 kB
"""
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>"""