Ejemplo n.º 1
0
        protected override FbxScene CreateScene(FbxManager manager)
        {
            FbxScene scene = base.CreateScene(manager);

            // mesh shared by all instances
            FbxMesh            sharedMesh     = FbxMesh.Create(scene, m_meshName);
            FbxSurfaceMaterial sharedMaterial = FbxSurfacePhong.Create(scene, m_materialName);

            // add mesh to all nodes
            Queue <FbxNode> nodes = new Queue <FbxNode>();

            for (int i = 0; i < scene.GetRootNode().GetChildCount(); i++)
            {
                nodes.Enqueue(scene.GetRootNode().GetChild(i));
            }

            while (nodes.Count > 0)
            {
                FbxNode node = nodes.Dequeue();
                node.SetNodeAttribute(sharedMesh);
                node.AddMaterial(sharedMaterial);
                for (int i = 0; i < node.GetChildCount(); i++)
                {
                    nodes.Enqueue(node.GetChild(i));
                }
            }

            return(scene);
        }
Ejemplo n.º 2
0
            /// <summary>
            /// Unconditionally export this mesh object to the file.
            /// We have decided; this mesh is definitely getting exported.
            /// </summary>
            public FbxMesh ExportMesh(GameObject unityGo, FbxScene fbxScene)
            {
                var meshInfo = GetMeshInfo(unityGo);

                if (!meshInfo.IsValid)
                {
                    return(null);
                }

                // create the mesh structure.
                FbxMesh fbxMesh = FbxMesh.Create(fbxScene, "Scene");

                // Create control points.
                int NumControlPoints = meshInfo.VertexCount;

                fbxMesh.InitControlPoints(NumControlPoints);

                // copy control point data from Unity to FBX
                for (int v = 0; v < NumControlPoints; v++)
                {
                    fbxMesh.SetControlPointAt(new FbxVector4(meshInfo.Vertices [v].x, meshInfo.Vertices [v].y, meshInfo.Vertices [v].z), v);
                }

                for (int f = 0; f < meshInfo.Triangles.Length / 3; f++)
                {
                    fbxMesh.BeginPolygon();
                    fbxMesh.AddPolygon(meshInfo.Triangles [3 * f]);
                    fbxMesh.AddPolygon(meshInfo.Triangles [3 * f + 1]);
                    fbxMesh.AddPolygon(meshInfo.Triangles [3 * f + 2]);
                    fbxMesh.EndPolygon();
                }

                return(fbxMesh);
            }
Ejemplo n.º 3
0
 public void TestGetMesh()
 {
     // make sure it doesn't crash
     using (FbxNode node = CreateObject("root")) {
         FbxMesh mesh = FbxMesh.Create(Manager, "mesh");
         node.SetNodeAttribute(mesh);
         Assert.AreEqual(mesh, node.GetMesh());
     }
 }
Ejemplo n.º 4
0
 public void Init()
 {
     m_fbxManager = FbxManager.Create();
     m_fbxMesh    = FbxMesh.Create(m_fbxManager, "");
     m_fbxLayer   = m_fbxMesh.GetLayer(0);
     if (m_fbxLayer == null)
     {
         m_fbxMesh.CreateLayer();
         m_fbxLayer = m_fbxMesh.GetLayer(0 /* default layer */);
     }
 }
Ejemplo n.º 5
0
            /// <summary>
            /// Unconditionally export this mesh object to the file.
            /// We have decided; this mesh is definitely getting exported.
            /// </summary>
            public void ExportMesh(MeshInfo mesh, FbxNode fbxNode, FbxScene fbxScene)
            {
                if (!mesh.IsValid)
                {
                    return;
                }

                NumMeshes++;
                NumTriangles += mesh.Triangles.Length / 3;
                NumVertices  += mesh.VertexCount;

                // create the mesh structure.
                FbxMesh fbxMesh = FbxMesh.Create(fbxScene, "Mesh");

                // Create control points.
                int NumControlPoints = mesh.VertexCount;

                fbxMesh.InitControlPoints(NumControlPoints);

                // copy control point data from Unity to FBX
                for (int v = 0; v < NumControlPoints; v++)
                {
                    // convert from left to right-handed by negating x (Unity negates x again on import)
                    fbxMesh.SetControlPointAt(new FbxVector4(-mesh.Vertices [v].x, mesh.Vertices [v].y, mesh.Vertices [v].z), v);
                }

                ExportNormalsEtc(mesh, fbxMesh);
                ExportVertexColors(mesh, fbxMesh);
                ExportUVs(mesh, fbxMesh);

                /*
                 * Create polygons
                 * Triangles have to be added in reverse order,
                 * or else they will be inverted on import
                 * (due to the conversion from left to right handed coords)
                 */
                for (int f = 0; f < mesh.Triangles.Length / 3; f++)
                {
                    fbxMesh.BeginPolygon();
                    fbxMesh.AddPolygon(mesh.Triangles [3 * f + 2]);
                    fbxMesh.AddPolygon(mesh.Triangles [3 * f + 1]);
                    fbxMesh.AddPolygon(mesh.Triangles [3 * f]);
                    fbxMesh.EndPolygon();
                }

                // set the fbxNode containing the mesh
                fbxNode.SetNodeAttribute(fbxMesh);
                fbxNode.SetShadingMode(FbxNode.EShadingMode.eWireFrame);
            }
Ejemplo n.º 6
0
            /// <summary>
            /// Unconditionally export this mesh object to the file.
            /// We have decided; this mesh is definitely getting exported.
            /// </summary>
            public FbxNode ExportMesh(MeshInfo meshInfo, FbxScene fbxScene, FbxNode fbxNode)
            {
                if (!meshInfo.IsValid)
                {
                    Debug.LogError("Invalid mesh info");
                    return(null);
                }

                // create a node for the mesh
                FbxNode meshNode = FbxNode.Create(fbxScene, "geo");

                // create the mesh structure.
                FbxMesh fbxMesh = FbxMesh.Create(fbxScene, "Mesh");

                // Create control points.
                int NumControlPoints = meshInfo.VertexCount;

                fbxMesh.InitControlPoints(NumControlPoints);

                // copy control point data from Unity to FBX
                for (int v = 0; v < NumControlPoints; v++)
                {
                    // convert from left to right-handed by negating x (Unity negates x again on import)
                    fbxMesh.SetControlPointAt(new FbxVector4(-meshInfo.Vertices [v].x, meshInfo.Vertices [v].y, meshInfo.Vertices [v].z), v);
                }

                /*
                 * Create polygons
                 * Triangles have to be added in reverse order,
                 * or else they will be inverted on import
                 * (due to the conversion from left to right handed coords)
                 */
                for (int f = 0; f < meshInfo.Triangles.Length / 3; f++)
                {
                    fbxMesh.BeginPolygon();
                    fbxMesh.AddPolygon(meshInfo.Triangles [3 * f + 2]);
                    fbxMesh.AddPolygon(meshInfo.Triangles [3 * f + 1]);
                    fbxMesh.AddPolygon(meshInfo.Triangles [3 * f]);
                    fbxMesh.EndPolygon();
                }

                // set the fbxNode containing the mesh
                meshNode.SetNodeAttribute(fbxMesh);
                meshNode.SetShadingMode(FbxNode.EShadingMode.eWireFrame);

                fbxNode.AddChild(meshNode);

                return(meshNode);
            }
Ejemplo n.º 7
0
            /// <summary>
            /// Unconditionally export this mesh object to the file.
            /// We have decided; this mesh is definitely getting exported.
            /// </summary>
            public FbxMesh ExportMesh(MeshInfo meshInfo, FbxNode fbxNode, FbxScene fbxScene)
            {
                if (!meshInfo.IsValid)
                {
                    return(null);
                }

                // create the mesh structure.
                FbxMesh fbxMesh = FbxMesh.Create(fbxScene, "Mesh");

                // Create control points.
                int NumControlPoints = meshInfo.VertexCount;

                fbxMesh.InitControlPoints(NumControlPoints);

                // copy control point data from Unity to FBX
                for (int v = 0; v < NumControlPoints; v++)
                {
                    // convert from left to right-handed by negating x (Unity negates x again on import)
                    fbxMesh.SetControlPointAt(new FbxVector4(-meshInfo.Vertices [v].x, meshInfo.Vertices [v].y, meshInfo.Vertices [v].z), v);
                }

                ExportNormalsEtc(meshInfo, fbxMesh);
                ExportUVs(meshInfo, fbxMesh);

                var fbxMaterial = ExportMaterial(meshInfo.Material, fbxScene);

                fbxNode.AddMaterial(fbxMaterial);

                /*
                 * Create polygons after FbxLayerElementMaterial have been created.
                 * Triangles have to be added in reverse order,
                 * or else they will be inverted on import
                 * (due to the conversion from left to right handed coords)
                 */
                for (int f = 0; f < meshInfo.Triangles.Length / 3; f++)
                {
                    fbxMesh.BeginPolygon();
                    fbxMesh.AddPolygon(meshInfo.Triangles [3 * f + 2]);
                    fbxMesh.AddPolygon(meshInfo.Triangles [3 * f + 1]);
                    fbxMesh.AddPolygon(meshInfo.Triangles [3 * f]);
                    fbxMesh.EndPolygon();
                }

                return(fbxMesh);
            }
        protected override FbxScene CreateScene(FbxManager manager)
        {
            // Create a cube as a static mesh

            FbxScene scene = FbxScene.Create(manager, "myScene");

            FbxNode meshNode = FbxNode.Create(scene, "MeshNode");
            FbxMesh cubeMesh = FbxMesh.Create(scene, "cube");

            meshNode.SetNodeAttribute(cubeMesh);

            scene.GetRootNode().AddChild(meshNode);

            cubeMesh.InitControlPoints(24);

            for (int i = 0; i < cubeMesh.GetControlPointsCount(); i++)
            {
                cubeMesh.SetControlPointAt(m_controlPoints [i], i);
            }

            // A cube: 6 polygons with 4 vertices each
            int[] vertices =
            {
                0,   1,  2,  3,
                4,   5,  6,  7,
                8,   9, 10, 11,
                12, 13, 14, 15,
                16, 17, 18, 19,
                20, 21, 22, 23
            };

            for (int i = 0; i < 6; i++)
            {
                cubeMesh.BeginPolygon(pGroup: -1);
                for (int j = 0; j < 4; j++)
                {
                    cubeMesh.AddPolygon(vertices[i * 4 + j]);
                }

                cubeMesh.EndPolygon();
            }

            return(scene);
        }
Ejemplo n.º 9
0
            /// <summary>
            /// Unconditionally export this mesh object to the file.
            /// We have decided; this mesh is definitely getting exported.
            /// </summary>
            public void ExportMesh(MeshInfo mesh, FbxNode fbxNode, FbxScene fbxScene)
            {
                if (!mesh.IsValid)
                {
                    return;
                }

                NumMeshes++;
                NumTriangles += mesh.Triangles.Length / 3;
                NumVertices  += mesh.VertexCount;

                // create the mesh structure.
                FbxMesh fbxMesh = FbxMesh.Create(fbxScene, "Mesh");

                // Create control points.
                int NumControlPoints = mesh.VertexCount;

                fbxMesh.InitControlPoints(NumControlPoints);

                // copy control point data from Unity to FBX
                for (int v = 0; v < NumControlPoints; v++)
                {
                    fbxMesh.SetControlPointAt(new FbxVector4(mesh.Vertices[v].x, mesh.Vertices[v].y, mesh.Vertices[v].z), v);
                }

                /*
                 * Create polygons after FbxGeometryElementMaterial are created.
                 * TODO: Assign material indices.
                 */
                int vId = 0;

                for (int f = 0; f < mesh.Triangles.Length / 3; f++)
                {
                    fbxMesh.BeginPolygon();
                    fbxMesh.AddPolygon(mesh.Triangles [vId++]);
                    fbxMesh.AddPolygon(mesh.Triangles [vId++]);
                    fbxMesh.AddPolygon(mesh.Triangles [vId++]);
                    fbxMesh.EndPolygon();
                }

                // set the fbxNode containing the mesh
                fbxNode.SetNodeAttribute(fbxMesh);
                fbxNode.SetShadingMode(FbxNode.EShadingMode.eWireFrame);
            }
Ejemplo n.º 10
0
        protected override FbxScene CreateScene(FbxManager manager)
        {
            // Create a cube as a static mesh

            FbxScene scene = FbxScene.Create(manager, "myScene");

            FbxNode meshNode = FbxNode.Create(scene, "MeshNode");
            FbxMesh cubeMesh = FbxMesh.Create(scene, "cube");

            meshNode.SetNodeAttribute(cubeMesh);

            scene.GetRootNode().AddChild(meshNode);

            cubeMesh.InitControlPoints(24);

            for (int i = 0; i < cubeMesh.GetControlPointsCount(); i++)
            {
                cubeMesh.SetControlPointAt(m_controlPoints [i], i);
            }

            return(scene);
        }
        public void TestBasics()
        {
            Assert.That(!string.IsNullOrEmpty(ModelExporter.GetVersionFromReadme()));

            // Test GetOrCreateLayer
            using (var fbxManager = FbxManager.Create()) {
                var fbxMesh = FbxMesh.Create(fbxManager, "name");
                var layer0  = ModelExporter.GetOrCreateLayer(fbxMesh);
                Assert.That(layer0, Is.Not.Null);
                Assert.That(ModelExporter.GetOrCreateLayer(fbxMesh), Is.EqualTo(layer0));
                var layer5 = ModelExporter.GetOrCreateLayer(fbxMesh, layer: 5);
                Assert.That(layer5, Is.Not.Null);
                Assert.That(layer5, Is.Not.EqualTo(layer0));
            }

            // Test axis conversion: a x b in left-handed is the same as b x a
            // in right-handed (that's why we need to flip the winding order).
            var a         = new Vector3(1, 0, 0);
            var b         = new Vector3(0, 0, 1);
            var crossLeft = Vector3.Cross(a, b);

            Assert.That(ModelExporter.DefaultMaterial);

            // Test non-static functions.
            using (var fbxManager = FbxManager.Create()) {
                var fbxScene = FbxScene.Create(fbxManager, "scene");
                var fbxNode  = FbxNode.Create(fbxScene, "node");
                var exporter = new ModelExporter();

                // Test ExportMaterial: it exports and it re-exports
                bool result = exporter.ExportMaterial(ModelExporter.DefaultMaterial, fbxScene, fbxNode);
                Assert.IsTrue(result);
                var fbxMaterial = fbxNode.GetMaterial(0);
                Assert.That(fbxMaterial, Is.Not.Null);

                result = exporter.ExportMaterial(ModelExporter.DefaultMaterial, fbxScene, fbxNode);
                var fbxMaterial2 = fbxNode.GetMaterial(1);
                Assert.AreEqual(fbxMaterial, fbxMaterial2);

                // Test ExportTexture: it finds the same texture for the default-material (it doesn't create a new one)
                var fbxMaterialNew = FbxSurfaceLambert.Create(fbxScene, "lambert");
                exporter.ExportTexture(ModelExporter.DefaultMaterial, "_MainTex",
                                       fbxMaterialNew, FbxSurfaceLambert.sBump);
                Assert.AreEqual(
                    fbxMaterial.FindProperty(FbxSurfaceLambert.sDiffuse).GetSrcObject(),
                    fbxMaterialNew.FindProperty(FbxSurfaceLambert.sBump).GetSrcObject()
                    );

                // Test ExportMesh: make sure we exported a mesh with welded vertices.
                var cube     = GameObject.CreatePrimitive(PrimitiveType.Cube);
                var cubeNode = FbxNode.Create(fbxScene, "cube");
                exporter.ExportMesh(cube.GetComponent <MeshFilter>().sharedMesh, cubeNode);
                Assert.That(cubeNode.GetMesh(), Is.Not.Null);
                Assert.That(cubeNode.GetMesh().GetControlPointsCount(), Is.EqualTo(8));
            }

            // Test exporting a skinned-mesh. Make sure it doesn't leak (it did at one point)
            {
                var cube      = GameObject.CreatePrimitive(PrimitiveType.Cube);
                var character = new GameObject();
                var smr       = character.AddComponent <SkinnedMeshRenderer>();
                smr.sharedMesh = cube.GetComponent <MeshFilter>().sharedMesh;
                var meshCount = Object.FindObjectsOfType <Mesh>().Length;
                ModelExporter.ExportObject(GetRandomFbxFilePath(), character);
                Assert.AreEqual(meshCount, Object.FindObjectsOfType <Mesh>().Length);
            }

            // Test euler to quaternion conversion
            {
                // EulerToQuaternionZXY
                var v         = new Vector3(50, 45, 190);
                var quat      = ModelExporter.EulerToQuaternionZXY(v);
                var unityQuat = Quaternion.Euler(v);
                Assert.That((float)quat.X, Is.EqualTo(unityQuat.x));
                Assert.That((float)quat.Y, Is.EqualTo(unityQuat.y));
                Assert.That((float)quat.Z, Is.EqualTo(unityQuat.z));
                Assert.That((float)quat.W, Is.EqualTo(unityQuat.w));

                // EulerToQuaternionXYZ
                var fbxV    = new FbxVector4(v.x, v.y, v.z);
                var xyzQuat = ModelExporter.EulerToQuaternionXYZ(fbxV);

                // get the vector from the quaternion
                FbxAMatrix m = new FbxAMatrix();
                m.SetR(fbxV);
                var actualQuat = m.GetQ();

                // since this quaternion is XYZ instead of ZXY, it should not match the quaternion
                // created with EulerToQuaternionZXY
                Assert.That(xyzQuat, Is.Not.EqualTo(quat));
                Assert.That(xyzQuat, Is.EqualTo(actualQuat));
            }
        }
Ejemplo n.º 12
0
        // For use only by FbxExportGlobals.
        internal static FbxMesh CreateFbxMesh(FbxExportGlobals G, GeometryPool pool, string poolName)
        {
            FbxMesh fbxMesh = FbxMesh.Create(G.m_manager, poolName);

            ExportMesh mesh   = new ExportMesh(pool);
            int        nVerts = mesh.m_pool.m_Vertices.Count;

            fbxMesh.InitControlPoints(nVerts);

            unsafe
            {
                fixed(Vector3 *f = mesh.m_pool.m_Vertices.GetBackingArray())
                {
                    Globals.SetControlPoints(fbxMesh, (IntPtr)f);
                }
            }

            List <int> triangles = mesh.m_pool.m_Tris;

            // Not available in Unity's wrappers
            // fbxMesh.ReservePolygonCount(triangles.Count / 3);
            // fbxMesh.ReservePolygonVertexCount(triangles.Count);
            for (int i = 0; i < triangles.Count; i += 3)
            {
                fbxMesh.BeginPolygon(-1 /* Material */, -1 /* Texture */, -1 /* Group */, false /* Legacy */);
                fbxMesh.AddPolygon(triangles[i]);
                fbxMesh.AddPolygon(triangles[i + 1]);
                fbxMesh.AddPolygon(triangles[i + 2]);
                fbxMesh.EndPolygon();
            }

            FbxLayer layer0 = fbxMesh.GetLayer(0);

            if (layer0 == null)
            {
                fbxMesh.CreateLayer();
                layer0 = fbxMesh.GetLayer(0);
            }

            var layerElementNormal = FbxLayerElementNormal.Create(fbxMesh, "normals");

            layerElementNormal.SetMappingMode(FbxLayerElement.EMappingMode.eByControlPoint);
            layerElementNormal.SetReferenceMode(FbxLayerElement.EReferenceMode.eDirect);
            CopyToFbx(layerElementNormal.GetDirectArray(), mesh.m_pool.m_Normals);
            layer0.SetNormals(layerElementNormal);

            var layerElementColor = FbxLayerElementVertexColor.Create(fbxMesh, "color");

            layerElementColor.SetMappingMode(FbxLayerElement.EMappingMode.eByControlPoint);
            layerElementColor.SetReferenceMode(FbxLayerElement.EReferenceMode.eDirect);
            CopyToFbx(layerElementColor.GetDirectArray(), mesh.m_linearColor);
            layer0.SetVertexColors(layerElementColor);

            var layerElementTangent = FbxLayerElementTangent.Create(fbxMesh, "tangents");

            layerElementTangent.SetMappingMode(FbxLayerElement.EMappingMode.eByControlPoint);
            layerElementTangent.SetReferenceMode(FbxLayerElement.EReferenceMode.eDirect);
            CopyToFbx(layerElementTangent.GetDirectArray(), mesh.m_pool.m_Tangents);
            layer0.SetTangents(layerElementTangent);

            // Compute and export binormals since Unity's FBX importer won't import the tangents without
            // them, even though they're not used.
            var layerElementBinormal = FbxLayerElementBinormal.Create(fbxMesh, "binormals");

            layerElementBinormal.SetMappingMode(FbxLayerElement.EMappingMode.eByControlPoint);
            layerElementBinormal.SetReferenceMode(FbxLayerElement.EReferenceMode.eDirect);
            var binormals = mesh.m_pool.m_Tangents
                            .Select((tan, idx) => {
                var b3 = Vector3.Cross(tan, mesh.m_pool.m_Normals[idx]) * tan.w;
                return(new Vector4(b3.x, b3.y, b3.z, 1));
            })
                            .ToList();

            CopyToFbx(layerElementBinormal.GetDirectArray(), binormals);
            layer0.SetBinormals(layerElementBinormal);

            var layerElementMaterial = FbxLayerElementMaterial.Create(fbxMesh, "materials");

            layerElementMaterial.SetMappingMode(FbxLayerElement.EMappingMode.eAllSame);
            layer0.SetMaterials(layerElementMaterial);

            // Export everything up to the last uvset containing data
            // even if some intermediate uvsets have no data.
            // Otherwise Unity will get the uvset numbering wrong on import

            List <List <Vector2> > uvSets = DemuxTexcoords(mesh.m_pool);

            for (int i = 0; i < uvSets.Count; i++)
            {
                FbxLayer layerN = fbxMesh.GetLayer(i);
                while (layerN == null)
                {
                    fbxMesh.CreateLayer();
                    layerN = fbxMesh.GetLayer(i);
                }
                var layerElementUV = FbxLayerElementUV.Create(fbxMesh, String.Format("uv{0}", i));
                layerElementUV.SetMappingMode(FbxLayerElement.EMappingMode.eByControlPoint);
                layerElementUV.SetReferenceMode(FbxLayerElement.EReferenceMode.eDirect);

                List <Vector2> uvSet = uvSets[i];
                if (uvSet == null)
                {
                    // Do nothing
                    // Replicates what the old fbx export code did; seems to work fine
                }
                else
                {
                    Debug.Assert(uvSet.Count == nVerts);
                    CopyToFbx(layerElementUV.GetDirectArray(), uvSet);
                }

                layerN.SetUVs(layerElementUV, FbxLayerElement.EType.eTextureDiffuse);
            }
            return(fbxMesh);
        }
Ejemplo n.º 13
0
        public static bool ExportToFBX(Component_Mesh sourceMesh, string realFileName, out string error)
        {
            //!!!!как для Vegetation. оверрайдить в Component_Mesh?

            //get mesh data
            var operations = new List <Component_RenderingPipeline.RenderSceneData.MeshDataRenderOperation>();

            foreach (var geometry in sourceMesh.GetComponents <Component_MeshGeometry>())
            {
                if (geometry.Enabled)
                {
                    geometry.CompileDataOfThisObject(out var operation);
                    if (operation != null)
                    {
                        operations.Add(operation);
                    }
                }
            }
            //foreach( var geometry in mesh.Result.MeshData.RenderOperations )
            //{
            //}

            FbxManager    manager  = null;
            FbxIOSettings setting  = null;
            FbxExporter   exporter = null;
            FbxScene      scene    = null;

            try
            {
                //init FBX manager
                manager = FbxManager.Create();
                setting = FbxIOSettings.Create(manager, "IOSRoot");
                manager.SetIOSettings(setting);

                scene = FbxScene.Create(manager, "scene");
                scene.GetGlobalSettings().SetAxisSystem(new FbxAxisSystem(FbxAxisSystem.EPreDefinedAxisSystem.eMax));
                scene.GetGlobalSettings().SetSystemUnit(new FbxSystemUnit(100));

                //init FBX scene
                for (int nOper = 0; nOper < operations.Count; nOper++)
                {
                    var oper = operations[nOper];

                    //get data

                    Vector3F[]   positions = null;
                    Vector3F[]   normals   = null;
                    var          texCoords = new List <Vector2F[]>();
                    ColorValue[] colors    = null;
                    Vector3F[]   tangents  = null;
                    Vector3F[]   binormals = null;

                    //Position
                    {
                        if (oper.VertexStructure.GetElementBySemantic(VertexElementSemantic.Position, out VertexElement element) && element.Type == VertexElementType.Float3)
                        {
                            var buffer = oper.VertexBuffers[element.Source];
                            positions = buffer.ExtractChannel <Vector3F>(element.Offset);
                        }
                    }

                    //Normal
                    {
                        if (oper.VertexStructure.GetElementBySemantic(VertexElementSemantic.Normal, out VertexElement element) && element.Type == VertexElementType.Float3)
                        {
                            var buffer = oper.VertexBuffers[element.Source];
                            normals = buffer.ExtractChannel <Vector3F>(element.Offset);
                        }
                    }

                    //TexCoord
                    for (var channel = VertexElementSemantic.TextureCoordinate0; channel <= VertexElementSemantic.TextureCoordinate3; channel++)
                    {
                        if (oper.VertexStructure.GetElementBySemantic(channel, out VertexElement element) && element.Type == VertexElementType.Float2)
                        {
                            var buffer = oper.VertexBuffers[element.Source];
                            texCoords.Add(buffer.ExtractChannel <Vector2F>(element.Offset));
                        }
                    }

                    //Color
                    {
                        if (oper.VertexStructure.GetElementBySemantic(VertexElementSemantic.Color0, out VertexElement element))
                        {
                            if (element.Type == VertexElementType.Float4)
                            {
                                var buffer = oper.VertexBuffers[element.Source];
                                var values = buffer.ExtractChannel <Vector4F>(element.Offset);
                                colors = new ColorValue[positions.Length];
                                int destIndex = 0;
                                foreach (var p in values)
                                {
                                    colors[destIndex++] = p.ToColorValue();
                                }
                            }
                            else if (element.Type == VertexElementType.ColorABGR)
                            {
                                //!!!!check

                                var buffer = oper.VertexBuffers[element.Source];
                                var values = buffer.ExtractChannel <uint>(element.Offset);
                                colors = new ColorValue[positions.Length];
                                int destIndex = 0;
                                foreach (var p in values)
                                {
                                    colors[destIndex++] = new ColorValue(ColorByte.FromABGR(p));
                                }
                            }
                            else if (element.Type == VertexElementType.ColorARGB)
                            {
                                //!!!!check

                                var buffer = oper.VertexBuffers[element.Source];
                                var values = buffer.ExtractChannel <uint>(element.Offset);
                                colors = new ColorValue[positions.Length];
                                int destIndex = 0;
                                foreach (var p in values)
                                {
                                    colors[destIndex++] = new ColorValue(ColorByte.FromARGB(p));
                                }
                            }
                        }
                    }

                    //Tangent, Binormal
                    if (normals != null)
                    {
                        if (oper.VertexStructure.GetElementBySemantic(VertexElementSemantic.Tangent, out VertexElement element) && element.Type == VertexElementType.Float4)
                        {
                            var buffer    = oper.VertexBuffers[element.Source];
                            var tangents4 = buffer.ExtractChannel <Vector4F>(element.Offset);

                            tangents  = new Vector3F[tangents4.Length];
                            binormals = new Vector3F[tangents4.Length];

                            int destIndex = 0;
                            foreach (var p in tangents4)
                            {
                                tangents[destIndex]  = p.ToVector3F();
                                binormals[destIndex] = Vector3F.Cross(p.ToVector3F(), normals[destIndex]) * p.W;
                                destIndex++;
                            }
                        }
                    }

                    //indices
                    int[] indices = null;
                    if (oper.IndexBuffer != null)
                    {
                        indices = oper.IndexBuffer.Indices;
                    }


                    //create geometry

                    var geometryName = "Geometry " + nOper.ToString();
                    var mesh         = FbxMesh.Create(scene, geometryName);

                    mesh.InitControlPoints(positions.Length);

                    FbxLayerElementNormal elementNormals = null;
                    if (normals != null)
                    {
                        elementNormals = mesh.CreateElementNormal();
                        elementNormals.SetMappingMode(FbxLayerElement.EMappingMode.eByControlPoint);
                        elementNormals.SetReferenceMode(FbxLayerElement.EReferenceMode.eDirect);
                    }

                    FbxLayerElementVertexColor elementColors = null;
                    if (colors != null)
                    {
                        elementColors = mesh.CreateElementVertexColor();
                        elementColors.SetMappingMode(FbxLayerElement.EMappingMode.eByControlPoint);
                        elementColors.SetReferenceMode(FbxLayerElement.EReferenceMode.eDirect);
                    }

                    FbxLayerElementTangent elementTangents = null;
                    if (tangents != null)
                    {
                        elementTangents = mesh.CreateElementTangent();
                        elementTangents.SetMappingMode(FbxLayerElement.EMappingMode.eByControlPoint);
                        elementTangents.SetReferenceMode(FbxLayerElement.EReferenceMode.eDirect);
                    }

                    FbxLayerElementBinormal elementBinormals = null;
                    if (binormals != null)
                    {
                        elementBinormals = mesh.CreateElementBinormal();
                        elementBinormals.SetMappingMode(FbxLayerElement.EMappingMode.eByControlPoint);
                        elementBinormals.SetReferenceMode(FbxLayerElement.EReferenceMode.eDirect);
                    }

                    var uvElements = new List <FbxLayerElementUV>();
                    for (int uvIndex = 0; uvIndex < texCoords.Count; uvIndex++)
                    {
                        var pUVElement = mesh.CreateElementUV("texcoord" + uvIndex.ToString());
                        pUVElement.SetMappingMode(FbxLayerElement.EMappingMode.eByControlPoint);
                        pUVElement.SetReferenceMode(FbxLayerElement.EReferenceMode.eDirect);

                        uvElements.Add(pUVElement);
                    }

                    for (int n = 0; n < positions.Length; n++)
                    {
                        mesh.SetControlPointAt(ToFbxVector4(positions[n]), n);

                        if (normals != null)
                        {
                            elementNormals.GetDirectArray().Add(ToFbxVector4(normals[n]));
                        }

                        for (int uvIndex = 0; uvIndex < texCoords.Count; uvIndex++)
                        {
                            var texCoord = texCoords[uvIndex][n];
                            texCoord.Y = 1.0f - texCoord.Y;
                            uvElements[uvIndex].GetDirectArray().Add(ToFbxVector2(texCoord));
                        }

                        if (colors != null)
                        {
                            elementColors.GetDirectArray().Add(ToFbxColor(colors[n]));
                        }

                        if (tangents != null)
                        {
                            elementTangents.GetDirectArray().Add(ToFbxVector4(tangents[n]));
                        }

                        if (binormals != null)
                        {
                            elementBinormals.GetDirectArray().Add(ToFbxVector4(binormals[n]));
                        }
                    }

                    if (normals != null)
                    {
                        mesh.GetLayer(0).SetNormals(elementNormals);
                    }
                    if (colors != null)
                    {
                        mesh.GetLayer(0).SetVertexColors(elementColors);
                    }
                    if (tangents != null)
                    {
                        mesh.GetLayer(0).SetTangents(elementTangents);
                    }
                    if (binormals != null)
                    {
                        mesh.GetLayer(0).SetBinormals(elementBinormals);
                    }


                    int polygonCount = indices.Length / 3;
                    for (int i = 0; i < polygonCount; i++)
                    {
                        mesh.BeginPolygon(-1, -1, -1, false);
                        for (int j = 0; j < 3; j++)
                        {
                            int currentIndex = i * 3 + j;
                            int vertexIndex  = indices[currentIndex];
                            mesh.AddPolygon(vertexIndex);
                        }
                        mesh.EndPolygon();
                    }

                    var node = FbxNode.Create(scene, geometryName);
                    node.SetNodeAttribute(mesh);

                    scene.GetRootNode().AddChild(mesh.GetNode());
                }

                //save

                exporter = FbxExporter.Create(manager, "");
                if (!exporter.Initialize(realFileName, -1, manager.GetIOSettings()))
                {
                    error = "Can't initialize FBX exporter.";
                    return(false);
                }

                if (!exporter.Export(scene))
                {
                    error = "Export to FBX failed.";
                    return(false);
                }
            }
            finally
            {
                try { scene?.Destroy(); } catch { }
                try { exporter?.Destroy(); } catch { }
                try { setting?.Destroy(); } catch { }
                try { manager?.Destroy(); } catch { }
            }

            foreach (var op in operations)
            {
                op.DisposeBuffers();
            }

            error = "";
            return(true);
        }
Ejemplo n.º 14
0
        public void TestBasics()
        {
            Assert.That(!string.IsNullOrEmpty(ModelExporter.GetVersionFromReadme()));

            // Test GetOrCreateLayer
            using (var fbxManager = FbxManager.Create()) {
                var fbxMesh = FbxMesh.Create(fbxManager, "name");
                var layer0  = ModelExporter.GetOrCreateLayer(fbxMesh);
                Assert.That(layer0, Is.Not.Null);
                Assert.That(ModelExporter.GetOrCreateLayer(fbxMesh), Is.EqualTo(layer0));
                var layer5 = ModelExporter.GetOrCreateLayer(fbxMesh, layer: 5);
                Assert.That(layer5, Is.Not.Null);
                Assert.That(layer5, Is.Not.EqualTo(layer0));
            }

            // Test axis conversion: a x b in left-handed is the same as b x a
            // in right-handed (that's why we need to flip the winding order).
            var a         = new Vector3(1, 0, 0);
            var b         = new Vector3(0, 0, 1);
            var crossLeft = Vector3.Cross(a, b);

            var afbx = ModelExporter.ConvertToRightHanded(a);
            var bfbx = ModelExporter.ConvertToRightHanded(b);

            Assert.AreEqual(ModelExporter.ConvertToRightHanded(crossLeft), bfbx.CrossProduct(afbx));

            // Test scale conversion. Nothing complicated here...
            var afbxPosition = ModelExporter.ConvertToRightHanded(a, ModelExporter.UnitScaleFactor);

            Assert.AreEqual(100, afbxPosition.Length());

            // Test rotation conversion.
            var q         = Quaternion.Euler(new Vector3(0, 90, 0));
            var fbxAngles = ModelExporter.ConvertQuaternionToXYZEuler(q);

            Assert.AreEqual(fbxAngles.X, 0);
            Assert.That(fbxAngles.Y, Is.InRange(-90.001, -89.999));
            Assert.AreEqual(fbxAngles.Z, 0);

            Assert.That(ModelExporter.DefaultMaterial);

            // Test non-static functions.
            using (var fbxManager = FbxManager.Create()) {
                var fbxScene = FbxScene.Create(fbxManager, "scene");
                var fbxNode  = FbxNode.Create(fbxScene, "node");
                var exporter = new ModelExporter();

                // Test ExportMaterial: it exports and it re-exports
                bool result = exporter.ExportMaterial(ModelExporter.DefaultMaterial, fbxScene, fbxNode);
                Assert.IsTrue(result);
                var fbxMaterial = fbxNode.GetMaterial(0);
                Assert.That(fbxMaterial, Is.Not.Null);

                result = exporter.ExportMaterial(ModelExporter.DefaultMaterial, fbxScene, fbxNode);
                var fbxMaterial2 = fbxNode.GetMaterial(1);
                Assert.AreEqual(fbxMaterial, fbxMaterial2);

                // Test ExportTexture: it finds the same texture for the default-material (it doesn't create a new one)
                var fbxMaterialNew = FbxSurfaceLambert.Create(fbxScene, "lambert");
                exporter.ExportTexture(ModelExporter.DefaultMaterial, "_MainTex",
                                       fbxMaterialNew, FbxSurfaceLambert.sBump);
                Assert.AreEqual(
                    fbxMaterial.FindProperty(FbxSurfaceLambert.sDiffuse).GetSrcObject(),
                    fbxMaterialNew.FindProperty(FbxSurfaceLambert.sBump).GetSrcObject()
                    );

                // Test ExportMesh: make sure we exported a mesh with welded vertices.
                var cube     = GameObject.CreatePrimitive(PrimitiveType.Cube);
                var cubeNode = FbxNode.Create(fbxScene, "cube");
                exporter.ExportMesh(cube.GetComponent <MeshFilter>().sharedMesh, cubeNode);
                Assert.That(cubeNode.GetMesh(), Is.Not.Null);
                Assert.That(cubeNode.GetMesh().GetControlPointsCount(), Is.EqualTo(8));
            }

            // Test exporting a skinned-mesh. Make sure it doesn't leak (it did at one point)
            {
                var cube      = GameObject.CreatePrimitive(PrimitiveType.Cube);
                var character = new GameObject();
                var smr       = character.AddComponent <SkinnedMeshRenderer>();
                smr.sharedMesh = cube.GetComponent <MeshFilter>().sharedMesh;
                var meshCount = Object.FindObjectsOfType <Mesh>().Length;
                ModelExporter.ExportObject(GetRandomFbxFilePath(), character);
                Assert.AreEqual(meshCount, Object.FindObjectsOfType <Mesh>().Length);
            }
        }