public void Dispose() { if (m_exporter != null) { m_exporter.Destroy(); m_exporter = null; } if (m_ioSettings != null) { m_ioSettings.Destroy(); m_ioSettings = null; } if (m_manager != null) { m_manager.Destroy(); m_manager = null; } }
public (GameObject, List <string> warnings, ImportMaterialCollector) Import() { FbxManager fbxManager = FbxManager.Create(); FbxIOSettings ioSettings = FbxIOSettings.Create(fbxManager, Globals.IOSROOT); fbxManager.SetIOSettings(ioSettings); FbxImporter fbxImporter = FbxImporter.Create(fbxManager, ""); if (!fbxImporter.Initialize(m_path, -1, ioSettings)) { warnings.Add("Failed to initialize FBX importer"); return(null, warnings, null); } FbxScene scene = FbxScene.Create(fbxManager, "scene"); fbxImporter.Import(scene); FbxNode root = scene.GetRootNode(); SetPivots(root); root.ConvertPivotAnimationRecursive(null, FbxNode.EPivotSet.eDestinationPivot, 30); long totalVerts = GetTotalVerts(root); long completedVerts = 0; float fbxUnitToTiltUnit; { var unit = scene.GetGlobalSettings().GetSystemUnit(); if (Path.GetExtension(m_path).ToLower() == ".obj") { // Obj doesn't specify units. We'd rather assume m, but fbx assumes cm. unit = FbxSystemUnit.m; } fbxUnitToTiltUnit = (float)unit.GetConversionFactorTo(FbxSystemUnit.m) * App.METERS_TO_UNITS; } GameObject go = ImportNodes( root, fbxUnitToTiltUnit, ref completedVerts, totalVerts); Debug.Assert(completedVerts == totalVerts); fbxImporter.Destroy(); ioSettings.Destroy(); fbxManager.Destroy(); return(go, warnings.Distinct().ToList(), m_collector); }
//static bool ContainsMeshesRecursive( Node node ) //{ // if( node.HasMeshes ) // return true; // foreach( var child in node.Children ) // { // if( ContainsMeshesRecursive( child ) ) // return true; // } // return false; //} public static void DoImport(Settings settings, out string error) { error = "(NO ERROR MESSAGE)"; LoadNativeLibrary(); FbxManager manager = null; FbxIOSettings setting = null; FbxImporter importer = null; FbxScene scene = null; try { manager = FbxManager.Create(); setting = FbxIOSettings.Create(manager, "IOSRoot"); manager.SetIOSettings(setting); importer = FbxImporter.Create(manager, ""); var realFileName = VirtualPathUtility.GetRealPathByVirtual(settings.virtualFileName); //VirtualFileStream stream = null; //ToDo : FromStream bool status; if (!string.IsNullOrEmpty(realFileName) && File.Exists(realFileName)) { status = importer.Initialize(realFileName, -1, setting); } else { error = "File is not exists."; return; //throw new NotImplementedException(); //ToDo : .... //stream = VirtualFile.Open( settings.virtualFileName ); //FbxStream fbxStream = null; //SWIGTYPE_p_void streamData = null; //status = impoter.Initialize( fbxStream, streamData, -1, setting ); } if (!status) { return; } scene = FbxScene.Create(manager, "scene1"); status = importer.Import(scene); if (!status) { return; } error = ""; var importContext = new ImportContext(); importContext.manager = manager; importContext.scene = scene; importContext.settings = settings; importContext.directoryName = Path.GetDirectoryName(settings.virtualFileName); ImportScene(importContext); ////create meshes (Scene mode) //if( settings.component.Mode.Value == Component_Import3D.ModeEnum.Scene /*&& scene.HasMeshes && scene.MeshCount != 0 */) //{ // importContext.meshesGroup = settings.component.GetComponentByName( "Meshes" ) as Component_Mesh; // if( importContext.meshesGroup == null ) // { // importContext.meshesGroup = settings.component.CreateComponent<Component>( -1, false ); // importContext.meshesGroup.Name = "Meshes"; // } // else // importContext.meshesGroup.Enabled = false; //} ////enable groups //if( importContext.meshesGroup != null ) // importContext.meshesGroup.Enabled = true; //if( importContext.sceneObjectsGroup != null ) // importContext.sceneObjectsGroup.Enabled = true; //stream?.Dispose(); } finally { //Особенности удаления. //Создается через функцию: impoter = FbxImporter.Create(manager, ""); //В таких случаях(создание не через конструктор, а возврат указателя из функции) SWIG задает флажок что объект не владеет ссылкой, поэтому Dispose ничего не делает. //Хотя в SWIG можно задать в конфигурации: %newobject FbxImporter::Create; Тогда объект будет владеть ссылкой. Но все равно в С++ наследники FbxObject не имеют public destructor //поэтому в Dispose вставлен: throw new MethodAccessException("C++ destructor does not have public access"). Поэтому удалять только через Destroy. try { scene?.Destroy(); } catch { } try { importer?.Destroy(); } catch { } try { setting?.Destroy(); } catch { } try { manager?.Destroy(); } catch { } } }
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); }
static bool LoadFBX(ImportContext context, string virtualFileName, out List <MeshData> geometries) { geometries = null; var settings = context.settings; ImportFBX.LoadNativeLibrary(); FbxManager manager = null; FbxIOSettings setting = null; FbxImporter importer = null; FbxScene scene = null; try { manager = FbxManager.Create(); setting = FbxIOSettings.Create(manager, "IOSRoot"); manager.SetIOSettings(setting); importer = FbxImporter.Create(manager, ""); var realFileName = VirtualPathUtility.GetRealPathByVirtual(virtualFileName); //VirtualFileStream stream = null; //ToDo : FromStream bool status; if (!string.IsNullOrEmpty(realFileName) && File.Exists(realFileName)) { status = importer.Initialize(realFileName, -1, setting); } else { return(false); //throw new NotImplementedException(); //ToDo : .... //stream = VirtualFile.Open( settings.virtualFileName ); //FbxStream fbxStream = null; //SWIGTYPE_p_void streamData = null; //status = impoter.Initialize( fbxStream, streamData, -1, setting ); } if (!status) { return(false); } scene = FbxScene.Create(manager, "scene1"); status = importer.Import(scene); if (!status) { return(false); } //convert axis if (context.settings.component.ForceFrontXAxis) { //Через такой конструктор не получится создать такие же оси как EPreDefinedAxisSystem.eMax - Front Axis имеет обратное направление, а направление задать нельзя. //new FbxAxisSystem( FbxAxisSystem.EUpVector.eZAxis, FbxAxisSystem.EFrontVector.eParityOdd, FbxAxisSystem.ECoordSystem.eRightHanded ); //FromFBX Docs: //The enum values ParityEven and ParityOdd denote the first one and the second one of the remain two axes in addition to the up axis. //For example if the up axis is X, the remain two axes will be Y And Z, so the ParityEven is Y, and the ParityOdd is Z ; //We desire to convert the scene from Y-Up to Z-Up. Using the predefined axis system: Max (UpVector = +Z, FrontVector = -Y, CoordSystem = +X (RightHanded)) var maxAxisSystem = new FbxAxisSystem(FbxAxisSystem.EPreDefinedAxisSystem.eMax); if (!scene.GetGlobalSettings().GetAxisSystem().eq(maxAxisSystem)) { maxAxisSystem.ConvertScene(scene); //No conversion will take place if the scene current axis system is equal to the new one. So condition can be removed. } } //convert units if (!scene.GetGlobalSettings().GetSystemUnit().eq(FbxSystemUnit.m)) { FbxSystemUnit.m.ConvertScene(scene); } var additionalTransform = new Matrix4(settings.component.Rotation.Value.ToMatrix3() * Matrix3.FromScale(settings.component.Scale), settings.component.Position); var options = new ImportOptions { NormalsOptions = NormalsAndTangentsLoadOptions.FromFileIfPresentOrCalculate, TangentsOptions = NormalsAndTangentsLoadOptions.FromFileIfPresentOrCalculate, ImportPostProcessFlags = ImportPostProcessFlags.FixInfacingNormals }; options.ImportPostProcessFlags |= ImportPostProcessFlags.SmoothNormals | ImportPostProcessFlags.SmoothTangents; if (context.settings.component.FlipUVs) { options.ImportPostProcessFlags |= ImportPostProcessFlags.FlipUVs; } //if( importContext.settings.component.MergeMeshGeometries ) // options.ImportPostProcessFlags |= ImportPostProcessFlags.MergeGeometriesByMaterials; var sceneLoader = new SceneLoader(); sceneLoader.Load(scene, manager, options, additionalTransform); geometries = sceneLoader.Geometries; //foreach( var geometry in sceneLoader.Geometries ) // ImportGeometry( context, destinationMesh, geometry ); ////check is it a billboard //MeshGetIsBillboard( context, destinationMesh ); //stream?.Dispose(); } finally { //Особенности удаления. //Создается через функцию: impoter = FbxImporter.Create(manager, ""); //В таких случаях(создание не через конструктор, а возврат указателя из функции) SWIG задает флажок что объект не владеет ссылкой, поэтому Dispose ничего не делает. //Хотя в SWIG можно задать в конфигурации: %newobject FbxImporter::Create; Тогда объект будет владеть ссылкой. Но все равно в С++ наследники FbxObject не имеют public destructor //поэтому в Dispose вставлен: throw new MethodAccessException("C++ destructor does not have public access"). Поэтому удалять только через Destroy. try { scene?.Destroy(); } catch { } try { importer?.Destroy(); } catch { } try { setting?.Destroy(); } catch { } try { manager?.Destroy(); } catch { } } return(true); }