evoneuralIn3D / scripts /mesh_generator.py
evoneuralai's picture
Upload folder using huggingface_hub
74f0b48 verified
"""
Mesh generator: image → 3D mesh via TripoSR (local).
Expects TripoSR repo cloned at project_root/TripoSR. Uses subprocess to run run.py.
For text→mesh: first generate image with text_to_image(), then call this.
"""
import os
import subprocess
import sys
import time
from pathlib import Path
def find_triposr_root(project_root: str | None = None) -> str | None:
"""Locate TripoSR repo: ./TripoSR or ../TripoSR from script dir."""
if project_root is None:
project_root = str(Path(__file__).resolve().parent.parent)
candidates = [
os.path.join(project_root, "TripoSR"),
os.path.join(project_root, "..", "TripoSR"),
]
for p in candidates:
run_py = os.path.join(p, "run.py")
if os.path.isfile(run_py):
return p
return None
def generate_mesh_from_image(
image_path: str,
output_dir: str = "outputs",
mesh_format: str = "glb",
triposr_root: str | None = None,
device: str = "cuda:0",
) -> tuple[str | None, float, str]:
"""
Run TripoSR on an image. Returns (path_to_mesh, inference_time_sec, message).
If TripoSR is not found, returns (None, 0, error_message).
"""
project_root = str(Path(__file__).resolve().parent.parent)
triposr_root = triposr_root or find_triposr_root(project_root)
if not triposr_root:
return (
None,
0.0,
"TripoSR not found. Clone it: git clone https://github.com/VAST-AI-Research/TripoSR.git",
)
Path(output_dir).mkdir(parents=True, exist_ok=True)
# TripoSR writes to output_dir/0/mesh.obj (or mesh.glb)
run_py = os.path.join(triposr_root, "run.py")
cmd = [
sys.executable,
run_py,
image_path,
"--output-dir",
output_dir,
"--model-save-format",
mesh_format,
"--device",
device,
]
t0 = time.perf_counter()
try:
result = subprocess.run(
cmd,
cwd=triposr_root,
capture_output=True,
text=True,
timeout=120,
)
t1 = time.perf_counter()
if result.returncode != 0:
return (
None,
t1 - t0,
f"TripoSR failed: {result.stderr or result.stdout or 'unknown'}",
)
# Output is output_dir/0/mesh.glb or mesh.obj
mesh_path = os.path.join(output_dir, "0", f"mesh.{mesh_format}")
if not os.path.isfile(mesh_path):
return (None, t1 - t0, f"TripoSR did not produce {mesh_path}")
return (os.path.abspath(mesh_path), t1 - t0, "OK")
except subprocess.TimeoutExpired:
t1 = time.perf_counter()
return (None, t1 - t0, "TripoSR timed out (120s)")
except Exception as e:
t1 = time.perf_counter()
return (None, t1 - t0, str(e))
def generate_mesh_from_text(
prompt: str,
output_dir: str = "outputs",
mesh_format: str = "glb",
seed: int | None = None,
) -> tuple[str | None, float, str]:
"""
Text → image (SD) → mesh (TripoSR). Returns (path_to_mesh, total_time_sec, message).
"""
# Import here so script can run from any cwd
_root = str(Path(__file__).resolve().parent.parent)
if _root not in sys.path:
sys.path.insert(0, _root)
from scripts.text_to_image import text_to_image
Path(output_dir).mkdir(parents=True, exist_ok=True)
t0 = time.perf_counter()
try:
image_path, _ = text_to_image(prompt, output_dir=output_dir, seed=seed)
except Exception as e:
return (None, 0.0, f"Text-to-image failed: {e}")
mesh_path, mesh_time, msg = generate_mesh_from_image(
image_path,
output_dir=os.path.join(output_dir, "mesh_run"),
mesh_format=mesh_format,
)
total_time = time.perf_counter() - t0
if mesh_path:
return (mesh_path, total_time, msg)
return (None, total_time, msg)