$ cat node-template.py

R

Retexture Mesh

// Re-textures an existing 3D mesh (GLB) from a reference image, producing higher-fidelity PBR textures (up to 4K). Runs the TRELLIS.2 texturing pass on the input mesh.

Process
3D
#3d#mesh#texture#retexture#pbr
template.py
1"""retexture-mesh — re-texture a Model3D from a reference image (gais-retexture).23Runs the TRELLIS.2 texturing pass on an existing GLB mesh, guided by a4reference image, producing higher-fidelity PBR textures (up to 4K). The5node only stages files and normalizes types; privileged transport lives in6the gais SDK; no os/pathlib/HTTP here (lint-blocked).7"""89from __future__ import annotations1011import json12import sys13import traceback14from typing import Any1516from gais import Gais1718INPUT_DIR = "/data/input"19OUTPUT_DIR = "/data/output"2021OUTPUT_FILENAME = "retextured_model.glb"222324def _input_file_path(inputs: dict[str, Any], key: str) -> str | None:25    """Upstream file ports deliver a bare filename under /data/input."""26    name = inputs.get(key)27    if not name or not isinstance(name, str):28        return None29    base = name.replace("\\", "/").rsplit("/", 1)[-1].strip()30    if not base or base in (".", ".."):31        return None32    return f"{INPUT_DIR}/{base}"333435def process(inputs: dict[str, Any]) -> dict[str, Any]:36    mesh_path = _input_file_path(inputs, "mesh")37    if mesh_path is None:38        raise ValueError("Required input 'mesh' not provided")3940    image_path = _input_file_path(inputs, "image")41    if image_path is None:42        raise ValueError("Required input 'image' not provided")4344    texture_size = str(inputs.get("texture_size") or "2048")45    resolution = str(inputs.get("resolution") or "1024")4647    result = Gais.model.retexture(48        mesh=mesh_path,49        image=image_path,50        texture_size=texture_size,51        resolution=resolution,52    )5354    glb_bytes = result.content55    if not glb_bytes:56        raise RuntimeError("gais-retexture returned an empty model")5758    with open(f"{OUTPUT_DIR}/{OUTPUT_FILENAME}", "wb") as fh:59        fh.write(glb_bytes)6061    inference_time = result.metadata.get("inference_time_ms")62    if inference_time:63        print(64            f"[retexture-mesh] time={inference_time}ms "65            f"texture_size={texture_size} resolution={resolution}",66            file=sys.stderr,67        )6869    return {"model": OUTPUT_FILENAME}707172def main() -> None:73    try:74        envelope = json.loads(sys.stdin.read() or "{}")75        if not isinstance(envelope, dict):76            envelope = {}77        inputs = envelope.get("inputs", {}) or {}78        json.dump(process(inputs), sys.stdout)79    except Exception as e:80        print(81            json.dumps({82                "error": str(e),83                "errorType": type(e).__name__,84                "traceback": traceback.format_exc(),85            }),86            file=sys.stderr,87        )88        sys.exit(1)899091if __name__ == "__main__":92    main()

$ git log --oneline

v1.0.1
HEAD
2026-08-18