예제 #1
0
        protected void ExportBindPose(FbxNode meshNode, FbxScene fbxScene, List <FbxNode> boneNodes)
        {
            FbxPose fbxPose = FbxPose.Create(fbxScene, "Pose");

            // set as bind pose
            fbxPose.SetIsBindPose(true);

            // assume each bone node has one weighted vertex cluster
            foreach (FbxNode fbxNode in boneNodes)
            {
                // EvaluateGlobalTransform returns an FbxAMatrix (affine matrix)
                // which has to be converted to an FbxMatrix so that it can be passed to fbxPose.Add().
                // The hierarchy for FbxMatrix and FbxAMatrix is as follows:
                //
                //      FbxDouble4x4
                //      /           \
                // FbxMatrix     FbxAMatrix
                //
                // Therefore we can't convert directly from FbxAMatrix to FbxMatrix,
                // however FbxMatrix has a constructor that takes an FbxAMatrix.
                FbxMatrix fbxBindMatrix = new FbxMatrix(fbxNode.EvaluateGlobalTransform());

                fbxPose.Add(fbxNode, fbxBindMatrix);
            }

            FbxMatrix bindMatrix = new FbxMatrix(meshNode.EvaluateGlobalTransform());

            fbxPose.Add(meshNode, bindMatrix);

            // add the pose to the scene
            fbxScene.AddPose(fbxPose);
        }
예제 #2
0
        protected void LinkMeshToSkeleton(FbxScene scene, FbxNode meshNode, FbxNode skelRootNode)
        {
            FbxNode limb1 = skelRootNode.GetChild(0);
            FbxNode limb2 = limb1.GetChild(0);

            FbxCluster rootCluster = FbxCluster.Create(scene, "RootCluster");

            rootCluster.SetLink(skelRootNode);
            rootCluster.SetLinkMode(FbxCluster.ELinkMode.eTotalOne);
            for (int i = 0; i < 4; i++)
            {
                for (int j = 0; j < 4; j++)
                {
                    rootCluster.AddControlPointIndex(4 * i + j, 1.0 - 0.25 * i);
                }
            }

            FbxCluster limb1Cluster = FbxCluster.Create(scene, "Limb1Cluster");

            limb1Cluster.SetLink(limb1);
            limb1Cluster.SetLinkMode(FbxCluster.ELinkMode.eTotalOne);
            for (int i = 1; i < 6; i++)
            {
                for (int j = 0; j < 4; j++)
                {
                    limb1Cluster.AddControlPointIndex(4 * i + j, (i == 1 || i == 5 ? 0.25 : 0.5));
                }
            }

            FbxCluster limb2Cluster = FbxCluster.Create(scene, "Limb2Cluster");

            limb2Cluster.SetLink(limb2);
            limb2Cluster.SetLinkMode(FbxCluster.ELinkMode.eTotalOne);
            for (int i = 3; i < 7; i++)
            {
                for (int j = 0; j < 4; j++)
                {
                    limb2Cluster.AddControlPointIndex(4 * i + j, 0.25 * (i - 2));
                }
            }

            FbxAMatrix globalTransform = meshNode.EvaluateGlobalTransform();

            rootCluster.SetTransformMatrix(globalTransform);
            limb1Cluster.SetTransformMatrix(globalTransform);
            limb2Cluster.SetTransformMatrix(globalTransform);

            rootCluster.SetTransformLinkMatrix(skelRootNode.EvaluateGlobalTransform());
            limb1Cluster.SetTransformLinkMatrix(limb1.EvaluateGlobalTransform());
            limb2Cluster.SetTransformLinkMatrix(limb2.EvaluateGlobalTransform());

            FbxSkin skin = FbxSkin.Create(scene, "Skin");

            skin.AddCluster(rootCluster);
            skin.AddCluster(limb1Cluster);
            skin.AddCluster(limb2Cluster);
            meshNode.GetMesh().AddDeformer(skin);
        }
예제 #3
0
        public static FbxAMatrix EvaluateGlobalTransform(FbxNode node)
        {
            return(node.EvaluateGlobalTransform());

            //Warning: Эквивалент node.EvaluateGlobalTransform(). Но обнаружилось отличие на модели BaseMesh_Anim.fbx, эта модель в MaxAxisSystem не происходит конверсия.
            // На этой модели в контексте использования в Skeleton работает корректно. А в контексте использования координат Mesh не корректно: модель повернута на 90 градусов.
            // Видимо еще что-то надо учитывать кроме AxisSystem. Либо в CalculateGlobalTransform AxisSystem учитывается не полностью.
            // Сейчас в этой функции нет необходимости, достаточно node.EvaluateGlobalTransform() т.к. только в момент импорта все вычисляется.
            //return CalculateGlobalTransform(node);
        }
예제 #4
0
        public void NodesInHierarchy_CalcGlobalTransformWithTranslationAndWithRotation_ReturnsRotatedThenTranslated()
        {
            // given:
            var node1 = new FbxNode("node1");
            var node2 = new FbxNode("node2");

            node1.AddChild(node2);
            var t = new FbxVector4(2, 3, 4);
            var r = new FbxVector4(45, 0, 0);

            node1.LclTranslation.Set(t);
            node2.LclRotation.Set(r);

            // when:
            var actual = node1.EvaluateGlobalTransform();

            // then:
            Assert.AreEqual(1.000000f, actual.Get(0, 0), 0.000001f);
            Assert.AreEqual(0.000000f, actual.Get(0, 1), 0.000001f);
            Assert.AreEqual(0.000000f, actual.Get(0, 2), 0.000001f);
            Assert.AreEqual(0.000000f, actual.Get(0, 3), 0.000001f);
            Assert.AreEqual(0.000000f, actual.Get(1, 0), 0.000001f);
            Assert.AreEqual(1.000000f, actual.Get(1, 1), 0.000001f);
            Assert.AreEqual(0.000000f, actual.Get(1, 2), 0.000001f);
            Assert.AreEqual(0.000000f, actual.Get(1, 3), 0.000001f);
            Assert.AreEqual(0.000000f, actual.Get(2, 0), 0.000001f);
            Assert.AreEqual(0.000000f, actual.Get(2, 1), 0.000001f);
            Assert.AreEqual(1.000000f, actual.Get(2, 2), 0.000001f);
            Assert.AreEqual(0.000000f, actual.Get(2, 3), 0.000001f);
            Assert.AreEqual(2.000000f, actual.Get(3, 0), 0.000001f);
            Assert.AreEqual(3.000000f, actual.Get(3, 1), 0.000001f);
            Assert.AreEqual(4.000000f, actual.Get(3, 2), 0.000001f);
            Assert.AreEqual(1.000000f, actual.Get(3, 3), 0.000001f);

            // when:
            actual = node2.EvaluateGlobalTransform();

            // then:
            Assert.AreEqual(1.000000f, actual.Get(0, 0), 0.000001f);
            Assert.AreEqual(0.000000f, actual.Get(0, 1), 0.000001f);
            Assert.AreEqual(0.000000f, actual.Get(0, 2), 0.000001f);
            Assert.AreEqual(0.000000f, actual.Get(0, 3), 0.000001f);
            Assert.AreEqual(0.000000f, actual.Get(1, 0), 0.000001f);
            Assert.AreEqual(0.707107f, actual.Get(1, 1), 0.000001f);
            Assert.AreEqual(0.707107f, actual.Get(1, 2), 0.000001f);
            Assert.AreEqual(0.000000f, actual.Get(1, 3), 0.000001f);
            Assert.AreEqual(0.000000f, actual.Get(2, 0), 0.000001f);
            Assert.AreEqual(-0.707107f, actual.Get(2, 1), 0.000001f);
            Assert.AreEqual(0.707107f, actual.Get(2, 2), 0.000001f);
            Assert.AreEqual(0.000000f, actual.Get(2, 3), 0.000001f);
            Assert.AreEqual(2.000000f, actual.Get(3, 0), 0.000001f);
            Assert.AreEqual(3.000000f, actual.Get(3, 1), 0.000001f);
            Assert.AreEqual(4.000000f, actual.Get(3, 2), 0.000001f);
            Assert.AreEqual(1.000000f, actual.Get(3, 3), 0.000001f);
        }
예제 #5
0
        public void NodesInHierarchy_CalcGlobalTransform_ChildsIsTimesParent()
        {
            // given:
            var node1 = new FbxNode("node1");
            var node2 = new FbxNode("node2");

            node1.AddChild(node2);
            var r1 = new FbxVector4(45, 0, 0);
            var r2 = new FbxVector4(0, 60, 0);

            node1.LclRotation.Set(r1);
            node2.LclRotation.Set(r2);

            // when:
            var g1 = node1.EvaluateGlobalTransform();
            var g2 = node2.EvaluateGlobalTransform();
            var l1 = node1.EvaluateLocalTransform();
            var l2 = node2.EvaluateLocalTransform();

            Assert.AreEqual(l1.Get(0, 0), g1.Get(0, 0), 0.000001f);
            Assert.AreEqual(l1.Get(0, 1), g1.Get(0, 1), 0.000001f);
            Assert.AreEqual(l1.Get(0, 2), g1.Get(0, 2), 0.000001f);
            Assert.AreEqual(l1.Get(0, 3), g1.Get(0, 3), 0.000001f);
            Assert.AreEqual(l1.Get(1, 0), g1.Get(1, 0), 0.000001f);
            Assert.AreEqual(l1.Get(1, 1), g1.Get(1, 1), 0.000001f);
            Assert.AreEqual(l1.Get(1, 2), g1.Get(1, 2), 0.000001f);
            Assert.AreEqual(l1.Get(1, 3), g1.Get(1, 3), 0.000001f);
            Assert.AreEqual(l1.Get(2, 0), g1.Get(2, 0), 0.000001f);
            Assert.AreEqual(l1.Get(2, 1), g1.Get(2, 1), 0.000001f);
            Assert.AreEqual(l1.Get(2, 2), g1.Get(2, 2), 0.000001f);
            Assert.AreEqual(l1.Get(2, 3), g1.Get(2, 3), 0.000001f);
            Assert.AreEqual(l1.Get(3, 0), g1.Get(3, 0), 0.000001f);
            Assert.AreEqual(l1.Get(3, 1), g1.Get(3, 1), 0.000001f);
            Assert.AreEqual(l1.Get(3, 2), g1.Get(3, 2), 0.000001f);
            Assert.AreEqual(l1.Get(3, 3), g1.Get(3, 3), 0.000001f);

            var m = l1 * l2;

            Assert.AreEqual(m.Get(0, 0), g2.Get(0, 0), 0.000001f);
            Assert.AreEqual(m.Get(0, 1), g2.Get(0, 1), 0.000001f);
            Assert.AreEqual(m.Get(0, 2), g2.Get(0, 2), 0.000001f);
            Assert.AreEqual(m.Get(0, 3), g2.Get(0, 3), 0.000001f);
            Assert.AreEqual(m.Get(1, 0), g2.Get(1, 0), 0.000001f);
            Assert.AreEqual(m.Get(1, 1), g2.Get(1, 1), 0.000001f);
            Assert.AreEqual(m.Get(1, 2), g2.Get(1, 2), 0.000001f);
            Assert.AreEqual(m.Get(1, 3), g2.Get(1, 3), 0.000001f);
            Assert.AreEqual(m.Get(2, 0), g2.Get(2, 0), 0.000001f);
            Assert.AreEqual(m.Get(2, 1), g2.Get(2, 1), 0.000001f);
            Assert.AreEqual(m.Get(2, 2), g2.Get(2, 2), 0.000001f);
            Assert.AreEqual(m.Get(2, 3), g2.Get(2, 3), 0.000001f);
            Assert.AreEqual(m.Get(3, 0), g2.Get(3, 0), 0.000001f);
            Assert.AreEqual(m.Get(3, 1), g2.Get(3, 1), 0.000001f);
            Assert.AreEqual(m.Get(3, 2), g2.Get(3, 2), 0.000001f);
            Assert.AreEqual(m.Get(3, 3), g2.Get(3, 3), 0.000001f);
        }
예제 #6
0
        public void Node_CalcGlobalTransformFromCreatedState_ReturnsIdentity()
        {
            // given:
            var node     = new FbxNode("");
            var t        = new FbxVector4(0, 0, 0);
            var r        = new FbxVector4(0, 0, 0);
            var s        = new FbxVector4(1, 1, 1);
            var expected = new FbxMatrix(t, r, s);

            // when:
            var actual = node.EvaluateGlobalTransform();

            // then:
            Assert.AreEqual(expected, actual);
        }
예제 #7
0
        public void Node_CalcGlobalTransformWithScale_ReturnsScale()
        {
            // given:
            var node     = new FbxNode("");
            var t        = new FbxVector4(0, 0, 0);
            var r        = new FbxVector4(0, 0, 0);
            var s        = new FbxVector4(5, 6, 7);
            var expected = new FbxMatrix(t, r, s);

            node.LclScaling.Set(s);

            // when:
            var actual = node.EvaluateGlobalTransform();

            // then:
            Assert.AreEqual(expected, actual);
        }
예제 #8
0
        public void Node_CalcGlobalTransformWithRotation_ReturnsRotation()
        {
            // given:
            var node     = new FbxNode("");
            var t        = new FbxVector4(0, 0, 0);
            var r        = new FbxVector4(22, 33, 44);
            var s        = new FbxVector4(1, 1, 1);
            var expected = new FbxMatrix(t, r, s);

            node.LclRotation.Set(r);

            // when:
            var actual = node.EvaluateGlobalTransform();

            // then:
            Assert.AreEqual(expected, actual);
        }
예제 #9
0
            /// <summary>
            /// Export binding of mesh to skeleton
            /// </summary>
            protected void ExportSkin(MeshInfo meshInfo, FbxScene fbxScene, FbxMesh fbxMesh,
                                      FbxNode fbxRootNode,
                                      Dictionary <Transform, FbxNode> boneNodes)
            {
                SkinnedMeshRenderer unitySkinnedMeshRenderer
                    = meshInfo.renderer as SkinnedMeshRenderer;

                FbxSkin fbxSkin = FbxSkin.Create(fbxScene, (meshInfo.unityObject.name + "_Skin"));

                FbxAMatrix fbxMeshMatrix = fbxRootNode.EvaluateGlobalTransform();

                // keep track of the bone index -> fbx cluster mapping, so that we can add the bone weights afterwards
                Dictionary <int, FbxCluster> boneCluster = new Dictionary <int, FbxCluster> ();

                for (int i = 0; i < unitySkinnedMeshRenderer.bones.Length; i++)
                {
                    FbxNode fbxBoneNode = boneNodes [unitySkinnedMeshRenderer.bones[i]];

                    // Create the deforming cluster
                    FbxCluster fbxCluster = FbxCluster.Create(fbxScene, "BoneWeightCluster");

                    fbxCluster.SetLink(fbxBoneNode);
                    fbxCluster.SetLinkMode(FbxCluster.ELinkMode.eTotalOne);

                    boneCluster.Add(i, fbxCluster);

                    // set the Transform and TransformLink matrix
                    fbxCluster.SetTransformMatrix(fbxMeshMatrix);

                    FbxAMatrix fbxLinkMatrix = fbxBoneNode.EvaluateGlobalTransform();
                    fbxCluster.SetTransformLinkMatrix(fbxLinkMatrix);

                    // add the cluster to the skin
                    fbxSkin.AddCluster(fbxCluster);
                }

                // set the vertex weights for each bone
                SetVertexWeights(meshInfo, boneCluster);

                // Add the skin to the mesh after the clusters have been added
                fbxMesh.AddDeformer(fbxSkin);
            }
예제 #10
0
        public SkeletonBone(FbxNode boneNode, SkeletonBone parentBone, FbxSkin[] skins, SceneLoader scene)
        {
            //this.scene = scene;
            this.scene = scene;
            Node       = boneNode;
            ParentBone = parentBone;
            //animationTrackKeyFrames = new List<HashSet<double>>();
            cluster = Skeleton.FindCluster(Node, skins, out skin);               //Поиск по всем skins во всех mesh. Можно было бы сделать эффективнее.

            globalMeshTransform = new FbxAMatrix();
            globalMeshTransform.SetIdentity();
            geometryOffset = new FbxAMatrix();
            geometryOffset.SetIdentity();
            if (cluster != null)
            {
                FbxNode meshNode = skin.GetGeometry()?.GetNode();
                if (meshNode != null)
                {
                    globalMeshTransform = meshNode.EvaluateGlobalTransform(FbxExtensions.ToFbxTime(-1));                         // FbxMath.GetGlobalPosition( meshNode, FbxExtensions.ToFbxTime( -1 ), null );
                    geometryOffset      = FbxMath.GetGeometryOffset(meshNode);
                }
            }
            InitialTransform = GetInitialTransform().ToMatrix4();             //Во внешнем коде надо использовать это значение, т.к. результат GetInitialTransform() может зависеть от установленного AnimationTrack
        }