# history

source:
  import os, sys, subprocess, pathlib

  REGISTRY_ROOT = pathlib.Path(os.environ['FN_REGISTRY_ROOT'])
  SOURCES_DIR   = REGISTRY_ROOT / 'sources' / 'TripoSR'
  VAULT_DIR     = pathlib.Path.home() / 'vaults' / 'imagegen_models' / 'image_to_3d' / 'triposr'
  VAULT_DIR.mkdir(parents=True, exist_ok=True)

  if not SOURCES_DIR.exists():
      SOURCES_DIR.parent.mkdir(parents=True, exist_ok=True)
      subprocess.run(['git', 'clone', '--depth=1',
                      'https://github.com/VAST-AI-Research/TripoSR.git',
                      str(SOURCES_DIR)], check=True)

  # Anadir al sys.path para importar el paquete tsr/
  if str(SOURCES_DIR) not in sys.path:
      sys.path.insert(0, str(SOURCES_DIR))

  print('SOURCES_DIR:', SOURCES_DIR)
  print('VAULT_DIR:  ', VAULT_DIR)

source_raw:
  import os, sys, subprocess, pathlib

  REGISTRY_ROOT = pathlib.Path(os.environ['FN_REGISTRY_ROOT'])
  SOURCES_DIR   = REGISTRY_ROOT / 'sources' / 'TripoSR'
  VAULT_DIR     = pathlib.Path.home() / 'vaults' / 'imagegen_models' / 'image_to_3d' / 'triposr'
  VAULT_DIR.mkdir(parents=True, exist_ok=True)

  if not SOURCES_DIR.exists():
      SOURCES_DIR.parent.mkdir(parents=True, exist_ok=True)
      subprocess.run(['git', 'clone', '--depth=1',
                      'https://github.com/VAST-AI-Research/TripoSR.git',
                      str(SOURCES_DIR)], check=True)

  # Anadir al sys.path para importar el paquete tsr/
  if str(SOURCES_DIR) not in sys.path:
      sys.path.insert(0, str(SOURCES_DIR))

  print('SOURCES_DIR:', SOURCES_DIR)
  print('VAULT_DIR:  ', VAULT_DIR)


source:
  # Deps ya instaladas en sesion previa (omegaconf, einops, rembg[cpu], xatlas, onnxruntime).
  # Saltar uv add (rembg[gpu] requiere nvcc — usamos onnxruntime CPU para rembg).
  print('deps OK (instaladas fuera del notebook)')

source_raw:
  # Deps ya instaladas en sesion previa (omegaconf, einops, rembg[cpu], xatlas, onnxruntime).
  # Saltar uv add (rembg[gpu] requiere nvcc — usamos onnxruntime CPU para rembg).
  print('deps OK (instaladas fuera del notebook)')


source:
  from PIL import Image
  sample_path = SOURCES_DIR / 'examples' / 'chair.png'
  assert sample_path.exists(), f'sample faltante: {sample_path}'
  img = Image.open(sample_path).convert('RGB')
  print('imagen:', img.size, img.mode)
  img.thumbnail((256, 256))
  img

source_raw:
  from PIL import Image
  sample_path = SOURCES_DIR / 'examples' / 'chair.png'
  assert sample_path.exists(), f'sample faltante: {sample_path}'
  img = Image.open(sample_path).convert('RGB')
  print('imagen:', img.size, img.mode)
  img.thumbnail((256, 256))
  img


source:
  import os, sys, subprocess, pathlib

  REGISTRY_ROOT = pathlib.Path(os.environ['FN_REGISTRY_ROOT'])
  SOURCES_DIR   = REGISTRY_ROOT / 'sources' / 'TripoSR'
  VAULT_DIR     = pathlib.Path.home() / 'vaults' / 'imagegen_models' / 'image_to_3d' / 'triposr'
  VAULT_DIR.mkdir(parents=True, exist_ok=True)

  if not SOURCES_DIR.exists():
      SOURCES_DIR.parent.mkdir(parents=True, exist_ok=True)
      subprocess.run(['git', 'clone', '--depth=1',
                      'https://github.com/VAST-AI-Research/TripoSR.git',
                      str(SOURCES_DIR)], check=True)

  if str(SOURCES_DIR) not in sys.path:
      sys.path.insert(0, str(SOURCES_DIR))

  print('SOURCES_DIR:', SOURCES_DIR)
  print('VAULT_DIR:  ', VAULT_DIR)

source_raw:
  import os, sys, subprocess, pathlib

  REGISTRY_ROOT = pathlib.Path(os.environ['FN_REGISTRY_ROOT'])
  SOURCES_DIR   = REGISTRY_ROOT / 'sources' / 'TripoSR'
  VAULT_DIR     = pathlib.Path.home() / 'vaults' / 'imagegen_models' / 'image_to_3d' / 'triposr'
  VAULT_DIR.mkdir(parents=True, exist_ok=True)

  if not SOURCES_DIR.exists():
      SOURCES_DIR.parent.mkdir(parents=True, exist_ok=True)
      subprocess.run(['git', 'clone', '--depth=1',
                      'https://github.com/VAST-AI-Research/TripoSR.git',
                      str(SOURCES_DIR)], check=True)

  if str(SOURCES_DIR) not in sys.path:
      sys.path.insert(0, str(SOURCES_DIR))

  print('SOURCES_DIR:', SOURCES_DIR)
  print('VAULT_DIR:  ', VAULT_DIR)


source:
  import time, torch
  from tsr.system import TSR

  DEVICE = 'cuda' if torch.cuda.is_available() else 'cpu'
  print('device:', DEVICE)

  t0 = time.perf_counter()
  model = TSR.from_pretrained('stabilityai/TripoSR', config_name='config.yaml', weight_name='model.ckpt')
  model.renderer.set_chunk_size(8192)
  model.to(DEVICE)
  print(f'load: {time.perf_counter() - t0:.2f}s')

source_raw:
  import time, torch
  from tsr.system import TSR

  DEVICE = 'cuda' if torch.cuda.is_available() else 'cpu'
  print('device:', DEVICE)

  t0 = time.perf_counter()
  model = TSR.from_pretrained('stabilityai/TripoSR', config_name='config.yaml', weight_name='model.ckpt')
  model.renderer.set_chunk_size(8192)
  model.to(DEVICE)
  print(f'load: {time.perf_counter() - t0:.2f}s')


source:
  from tsr.utils import remove_background, resize_foreground
  from rembg import new_session

  rembg_session = new_session()
  raw = Image.open(sample_path)
  fg  = remove_background(raw, rembg_session)
  fg  = resize_foreground(fg, 0.85)
  fg.thumbnail((384, 384))
  fg

source_raw:
  from tsr.utils import remove_background, resize_foreground
  from rembg import new_session

  rembg_session = new_session()
  raw = Image.open(sample_path)
  fg  = remove_background(raw, rembg_session)
  fg  = resize_foreground(fg, 0.85)
  fg.thumbnail((384, 384))
  fg


source:
  torch.cuda.reset_peak_memory_stats()
  _ = model([fg], device=DEVICE)
  torch.cuda.synchronize()

  runs = []
  for i in range(3):
      torch.cuda.reset_peak_memory_stats()
      t0 = time.perf_counter()
      scene_codes = model([fg], device=DEVICE)
      torch.cuda.synchronize()
      dt = time.perf_counter() - t0
      peak = torch.cuda.max_memory_allocated() / 1e9
      runs.append({'idx': i, 'inference_s': round(dt, 3), 'vram_peak_gb': round(peak, 2)})

  import pandas as pd
  pd.DataFrame(runs)

source_raw:
  torch.cuda.reset_peak_memory_stats()
  _ = model([fg], device=DEVICE)
  torch.cuda.synchronize()

  runs = []
  for i in range(3):
      torch.cuda.reset_peak_memory_stats()
      t0 = time.perf_counter()
      scene_codes = model([fg], device=DEVICE)
      torch.cuda.synchronize()
      dt = time.perf_counter() - t0
      peak = torch.cuda.max_memory_allocated() / 1e9
      runs.append({'idx': i, 'inference_s': round(dt, 3), 'vram_peak_gb': round(peak, 2)})

  import pandas as pd
  pd.DataFrame(runs)


source:
  t0 = time.perf_counter()
  meshes = model.extract_mesh(scene_codes, has_vertex_color=False, resolution=192)
  dt_mesh = time.perf_counter() - t0
  mesh = meshes[0]
  print(f'extract_mesh: {dt_mesh:.2f}s')
  print(f'vertices: {len(mesh.vertices):,}')
  print(f'faces:    {len(mesh.faces):,}')

source_raw:
  t0 = time.perf_counter()
  meshes = model.extract_mesh(scene_codes, has_vertex_color=False, resolution=192)
  dt_mesh = time.perf_counter() - t0
  mesh = meshes[0]
  print(f'extract_mesh: {dt_mesh:.2f}s')
  print(f'vertices: {len(mesh.vertices):,}')
  print(f'faces:    {len(mesh.faces):,}')


source:
  import trimesh, numpy as np
  tm = trimesh.Trimesh(vertices=np.asarray(mesh.vertices), faces=np.asarray(mesh.faces), process=True)
  stats = {
      'n_vertices': len(tm.vertices),
      'n_faces':    len(tm.faces),
      'watertight': bool(tm.is_watertight),
      'area':       float(tm.area),
      'bounds':     tm.bounds.tolist(),
      'euler':      int(tm.euler_number),
  }
  stats

source_raw:
  import trimesh, numpy as np
  tm = trimesh.Trimesh(vertices=np.asarray(mesh.vertices), faces=np.asarray(mesh.faces), process=True)
  stats = {
      'n_vertices': len(tm.vertices),
      'n_faces':    len(tm.faces),
      'watertight': bool(tm.is_watertight),
      'area':       float(tm.area),
      'bounds':     tm.bounds.tolist(),
      'euler':      int(tm.euler_number),
  }
  stats


source:
  from datetime import datetime
  out_path = VAULT_DIR / f'smoke_{datetime.now():%Y%m%d_%H%M%S}.glb'
  tm.export(out_path)
  size_kb = out_path.stat().st_size / 1024
  print(f'saved: {out_path}  ({size_kb:.1f} KB)')

  roundtrip = trimesh.load(out_path, force='mesh')
  print(f'roundtrip: {len(roundtrip.vertices):,} verts / {len(roundtrip.faces):,} faces')

source_raw:
  from datetime import datetime
  out_path = VAULT_DIR / f'smoke_{datetime.now():%Y%m%d_%H%M%S}.glb'
  tm.export(out_path)
  size_kb = out_path.stat().st_size / 1024
  print(f'saved: {out_path}  ({size_kb:.1f} KB)')

  roundtrip = trimesh.load(out_path, force='mesh')
  print(f'roundtrip: {len(roundtrip.vertices):,} verts / {len(roundtrip.faces):,} faces')


source:
  from tsr.utils import remove_background, resize_foreground
  from rembg import new_session
  import numpy as np

  rembg_session = new_session()
  raw = Image.open(sample_path)
  fg  = remove_background(raw, rembg_session)
  fg  = resize_foreground(fg, 0.85)

  # Composite RGBA -> RGB sobre gris 0.5 (preprocesado canonico TripoSR run.py).
  # Sin esto el tokenizer DINO recibe 4 canales y peta (expected 3).
  arr = np.array(fg).astype(np.float32) / 255.0
  arr = arr[:, :, :3] * arr[:, :, 3:4] + (1 - arr[:, :, 3:4]) * 0.5
  fg  = Image.fromarray((arr * 255.0).astype(np.uint8))

  fg_disp = fg.copy(); fg_disp.thumbnail((384, 384))
  fg_disp

source_raw:
  from tsr.utils import remove_background, resize_foreground
  from rembg import new_session
  import numpy as np

  rembg_session = new_session()
  raw = Image.open(sample_path)
  fg  = remove_background(raw, rembg_session)
  fg  = resize_foreground(fg, 0.85)

  # Composite RGBA -> RGB sobre gris 0.5 (preprocesado canonico TripoSR run.py).
  # Sin esto el tokenizer DINO recibe 4 canales y peta (expected 3).
  arr = np.array(fg).astype(np.float32) / 255.0
  arr = arr[:, :, :3] * arr[:, :, 3:4] + (1 - arr[:, :, 3:4]) * 0.5
  fg  = Image.fromarray((arr * 255.0).astype(np.uint8))

  fg_disp = fg.copy(); fg_disp.thumbnail((384, 384))
  fg_disp


source:
  print('scene_codes' in dir(), [k for k in dir() if k in ('scene_codes','runs','fg','model','meshes')])

source_raw:
  print('scene_codes' in dir(), [k for k in dir() if k in ('scene_codes','runs','fg','model','meshes')])


