Mike0021's picture
llms.txt: PBR option served by the v2 LoRA; name materials for metal
b83a088 verified
|
Raw History Blame Contribute Delete
6.47 kB
metadata
title: projtex · Projection Texturing API
emoji: 🎨
colorFrom: green
colorTo: yellow
sdk: docker
app_port: 7860
pinned: false
license: mit
short_description: Agent-first API to texture 3D meshes with Qwen-Image / Fibo
models:
  - Qwen/Qwen-Image-2.1-Turbo
  - Qwen/Qwen-Image-2.1
  - briaai/Fibo-2.0-edit-turbo
tags:
  - 3d
  - texturing
  - mcp-server
  - agents
  - image-editing

projtex: projection texturing API (agent-first)

Send a 3D mesh and a prompt; get back the mesh with a baked colour texture (GLB). The service:

  1. generates images from virtual cameras, each conditioned on what is already painted;
  2. checks every image against the geometry;
  3. projects the images onto the mesh and blends them in texture space;
  4. bakes the result into the mesh's UVs.

Three image models are available, through Hugging Face Spaces:

Designed for agents:

  • Asynchronous jobs. POST /api/jobs returns at once. Poll GET /api/jobs/{id}; every status includes progress, quality summary, file URLs and a next list of concrete follow-up calls.
  • Three equivalent interfaces:
    • REST with OpenAPI at /docs;
    • remote MCP (streamable HTTP) at /mcp;
    • an agent guide at /llms.txt.
  • Inputs agents can produce: a local file uploaded as raw bytes (POST /api/uploads -> upload_id, then a plain JSON job), mesh_base64, a public mesh_url, or a built-in sample. GLB from Blender or three.js (GLTFExporter), glTF with embedded data, OBJ, PLY, STL or a zip.
  • Outputs that drop back into your scene: the GLB keeps your objects (names, transforms), materials (names, metallic/roughness/alpha) and orientation; every material's base colour uses one baked texture. When your UVs are kept, the albedo PNG also fits your original model. Inside-out surfaces are detected and flipped.
  • Honest progress and quality: queue position and ETA while waiting; a verdict (good / usable / needs work) with coverage measured over what cameras can see (the underside is reported apart).
  • A quality loop as API calls: regenerate views, disable views, fill gaps, local retouch (repair / replace / upscale), pick 3D points from pixels, and re-bake.
  • Free dry runs with "backend": "mock", and bring-your-own images with "backend": "external".
  • Flat errors {"error", "hint"}.

Quick start

BASE=https://townbox-projection-texturing.hf.space
curl -s --data-binary @house.glb -H 'content-type: model/gltf-binary' $BASE/api/uploads
# -> {"upload_id": "up_...", ...}
curl -s -X POST $BASE/api/jobs -H 'content-type: application/json' -H "X-HF-Token: $HF_TOKEN" \
  -d '{"upload_id":"up_...","prompt":"white clapboard siding, grey shingle roof; dark green door"}'
# -> {"job_id": "...", "state": "queued", "poll_after_seconds": 15, "next": [...]}
curl -s $BASE/api/jobs/<job_id>
# when "state" is "done": files.textured_glb, files.contact_sheet, summary.verdict, output, next

Try it without a mesh: {"sample": "lantern", "prompt": "black wrought iron, weathered oak post, warm glass"}.

Terrain and ground: POST /api/terrain {"upload_id": "up_...", "prompt": "an alpine valley in early summer"} (or a heightmap, and your own layers) returns files.terrain_glb (the ground with a top-down colour map) and files.bundle_zip (splat maps, seamless detail textures, blender_terrain.py, three_terrain.js). See the "Terrain and ground" section of /llms.txt.

PBR materials: add "pbr": true to a texture job (or POST /api/jobs/{id}/pbr afterwards) for files.textured_pbr_glb with a de-lit base colour and a metallicRoughness texture (roughness, metallic maps from a LoRA on Qwen-Image-Edit-2511, run on the caller's ZeroGPU quota).

MCP client configuration:

{"mcpServers": {"projtex": {"type": "http", "url": "https://townbox-projection-texturing.hf.space/mcp",
                            "headers": {"X-HF-Token": "hf_..."}}}}

Tools:

  • texture_mesh, texture_terrain, get_job (with a preview image) and view_image;
  • the quality loop: regenerate_views, disable_views, fill_gaps, retouch, undo_retouch, bake, pick_point;
  • submit_view_image (bring your own images);
  • service_info and guide.

Quota: who pays for generation

Image generation runs on ZeroGPU Spaces and spends the caller's daily GPU quota, about 30 s per view.

  • Your token: send it as X-HF-Token (or the hf_token field) so your own quota is used. It stays in memory for that job only and is never written to disk, logged or returned.
  • No token: the job runs as the visitor identity the Hub forwards, if present, otherwise as the shared anonymous quota (about 2 GPU-minutes per day). GET /api/identity shows which applies to your requests.
  • No quota needed: the mock and external backends.

What runs here

The CPU part of projtex runs in this container, with software OpenGL:

  • mesh import and UV repair;
  • camera planning (objects, characters with face close-ups, 360° environment probes);
  • validation of every generated view (rejects re-framed outputs);
  • texel-space fusion weighted by angle and depth;
  • push-pull hole filling, leave-one-out consistency checks, local retouch layers;
  • GLB export.

Limits:

  • meshes: 60 MB, 600k triangles;
  • texture size: 1024, 2048 or 4096;
  • 8 operations run at once (the CPU-heavy parts share 2 CPU slots), the rest are queued;
  • jobs expire after 12 h or when the Space restarts.

Licences

  • Code: MIT.
  • Qwen-Image-2.1 and Qwen-Image-2.1-Turbo outputs: Qwen research licence.
  • Fibo 2.0 Edit Turbo outputs: CC BY-NC 4.0 (non-commercial).
  • Samples: Avocado and Lantern are CC0 (Khronos glTF-Sample-Assets). The head is the Lee Perry-Smith scan, CC-BY 3.0, by Infinite-Realities.

Inspired by the projection-texturing workflow shown by @alexfredo87. This is an independent implementation.