agents/skills/text-to-3d/SKILL.md
Generate a game-ready 3D asset by running the local AI pipeline sequentially: Fooocus (SDXL text-to-image) -> Hunyuan3D-2 (image-to-textured-GLB) -> optional Blender FBX convert + Unreal import. Use when the user wants to create/generate a 3D model, mesh, or racer for the Unreal train-racer project from a text prompt or a photo. Covers launching both local Gradio services, generating, and wiring the result into Unreal.
npx skillsauth add nounder/dotfiles text-to-3dInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Two local AI services on this machine chain together to turn a text prompt or photo
into a textured 3D .glb, which then imports into the Unreal train-racer project.
Related background: hunyuan3d-deployment memory.
prompt --(Fooocus SDXL)--> image.png --(Hunyuan3D-2)--> textured.glb --(Blender)--> .fbx --(Unreal MCP)--> BP racer
[Stage 1: optional] [Stage 2: core] [Stage 3: optional, Unreal only]
If the user already has a photo, skip Stage 1 and start at Stage 2.
Validation status (2026-07-24): Full chain tested end-to-end. Stage 1 automated via Fooocus-API
(installed at C:\AI\Fooocus-API; REST text-to-image returned a clean locomotive image). Stage 2
(hunyuan_gen.py) + Stage 3 convert (glb_to_fbx.py) working (image -> textured .glb -> .fbx,
~60–130 s for the 3D step). Stage 3 Unreal import validated (Caitlin). Vanilla Fooocus is NOT drivable
via gradio_client — that's why the Fooocus-API wrapper exists.
Only one image/3D service loaded at a time. Don't just avoid concurrent generation — don't keep both servers resident. Measured 2026-07-24: running Fooocus with the Hunyuan3D server still loaded made SDXL take ~14 min (27 s/step) instead of ~1 min, because the two exhaust RAM and swap to disk. So: stop the other server before generating. Stage 1 → stop Hunyuan (8080), run Fooocus. Stage 2 → stop Fooocus-API (8888), run Hunyuan. Relaunching a server is cheap vs. the slowdown.
| Thing | Path |
|---|---|
| Fooocus | C:\projects\unreal-game\Fooocus_win64_2-5-0 (launch run.bat) |
| Fooocus UI | http://localhost:7865 |
| Fooocus outputs | C:\projects\unreal-game\Fooocus_win64_2-5-0\Fooocus\outputs\<YYYY-MM-DD>\ |
| Fooocus-API (REST) | C:\AI\Fooocus-API — isolated python_embeded; config.txt reuses models |
| Fooocus-API endpoint | http://127.0.0.1:8888 — POST /v1/generation/text-to-image |
| Hunyuan3D | C:\AI\HY3D2\Hunyuan3D2_WinPortable (launch launch_server.bat) |
| Hunyuan3D UI/API | http://localhost:8080 |
| Bundle python (has gradio_client) | C:\AI\HY3D2\Hunyuan3D2_WinPortable\python_standalone\python.exe |
| Blender | C:\Program Files\Blender Foundation\Blender 4.4\blender.exe |
| Skill scripts | this skill's scripts/ folder |
Only if starting from a text prompt. Model already installed: juggernautXL_v8Rundiffusion (photoreal).
For best downstream 3D: prompt for a single centered subject, plain/simple background,
3/4 or front view, even lighting. Hunyuan3D's auto background-removal expects one clear subject.
Add e.g. , single object, centered, plain white background, studio lighting, full view.
Vanilla Fooocus has no gradio_client API (Gradio 3.41.2, 0 named endpoints, gr.State generate
flow). That's why the Fooocus-API REST wrapper is installed — use it (Method A). UI is the fallback.
Isolated env at C:\AI\Fooocus-API\python_embeded (copy of Fooocus's embedded python + fastapi/uvicorn/
sqlalchemy/colorlog/rich/chardet; its python310._pth was patched to add .. and ../repositories/Fooocus).
config.txt (copied from the Fooocus install) makes it reuse juggernautXL + LoRA + expansion — no re-download.
$c=Get-NetTCPConnection -LocalPort 8080 -State Listen -EA SilentlyContinue; if($c){Stop-Process -Id $c.OwningProcess -Force} (relaunch it for Stage 2)../config.txt is found):
cmd /c "cd /d C:\AI\Fooocus-API && python_embeded\python.exe -s main.py --skip-pip --disable-preset-download --port 8888 --host 127.0.0.1 > C:\AI\Fooocus-API\api.log 2>&1"
Wait for Uvicorn running on http://127.0.0.1:8888 in api.log (loads SDXL, ~20–40 s).C:\AI\Fooocus-API\python_embeded\python.exe -s "<this skill>\scripts\fooocus_gen.py" --prompt "<subject>, single centered object, plain white background, studio lighting, full view" --out "<path\img.png>"
Blocks until done, saves the PNG. ~1–2 min when Fooocus has the GPU to itself (10x slower if Hunyuan is still loaded).Launch cmd /c "cd /d C:\projects\unreal-game\Fooocus_win64_2-5-0 && run.bat" (cold start ~5–6 min;
poll port 7865, the log doesn't flush). Open http://localhost:7865, enter prompt, click Generate,
grab the newest PNG from Fooocus\outputs\<date>\.
Either way, Stage 1 produces a PNG on disk. Stop Fooocus-API (port 8888) before Stage 2. Pass the PNG to Stage 2.
Invoke-WebRequest http://localhost:8080 -UseBasicParsing. If down, launch in background:
cmd /c "C:\AI\HY3D2\Hunyuan3D2_WinPortable\launch_server.bat > C:\AI\HY3D2\server.log 2>&1"
then watch C:\AI\HY3D2\server.log for Uvicorn running on http://0.0.0.0:8080 (~1–2 min; models cached).C:\AI\HY3D2\Hunyuan3D2_WinPortable\python_standalone\python.exe -s ^
"<this skill>\scripts\hunyuan_gen.py" --image "<path\to\image.png>" --name <AssetName>
--mode textured (default) = shape + texture (~60–75 s). --mode shape = geometry only (faster).C:\AI\HY3D2\outputs\<AssetName>_textured.glb (+ _white.glb).The unreal-mcp StaticMeshTools.import_file accepts only fbx/obj, not glb. Convert first.
"C:\Program Files\Blender Foundation\Blender 4.4\blender.exe" --background ^
--python "<this skill>\scripts\glb_to_fbx.py" -- --src "<asset.glb>" --dst "<asset.fbx>"
StaticMeshTools.import_file with
folder_path=/Game/Meshes/<Name>GLB, asset_name=<Name>, import_materials=true,
import_textures=true, combine_meshes=true. Then AssetTools.save_assets.hunyuan3d-deployment memory): racer BPs derive
from BP_TrainBase; each adds a GLBBody StaticMeshComponent. To add a new engine, mirror
BP_Thomas (single GLBBody, scale to length-match Thomas ≈ 1197 / mesh_local_Y_extent,
relativeRotation yaw -90, relativeLocation.z = -mesh_local_min_z * scale so it sits on the ground).
Access SCS templates via ActorTools.get_components on the CDO
(/Game/Blueprints/BP_<Name>.Default__BP_<Name>_C) -> BP_<Name>_C:<Comp>_GEN_VARIABLE, then
ObjectTools.get/set_properties. Compile + save the Blueprint. Verify by spawning an instance and
EditorAppToolset.CaptureViewport (decode per the unreal-mcp-screenshot-extraction memory).launch_server.bat.--profile 5 (already default in launch_server.bat).huggingface_hub API with
HF_HUB_DISABLE_SYMLINKS=1 (see hunyuan3d-deployment memory) — but for generation you only need
the server up, not re-downloads.*.ply: normal (Hunyuan meshes carry no node name); the FBX
still exports fine.development
Use when writing Zig code. Contains Zig 0.15 API changes and patterns.
testing
Interview the user relentlessly about a plan or design until reaching shared understanding, resolving each branch of the decision tree. Use when user wants to stress-test a plan, get grilled on their design, or mentions "grill me".
development
Guides working with exe.dev VMs. Use when the user mentions exe.dev, exe VMs, *.exe.xyz, or tasks involving exe.dev infrastructure.
development
Use when writing tests for Effect.ts code