Download

C++ AnimGraph - Modify transform on array of bones

Hi all,

i’m working on game from some times, and i switched to C++ because i need specifics customs functionnality.
But thoses days i have a problem with modify an array of bones from my custom Anim Graph, let me explain:

I want modify rotation many spine bones (an array of bones), thoses bones wil lcopy with RInterpTo the **Effector **bone (to do dynamic dragon snake tail interpolation).

Like i see in source code for Transform Modify and Spline IK, the update it’s writing in


EvaluateSkeletalControl_AnyThread

The rotation work perfectly today, but the true problem it’s about update **Joint **position from parent bone of each bone iteration.

As i update an array of bones with the **OutBoneTransforms **FBoneTransform array, i think the component space don’t enought update the new bone transformation as long as we are in the **EvaluateSkeletalControl_AnyThread **function. So we need to recalculate new Joint bone from parent bone.

I’m insipired of **SplineIk **and **TwoBoneIk **to stuff it, but, there are things that escapes me (i have some many bugs with several try).
Usually I find the solution shortly with Google Search and Documentation, but i don’t find any solution in Forums and some web sites yet. :frowning:

**Reference of TwoBoneIK.cpp who try to updtae joint post of LowerClimb : **

I saturate on these calculations, that’s why I post here to have your lights / tips, can you help me please ? ^^

Sorry for this long text to read !

It’s the update transform part code :



// Effect it's the head bone in this exemple
FCompactPoseBoneIndex CompactEffectorPoseBoneToModify = Effector.GetCompactPoseIndex(BoneContainer);
// -- used for read only
const FTransform EffectorBoneTransform = Output.Pose.GetComponentSpaceTransform(CompactEffectorPoseBoneToModify);

// Last bone transform (the parent of current bone in for each)
FTransform InitialLastBoneTransform = EffectorBoneTransform;
FTransform LastBoneTransform = EffectorBoneTransform;

// For each child bone stored in my custom struct
for(MyCachedBone& CurrentCachdBone : MyCachedBoneList)
{
    // Get current compact bone to modify
    FCompactPoseBoneIndex CurrentCompactPoseBoneToModify = CurrentCachdBone.Bone.GetCompactPoseIndex(BoneContainer);
    // -- used for read only
    const FTransform CurrentBoneTransform = Output.Pose.GetComponentSpaceTransform(CurrentCompactPoseBoneToModify);
    // -- used for modification
    FTransform NewBoneTM = CurrentBoneTransform;
    FTransform ComponentTransform = Output.AnimInstanceProxy->GetComponentTransform();

    // =================================================
    // -- ROTATION PART
    // =================================================
    // Convert to Bone Space.
    FAnimationRuntime::ConvertCSTransformToBoneSpace(ComponentTransform, Output.Pose, NewBoneTM, CurrentCompactPoseBoneToModify, RotationSpace);

    // -- Update Rotation Transform
    const FQuat BoneQuat(NewRotation);
    NewBoneTM.SetRotation(BoneQuat);

    // Convert back to Component Space.
    FAnimationRuntime::ConvertBoneSpaceTransformToCS(ComponentTransform, Output.Pose, NewBoneTM, CurrentCompactPoseBoneToModify, RotationSpace);

    // =================================================
    // -- LOCATION PART
    // =================================================
     // Convert to Bone Space.
    FAnimationRuntime::ConvertCSTransformToBoneSpace(ComponentTransform, Output.Pose, NewBoneTM, CurrentCompactPoseBoneToModify, TranslationSpace);

    // -- Update Translation Transform
    FVector FinalJoinPos = LastBoneTransform.GetTranslation();

    // Calcul length of joint
    float BoneLength = (CurrentBoneTransform.GetTranslation() - InitialLastBoneTransform.GetTranslation()).Size();

    // -- TODO
    // will modify FinalJoinPos from some formula etc...
    // ... Some stuff ...

    // -- Apply final translation
    NewBoneTM.SetTranslation(FinalJoinPos);

    // Convert back to Component Space.
    FAnimationRuntime::ConvertBoneSpaceTransformToCS(ComponentTransform, Output.Pose, NewBoneTM, CurrentCompactPoseBoneToModify, TranslationSpace);

    // =================================================
    // -- Apply transform and update next var
    // =================================================
    // Apply nexw transform
    OutBoneTransforms.Add( FBoneTransform(BoneToModify.GetCompactPoseIndex(BoneContainer), NewBoneTM) );

    // Finally update last transform
    LastBoneTransform = NewBoneTM;

    // And update last initial bone transform for next child
    InitialLastBoneTransform = CurrentBoneTransform;
}


i would love to have your help,

Best regards :smiley:

Hi all,

Finally with more tests and research, i found a Korean web site which use


Output.Pose.LocalBlendCSBoneTransforms(Transform, 1.0f);

to keep offset for each bone !

I don’t need to set translation, can only use rotation transform in a foreach iterations from cached bone list :slight_smile:

S i don’t use


OutBoneTransforms.Add(FBoneTransform(CompactCurrentPoseBoneToModify, NewBoneTM));

but i write this for each iterations :


       
        // Workaround ensure our rotations are offset for each bone
        CachedTransformList.Add(FBoneTransform(CachedBoneData.Bone.GetCompactPoseIndex(BoneContainer), NewBoneTM));
        Output.Pose.LocalBlendCSBoneTransforms(CachedTransformList, 1.0f);
        CachedTransformList.Reset();


I share this for those who were in the same situation as me, hope that it helps you :smiley:

Have good days !

Can you share how you added your C++ code to be executed by the anim instance?
EvaluateSkeletalControl_AnyThread is part of the anim nodes but how did you get it into the anim instance in C++?

Thanks!

Hi !

I just made Anim Graph Node in C++ but used in Blueprint. I have “AnimNode_DUTransformBone” and “DUAnimGraphNode_ModifyBone”.

If you want see the code i uploaded here for you: https://drive.google.com/open?id=1FKfShj84pxiksQmISQ2RLQYa5d7Zf4Dq

Have a good days !

@D-Zak Ah I see, thank you good sir!