Replace TownSquare with HomeCamp art and land humanoid bots, LittleBear, and LmGirl review assets.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
"""LittleBear: Hunyuan high -> Studio low/UV -> bake -> UV-preserving reduction.
|
||||
|
||||
Run with the LLM3DGraphics virtualenv. Only this character's output is written.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
import json
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
STUDIO = Path(r"D:\UD\AI\XModel\LLM3DGraphics")
|
||||
BLENDER = Path(r"D:\Tools\Blender\blender-5.0.0-windows-x64\blender.exe")
|
||||
IMAGE = ROOT / "Doc/Design/Character/LittleBear/littlebear_tpose.png"
|
||||
HIGH = ROOT / "Tools/output/littlebear_3d/littlebear.glb"
|
||||
OUT = ROOT / "Tools/output/littlebear_studio"
|
||||
NAME, TARGET, SIZE = "LittleBear", 3000, 1024
|
||||
|
||||
|
||||
def update(**data):
|
||||
print(json.dumps(data, ensure_ascii=False), flush=True)
|
||||
|
||||
|
||||
def blender(script, args, logfile):
|
||||
with (OUT / logfile).open("w", encoding="utf-8") as log:
|
||||
subprocess.run([str(BLENDER), "-b", "-t", "2", "--factory-startup", "--python",
|
||||
str(ROOT / "Tools/model_tools" / script), "--", *map(str, args)],
|
||||
stdout=log, stderr=subprocess.STDOUT, check=True, timeout=1800)
|
||||
|
||||
|
||||
def main():
|
||||
sys.path.insert(0, str(ROOT / "Tools"))
|
||||
sys.path.insert(0, str(STUDIO))
|
||||
from hunyuan_3d import auth
|
||||
from hunyuan_3d.glb_check import assert_glb_textures_ok
|
||||
from backend import hunyuan_studio as studio
|
||||
from backend.retopology import _run_blender_step, compress_bake_maps, limit_studio_faces
|
||||
from model_tools.png_compress import compress_dir_pngs
|
||||
|
||||
if not HIGH.is_file():
|
||||
raise SystemExit("Generate the Hunyuan 50k high mesh first: " + str(HIGH))
|
||||
assert_glb_textures_ok(HIGH)
|
||||
OUT.mkdir(parents=True, exist_ok=True)
|
||||
shutil.copy2(HIGH, OUT / "model.glb")
|
||||
studio.is_logged_in = lambda client_id=None: auth.is_logged_in()
|
||||
studio.load_storage_state = lambda client_id=None: (
|
||||
json.loads(auth.storage_state_path().read_text(encoding="utf-8")), None)
|
||||
uv = OUT / "model_lowpoly_uv.glb"
|
||||
if uv.is_file():
|
||||
studio.validate_uv_glb(uv)
|
||||
else:
|
||||
path = OUT / "hunyuan_studio.json"
|
||||
meta = json.loads(path.read_text(encoding="utf-8")) if path.is_file() else {}
|
||||
studio.process_existing(HIGH, OUT, update, target_faces=TARGET,
|
||||
resume_low_id=meta.get("lowpoly_works_id"),
|
||||
resume_uv_id=meta.get("uv_works_id"))
|
||||
aligned = OUT / "model_lowpoly_uv_aligned.glb"
|
||||
if not aligned.is_file():
|
||||
blender("bl_align_studio_uv.py", [OUT], "alignment.log")
|
||||
baked = OUT / "model_baked.glb"
|
||||
if not baked.is_file():
|
||||
_run_blender_step(OUT, str(BLENDER), "blender_lowpoly_bake.py",
|
||||
(OUT / "model.glb", baked, 1, SIZE, aligned),
|
||||
"bake.log", marker="Lowpoly bake saved to")
|
||||
compress_bake_maps(OUT)
|
||||
shutil.copy2(baked, OUT / "model_ex.glb")
|
||||
mesh, decimation = limit_studio_faces(OUT, TARGET, str(BLENDER), update)
|
||||
blender("bl_prepare_studio_trial.py", [OUT, NAME], "static_export.log")
|
||||
blender("bl_convert.py", [OUT / "static" / (NAME + ".fbx"), OUT / "xpbr", SIZE], "xpbr.log")
|
||||
compress_dir_pngs(str(OUT / "xpbr"), suffixes=("_base.png", "_mix.png"))
|
||||
report = dict(character=NAME, image=str(IMAGE.relative_to(ROOT)),
|
||||
source=str(HIGH.relative_to(ROOT)), targetTriangles=TARGET,
|
||||
triangles=len(mesh.faces), vertices=len(mesh.vertices),
|
||||
textureSize=SIZE, decimation=decimation,
|
||||
staticFbx=str((OUT / "static" / (NAME + ".fbx")).relative_to(ROOT)),
|
||||
rig=False, skinningPolicy="fixed Mixamo skeleton + TokenRig weights only",
|
||||
fbxAxes=json.loads((OUT / "static_export.json").read_text(encoding="utf-8"))["fbxAxes"])
|
||||
(OUT / "mesh_receipt.json").write_text(json.dumps(report, ensure_ascii=False, indent=2), encoding="utf-8")
|
||||
update(**report)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user