예제 #1
0
        protected override void CheckScene(FbxScene scene)
        {
            base.CheckScene(scene);

            FbxScene origScene = CreateScene(FbxManager);

            Assert.AreEqual(origScene.GetRootNode().GetChildCount(), origScene.GetRootNode().GetChildCount());

            FbxNode origMeshNode   = origScene.GetRootNode().GetChild(0);
            FbxNode importMeshNode = scene.GetRootNode().GetChild(0);

            FbxNode origSkelRootNode   = origScene.GetRootNode().GetChild(1);
            FbxNode importSkelRootNode = scene.GetRootNode().GetChild(1);

            // Check that the skeletons match
            CheckSkeleton(origSkelRootNode, importSkelRootNode);

            // TODO: Fix so that calling GetDeformer either allows us to downcast
            //       to FbxSkin, or so that it just returns the correct type.
            // Check that the mesh is correctly linked to the skeleton
            //CheckMeshLinkedToSkeleton(origMeshNode.GetMesh(), importMeshNode.GetMesh());
            origMeshNode.GetMesh();
            importMeshNode.GetMesh();

            // Check that bind pose is set correctly
            CheckExportBindPose(origScene, scene);
        }
        // Test for bug where exporting FbxShapes with empty names would fail to import all
        // blendshapes except the first in Maya (fixed by UT-3216)
        private void TestFbxShapeNamesNotEmpty(FbxNode node)
        {
            var mesh = node.GetMesh();

            if (mesh != null)
            {
                for (int i = 0; i < mesh.GetDeformerCount(); i++)
                {
                    var blendshape = mesh.GetBlendShapeDeformer(i);
                    if (blendshape == null)
                    {
                        continue;
                    }

                    for (int j = 0; j < blendshape.GetBlendShapeChannelCount(); j++)
                    {
                        var blendShapeChannel = blendshape.GetBlendShapeChannel(j);
                        for (int k = 0; k < blendShapeChannel.GetTargetShapeCount(); k++)
                        {
                            var shape = blendShapeChannel.GetTargetShape(k);
                            Assert.That(string.IsNullOrEmpty(shape.GetName()), Is.False, string.Format("FbxShape missing name on blendshape {0}", blendshape.GetName()));
                        }
                    }
                }
            }

            for (int i = 0; i < node.GetChildCount(); i++)
            {
                TestFbxShapeNamesNotEmpty(node.GetChild(i));
            }
        }
예제 #3
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);
        }
예제 #4
0
            /// <summary>
            /// Convert scene's system units but leave scaling unchanged
            /// </summary>
            public void ConvertScene(FbxScene fbxScene, FbxSystemUnit toUnits)
            {
                // Get scale factor.
                float scaleFactor = 1.0f;

                scaleFactor = (float)fbxScene.GetGlobalSettings().GetSystemUnit().GetConversionFactorTo(toUnits);

                if (scaleFactor.Equals(1.0f))
                {
                    return;
                }

                // Get root node.
                FbxNode fbxRootNode = fbxScene.GetRootNode();

                // For all the nodes to convert the translations
                Queue <FbxNode> fbxNodes = new Queue <FbxNode> ();

                fbxNodes.Enqueue(fbxRootNode);

                while (fbxNodes.Count > 0)
                {
                    FbxNode fbxNode = fbxNodes.Dequeue();

                    // Convert node's translation.
                    FbxDouble3 lclTrs = fbxNode.LclTranslation.Get();

#if UNI_18844
                    lclTrs *= scaleFactor;
                    lclTrs *= scaleFactor;
                    lclTrs *= scaleFactor;
#endif
                    fbxNode.LclTranslation.Set(lclTrs);

                    FbxMesh fbxMesh = fbxNode.GetMesh();

                    if (fbxMesh != null)
                    {
                        for (int i = 0; i < fbxMesh.GetControlPointsCount(); ++i)
                        {
                            FbxVector4 fbxVector4 = fbxMesh.GetControlPointAt(i);
#if UNI_18844
                            fbxVector4 *= scaleFactor;
#endif
                            fbxMesh.SetControlPointAt(fbxVector4, i);
                        }
                    }

                    for (int i = 0; i < fbxNode.GetChildCount(); ++i)
                    {
                        fbxNodes.Enqueue(fbxNode.GetChild(i));
                    }
                }
            }
예제 #5
0
        private void CheckSceneHelper(FbxNode node, FbxMesh mesh, FbxSurfaceMaterial material)
        {
            if (node == null)
            {
                return;
            }

            Assert.AreEqual(mesh, node.GetMesh());

            int matIndex = node.GetMaterialIndex(m_materialName);

            Assert.GreaterOrEqual(matIndex, 0);
            Assert.AreEqual(material, node.GetMaterial(matIndex));

            for (int i = 0; i < node.GetChildCount(); i++)
            {
                // recurse through the hierarchy
                CheckSceneHelper(node.GetChild(i), mesh, material);
            }
        }
예제 #6
0
        static void LoadSkinsFromNodeRecursive(FbxNode pNode, List <FbxSkin> skinsResult)
        {
            FbxNodeAttribute pNodeAttribute = pNode.GetNodeAttribute();

            if (pNodeAttribute?.GetAttributeType() == FbxNodeAttribute.EType.eMesh)
            {
                FbxMesh pMesh     = pNode.GetMesh();
                int     skinCount = pMesh.GetDeformerCount(FbxDeformer.EDeformerType.eSkin);
                for (int i = 0; i < skinCount; i++)
                {
                    FbxSkin pSkin = FbxSkin.Cast(pMesh.GetDeformer(i, FbxDeformer.EDeformerType.eSkin));
                    skinsResult.Add(pSkin);
                }
            }

            for (int i = 0; i < pNode.GetChildCount(); i++)
            {
                LoadSkinsFromNodeRecursive(pNode.GetChild(i), skinsResult);
            }
        }
예제 #7
0
    Transform CreateNode(Transform parent, FbxNode fbxNode)
    {
        var       unityNode      = new GameObject(fbxNode.GetName());
        Transform unityTransform = unityNode.transform;

        unityTransform.parent = parent;

        // If there's a mesh attached, create it
        var fbxMesh = fbxNode.GetMesh();

        if (fbxMesh != null)
        {
            var mesh       = GetOrCreateInstance(fbxMesh);
            var meshFilter = unityNode.AddComponent <MeshFilter>();
            var meshRender = unityNode.AddComponent <MeshRenderer>();
            meshFilter.sharedMesh = mesh;
            meshRender.material   = DefaultMaterial;
        }

        return(unityTransform);
    }
예제 #8
0
        private static long GetTotalVerts(FbxNode node)
        {
            FbxNodeAttribute a = node.GetNodeAttribute();
            int  nChildren     = node.GetChildCount();
            long vertCount     = 0;

            if (a != null)
            {
                var attrType = a.GetAttributeType();
                if (attrType == FbxNodeAttribute.EType.eMesh)
                {
                    FbxMesh fbxMesh = node.GetMesh();
                    fbxMesh.SplitPoints();
                    vertCount = fbxMesh.GetControlPointsCount();
                }
            }
            for (int i = 0; i < nChildren; i++)
            {
                vertCount += GetTotalVerts(node.GetChild(i));
            }
            return(vertCount);
        }
예제 #9
0
        protected override void CheckScene(FbxScene scene)
        {
            base.CheckScene(scene);

            FbxNode rootNode = scene.GetRootNode().GetChild(0);

            Assert.IsNotNull(rootNode);

            FbxMesh sharedMesh = rootNode.GetMesh();

            Assert.IsNotNull(sharedMesh);
            Assert.AreEqual(m_meshName, sharedMesh.GetName());

            int matIndex = rootNode.GetMaterialIndex(m_materialName);

            Assert.GreaterOrEqual(matIndex, 0);
            FbxSurfaceMaterial sharedMat = rootNode.GetMaterial(matIndex);

            Assert.IsNotNull(sharedMat);

            // check that the mesh is the same for all children
            CheckSceneHelper(rootNode, sharedMesh, sharedMat);
        }
예제 #10
0
            /// <summary>
            /// Process mesh data and setup MeshFilter component
            /// </summary>
            private void ProcessMesh(FbxNode fbxNode, GameObject unityGo)
            {
                FbxMesh fbxMesh = fbxNode.GetMesh();

                if (fbxMesh == null)
                {
                    return;
                }

                var unityMesh = new Mesh();

                // create mesh
                var unityVertices        = new List <Vector3> ();
                var unityTriangleIndices = new List <int> ();

                // transfer vertices
                for (int i = 0; i < fbxMesh.GetControlPointsCount(); ++i)
                {
                    FbxVector4 fbxVector4 = fbxMesh.GetControlPointAt(i);
                    Debug.Assert(fbxVector4.X <= float.MaxValue && fbxVector4.X >= float.MinValue);
                    Debug.Assert(fbxVector4.Y <= float.MaxValue && fbxVector4.Y >= float.MinValue);
                    Debug.Assert(fbxVector4.Z <= float.MaxValue && fbxVector4.Z >= float.MinValue);

                    unityVertices.Add(new Vector3((float)fbxVector4.X, (float)fbxVector4.Y, (float)fbxVector4.Z));
                }

                // transfer triangles
                for (int polyIndex = 0; polyIndex < fbxMesh.GetPolygonCount(); ++polyIndex)
                {
                    int polySize = fbxMesh.GetPolygonSize(polyIndex);

                    // only support triangles
                    Debug.Assert(polySize == 3);

                    for (int polyVertexIndex = 0; polyVertexIndex < polySize; ++polyVertexIndex)
                    {
                        int vertexIndex = fbxMesh.GetPolygonVertex(polyIndex, polyVertexIndex);

                        unityTriangleIndices.Add(vertexIndex);
                    }
                }

                unityMesh.vertices = unityVertices.ToArray();

                // TODO:
                // - support Mesh.SetTriangles - multiple materials per mesh
                // - support Mesh.SetIndices - other topologies e.g. quads
                unityMesh.triangles = unityTriangleIndices.ToArray();

                unityMesh.RecalculateNormals();

                var unityMeshFilter = unityGo.AddComponent <MeshFilter> ();

                unityMeshFilter.sharedMesh = unityMesh;

                var unityRenderer = unityGo.AddComponent <MeshRenderer> ();
                {
                    // Assign the default material (hack!)
                    var unityPrimitive = GameObject.CreatePrimitive(PrimitiveType.Quad);
                    var unityMat       = unityPrimitive.GetComponent <MeshRenderer> ().sharedMaterial;
                    unityRenderer.sharedMaterial = unityMat;
                    UnityEngine.Object.DestroyImmediate(unityPrimitive);
                }
            }
예제 #11
0
            /// <summary>
            /// Export GameObject's as a skinned mesh with bones
            /// </summary>
            protected void ExportSkinnedMesh(Animator unityAnimator, FbxScene fbxScene, FbxNode fbxParentNode)
            {
                GameObject unityGo = unityAnimator.gameObject;

                SkinnedMeshRenderer unitySkin
                    = unityGo.GetComponentInChildren <SkinnedMeshRenderer> ();

                if (unitySkin == null)
                {
                    Debug.LogError("could not find skinned mesh");
                    return;
                }

                var meshInfo = GetSkinnedMeshInfo(unityGo);

                if (meshInfo.renderer == null)
                {
                    Debug.LogError("mesh has no renderer");
                    return;
                }

                // create an FbxNode and add it as a child of fbxParentNode
                FbxNode fbxNode = FbxNode.Create(fbxScene, unityAnimator.name);


                Dictionary <Transform, FbxNode> boneNodes
                    = new Dictionary <Transform, FbxNode> ();

                // export skeleton
                if (ExportSkeleton(meshInfo, fbxScene, fbxNode, ref boneNodes))
                {
                    // export skin
                    FbxNode fbxMeshNode = ExportMesh(meshInfo, fbxScene, fbxNode);

                    FbxMesh fbxMesh = fbxMeshNode.GetMesh();

                    if (fbxMesh == null)
                    {
                        Debug.LogError("Could not find mesh");
                        return;
                    }

                    // bind mesh to skeleton
                    ExportSkin(meshInfo, fbxScene, fbxMesh, fbxMeshNode, boneNodes);

                    // add bind pose
                    ExportBindPose(fbxNode, fbxMeshNode, fbxScene, boneNodes);

                    fbxParentNode.AddChild(fbxNode);
                    NumNodes++;

                    if (Verbose)
                    {
                        Debug.Log(string.Format("exporting {0} {1}", "Skin", fbxNode.GetName()));
                    }
                }
                else
                {
                    Debug.LogError("failed to export skeleton");
                }
            }