-1

Collada ファイルに保存されている骨格アニメーションを使用してスキニングを実装しようとしています。それを読み込んで正しくスキニングせずにモデルをレンダリングすることはできましたが、スキニング アルゴリズムを適用するとすべてのパーツがまとまってしまう理由がわかりません。モデルの足元、または極端に変形しています。プロジェクト全体は、参照用にGitHubに保存されています (スキン ブランチ)。

恒等変換をボーンに渡すとデフォルトのポーズ モデルが得られるので、頂点シェーダーは正しいと思います。ファイル内の骨格アニメーションに基づいてボーン変換が計算されますが、これは.dae何らかの形で壊れています。これは、モデルがデフォルトのポーズでどのように見えるかに対して、私の問題がどのように見えるかです:

スキニングあり スキニングなし

私の問題は、再帰的な骨の変換を適用しているときにどこかにあると思います:

        public void Update(double deltaSec)
        {
            if (CurrentAnimationName is null) return;

            var anim = animations[CurrentAnimationName];
            currentAnimationSec = (currentAnimationSec + deltaSec) % anim.Duration.TotalSeconds;

            void calculateBoneTransforms(BoneNode boneNode, Matrix4x4 parentTransform)
            {
                var bone = anim.Bones.FirstOrDefault(b => b.Id == boneNode.Id);
                var nodeTransform = bone?[TimeSpan.FromSeconds(currentAnimationSec)] ?? boneNode.Transform;
                var globalTransform = parentTransform * nodeTransform;

                if (boneNode.Id >= 0)
                    for (int meshIdx = 0; meshIdx < perMeshData.Length; ++meshIdx)
                        perMeshData[meshIdx].FinalBoneMatrices[boneNode.Id] = globalTransform * perMeshData[meshIdx].boneOffsetMatrices[boneNode.Id];

                foreach (var child in boneNode.Children)
                    calculateBoneTransforms(child, globalTransform);
            }
            calculateBoneTransforms(rootBoneNode, Matrix4x4.Identity);
        }

または、変換を使用してボーン データの再帰構造を構築する場合:

            BoneNode visitTransforms(Node node, Matrix4x4 mat)
            {
                var boneNode = new BoneNode
                {
                    Children = new BoneNode[node.ChildCount],
                    Id = boneIds.TryGetValue(node.Name, out var id) ? id : -1,
                    Transform = Matrix4x4.Transpose(node.Transform.ToNumerics()),
                };

                mat = node.Transform.ToNumerics() * mat;
                foreach (var meshIndex in node.MeshIndices)
                    transformsDictionary[scene.Meshes[meshIndex]] = mat;
                int childIdx = 0;
                foreach (var child in node.Children)
                    boneNode.Children[childIdx++] = visitTransforms(child, mat);

                return boneNode;
            }
            rootBoneNode = visitTransforms(scene.RootNode, Matrix4x4.Identity);

ボーンから頂点への重みが正しく収集され、シェーダーにアップロードされ、最終的なボーン配列のユニフォームが正しくアップロードされていると思います (ただし、正しく計算されていない可能性があります)。また、行列の乗算の順序と、シェーダーにアップロードするときに何かを転置するかどうかもわかりませんが、すべての試行で両方の方法を試しました.

4

1 に答える 1

0

誰かが同様の問題に遭遇した場合、私の問題は、変換チェーンの残りの部分が計算された方法と比較して、キーフレームのボーン変換が転置されていたため、それらを乗算するとすべてがおかしくなった. そのため、どの行列が左手系でどれが右手系かを追跡してください!

于 2021-03-13T22:02:57.917 に答える