feat: clothing lane, character sources, and DCC bridges
Bulk import of the working lanes that were living untracked on the PC. Content: - characters/ Lena/male body lanes, bakes, texture work, run logs - clothing/ garment pipeline, configs, gates, contract docs - garments/ MD-authored garment sources (.zprj/.zpac) - UAL-Lib/ Universal Animation Library 2 source (.blend/.fbx/.glb) - tools/ blender_bridge, iclone_bridge, md_bridge, tailor, glm_agent - docs/, plans/, dev/, .agents/plans/ Repo hygiene: - .gitattributes: LFS now covers .blend, .zprj, .zpac, .obj, .npy and the Reallusion .iAvatar/.ccAvatar/.ccRestore containers. Without this the ~3.8 GB in this commit would land as raw blobs. .png/.jpg are left out on purpose — ~250 are already tracked raw and converting them would rewrite every one without shrinking history. - .gitignore: exclude /accurig/ (~1 GB AccuRig program files, redistributable from Reallusion, nothing authored here) and /dev/null/ (git-lfs hook copies dropped by a `>/dev/null` redirect on Windows). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
# GLM advice (glm-5.2 via api.z.ai)
|
||||
|
||||
## 1. Weld+decimate 4.3M→1.5k: better approach
|
||||
|
||||
Collapse-decimating unwelded MD soup at ~3000:1 will eat pleats. Three concrete changes:
|
||||
|
||||
**(a) Reorder the pipeline: weld → fit (shrinkwrap high-poly) → decimate → bake.** Fitting before decimating lets Shrinkwrap use real pleat geometry; fitting a faceted 1500-tri proxy to a 25k body gives poor contact and lost silhouette. This is the single biggest fix to the plan.
|
||||
|
||||
**(b) Use Decimate in DISSOLVE (planar) mode for flat-panel parts**, not COLLAPSE. MD panels are nearly planar, so `DecimateModifier(decimate_mode='DISSOLVE', angle_limit=rad(5°))` merges coplanar faces and preserves panel boundaries + UVs far better than collapse. Use 8–10° for the bow. Collapse mode is only acceptable on truly curved regions.
|
||||
|
||||
**(c) For the pleated skirt, do not decimate the MD mesh — build a low-poly proxy.** Cylinder, 28–32 segments, 3–4 vertical loops, knee length, denser waistband ring. `ShrinkwrapModifier(wrap_mode='NEAREST_SURFACE', offset=0.002–0.003)` to the high-poly skirt. Bake normals high→low (see Q5). At 1500 tris, geometric pleats read as noise; normal-map pleats read as pleats.
|
||||
|
||||
Reject voxel remesh: destroys UVs, loses 6–8mm pleats at any feasible voxel resolution (you'd need ~0.5mm voxels = tens of millions). Reject Quad Remesher add-on: not headless-stable, license-bound. If you can re-export from MD, lower particle distance to 5–7mm and reduce pleat segment counts before sim — gives a 50–100k mesh that decimates cleanly.
|
||||
|
||||
Keep the high-poly around (hidden, excluded from export) for baking.
|
||||
|
||||
## 2. Skirt weights without extra bones
|
||||
|
||||
Nearest-vertex KDTree is the wrong tool — it snaps to the closer leg, giving a hard medial seam. Standard recipe is a **weight-transfer proxy**:
|
||||
|
||||
1. **Build a skirt cone**: duplicate Lena's body, keep pelvis→mid-thigh, bridge the leg gap into a tapered cylinder covering the skirt volume (waist ring at pelvis, knee ring at hem). Or extrude the pelvis ring downward to a knee-level ring scaled to skirt radius.
|
||||
2. **Weight the cone by Z-gradient**: top ring = copy body weights via `DataTransferModifier(vert_mapping='NEAREST_SURFACE', data_type='VGROUP_WEIGHTS')`. Bottom ring = 100% pelvis, 0% thighs. Blend linearly by world-Z between waist and hem. Add a small L/R thigh bias by X-sign so the hem still leans slightly with the stance leg.
|
||||
3. **Transfer cone→skirt**: `DataTransferModifier(vert_mapping='NEAREST_SURFACE', layers='ALL')`, apply, then `bpy.ops.object.vertex_group_smooth(repeat=3, factor=0.5)`.
|
||||
|
||||
This gives smooth L/R blend at the crotch (continuous cone surface) and pelvis-dominant hem. No hard seam. The Z-gradient is forward-compatible with future skirt bones — you can blend skirt-bone weights in by Z-band without redoing the transfer.
|
||||
|
||||
Fallback if you can't build the cone: per-vertex, compute distance to each bone segment (pelvis, thigh L, thigh R) with Gaussian falloff (σ≈15cm), normalize. Fast, scriptable, fuzzier than the cone.
|
||||
|
||||
## 3. Multi-layer shrinkwrap pitfalls
|
||||
|
||||
Three issues:
|
||||
|
||||
**(a) Offset vs. low-poly faceting.** At 1500 tris, facet normals deviate from the true surface; 6–8mm along vertex normals can still poke through at facet edges on curved regions (bust, scapula, glutes). Use `wrap_mode='NEAREST_SURFACE'` with offset, and keep the shrinkwrap **target** high-poly (original MD mesh or Lena's 25k body), not the decimated garment. Apply shrinkwrap before decimation (Q1).
|
||||
|
||||
**(b) Layer-to-layer wrapping.** Don't shrinkwrap the bow to the body — it'll sit inside the bodice. Stack: bow → bodice (offset = bodice thickness + 1mm), bodice → body (offset = 6–8mm). Or wrap all to body with cumulative offsets (body+6mm, body+10mm, body+14mm) — simpler to script but breaks if layers aren't concentric.
|
||||
|
||||
**(c) Self-intersection at boundaries.** Where bow meets bodice, low-poly faceting causes z-fighting. Add 1–2mm depth_bias per layer in Godot material, or ensure geometric offset exceeds the low-poly facet amplitude (~2mm at 1500 tris on a 30cm-radius curve).
|
||||
|
||||
Also: shrinkwrap inverts normals on concave regions (armpits, under-bust). After applying, run `bpy.ops.mesh.normals_make_consistent(inside=False)` and check for flipped faces.
|
||||
|
||||
## 4. Re-posing sleeves to T-pose (v2)
|
||||
|
||||
Two scripted options:
|
||||
|
||||
**(a) Rigid rotation (fast, OK for slight arms-down ~30–45°):** detect sleeve vertices by material or bbox (|X| beyond shoulder ± threshold). Shoulder pivot = Lena's `upper_arm_L/R` bone head. Build rotation matrix: axis = forward (Y), angle = -(current_arm_angle − 90°). Apply via `mesh.transform(matrix, vertex_group='sleeve_L')`. Fine if sleeves are near-cylindrical; test the cap — if it kinks, use (b).
|
||||
|
||||
**(b) 2-bone armature per sleeve (cleaner):** create a 3-bone chain (shoulder→elbow→wrist) per arm along the sleeve's medial axis (PCA on sleeve vertices, or sample). Parent sleeve vertices to nearest bone with `bpy.ops.object.parent_set(type='ARMATURE_AUTO')` restricted to the sleeve vertex group. Rotate elbow+wrist to bring cuff to T-pose height. `bpy.ops.pose.armature_apply(selected=False)`, apply armature modifier. Preserves sleeve length and cap shape.
|
||||
|
||||
For "slightly arms-down", (a) is ~10 lines of script. For full A-pose or reaching, use (b). Pitfall: if the jacket torso has shoulder wrinkles from the arms-down pose, rigid rotation leaves them — they'll bake into the normal map, which may be fine.
|
||||
|
||||
## 5. Baking normals/AO at 1.5k tris
|
||||
|
||||
Worth it. At 1500 tris, geometric pleats are noise; normal-map pleats read as pleats. AO grounds the garment. Do it.
|
||||
|
||||
Workflow notes for MD unwelded sources:
|
||||
|
||||
- **UVs**: MD gives per-panel islands (one per pattern piece). After welding they're still clean — good. But decimated low-poly UVs will distort. **Create a second UV map** ("bake_uv") on the low-poly, `bpy.ops.uv.smart_project(angle_limit=1.15)`, bake to that. Keep original MD UVs as UV1 for future texture work. Godot 4.7 supports 2 UV channels.
|
||||
- **Normals**: MD unwelded output has inconsistent normals across seams. On the high-poly: `mesh.normals_make_consistent(inside=False)`, then `mesh.smooth_normals()`. Bake `type='NORMAL'`, `space='TANGENT'`, `use_selected_to_active=True`, `cage_extrusion=0.0005–0.001` (0.5–1mm). Cycles.
|
||||
- **AO**: bake separately, `type='AO'`, `samples=64`. Multiply in shader at 0.5–0.7. Or bake Combined with world light disabled for AO+curvature in one texture.
|
||||
- **Layer bleed**: multi-layer cloth — bake each layer separately with others hidden, or cage_extrusion < layer separation. MD layers are 2–5mm apart; use cage_extrusion=1mm.
|
||||
- **Color**: flat MD material colors → assign directly as base color on the low-poly material. No bake needed. One material per part: base color + normal map + AO multiply.
|
||||
|
||||
Texture size: 512² for bodice/bow, 512×1024 for skirt (pleats need vertical resolution). 1500-tri parts don't justify 2K.
|
||||
|
||||
## 6. Overall plan critique
|
||||
|
||||
Do differently:
|
||||
|
||||
**(a) Reorder: fit before decimate, bake after decimate.** Current plan decimates then fits. Pipeline should be: split → weld → (build proxy for skirt) → fit high-poly to body → decimate → bake high→low → weight transfer → export. This is the biggest issue.
|
||||
|
||||
**(b) Per-part tri budget should vary.** 1500 for bow is wasteful; 1500 for skirt is starving. Suggest: bow 300–500, bodice 1000–1200, skirt 2000–2500. If 1500 is a hard total-per-character crowd budget, state it as a total and allocate.
|
||||
|
||||
**(c) Poke-through is under-addressed.** 6–8mm offset on 1500-tri garments in walk/dance will poke at crotch, armpits, under-bust, and back of skirt during forward leg swing. Build an **inner shell**: a 3–5mm inflated copy of Lena's body; shrinkwrap garments to the shell, not the body. Test in the in-game test bed immediately after weight transfer, not at the end.
|
||||
|
||||
**(d) Weight transfer: use Data Transfer (Nearest Surface), not KDTree nearest-vertex, for body-conforming parts.** KDTree is fine for the snug bodice but fails on overhangs (collar, bow tails) where the nearest body vertex is on the wrong side. KDTree is also non-deterministic at equidistant vertices — add a lowest-index tiebreak if you keep it.
|
||||
|
||||
**(e) Shrinkwrap mask must be scripted.** Build the "fit influence" vertex group from world-Z relative to pelvis bone head: 1.0 above waist, linear ramp to 0.0 at hip-crotch height. Don't hand-paint in a headless pipeline.
|
||||
|
||||
**(f) Missing: LOD strategy.** 1500 tris is LOD0 for a hero, LOD1 for crowd. If crowd-scale, plan LOD2 (400–500 tris) with aggressive decimate + no normal map. Mention now even if deferred.
|
||||
|
||||
**(g) Missing: determinism audit.** KDTree, Smart UV Project, and auto-weights have non-deterministic corners. Pin `bpy.context.scene.cycles.seed` and `random.seed`, and add a regression check: hash exported GLB vertex positions; fail the pipeline if the hash changes between runs on the same input.
|
||||
|
||||
**(h) 12 materials → 3 parts: verify contiguity.** MD sometimes assigns multiple materials to one panel (trim + shell). After splitting, check `bmesh` connectivity; if a "part" has >1 connected component, merge materials or split further.
|
||||
|
||||
**(i) Test bed timing.** After weight transfer, do a quick GLB round-trip into Godot with the walk cycle before finalizing bake/export. Catch tearing early — don't wait until the end.
|
||||
@@ -0,0 +1,56 @@
|
||||
# GLM advice (glm-4.6 via api.z.ai)
|
||||
|
||||
### 1. Weld+Decimate Strategy
|
||||
**Do not use Collapse Decimate directly on 4.3M verts.** It is computationally expensive ($O(N \log N)$ or worse depending on implementation) and creates chaotic, sliver triangles that destroy the silhouette of pleats and deform poorly.
|
||||
|
||||
**Better Approach:**
|
||||
1. **Clean:** `bpy.ops.mesh.merge_objects()` or `bpy.ops.mesh.remove_doubles(threshold=0.0001)` to weld the MD "soup".
|
||||
2. **Retopologize (Quadriflow):** Use `bpy.ops.object.quadriflow_remesh(target_face_count=1600)`.
|
||||
* **Why:** Quadriflow generates a consistent quad flow that preserves curvature and sharp features (pleat edges) far better than decimation. It handles the high-density input robustly and outputs a mesh that deforms cleanly for skinning.
|
||||
* **Scripting Note:** Quadriflow is deterministic in Blender 5.1 headless mode if you set `seed` and `use_mesh_symmetry=False`.
|
||||
3. **Alternative (Faster):** **Decimate -> Unsubdivide**.
|
||||
* MD meshes are grid-based. `bpy.ops.object.decimate(ratio=0.5, mode='UNSUBDIVIDE')` iteratively removes edge loops while maintaining the grid structure. This preserves the "flow" of the fabric better than Collapse, which eats holes in the mesh.
|
||||
|
||||
### 2. Skirt Weighting Recipe
|
||||
Nearest-vertex transfer is incorrect for skirts; it creates a "hard" seam where the skirt splits to follow the legs.
|
||||
|
||||
**Standard Recipe: "Pelvic Lock with Geometric Falloff"**
|
||||
1. **Initial Transfer:** Perform your standard KDTree transfer to get base weights.
|
||||
2. **Geometric Masking:** Define a "Skirt Zone" via Python (e.g., all vertices with local Y < `hip_joint_y`).
|
||||
3. **Nullify Leg Weights:** Iterate vertices in the Skirt Zone. Force `vertex_groups["Thigh_L"].weight = 0.0` and `vertex_groups["Thigh_R"].weight = 0.0`.
|
||||
4. **Pelvic Dominance:** Set `vertex_groups["Hips"].weight = 1.0` (or `Spine` if Hips is unweighted in your source).
|
||||
5. **Transition Blend:** Select vertices in a band around the waist (e.g., `hip_joint_y - 0.05m < y < hip_joint_y`). Run `bpy.ops.object.vertex_group_smooth(iterations=3)` to blend the sharp cut between the Pelvis-locked skirt and the torso-weighted bodice.
|
||||
6. **Normalize:** `bpy.ops.object.vertex_group_normalize_all()`.
|
||||
|
||||
### 3. Multi-Layer Shrinkwrap Pitfalls
|
||||
**Pitfall:** "Snapping through." If you shrinkwrap the Bow to the Body, it will clip inside the Bodice. If you use "Nearest Surface" without care, the Bow might wrap around the back of the Bodice.
|
||||
|
||||
**Solution: Sequential Shrinkwrapping & Projection**
|
||||
1. **Pass 1 (Bodice):** Shrinkwrap Bodice to Body. Mode: **Project** (along normal). Offset: `2mm` (fabric thickness).
|
||||
2. **Pass 2 (Bow):** Shrinkwrap Bow to **Bodice** (not Body). Mode: **Project**. Offset: `4mm` (Bodice thickness + air gap).
|
||||
3. **Vertex Group Masking:** Crucial for the Bow. Assign a Vertex Group to only the "knot" area of the Bow. Restrict the Shrinkwrap modifier to this group so the loops float freely but the knot sits tight.
|
||||
|
||||
### 4. Re-posing Sleeves (Arms-Down to T-Pose)
|
||||
**Cleanest Scripted Approach: Bind & Apply**
|
||||
Do not try to geometrically rotate the mesh; it will twist the UVs and volume.
|
||||
1. **Transfer Weights:** Copy weights from T-pose Lena to the Arms-Down Garment (using `DATA_TRANSFER`, 'Nearest Face Interpolated'). Even though the poses differ, this maps the arm volume to the arm bones.
|
||||
2. **Apply Armature:** Add an Armature modifier pointing to the T-pose skeleton. Run `bpy.ops.object.modifier_apply(modifier="Armature")`.
|
||||
3. **Result:** This bakes the T-pose transformation into the mesh coordinates. The sleeve will physically stretch/rotate to align with the T-pose bones.
|
||||
4. **Correction:** If the mesh distorts slightly, run a `Smooth` or `Laplacian` deform pass, but usually, the high vertex count of the MD source handles the linear interpolation fine.
|
||||
|
||||
### 5. UVs and Baking
|
||||
**Is it worth it?** Yes. At 1.5k tris, geometric pleats will look like jagged low-poly spikes. A normal map is mandatory for the "fabric" look.
|
||||
|
||||
**Workflow Notes for MD Unwelded Sources:**
|
||||
1. **UV Unwrap:** The MD UVs are likely per-panel and may be overlapping or messy. Run `bpy.ops.uv.select_all(action='SELECT')` -> `bpy.ops.uv.pack_islands()` on the *Low-Poly* target to ensure a clean layout for baking.
|
||||
2. **Cage Object:** Essential. Because the Low-Poly is a simplified shell of the High-Poly, ray-casting will miss or hit the back-faces of the thin MD mesh.
|
||||
* Create a Cage: Duplicate the Low-Poly mesh. `bpy.ops.object.transform_apply(scale=True)`. Scale it up by ~5% (`obj.scale = (1.05, 1.05, 1.05)`).
|
||||
* In `bpy.ops.object.bake()`, assign this object to the `cage` parameter.
|
||||
3. **Source Normals:** Ensure the High-Poly MD mesh has **Auto Smooth** enabled or is set to Flat shading before baking. If you bake from a smooth-shaded high-poly to a low-poly, you will lose the sharp crease definitions of the pleats in the normal map.
|
||||
|
||||
### 6. Overall Plan Critique
|
||||
1. **Missing: Hard Edges / Shading.** You are exporting flat colors. At 1.5k tris, smooth shading will make the cloth look like inflated plastic. You must define seams.
|
||||
* **Fix:** Add an **Edge Split** modifier (`bpy.ops.object.modifier_add(type='EDGE_SPLIT')`) with `split_angle=0.5` (approx 30 deg) before export. This preserves sharp cuffs, collars, and hems without increasing poly count.
|
||||
2. **Missing: Clearance Verification.** A static 6-8mm offset is risky for a "crowd-scale" game where animations might include deep squats or extreme twists.
|
||||
* **Fix:** In the script, generate a "Clearance Mesh" by scaling the Body mesh up by 1.05 (or offsetting along normals). Shrinkwrap the garment to this *expanded* mesh, not the body itself. This guarantees mathematical clearance regardless of animation pose.
|
||||
3. **Export Rig:** Ensure you export the **full 65-bone skeleton** with every garment, even if the garment only uses 10 bones. Godot's Skeleton3D expects a consistent bone hierarchy to stack skins correctly. Do not export "rest pose only" or a stripped skeleton.
|
||||
@@ -0,0 +1,39 @@
|
||||
# Brief: Blender-only garment pipeline for ariki-game — request for review
|
||||
|
||||
You are being asked to review a technical plan and give advice: identify risks, suggest better techniques, and flag anything missing. Be concrete and critical. You have no file access — everything you need is in this brief.
|
||||
|
||||
## Context
|
||||
|
||||
- Godot 4.7 game. All characters share one 65-bone skeleton ("Quaternius", UE-style bone names, T-pose rest). Runtime clothing system stacks garment GLBs onto the character's Skeleton3D by bone-name binding — this works and ships.
|
||||
- Hero character "Lena": a Tripo photo-scan mesh (25.7k tris, baked albedo texture), rigged to the shared skeleton. She is the fit target. Her body mesh + full vertex-group weights are available in Blender.
|
||||
- Existing tooling (headless Blender 5.1, Python): GLB/FBX import; KDTree nearest-vertex weight-copy from body→garment (proven on prior outfit sets); a skeleton-anchored alignment tool (scales/positions a garment onto the body by hip/head/arm frame); collapse-decimation with per-part tri budget (~1,500 tris/part); glTF export. Deterministic, scriptable, no GUI.
|
||||
- We deliberately rejected Character Creator 5 for clothing: our characters are AccuRig "Humanoid" avatars, and CC5 provably refuses conform/Transfer-Skin-Weights on Humanoids (verified via its Python API and GUI this week). CC5's conform also only fits its own proxy bodies, so a Blender fit pass to the real mesh is needed regardless.
|
||||
|
||||
## The garment to process
|
||||
|
||||
A Marvelous Designer FBX export ("thin, unwelded"): ONE mesh, 2.49M verts / 4.30M tris, human-scale (zmin 0.59m, zmax 1.65m), 12 materials that partition it into logical parts: cropped jacket (sleeved), shirt-dress bodice, pleated knee-length skirt, bow belt, second cloth layers. No textures (flat MD material colors), single UV map. Modeled in a slightly arms-down pose (not T-pose).
|
||||
|
||||
## The plan (v1 scope: bodice + skirt + bow; jacket with sleeves deferred)
|
||||
|
||||
1. Split the mesh by material into parts; group into Body-slot (bodice+bow) and Legs-slot (skirt).
|
||||
2. Per part: merge-by-distance weld (it's unwelded MD output), then collapse-decimate to ≤1,500 tris. Keep the UV map.
|
||||
3. Align the garment set onto Lena's body (uniform scale + translation; both are upright human-scale so a bbox/landmark alignment suffices).
|
||||
4. Fit pass: Shrinkwrap (nearest-surface, ~6-8mm offset) masked by a vertex group — full influence on the snug bodice, fading to zero influence a little below the hip so the skirt keeps its hanging silhouette and only the waistband conforms.
|
||||
5. Weight transfer: KDTree nearest-body-vertex copy from Lena's weighted body mesh to each garment part. Known weak point: the skirt — nearest-vertex copy gives hard left/right leg weights near the hem, causing tearing/stretching in walk cycles. Planned mitigation v1: below-crotch vertices get blended thigh weights or pelvis-dominant weights (accept reduced skirt motion); skirt bones + jiggle are a later upgrade, not v1.
|
||||
6. Export per-part GLBs bound to the shared skeleton; register in the game's outfit catalog; verify in the in-game clothing test bed (idle, walk, dance).
|
||||
|
||||
## Constraints
|
||||
|
||||
- End result must be statically skinned (no runtime cloth sim; Godot, crowd-scale).
|
||||
- Tri budget ~1,500/part. One material per part preferred; flat colors acceptable for now.
|
||||
- Everything must run headless/scripted (agent-driven pipeline, repeatable for future garments).
|
||||
- The body stays under the garment (no body-hide system yet) — clearance must prevent poke-through across the animation set.
|
||||
|
||||
## Questions for you
|
||||
|
||||
1. Weld+decimate 4.3M→1.5k is a ~3000× reduction on unwelded MD triangle soup. Better approach than collapse-decimate? (e.g., voxel remesh then decimate; shrinkwrap a low-poly proxy onto the high-poly; MD's own quad-remesh if we re-export?) What preserves pleats/silhouette best at 1.5k tris?
|
||||
2. Best practice for the skirt weights on a humanoid rig without extra bones — is there a standard "skirt weighting" recipe (e.g., project weights from a cylinder, distance-weighted thigh blend, pelvis-locked hem)?
|
||||
3. Any pitfalls with shrinkwrap-fitting a multi-layer outfit (bodice over body, bow over bodice) — how to keep layer separation at low poly counts?
|
||||
4. The garment is in a slightly arms-down pose while the target binds in T-pose; v1 avoids sleeves entirely. For v2 (jacket), what's the cleanest scripted approach to re-pose garment sleeves to T before fitting?
|
||||
5. UVs and baked detail: at 1.5k tris the pleats will flatten. Is baking the high-poly's normals/AO onto the low-poly worth it in this budget, and any workflow notes for MD unwelded sources (UV islands per panel)?
|
||||
6. Anything in this plan you would do differently overall?
|
||||
BIN
Binary file not shown.
Reference in New Issue
Block a user