evoneural/evoneuralIn3D-app
0
1"""2Hunyuan3D-2 full text-to-3D pipeline integration.3Finds the Hunyuan3D-2 repo (env HUNYUAN3D2_ROOT or ./Hunyuan3D-2) and invokes the runner4with PYTHONPATH and cwd set so hy3dgen is importable. Returns (mesh_path, elapsed_sec, message).5"""6 7import os8import subprocess9import sys10import time11from pathlib import Path12 13 14def find_hunyuan3d2_root(project_root: str | None = None) -> str | None:15 """Locate Hunyuan3D-2 repo: HUNYUAN3D2_ROOT env, or ./Hunyuan3D-2, or ../Hunyuan3D-2."""16 root_env = os.environ.get("HUNYUAN3D2_ROOT", "").strip()17 if root_env and os.path.isdir(root_env) and os.path.isdir(os.path.join(root_env, "hy3dgen")):18 return os.path.abspath(root_env)19 20 if project_root is None:21 project_root = str(Path(__file__).resolve().parent.parent)22 for p in [23 os.path.join(project_root, "Hunyuan3D-2"),24 os.path.join(project_root, "..", "Hunyuan3D-2"),25 ]:26 if os.path.isdir(p) and os.path.isdir(os.path.join(p, "hy3dgen")):27 return os.path.abspath(p)28 return None29 30 31def _runner_script_path() -> Path:32 """Path to run_text_to_mesh.py (must be run with cwd=Hunyuan3D-2 so hy3dgen is found)."""33 return Path(__file__).resolve().parent / "hunyuan3d_runner" / "run_text_to_mesh.py"34 35 36def generate_mesh_from_text_hunyuan3d2(37 prompt: str,38 output_dir: str = "outputs",39 mesh_format: str = "glb",40 seed: int = 42,41 with_texture: bool = True,42 hunyuan_root: str | None = None,43 device: str = "cuda",44 timeout: int = 600,45) -> tuple[str | None, float, str]:46 """47 Full text-to-3D via Hunyuan3D-2: text → HunyuanDiT (image) → shape → texture → mesh.48 Returns (path_to_mesh, elapsed_sec, message). On failure returns (None, elapsed, error_message).49 """50 root = hunyuan_root or find_hunyuan3d2_root()51 if not root:52 return (53 None,54 0.0,55 "Hunyuan3D-2 repo not found. Set HUNYUAN3D2_ROOT or clone into ./Hunyuan3D-2 (see README).",56 )57 58 script = _runner_script_path()59 if not script.is_file():60 return (None, 0.0, f"Runner script not found: {script}")61 62 Path(output_dir).mkdir(parents=True, exist_ok=True)63 cmd = [64 sys.executable,65 str(script),66 "--prompt",67 prompt,68 "--output_dir",69 output_dir,70 "--format",71 mesh_format,72 "--seed",73 str(seed),74 "--device",75 device,76 ]77 if not with_texture:78 cmd.append("--no-texture")79 env = {**os.environ, "PYTHONPATH": root}80 81 t0 = time.perf_counter()82 try:83 result = subprocess.run(84 cmd,85 cwd=root,86 env=env,87 capture_output=True,88 text=True,89 timeout=timeout,90 )91 elapsed = time.perf_counter() - t092 if result.returncode != 0:93 err = (result.stderr or result.stdout or "unknown").strip()94 return (None, elapsed, f"Hunyuan3D-2 failed: {err[:500]}")95 # Runner prints the absolute output path on success96 out_line = (result.stdout or "").strip().splitlines()[-1] if result.stdout else ""97 if out_line and os.path.isfile(out_line):98 return (os.path.abspath(out_line), elapsed, "OK")99 # Fallback: standard output path100 out_path = Path(output_dir) / f"mesh.{mesh_format}"101 if out_path.is_file():102 return (str(out_path.resolve()), elapsed, "OK")103 return (None, elapsed, "Runner did not produce mesh file.")104 except subprocess.TimeoutExpired:105 elapsed = time.perf_counter() - t0106 return (None, elapsed, f"Hunyuan3D-2 timed out ({timeout}s)")107 except Exception as e:108 elapsed = time.perf_counter() - t0109 return (None, elapsed, str(e))110 111 112def generate_mesh_from_image_hunyuan3d2(113 image_path: str,114 output_dir: str = "outputs",115 mesh_format: str = "glb",116 seed: int = 42,117 with_texture: bool = True,118 hunyuan_root: str | None = None,119 device: str = "cuda",120 timeout: int = 600,121) -> tuple[str | None, float, str]:122 """123 Image-to-3D via Hunyuan3D-2: image → shape → texture → mesh.124 Returns (path_to_mesh, elapsed_sec, message).125 """126 root = hunyuan_root or find_hunyuan3d2_root()127 if not root:128 return (129 None,130 0.0,131 "Hunyuan3D-2 repo not found. Set HUNYUAN3D2_ROOT or clone into ./Hunyuan3D-2 (see README).",132 )133 134 script = _runner_script_path()135 if not script.is_file():136 return (None, 0.0, f"Runner script not found: {script}")137 138 if not os.path.isfile(image_path):139 return (None, 0.0, f"Image not found: {image_path}")140 141 Path(output_dir).mkdir(parents=True, exist_ok=True)142 cmd = [143 sys.executable,144 str(script),145 "--image",146 os.path.abspath(image_path),147 "--output_dir",148 output_dir,149 "--format",150 mesh_format,151 "--seed",152 str(seed),153 "--device",154 device,155 ]156 if not with_texture:157 cmd.append("--no-texture")158 env = {**os.environ, "PYTHONPATH": root}159 160 t0 = time.perf_counter()161 try:162 result = subprocess.run(163 cmd,164 cwd=root,165 env=env,166 capture_output=True,167 text=True,168 timeout=timeout,169 )170 elapsed = time.perf_counter() - t0171 if result.returncode != 0:172 err = (result.stderr or result.stdout or "unknown").strip()173 return (None, elapsed, f"Hunyuan3D-2 failed: {err[:500]}")174 out_line = (result.stdout or "").strip().splitlines()[-1] if result.stdout else ""175 if out_line and os.path.isfile(out_line):176 return (os.path.abspath(out_line), elapsed, "OK")177 out_path = Path(output_dir) / f"mesh.{mesh_format}"178 if out_path.is_file():179 return (str(out_path.resolve()), elapsed, "OK")180 return (None, elapsed, "Runner did not produce mesh file.")181 except subprocess.TimeoutExpired:182 elapsed = time.perf_counter() - t0183 return (None, elapsed, f"Hunyuan3D-2 timed out ({timeout}s)")184 except Exception as e:185 elapsed = time.perf_counter() - t0186 return (None, elapsed, str(e))187 