WIP: Anime style: VRoid's CC0 avatars drawn in the gacha style #135
Draft
khyretos
wants to merge 1 commit from
khyretos/claude/creator-anime into claude/creator-clothes
AGit
pull from: khyretos/claude/creator-anime
merge into: khyretos:claude/creator-clothes
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!135
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "khyretos/claude/creator-anime"
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
Stacked on the clothes PR #134 (base
claude/creator-clothes) and on PR 108 (glTF import, merged). One commit, cherry-picked onto the rebased clothes branch without conflicts.WIP: visual work. Kees's look-OK on the anime style is needed before merging; merge #134 first, then drop the WIP prefix.
Kees: the old anime mode (the realistic body toon-shaded) read as a cartoon, not as an anime game. The anime style is now its own body and its own renderer; the two styles only share bone names (kke::AnimRig).
What it adds
kke/Vrm.h,src/Vrm.cpp:loadVrmreads VRM 0.x (mesh/skeleton via the glTF import; face morph targets and expressions; MToon materials; spring bones and colliders; humanoid map; licence fields), turned to face +Z. CPUpose()with expressions.kke/VrmSprings.h: VRM 0.x spring bones in world space (hair, skirts), with collider spheres.kke/AnimeRenderer.h: MToon pushed to the gacha look: hard two-tone light, the face lit as one shape (head-sphere normals, no cast shadows on the face), coloured outlines along seam-averaged normals, rim light, hair angel ring, blended parts last, shadow casting. Shadersanime*.vert/frag,anime_common.glsl.assets/anime/HairSample_Female.vrm/HairSample_Male.vrm(VRoid Project, CC0 per VRoid's help page and the files' VRM licence fields) by the Gender slider, blinking, breathing, hair on spring bones.KKE_CREATOR_EXPRESSIONfor screenshots.Note: the two .vrm files are 18 MB each.
Tests
Vrm.ReadsTheAvatarItsFaceAndItsMaterials,Vrm.FacesPlusZ,Vrm.BlinkClosesTheEyes,VrmSprings.HairSwingsWhenTheFigureTurnsAndSettleskke_testson the rebased branch: 1346 passedKKE_CREATOR_STYLE=anime, female and male avatar: passed, VRM loaded without warningsUI change: holds for Kees's look-OK on the screenshots before merging.
🤖 Generated with Claude Code
https://claude.ai/code/session_014ehJmtmmZLukS7FKi1aYb6
Title
WIP: Anime style: VRoid's CC0 avatars drawn in the gacha style
User description
Requested by Kees · project thread
Stacked on the clothes PR #134 (base
claude/creator-clothes) and on PR 108 (glTF import, merged). One commit, cherry-picked onto the rebased clothes branch without conflicts.WIP: visual work. Kees's look-OK on the anime style is needed before merging; merge #134 first, then drop the WIP prefix.
Kees: the old anime mode (the realistic body toon-shaded) read as a cartoon, not as an anime game. The anime style is now its own body and its own renderer; the two styles only share bone names (kke::AnimRig).
What it adds
kke/Vrm.h,src/Vrm.cpp:loadVrmreads VRM 0.x (mesh/skeleton via the glTF import; face morph targets and expressions; MToon materials; spring bones and colliders; humanoid map; licence fields), turned to face +Z. CPUpose()with expressions.kke/VrmSprings.h: VRM 0.x spring bones in world space (hair, skirts), with collider spheres.kke/AnimeRenderer.h: MToon pushed to the gacha look: hard two-tone light, the face lit as one shape (head-sphere normals, no cast shadows on the face), coloured outlines along seam-averaged normals, rim light, hair angel ring, blended parts last, shadow casting. Shadersanime*.vert/frag,anime_common.glsl.assets/anime/HairSample_Female.vrm/HairSample_Male.vrm(VRoid Project, CC0 per VRoid's help page and the files' VRM licence fields) by the Gender slider, blinking, breathing, hair on spring bones.KKE_CREATOR_EXPRESSIONfor screenshots.Note: the two .vrm files are 18 MB each.
Tests
Vrm.ReadsTheAvatarItsFaceAndItsMaterials,Vrm.FacesPlusZ,Vrm.BlinkClosesTheEyes,VrmSprings.HairSwingsWhenTheFigureTurnsAndSettleskke_testson the rebased branch: 1346 passedKKE_CREATOR_STYLE=anime, female and male avatar: passed, VRM loaded without warningsUI 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 VRM 0.x loader for anime avatars
Implements MToon gacha renderer with outlines
Simulates spring bones for hair and skirts
Includes tests for loading and animation
Diagram Walkthrough
File Walkthrough
13 files
VRM 0.x loader: mesh, skeleton, morphs, expressions, MToon, springsAnime style integration: VRoid avatars, spring bones, rendererAnimeRenderer: MToon gacha look, face sphere normals, outlines, rimlightVrmSprings: CPU spring bone simulation for hair and skirtsAnime fragment shader: two-tone light, face sphere, rim, angel ringShared push constants and uniforms for anime rendering pipelineOutline shader: coloured line art from shade colour or fixed toneOutline vertex shader: hull expansion along seam-averaged normalsAnime vertex shader: transforms posed vertices to world spaceVrmAvatar, VrmToon, VrmSpringGroup structs and loadVrm functionAnimeRenderer class: materials, parts, update/draw methodsCharacterCreatorModule: anime flags, VRM and spring bone membersVrmSprings class: joint simulation and step/reset methods2 files
Tests for VRM loading, facing +Z, blinking, and spring bonesAdded test_vrm.cpp to test suite4 files
Documentation for anime style, VRM avatars, springs and rendererAdded VRoid sample avatars to dependencies listReplaced old anime style description with VRoid avatars infoUpdated character creator README to reflect new anime style2 files
CMake: copy anime VRMs and add anime shaders to buildAdded VRM and AnimeRenderer source files to build2 files
PR Reviewer Guide 🔍
📋 Focus areas: 🔴 7 open · ✅ 0 handled. Every push re-checks them; a handled area moves to Resolved findings at the bottom.
Missing Error Handling for Texture Loading
In the
readToonfunction, texture paths are resolved using a lambda that returns an empty string if the texture is not found. Later inAnimeRenderer::build, these empty strings are used to select fallback textures. However, if a critical texture (like the main albedo) is missing and the fallback logic doesn't handle it correctly, the shader might receive invalid or uninitialized data, leading to rendering artifacts or crashes. The code should explicitly validate that required textures are present before proceeding with material setup.Potential Null Pointer Dereference
In the
showAnimeBodyfunction,m_vrm->bone(bone)is called without checking ifm_vrmis valid first. Althoughm_vrmis initialized just before this call viastd::make_unique<VrmAvatar>(loadVrm(file)), there is a risk ifloadVrmthrows an exception and the catch block returns early without properly initializingm_vrm. The subsequent calls tom_vrm->expressions.size()and other methods could lead to undefined behavior ifm_vrmis not properly set up.Hardcoded Magic Numbers in Shader Logic
The shader
anime.fraguses hardcoded magic numbers like0.22,0.30,0.42,0.52,0.1,0.4for the angel ring effect. These values are not configurable and may need adjustment for different hair styles or lighting conditions. It would be better to parameterize these values through uniform buffers or push constants for easier tuning.Infinite Loop Risk in Spring Simulation
In the
substepfunction, the simulation step size is clamped to0.25fto prevent flinging. However, ifdtis extremely large (e.g., due to a frame drop), the number of substeps calculated asceil(dt * 30.0f)could still result in a very large number of iterations, potentially causing performance issues or numerical instability. Adding a maximum limit on the number of substeps would mitigate this risk.Missing Collider Sphere Initialization
The
VrmSpringsclass declares a memberm_spheresto store collider spheres for collision resolution, but the constructor and initialization logic are not visible in the diff. If this vector is left empty or uninitialized, the spring bone solver will fail to push tails out of colliders, causing hair and skirts to intersect with the body incorrectly. This needs verification thatm_spheresis populated from the VRM file's collider data during construction.Potential Resource Leak on Destruction
The
AnimeRendererclass holdsstd::unique_ptr<Buffer>members (indices,params) and aFrameDataarray containing averticesbuffer. While the destructor is declared, the diff does not show the implementation. If these buffers are not explicitly freed or if theuploadmethod leaks memory by not cleaning up previous frame data before uploading new data, it could lead to memory leaks over time, especially since the renderer is updated every frame.Missing Expression Update Logic
The
CharacterCreatorModulestoresm_expressionsand callsposeAnime, but the diff does not show the implementation ofposeAnime. If the expression weights are not correctly applied to the VRM avatar's morph targets during the pose update, facial animations (blinking, talking) will not work as intended. Ensure the mapping betweenm_expressionsandVrmAvatar::weightsis correct.ℹ️ Chunked review: the diff exceeded the model token budget, so it was reviewed in 2 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.Merge
Merge the changes and update on Forgejo.Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.