WIP: Character creator: clothes, eyes, body types, skin, anime style #134
Draft
khyretos
wants to merge 9 commits from
khyretos/claude/creator-clothes into main
AGit
pull from: khyretos/claude/creator-clothes
merge into: khyretos:main
khyretos:main
khyretos:renovate-hold-imgui-rnnoise
khyretos:gh-pages
khyretos:windows-results
khyretos:renovate/font-awesome-7.x
khyretos:lint-fix/yaml_prettier
khyretos:renovate/https-code.forgejo.org-forgejo-upload-artifact-5.x
khyretos:renovate/https-code.forgejo.org-forgejo-download-artifact-7.x
khyretos:renovate/https-code.forgejo.org-actions-cache-6.x
khyretos:renovate/xiph-rnnoise-0.x
khyretos:renovate/cmake-mirrors-non-major
khyretos:lint-fix/json_prettier
khyretos:lint-fix/bash_shfmt
khyretos:ci/coverage-ccache
khyretos:ci/speed-ccache-jobs
khyretos:claude/integration
khyretos:claude/creator-vitruvian-wip
khyretos:claude/park-engine-foundations
khyretos:claude/park-parity
khyretos:claude/jiggle-skeleton-base
khyretos:claude/creator-polish-base
khyretos:claude/creator-polish
khyretos:claude/creator-wardrobe
khyretos:claude/creator-anime
khyretos:claude/creator-clothes
khyretos:pre-release
khyretos:release
khyretos:claude/mpm-water
khyretos:lint-fix/markdown_markdownlint
khyretos:claude/lua-nav
khyretos:claude/creator-hair
khyretos:claude/dynamic-navmesh
khyretos:claude/lua-audio
khyretos:claude/save-slots
khyretos:archive/2026-10-24/clothref
khyretos:archive/2026-10-24/f01aref
khyretos:archive/2026-10-24/f02aref
khyretos:archive/2026-10-24/f12ref
khyretos:archive/2026-10-24/g18eref
khyretos:archive/2026-10-24/g19aref
khyretos:archive/2026-10-24/g19b2
khyretos:archive/2026-10-24/g19bref
khyretos:archive/2026-10-24/g19cref
khyretos:archive/2026-10-24/g19dref
khyretos:archive/2026-10-24/reflA
khyretos:archive/2026-10-24/reflB
khyretos:khyretos/rhi-shaders
khyretos:claude/rhi-light-sets
khyretos:claude/rhi-pipeline-state
khyretos:archive/2026-10-24/r1gref
khyretos:archive/2026-10-24/ciref
khyretos:archive/2026-10-24/r1eref
khyretos:archive/2026-10-24/r1dref
khyretos:archive/2026-10-24/r1cref
khyretos:archive/2026-10-24/r1bref
khyretos:archive/2026-10-24/r1aref
khyretos:archive/2026-10-24/f13ref
khyretos:archive/2026-10-24/f11ref
khyretos:archive/2026-10-24/f10dref
khyretos:khyretos/ci-on-prs
khyretos:archive/2026-10-24/f10cref
khyretos:archive/2026-10-24/f10bref
khyretos:claude/bloom
khyretos:archive/2026-10-24/f10ref
khyretos:archive/2026-10-24/f08ref
khyretos:archive/2026-10-24/f07ref
khyretos:archive/2026-10-24/f05bref
khyretos:archive/2026-10-24/f05ref
khyretos:archive/2026-10-24/f03ref
khyretos:archive/2026-10-24/f02cref
khyretos:benchmark-data
khyretos:claude/cloth-passes
khyretos:archive/2026-10-24/f02bref
khyretos:archive/2026-10-24/refl-merge-base
khyretos:archive/2026-10-24/claude-b087-ref
khyretos:archive/2026-10-24/claude-macos-cross
khyretos:archive/2026-10-24/claude-macos-ref
khyretos:archive/2026-10-24/stash-macos-ref
khyretos:archive/2026-10-24/claude-win-probe
khyretos:patches/inbox
khyretos:tennis-feedback-wip
khyretos:archive/2026-10-24/runner-kit-check
No reviewers
Labels
No labels
deps
deps-major
hold
security
Milestone
Clear milestone
No items
No milestone
Projects
Clear projects
No items
No project
Assignees
Clear assignees
No assignees
3 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".
No due date set.
Dependencies
No dependencies set.
Reference
khyretos/kk-engine!134
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "khyretos/claude/creator-clothes"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Requested by Kees · project thread
Builds on the hair PR #120 (merged). Rebased onto main
d2ee5ce6: two conflicts in the creator self-test (CharacterCreatorModule.cpp), resolved by keeping main's per-row hair check and adding this branch's clothes check.WIP: visual work. Kees's look-OK on the creator is needed before merging; drop the WIP prefix to let auto-merge take it.
What
kke/HumanClothes.h: clothes that fit every MakeHuman body, cut from the two helper shapes every morph target already moves (helper-tights,helper-skirt), so no fitting step. Fitted: T-shirt, tank top, crop top, long sleeve, shorts, trousers, socks, shoes (layered 1 to 6 mm out, tops tucked under the waist). Cloth: tennis skirt, skirt, long skirt as Jolt cloth pinned at the waistband, against the body collider the hair uses, drawn withcloth.frag.HumanLook: clothes in JSON and the share code, so a peer rebuilds the same outfit.kke::dress/bakeSkinned(): the game gets the dressed person as one skinned model on the body's bones.kke/HumanEyes.haddIrises(pupil, iris, rim, tinted the chosen eye colour; swatches on Skin & eyes). Scalp under the hair is the skin a shade darker.keepOutside).tools/makehuman/bake_skin.pybakes skin maps from MakeHuman's CC0 skin weights (lips, blush, eyelids, pores, gloss);vitruvian_export.py+bake_vitruvian.pywarp CharMorph Vitruvian's CC0 scanned skin onto the body. Brows and lashes as skinned hair strips (addBrows).ModelModule::setToon(MToon-likemodel_toon.frag+ inverted-hull outline, pipelines made on first use),Human::setStyle+Human::animeFace(), anime skin albedo, Realistic / Anime buttons;hairLocksdraws the guides as tapered outlined locks.canonicalBoneNamealso maps VRM humanoid bones (VRoidJ_Bip_*) and MakeHuman's rig; arootcounts as the pelvis only on a skeleton without one.KKE_CREATOR_CLOTHESfor screenshots.Tests
kke_testsafter the rebase: 1342 passed, 0 failed (new:HumanClothes.*,HumanEyes.*,HumanStyle.AnimeFaceReshapesWithoutChangingTheLook,HumanHair.LocksTaperFromRootToTip,AnimRig.CanonicalNamesPairVrmAndMakeHuman)character_creatorself-test under Xvfb: "creator self-test passed (code round-trips, floor ok, hair 'two-strand twists' ok, clothes 'crop top, long skirt, socks, shoes' ok)"; a second run with 'afro' + 'crop top, shorts, …' also passedcheck_std_includes,check_dependencies(161 listed),check_game_modules(26 games)-Wunused-lambda-captureon every changed .cpp: no unused captures🤖 Generated with Claude Code
https://claude.ai/code/session_014ehJmtmmZLukS7FKi1aYb6
Title
WIP: Character creator: clothes, eyes, body types, skin, anime style
User description
Requested by Kees · project thread
Builds on the hair PR #120 (merged). Rebased onto main
d2ee5ce6: two conflicts in the creator self-test (CharacterCreatorModule.cpp), resolved by keeping main's per-row hair check and adding this branch's clothes check.WIP: visual work. Kees's look-OK on the creator is needed before merging; drop the WIP prefix to let auto-merge take it.
What
kke/HumanClothes.h: clothes that fit every MakeHuman body, cut from the two helper shapes every morph target already moves (helper-tights,helper-skirt), so no fitting step. Fitted: T-shirt, tank top, crop top, long sleeve, shorts, trousers, socks, shoes (layered 1 to 6 mm out, tops tucked under the waist). Cloth: tennis skirt, skirt, long skirt as Jolt cloth pinned at the waistband, against the body collider the hair uses, drawn withcloth.frag.HumanLook: clothes in JSON and the share code, so a peer rebuilds the same outfit.kke::dress/bakeSkinned(): the game gets the dressed person as one skinned model on the body's bones.kke/HumanEyes.haddIrises(pupil, iris, rim, tinted the chosen eye colour; swatches on Skin & eyes). Scalp under the hair is the skin a shade darker.keepOutside).tools/makehuman/bake_skin.pybakes skin maps from MakeHuman's CC0 skin weights (lips, blush, eyelids, pores, gloss);vitruvian_export.py+bake_vitruvian.pywarp CharMorph Vitruvian's CC0 scanned skin onto the body. Brows and lashes as skinned hair strips (addBrows).ModelModule::setToon(MToon-likemodel_toon.frag+ inverted-hull outline, pipelines made on first use),Human::setStyle+Human::animeFace(), anime skin albedo, Realistic / Anime buttons;hairLocksdraws the guides as tapered outlined locks.canonicalBoneNamealso maps VRM humanoid bones (VRoidJ_Bip_*) and MakeHuman's rig; arootcounts as the pelvis only on a skeleton without one.KKE_CREATOR_CLOTHESfor screenshots.Tests
kke_testsafter the rebase: 1342 passed, 0 failed (new:HumanClothes.*,HumanEyes.*,HumanStyle.AnimeFaceReshapesWithoutChangingTheLook,HumanHair.LocksTaperFromRootToTip,AnimRig.CanonicalNamesPairVrmAndMakeHuman)character_creatorself-test under Xvfb: "creator self-test passed (code round-trips, floor ok, hair 'two-strand twists' ok, clothes 'crop top, long skirt, socks, shoes' ok)"; a second run with 'afro' + 'crop top, shorts, …' also passedcheck_std_includes,check_dependencies(161 listed),check_game_modules(26 games)-Wunused-lambda-captureon every changed .cpp: no unused captures🤖 Generated with Claude Code
https://claude.ai/code/session_014ehJmtmmZLukS7FKi1aYb6
PR Type
Enhancement, Tests, Documentation
Description
Adds fitted clothes and anime style to character creator
Implements realistic skin maps with Vitruvian scan detail
Enables VRM-to-MakeHuman bone retargeting for animations
Includes tests for new eyes, clothes and retargeting logic
Diagram Walkthrough
File Walkthrough
19 files
Adds clothes, anime style, eyes and hair locks to creatorImplements addIrises and addBrows for realistic eyesImplements garmentShape, dress and keepOutside functionsAdds VRM and MakeHuman bone name retargetingAdds toon shading and outline rendering pipelineAnime hair locks and scalp root placement logicClothes added to JSON serialization and share codesAnime face style offsets and shaping layer supportNew shader for anime toon shading with rim lightNew vertex shader for inverted hull outlineNew fragment shader for outline renderingClothes, anime style and eye meshes added to modulesetToon method and pipeline storage addedStyle layer and anime face offsets added to HumanaddIrises and addBrows functions declaredhairLocks and lockWidth functions declaredClothes vector added to HumanLook structureNew header for fitted clothes and garment shapesUI updated with clothes tab and anime style buttons2 files
Tests clothes baking, irises, brows and anime faceVRM and MakeHuman canonical bone name pairing test3 files
Python script to bake Vitruvian skin detail onto MakeHumanProcedural skin map generator for anime and base stylesBlender export script for CharMorph Vitruvian body3 files
Documentation for eyes, brows, skin, clothes and animeAdded clothes, body types and anime style to creator docsUpdated CI self-test comment to include garment check1 files
Adjusted CSS layout for clothes tab and sliders2 files
Added skin maps and cloth/toon shaders to buildRegistered HumanClothes and HumanEyes source files2 files
PR Reviewer Guide 🔍
📋 Focus areas: 🔴 10 open · ✅ 0 handled. Every push re-checks them; a handled area moves to Resolved findings at the bottom.
Missing Error Handling for Garment Loading
In
dressUp(), the code callsgarmentShape()andfindGarment()without checking if they return empty results or null pointers before using them. If a garment ID is invalid or missing from the asset pack, this could lead to undefined behavior or crashes when accessing.vertsor.id. The existing check forshape.verts.empty()only skips rendering but doesn't prevent potential issues earlier in the logic flow.Potential Null Pointer Dereference in Cloth Setup
In
dressUp(), when setting up cloth garments (skirts), the code accessesm_pack->groups()[static_cast<size_t>(g)]without verifying thatgis within valid bounds or that the group exists. Ifm_pack->findGroup(shape.group)returns a negative value (which it does when not found), the subsequent access tom_pack->groups()[g]will cause undefined behavior or a crash.Race Condition in Clothes Update Logic
The
update()function checksm_clothesDirtyand callsdressUp()after a delay (m_sinceEdit > 0.35f). However, if a user rapidly changes clothes or body sliders while the delay is active, multiple updates could occur in quick succession, potentially causing inconsistent state where clothes are dressed on an outdated body shape. The lack of synchronization between the dirty flag and the actual body reshape could lead to visual glitches or incorrect garment fitting.Missing Error Handling for Garment Shape
The
garmentShapefunction returns an emptyGarmentShapeif the garment ID is not found or if the shaped vector size doesn't match. However, the calling code indress(line 207) does not check for this empty shape before proceeding to create meshes. This could lead to undefined behavior or crashes if a garment ID is requested that doesn't exist in thegarments()list.Potential Out-of-Bounds Access in skinUnder
In the
skinUnderfunction (lines 169-183), the loop iterates overgarment.vertices.size(). Inside the loop, it accessesskin.vertices[s]wherescomes from iterating overskin.vertices.size(). Ifskin.verticesis empty (checked at line 171), the function returns early. However, ifskin.verticesis not empty but smaller thangarment.vertices, the inner loop conditiondd < bestwill eventually accessskin.vertices[s]wheresmight be out of bounds if the logic for finding the closest vertex doesn't guarantees < skin.vertices.size(). Specifically,under[i] = static_cast<uint32_t>(s)assignssdirectly without checking ifsis within the valid range ofskin.vertices.Hardcoded Limit on Clothes in Share Code
The
shareCodefunction (line 177) limits the number of clothes items encoded to 16 (std::min<size_t>(look.clothes.size(), 16)). While this prevents buffer overflows, it silently truncates any outfit with more than 16 items. This could lead to data loss when sharing complex outfits, as the extra clothes would be lost during reconstruction. It's unclear if there's a legitimate reason for this limit or if it should be increased or removed.Missing Dependency Check for OpenEXR
The script
bake_vitruvian.pyimportsOpenEXRat the top (line 36) without checking if it's installed. If a user runs the script without havingOpenEXRinstalled, the script will crash immediately with an ImportError. It's better to provide a clear error message or check for the dependency before attempting to use it.Missing include for std::move
The file uses
std::movein thesetStylemethod (line 55) but does not include<utility>. This will cause a compilation error. The fix is to add#include <utility>which is already present in the diff at line 11, so this is actually resolved. However, I should verify if there are any other missing includes. Upon re-examination, the include is added, so no issue here.Potential resource leak or undefined behavior in garmentMesh
The function
garmentMesh(lines 55-56) takes a pointerfromwhich is optional. If the caller passes a non-null pointer and expects it to be populated with vertex mappings, but the implementation doesn't guarantee filling it correctly for all cases, it could lead to incorrect vertex mapping when garments are skinned. The documentation mentions "from (optional): garment vertex -> bake vertex", but without seeing the implementation, we cannot confirm if this mapping is always correctly computed. This could cause visual artifacts or incorrect skinning if the mapping is incomplete.Missing error handling in addIrises and addBrows
The functions
addIrisesandaddBrowsreturn a bool indicating success or failure (e.g., when the model has no eyes). However, the callers in the character creator module (not shown in the diff) might not check this return value, leading to silent failures where eyes or brows are not added. While the PR description mentions these functions exist, the lack of explicit error handling in the API design could lead to runtime issues if not properly checked by consumers.ℹ️ Chunked review: the diff exceeded the model token budget, so it was reviewed in 3 chunks and the per-chunk results were merged.
PR Code Suggestions ✨
No code suggestions found for the PR.
🧹 Lint report · ❌ 38 problems in 6 checks · 🧹 3 formatting checks to tidy
Nothing here blocks the merge (report only).
MARKDOWN · markdownlint: first lines of the output
CPP · cppcheck: first lines of the output
YAML · yamllint: first lines of the output
BASH · shellcheck: first lines of the output
DOCKERFILE · hadolint: first lines of the output
REPOSITORY · trivy: first lines of the output
🧹 Formatting only (layout, no behaviour; the nightly lint-fix job applies these as a PR): YAML · prettier (57 files checked), BASH · shfmt (11 files checked), JSON · prettier (147 files checked)
✅ Clean: actionlint, git_diff, gitleaks, grype, jsonlint, secretlint, stylelint, trufflehog, xmllint
MegaLinter on soucouyant · full logs in the Actions run · comment
/improvefor AI fix suggestionsView command line instructions
Checkout
From your project repository, check out a new branch and test the changes.