Ktisis icon indicating copy to clipboard operation
Ktisis copied to clipboard

Correct Handling of Partial sklbs with >1 Root Bone

Open sleepybnuuy opened this issue 10 months ago • 0 comments

Issue

via two different discord issue reports, Ktisis has historically failed to handle propagating bone transform changes to portions of partial extra skeletons which have more than 1 root node or binding point. propagation is applied to all bones in the partial skeleton when transforming the first-identified root node in the partial, and does not apply when transforming bones that should parent/propagate to those in the partial related to any latter root nodes. this behavior is present on v0.3 and main branch

this can be observed with the extra sklb loaded by the Far Eastern Schoolgirl's and Schoolboy's Hakama, as well as any other sklbs which define multiple root nodes (usually used with long-sleeved gear for physics)

Gap

HavokPosing's interpretation of partial skeletons assumes:

  • a partial will only have one bind point to the parent skeleton; i.e. only one entry in ParentIndices for a partial will have a -1 value
  • the singular binding node will be at index 0 of hkaSkele->ParentIndices with a value of -1
  • so long as a partial's bind point is a descendant of the boneIx being manipulated in the parent skeleton, all bones defined by the partial must be descendants of boneIx and propagate accordingly

Fix

to avoid rewriting the entire HavokPosing file or establishing a completely new way of handling child-parent bone relations (ala VFXEdit's use of LayerOffset values to determine roots/priority, or brio's custom mapping into bone relationships), this commit:

  • adds helpers to determine when a given sklb has >1 root node (determined by multiple -1 values in hkaSkeleton->ParentIndices)
  • checks for a multi-root skeleton before running the parent < 1 shortcut in IsBoneDescendantOf()
  • allows Propagate() to trigger a partial propagate onto either a single-root partial or a multi-root partial
    • single-root logic is unchanged
    • multi-root logic evaluates the following for each bind point in a multi-root sklb:
      • if the bone being posed is a hierarchical parent of this root bone on the parent skeleton, call Propagate on this subPose for the partial index
      • if the bone being posed IS the root bone (determined by name comparison btwn partial and parent skeleton), call Propagate

Addtl Fixes

  1. correct a NullReference exception which can occur from HavokPosing when a partial skeleton index exists but has no data behind it due to the character having changed gear, but not fully reinstanced/cleaned out partial data. if a null subPartial is identified in Propagate, should be skipped to prevent jitters and error throws - https://discord.com/channels/975894364020686878/1004359659613859910/1233494906547474523
  2. prevents BoneEnumerator from adding an additional copy of a multi-root partial skeleton's secondary/tertiary binding bones in the same hierarchy position as the main skeleton's version of that bone. multi-roots should now correctly parent both/all sections to the root skeleton, rather than just one (thanks Cordelia for showing me this) - https://discord.com/channels/975894364020686878/1004359659613859910/1233279681915125771

sleepybnuuy avatar Apr 22 '24 23:04 sleepybnuuy