アニメーションノードによるボーン補正について

お世話になっております。

C++で、FAnimNode_ConvertLocalToComponentSpace、FAnimNode_ModifyBone、FAnimNode_ConvertComponentToLocalSpace を一つにまとめたアニメーションノードを作成しております。

アニメーションBPで一通りのアニメーションを行った後、最後にこの自作ノードを通ることで、任意のボーンに補正を加えることを目的としており、例えばAという名前のボーンをX軸で10度だけ回転をかけたいといった時に使用します。

またFAnimNode_ModifyBoneのTranltion、RotationといったパラメータをUpdate_AnyThread関数内で外部から取得し再設定できるようにすることでリアルタイムに補正値を調整できるようにしています。

例)モーションの開始時はX軸で20度、徐々に補正値を増加させて終了時にはX軸で30度補正されるようにする

一通りの実装を行い、実際に動作させた所、上記の例でいうところのAボーンが自作ノードに至るまでの間で諸々のアニメーションの影響を受けていない場合は想定した動きになったのですが、例えばモーションデータでAボーンが既に動いてしまっている場合、意図しない動きになってしまいました。

現在原因を探っている最中ではあるのですが、そもそもの方法として、こういったC++の自作ノードでボーンの姿勢(Transform、Matrix)を直接上書きする方法はございますでしょうか。
一応DebugDrawLine等で、自前で演算した補正後の姿勢情報自体は正しいことが確認できている為、そのまま利用する事はできないかと…。

また仕様のご確認となるのですが、例えば RotationSpace=BCS_BoneSpace、RotationMode=BMM_Additive とした場合、「加算」の対象はどの情報となるのでしょうか。
かろうじて正常動作している「アニメーションしていないボーン」に対して動作確認を行った際、BMM_Replaceと結果に差異が見当たらず、疑問に思っております。

以上、よろしくお願いいたします。

お世話になっております。自作の独自AnimNodeをC++によって作成されているライセンシー様はいらっしゃるので、なにか問題が別で起きているのかと思われます。ただ、恐縮なのですが教えて頂いた情報から何がデータを狂わせているのか疑わしいものを想像できず、ご指摘することができません。

直接上書きする方法としましては、おっしゃれれているようなFAnimNode_ModifyBoneのBMM_Replaceでの実装が参考になるかと思います。BMM_Addtiveの際に「アニメーションしていないボーン」がBMM_Replaceと差異がないのは正しい挙動かと思います。以下の様に、BMM_Additiveはオリジナルのそのノードに入ってくるBoneのTransformに対して加算を行いますが、ボーンがアニメーションしていないため、こちらのオリジナルのノードのTransform(Rotation)が0となることから、Replaceの場合と挙動が同様になるのだと思います。

ご参考になれば幸いです。

お世話になっております。

失礼いたしました。
計算上座標系をParentBoneSpaceにしなければいけないところをBoneSpaceのままで処理してしまっておりました。

Replaceパラメータと組み合わせて、ひとまず想定した動作を実装することができました。

また下記の件、承りました。

BMM_Addtiveの際に「アニメーションしていないボーン」がBMM_Replaceと差異がないのは正しい挙動かと思います。以下の様に、BMM_Additiveはオリジナルのそのノードに入ってくるBoneのTransformに対して加算を行いますが、ボーンがアニメーションしていないため、こちらのオリジナルのノードのTransform(Rotation)が0となることから、Replaceの場合と挙動が同様になるのだと思います。

ご対応ありがとうございました。

もしも本ノードを用いたサンプルを頂けるならば、そちらを見たほうが早そうですが、そちらは可能でしょうか?

また一応のご確認なのですが、今回ご提示頂いている疑似コードの前に

SourcePose.Evaluate(Output)

の様なSourcePoseのEvaluationが呼ばれているということでよろしかったでしょうか?

情報ありがとうございます。ComponentToLocalNodeが何か理解していなかったため、サンプルをちょうだいできないかお伺いしていましたが、頂いたリンクで実装内容を理解できました。

はい。問題ないかと思われます。ComponentToLocalNodeによってEvaluateが呼び出される前に、実際の入力であるSourcePoseのEvaluateが呼び出され適切にBone計算がされてます。ComponentToLocalNodeによるEvaluateが呼び出さrても、二重にSourcePoseのEvaluateが計算されることはなく、初回のもののキャッシュされたBoneが返ってくるので問題ないはずです。

お世話になっております。

当初の不具合は解決したのですが、実装を通じて不明な点がでてきた為、追加のご質問をさせていただきたいと思います。
内容的に別途ご質問をしたほうが良ければその旨お申し付けください。

現在、下記のようなアニメーションBPが組まれており、Custom Transformノードが当該のC++で作成しているカスタムノードに当たります。

またCustom Transfornの中でやっていることはBPにすると下記のような事となります。

Update_AnyThread(const FAnimationUpdateContext& Context)

Evaluate_AnyThread(FPoseContext& Output)
におきまして、Output.AnimInstanceProxyやOutput.Poseなどを介して、ボーンの姿勢情報(FTransform、FMatrix)を取得しております。

例)
FTransform Transform1 = Output.Pose.GetBoneContainer().GetRefPoseCompactArray()[tmpPoseBoneIndex];
FTransform Transform2 = Output.Pose.GetBoneContainer().GetReferenceSkeleton().GetRefBonePose()[tmpPoseBoneIndex];
FTransform Transform3 = Output.Pose.GetBones()[tmpPoseBoneIndex];
FCSPose CSPose;
CSPose.InitPose(Output.Pose);
FCompactPoseBoneIndex CompactPoseBoneToModify = Output.Pose.GetBoneContainer().GetCompactPoseIndexFromSkeletonIndex(tmpSkeletonBoneIndex);
FTransform Transform4 = CSPose.GetLocalSpaceTransform(CompactPoseBoneToModify);

しかし、その際上記の方法で取得される姿勢情報はステートマシンやスロットによるモーションが反映されていないボーンの姿勢情報が取得されている(どのタイミングで取得しても同じ値が変える)ようなのですが、この認識は正しいでしょうか。
またその場合、カスタムノードにはいってきたタイミングのボーンの姿勢情報(モーションが反映された状態)を取得する正しい方法をご教授いただけませんでしょうか。

ちなみにカスタムノードのEvaluate_AnyThread(FPoseContext& Output)で、

// ComponentToLocalNodeはカスタムノードで定義されているFAnimNode_ConvertComponentToLocalSpaceクラスのオブジェクト
ComponentToLocalNode.Evaluate_AnyThread(Output);

をコールした後のOutputを参照した場合、上記例のTransform3とTransform4にはモーションが反映された姿勢情報が返るようです。しかしComponentToLocalNode.Evaluate_AnyThreadをコールする前に、その情報を取得したく…

よろしくお願いいたします。

もしも本ノードを用いたサンプルを頂けるならば、そちらを見たほうが早そうですが、そちらは可能でしょうか?

ちょっと状況的に難しく…、申し訳ございません。

ただ、やっていることは下記のサイトで紹介されている内容をほぼほぼそのままです。

ですので、Evaluate_AnyThread(FPoseContext& Output)の中でやっていることは

ComponentToLocalNode.Evaluate_AnyThread(Output);

だけで

SourcePose.Evaluate(Output)

といったことはやっておりません。

試しにComponentToLocalNode.Evaluate_AnyThread より前にこちらをコールしてみたところ、前述例のtransform3とtransform4にモーション反映済の姿勢情報が返るようになりました。

このことで自分の要望は解決したことになるのですが、使い方(コールするタイミング等)はこれで問題ございませんでしょうか。

よろしくお願いいたします。

はい。問題ないかと思われます。ComponentToLocalNodeによってEvaluateが呼び出される前に、実際の入力であるSourcePoseのEvaluateが呼び出され適切にBone計算がされてます。ComponentToLocalNodeによるEvaluateが呼び出さrても、二重にSourcePoseのEvaluateが計算されることはなく、初回のもののキャッシュされたBoneが返ってくるので問題ないはずです。

承りました。ありがとうございます。