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
---
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:
- **Qwen-Image-2.1-Turbo** (8 steps) via [hugging-apps/qwen-qwen-image-2-1-turbo](https://huggingface.co/spaces/hugging-apps/qwen-qwen-image-2-1-turbo) (default: fastest, least GPU quota);
- **Qwen-Image-2.1** (full model, 40 steps) via the official [Qwen/Qwen-Image-2.1](https://huggingface.co/spaces/Qwen/Qwen-Image-2.1) (`"backend": "qwen-space"`);
- **Bria Fibo 2.0 Edit Turbo** via [briaai/Fibo-2.0-editing](https://huggingface.co/spaces/briaai/Fibo-2.0-editing) (`"backend": "fibo-space"`).
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`](/docs);
* remote **MCP** (streamable HTTP) at `/mcp`;
* an agent guide at [`/llms.txt`](/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
```bash
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:
```json
{"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](https://huggingface.co/spaces/townbox/projection-texturing/tree/main/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.