Character creator screen and demo (MakeHuman) #116
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "khyretos/claude/character-creator"
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?
Builds on the human pack PR (branch claude/human-pack): merge that first; this one then shows only its own commit.
What changes
kke::CharacterCreatorModule: a character creator screen any game can add (RmlUi,assets/ui/character_creator/). Tabs of about 300 sliders (body type, shape, torso, arms and legs, head and neck, eyes, nose, mouth and jaw, ears, skin), mirrored sides, undo/redo, a believable randomise, Body/Face/Profile/Back/turntable views, save/load (.kkhumanJSON), copy/paste share code. While a slider moves only vertices move (setDeformedVertices);bakeSkinned()gives the game a skinned, animatable body.kke/HumanLook.h: the look that travels in multiplayer. Only slider values and colours, as a share code (kh1.+ base64url: one bit per slider plus a byte per moved one; about 90 to 250 letters), tied to the pack's slider list.quantised()rounds the local player like the code so every machine bakes the same vertices. Also reads MakeHuman.mhmsaves.Human: feet on the floor (y = 0), macro-shape cache,setAll.games/character_creator: the demo; added to the headless smoke tests (both CI files) plus a self-test (KKE_CREATOR_SELFTEST=1: random person → share code → back, must be identical and on the floor). The self-test found two codes for one look; fixed, with a unit test.How I verified it
./build/bin/kke_tests: 1257 passed-Wall -Wextra -O2 -Werrorcharacter_creatorunder Xvfb + lavapipe withVK_LAYER_KHRONOS_validationand sync validation: no errors; self-test passed on repeated runsPerformance
Dragging a slider re-shapes ~19k vertices on the CPU and uploads them; no new buffers. In a game the body is one skinned model like any other.
Docs
UI change: holds for Kees's look-OK on the screenshots before merging.
🤖 Generated with Claude Code
https://claude.ai/code/session_014ehJmtmmZLukS7FKi1aYb6
Title
Character creator screen and demo (MakeHuman)
User description
Builds on the human pack PR (branch claude/human-pack): merge that first; this one then shows only its own commit.
What changes
kke::CharacterCreatorModule: a character creator screen any game can add (RmlUi,assets/ui/character_creator/). Tabs of about 300 sliders (body type, shape, torso, arms and legs, head and neck, eyes, nose, mouth and jaw, ears, skin), mirrored sides, undo/redo, a believable randomise, Body/Face/Profile/Back/turntable views, save/load (.kkhumanJSON), copy/paste share code. While a slider moves only vertices move (setDeformedVertices);bakeSkinned()gives the game a skinned, animatable body.kke/HumanLook.h: the look that travels in multiplayer. Only slider values and colours, as a share code (kh1.+ base64url: one bit per slider plus a byte per moved one; about 90 to 250 letters), tied to the pack's slider list.quantised()rounds the local player like the code so every machine bakes the same vertices. Also reads MakeHuman.mhmsaves.Human: feet on the floor (y = 0), macro-shape cache,setAll.games/character_creator: the demo; added to the headless smoke tests (both CI files) plus a self-test (KKE_CREATOR_SELFTEST=1: random person → share code → back, must be identical and on the floor). The self-test found two codes for one look; fixed, with a unit test.How I verified it
./build/bin/kke_tests: 1257 passed-Wall -Wextra -O2 -Werrorcharacter_creatorunder Xvfb + lavapipe withVK_LAYER_KHRONOS_validationand sync validation: no errors; self-test passed on repeated runsPerformance
Dragging a slider re-shapes ~19k vertices on the CPU and uploads them; no new buffers. In a game the body is one skinned model like any other.
Docs
UI change: holds for Kees's look-OK on the screenshots before merging.
🤖 Generated with Claude Code
https://claude.ai/code/session_014ehJmtmmZLukS7FKi1aYb6
PR Type
Enhancement, Tests, Documentation
Description
Adds character creator screen with sliders and views
Implements Human class for skinned models and packs
Introduces share codes and MakeHuman pack support
Includes demo app, unit tests and CI validation
Diagram Walkthrough
File Walkthrough
12 files
Implements character creator screen with sliders, views, save/load andshare codesAdds feet-on-floor positioning, macro-shape cache and setAll for wholelooksParses MakeHuman CC0 human pack file format with positions, targets,bones and modifiersImplements JSON saves, MakeHuman .mhm reads and short share codes forcharacter looksCreates demo application showing the character creator modulestandaloneDefines HumanPack data structures for positions, quads, targets, bonesand modifiersCooks MakeHuman CC0 data into a .kkhpack binary formatAdds CharacterCreatorModule with sliders, views and share codesImplements Human class to blend morph targets into skinned modelsDefines HumanLook struct and functions for multiplayer share codesStylesheet for the character creator UI with night themeRML layout for the character creator screen with tabs and sliders4 files
Adds unit tests for human pack loading, two-sided sliders, ancestrysums and share codesAdds character_creator to CI smoke test loop under validation layersUnit tests for the human pack cooker and readerAdds CI job to run cooker tests and character creator self-test8 files
Registers character_creator as a reserved game name in the new gametoolRegisters MakeHuman assets and creator screen in dependencies listAdds kke_use_character_creator function and character_creator demoAdds Humans and Character Creator pages to navigationCredits file listing MakeHuman authors and CC0 licenceAdds Human and CharacterCreatorModule source files to engine buildCMakeLists for character_creator demo linking engine and UIAdds test_human.cpp unit tests to kke_tests executable6 files
Documents the MakeHuman integration, pack format and creator screenUpdates roadmap to mark Humans feature as in progressREADME for the character creator demo with controls and build notesLinks character_creator demo in demos index pageLists character_creator demo in main README tableLinks HUMANS.md in docs README sidebar4 files
PR Reviewer Guide 🔍
📋 Focus areas: 🔴 6 open · ✅ 0 handled. Every push re-checks them; a handled area moves to Resolved findings at the bottom.
Missing Error Handling for Save Path
In the
save()function, ifSDL_GetPrefPathreturnsnullptr, the code returns early without setting a status message. This leaves the user unaware that the save operation failed due to missing preferences directory. Theload()function has similar behavior but at least logs "No saved character yet". Thesave()function should log an error or set a status message when the path is empty.Potential Null Pointer Dereference
In the
update()function, line 476 checks if a slider name matches ancestry macros and then iterates overm_slidersto update their values. However, ifm_slidersis empty (e.g., if no modifiers match the current tab), this loop will not execute, which is fine. But more critically, on line 486,setView(m_view)is called unconditionally after checkingm_shapeDirty. Ifm_viewwas never initialized or cleared unexpectedly, it might cause issues, though it's initialized ininit(). A more significant concern is thatm_orbitis used on line 486 without a null check before callingsetView, althoughsetViewitself checks for!m_orbiton line 520. The real issue is thatm_viewis accessed directly without ensuring it's valid in all contexts, but since it's initialized ininit(), this is less critical. The main issue is the lack of bounds checking or validation when accessingm_slidersin the ancestry update block.Division by Zero Risk
In the
jointPosition()function, line 270 divides byit->second.size(). If a joint has no associated vertices (empty vector), this will cause a division by zero, resulting in undefined behavior (NaN). While this might be a rare edge case, it's better to add a check to ensure the size is greater than zero before performing the division.Potential Integer Overflow in Base64 Encoding
In the
base64urlfunction, the variablenis constructed by shifting three bytes into auint32_t. While this fits within 32 bits, the subsequent bitwise operations and shifts are performed on this value. If the input vector contains more than 3 elements, the logic correctly processes them in chunks of 3. However, if the input size is not a multiple of 3, the padding logic for the output string is incomplete. The function does not append '=' padding characters as per standard Base64 encoding when the input length modulo 3 is 1 or 2. This could lead to incorrect decoding in strict parsers that expect padding, although the customunbase64urlfunction handles missing padding gracefully by checking bit counts. A more robust implementation should explicitly handle padding to ensure compatibility with standard decoders.Missing Error Handling for Non-UTF8 Strings
In the
read_objfunction, the file is opened withencoding="utf-8". If the OBJ file contains non-UTF8 characters (e.g., binary data or special symbols not in UTF-8), theopencall will raise aUnicodeDecodeError. While this stops execution, it does not provide a clear error message indicating whether the issue is with the file format or encoding. It would be better to catch this exception and provide a more descriptive error message, or validate the file encoding before attempting to read it.Hardcoded Step Size Assumption
The
quantisefunction assumes that all target offsets are exact multiples ofSTEP = 0.001. While this is documented in the code comments, there is no validation in thecookfunction to ensure that all.targetfiles adhere to this precision before quantization occurs. If a.targetfile contains an offset that is not a multiple of 0.001 (within floating-point tolerance), thequantisefunction will raise aValueError. This error handling is present but could be improved by providing a clearer warning or allowing for a fallback mechanism if the precision requirement is violated, rather than failing the entire cook process.ℹ️ 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 (56 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 suggestions