forked from lightningpixel/modly
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathexport.py
More file actions
49 lines (38 loc) · 1.51 KB
/
Copy pathexport.py
File metadata and controls
49 lines (38 loc) · 1.51 KB
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
import io
import trimesh
from fastapi import APIRouter, HTTPException
from fastapi.responses import Response, FileResponse
from services.generator_registry import WORKSPACE_DIR
router = APIRouter(tags=["export"])
SUPPORTED = {"glb", "stl", "obj", "ply"}
@router.get("/{fmt}")
def export_mesh(fmt: str, path: str):
if fmt not in SUPPORTED:
raise HTTPException(400, f"Unsupported format: {fmt}. Supported: {', '.join(SUPPORTED)}")
full_path = (WORKSPACE_DIR / path).resolve()
if not str(full_path).startswith(str(WORKSPACE_DIR.resolve())):
raise HTTPException(400, "Invalid path")
if not full_path.exists():
raise HTTPException(404, f"File not found: {path}")
# GLB — serve directly, no conversion needed
if fmt == "glb":
return FileResponse(str(full_path), media_type="model/gltf-binary")
# Load and flatten scene to a single mesh
loaded = trimesh.load(str(full_path))
if isinstance(loaded, trimesh.Scene):
geoms = list(loaded.geometry.values())
mesh = trimesh.util.concatenate(geoms) if len(geoms) > 1 else geoms[0]
else:
mesh = loaded
buf = io.BytesIO()
if fmt == "stl":
mesh.export(buf, file_type="stl")
media_type = "model/stl"
elif fmt == "ply":
mesh.export(buf, file_type="ply")
media_type = "application/octet-stream"
else: # obj
mesh.export(buf, file_type="obj")
media_type = "text/plain"
buf.seek(0)
return Response(content=buf.read(), media_type=media_type)