Пример #1
0
        /// <summary>
        /// Exports a scene to the specified format and writes it to a data blob.
        /// </summary>
        /// <param name="scene">Scene containing the model to export.</param>
        /// <param name="exportFormatId">FormatID representing the format to export to.</param>
        /// <param name="preProcessing">Preprocessing flags to apply to the model before it is exported.</param>
        /// <returns>The resulting data blob, or null if the export failed.</returns>
        /// <exception cref="ArgumentNullException">Thrown if the scene is null.</exception>
        /// <exception cref="System.ObjectDisposedException">Thrown if the context has already been disposed of.</exception>
        public ExportDataBlob ExportToBlob(Scene scene, String exportFormatId, PostProcessSteps preProcessing)
        {
            CheckDisposed();

            IntPtr fileIO   = IntPtr.Zero;
            IntPtr scenePtr = IntPtr.Zero;

            if (scene == null)
            {
                throw new ArgumentNullException("scene", "Scene must exist.");
            }

            try
            {
                scenePtr = Scene.ToUnmanagedScene(scene);

                return(AssimpLibrary.Instance.ExportSceneToBlob(scenePtr, exportFormatId, preProcessing));
            }
            finally
            {
                if (scenePtr != IntPtr.Zero)
                {
                    Scene.FreeUnmanagedScene(scenePtr);
                }
            }
        }
Пример #2
0
        /// <summary>
        /// Exports a scene to the specified format and writes it to a file.
        /// </summary>
        /// <param name="scene">Scene containing the model to export.</param>
        /// <param name="fileName">Path to the file.</param>
        /// <param name="exportFormatId">FormatID representing the format to export to.</param>
        /// <param name="preProcessing">Preprocessing flags to apply to the model before it is exported.</param>
        /// <returns>True if the scene was exported successfully, false otherwise.</returns>
        /// <exception cref="ArgumentNullException">Thrown if the scene is null.</exception>
        /// <exception cref="System.ObjectDisposedException">Thrown if the context has already been disposed of.</exception>
        public bool ExportFile(Scene scene, String fileName, String exportFormatId, PostProcessSteps preProcessing)
        {
            CheckDisposed();

            IntPtr fileIO   = IntPtr.Zero;
            IntPtr scenePtr = IntPtr.Zero;

            if (scene == null)
            {
                throw new ArgumentNullException("scene", "Scene must exist.");
            }

            try
            {
                scenePtr = Scene.ToUnmanagedScene(scene);

                ReturnCode status = AssimpLibrary.Instance.ExportScene(scenePtr, exportFormatId, fileName, fileIO, preProcessing);

                return(status == ReturnCode.Success);
            }
            finally
            {
                if (scenePtr != IntPtr.Zero)
                {
                    Scene.FreeUnmanagedScene(scenePtr);
                }
            }
        }
Пример #3
0
        public static ModelMesh[] LoadFromFile(GameMode gameMode, string filePath)
        {
            if (".pmesh".Equals(Path.GetExtension(filePath), StringComparison.OrdinalIgnoreCase))
            {
                return(new[] { LoadPMesh(gameMode, filePath) });
            }
            else
            {
                var modelDirectory = Path.GetDirectoryName(filePath);

                var context = new AssimpContext();
                const PostProcessSteps flags = PostProcessSteps.GenerateNormals | PostProcessSteps.GenerateUVCoords
                                               | PostProcessSteps.FlipWindingOrder
                                               | PostProcessSteps.FlipUVs;
                var scene = context.ImportFile(filePath, flags);

                var meshs = new List <ModelMesh>();
                foreach (var assimpMesh in scene.Meshes)
                {
                    var modelMesh = new ModelMesh(gameMode, scene, assimpMesh, modelDirectory);
                    meshs.Add(modelMesh);
                }

                return(meshs.ToArray());
            }
        }
Пример #4
0
 /// <summary>
 ///     Loads the model specified file path.
 /// </summary>
 /// <param name="filePath">The file path.</param>
 /// <param name="parallelLoad">if set to <c>true</c> [parallel load].</param>
 /// <param name="postprocessSteps">The postprocess steps.</param>
 /// <param name="configs">The configs.</param>
 /// <returns></returns>
 public HelixToolkitScene Load(string filePath, bool parallelLoad, PostProcessSteps postprocessSteps,
                               params PropertyConfig[] configs)
 {
     Configuration.EnableParallelProcessing = parallelLoad;
     Configuration.AssimpPostProcessSteps   = postprocessSteps;
     return(Load(filePath));
 }
Пример #5
0
        public Mesh(string FileName)
        {
            Vertices = new ModelPart <Vertex>();

            Indices = new ModelPart <int>();


            PostProcessSteps Flags = PostProcessSteps.GenerateSmoothNormals | PostProcessSteps.CalculateTangentSpace | PostProcessSteps.Triangulate;

            AssimpContext importer = new AssimpContext();

            Scene model = importer.ImportFile(FileName, Flags);


            foreach (Assimp.Mesh mesh in model.Meshes)
            {
                for (int i = 0; i < mesh.VertexCount; i++)
                {
                    Vector3D Pos    = mesh.Vertices[i];
                    Vector3D Normal = mesh.Normals[i];
                    Vector3D Tex    = mesh.HasTextureCoords(0) ? mesh.TextureCoordinateChannels[0][i] : new Vector3D();

                    Vertices.Data.Add(new Vertex(new Vector3(Pos.X, Pos.Y, Pos.Z), new Vector3(Normal.X, Normal.Y, Normal.Z), new Vector2(Tex.X, Tex.Y)));
                }



                int indexBase = Indices.Data.Count();

                foreach (Face Faces in mesh.Faces)
                {
                    if (Faces.IndexCount != 3)
                    {
                        continue;
                    }

                    Indices.Data.Add(indexBase + Faces.Indices[0]);
                    Indices.Data.Add(indexBase + Faces.Indices[1]);
                    Indices.Data.Add(indexBase + Faces.Indices[2]);
                }
            }



            Vertices.Count = Vertices.Data.Count();

            Vertices.SizeInBytes = Utilities.SizeOf <Vertex>() * Vertices.Data.Count();

            Vertices.Size = Utilities.SizeOf <Vertex>();



            Indices.Count = Indices.Data.Count();

            Indices.SizeInBytes = Utilities.SizeOf <int>() * Indices.Data.Count();

            Indices.Size = Utilities.SizeOf <int>();
        }
Пример #6
0
        /// <summary>
        /// Load an FBX file from a file on disk.
        /// </summary>
        /// <param name="filename">
        /// The filename of the FBX file to load.
        /// </param>
        /// <param name="additionalAnimationFiles">
        /// A dictionary mapping of animation names to filenames for additional FBX files to load.
        /// </param>
        /// <returns>
        /// The loaded <see cref="IModel"/>.
        /// </returns>
        public IModel Load(string filename, Dictionary <string, string> additionalAnimationFiles)
        {
            this.LoadAssimpLibrary();

            // Import the scene via AssImp.
            var importer = new AssimpContext();
            const PostProcessSteps ProcessFlags = 0
                                                  | PostProcessSteps.FlipUVs
                                                  | PostProcessSteps.FlipWindingOrder
            ;
            var scene = importer.ImportFile(filename, ProcessFlags);

            VertexPositionNormalTextureBlendable[] vertexes;
            int[]      indices;
            IModelBone boneHierarchy;

            if (scene.MeshCount >= 1)
            {
                var boneWeightingMap = this.BuildBoneWeightingMap(scene);

                boneHierarchy = this.ImportBoneHierarchy(scene.RootNode, scene.Meshes[0]);

                vertexes = this.ImportVertexes(scene, boneWeightingMap);
                indices  = this.ImportIndices(scene);
            }
            else
            {
                boneHierarchy = this.ImportBoneHierarchy(scene.RootNode, null);
                vertexes      = new VertexPositionNormalTextureBlendable[0];
                indices       = new int[0];
            }

            // Create the list of animations, including the null animation.
            var animations = new List <IAnimation>();

            // Import the basic animation.
            if (scene.AnimationCount > 0)
            {
                animations.AddRange(
                    scene.Animations.Select(
                        assimpAnimation => this.ImportAnimation(assimpAnimation.Name, assimpAnimation)));
            }

            // For each additional animation file, import that and add the animation to the existing scene.
            animations.AddRange(
                from kv in additionalAnimationFiles
                let animationImporter = new AssimpContext()
                                        let additionalScene = animationImporter.ImportFile(kv.Value, ProcessFlags)
                                                              where additionalScene.AnimationCount == 1
                                                              select this.ImportAnimation(kv.Key, additionalScene.Animations[0]));

            // Return the resulting model.
            return(new Model(
                       new AnimationCollection(animations),
                       boneHierarchy,
                       vertexes,
                       indices));
        }
Пример #7
0
 public Model(
     GraphicsDevice gd,
     ResourceFactory factory,
     Stream stream,
     string extension,
     VertexElementSemantic[] elementSemantics,
     ModelCreateInfo?createInfo,
     PostProcessSteps flags = DefaultPostProcessSteps)
 {
     Init(gd, factory, stream, extension, elementSemantics, createInfo, flags);
 }
Пример #8
0
 public Model(
     GraphicsDevice gd,
     ResourceFactory factory,
     Stream stream,
     string extension,
     VertexLayoutDescription layout,
     ModelCreateInfo?createInfo,
     PostProcessSteps flags = DefaultPostProcessSteps)
 {
     Init(gd, factory, stream, extension, layout, createInfo, flags);
 }
Пример #9
0
        /// <summary>
        /// Converts the model contained in the file to the specified format and save it to a file.
        /// </summary>
        /// <param name="inputFilename">Input file name to import</param>
        /// <param name="importProcessSteps">Post processing steps used for the import</param>
        /// <param name="outputFilename">Output file name to export to</param>
        /// <param name="exportFormatId">Format id that specifies what format to export to</param>
        /// <param name="exportProcessSteps">Pre processing steps used for the export</param>
        /// <returns>True if the conversion was successful or not, false otherwise.</returns>
        /// <exception cref="AssimpException">Thrown if there was a general error in importing the model.</exception>
        /// <exception cref="System.IO.FileNotFoundException">Thrown if the file could not be located.</exception>
        /// <exception cref="System.ObjectDisposedException">Thrown if the context has already been disposed of.</exception>
        public bool ConvertFromFileToFile(String inputFilename, PostProcessSteps importProcessSteps, String outputFilename, String exportFormatId, PostProcessSteps exportProcessSteps)
        {
            CheckDisposed();

            if (!TestIfExportIdIsValid(exportFormatId))
            {
                return(false);
            }

            IntPtr ptr    = IntPtr.Zero;
            IntPtr fileIO = IntPtr.Zero;

            //Only do file checks if not using a custom IOSystem
            if (UsingCustomIOSystem)
            {
                fileIO = m_ioSystem.AiFileIO;
            }
            else if (String.IsNullOrEmpty(inputFilename) || !File.Exists(inputFilename))
            {
                throw new FileNotFoundException("Filename was null or could not be found", inputFilename);
            }

            PrepareImport();

            try
            {
                ptr = AssimpLibrary.Instance.ImportFile(inputFilename, PostProcessSteps.None, fileIO, m_propStore);

                if (ptr == IntPtr.Zero)
                {
                    throw new AssimpException("Error importing file: " + AssimpLibrary.Instance.GetErrorString());
                }

                TransformScene(ptr);

                if (importProcessSteps != PostProcessSteps.None)
                {
                    ptr = AssimpLibrary.Instance.ApplyPostProcessing(ptr, importProcessSteps);
                }

                ReturnCode status = AssimpLibrary.Instance.ExportScene(ptr, exportFormatId, outputFilename, fileIO, exportProcessSteps);

                return(status == ReturnCode.Success);
            }
            finally
            {
                CleanupImport();

                if (ptr != IntPtr.Zero)
                {
                    AssimpLibrary.Instance.ReleaseImport(ptr);
                }
            }
        }
Пример #10
0
        /// <summary>
        /// Imports a model from the stream. The importer sets configurations
        /// and loads the model into managed memory, releasing the unmanaged memory used by Assimp. It is up to the caller to dispose of the stream.
        /// </summary>
        /// <param name="buffer">Pointer to memory location</param>
        /// <param name="length">Length of buffer in memory</param>
        /// <param name="postProcessFlags">Post processing flags, if any</param>
        /// <param name="formatHint">Format extension to serve as a hint to Assimp to choose which importer to use</param>
        /// <returns>The imported scene</returns>
        /// <exception cref="AssimpException">Thrown if the pointer is not valid (null or zero) or the length is zero or if the format hint is null or empty.</exception>
        /// <exception cref="System.ObjectDisposedException">Thrown if the context has already been disposed of.</exception>
        public Scene ImportFileFromMemory(IntPtr buffer, uint length, PostProcessSteps postProcessFlags, String formatHint)
        {
            CheckDisposed();

            if (buffer == IntPtr.Zero)
            {
                throw new AssimpException("buffer", "Pointer to memory location must not be zero.");
            }

            if (length <= 0)
            {
                throw new AssimpException("length", "Length of buffer must be greater than zero.");
            }

            if (String.IsNullOrEmpty(formatHint))
            {
                throw new AssimpException("formatHint", "Format hint is null or empty");
            }

            IntPtr ptr = IntPtr.Zero;

            PrepareImport();

            try
            {
                ptr = AssimpLibrary.Instance.ImportFileFromMemory(buffer, length, PostProcessSteps.None, formatHint, m_propStore);

                if (ptr == IntPtr.Zero)
                {
                    throw new AssimpException("Error importing file: " + AssimpLibrary.Instance.GetErrorString());
                }

                TransformScene(ptr);

                if (postProcessFlags != PostProcessSteps.None)
                {
                    ptr = AssimpLibrary.Instance.ApplyPostProcessing(ptr, postProcessFlags);
                }

                return(Scene.FromUnmanagedScene(ptr));
            }
            finally
            {
                CleanupImport();

                if (ptr != IntPtr.Zero)
                {
                    AssimpLibrary.Instance.ReleaseImport(ptr);
                }
            }
        }
Пример #11
0
 public Model(
     GraphicsDevice gd,
     ResourceFactory factory,
     string filename,
     VertexElementSemantic[] elementSemantics,
     ModelCreateInfo?createInfo,
     PostProcessSteps flags = DefaultPostProcessSteps)
 {
     using (FileStream fs = File.OpenRead(filename))
     {
         string extension = Path.GetExtension(filename);
         Init(gd, factory, fs, extension, elementSemantics, createInfo, flags);
     }
 }
Пример #12
0
        public Core.Entities.Mesh LoadFromFile(string path)
        {
            AssimpContext          context           = new AssimpContext();
            const PostProcessSteps ASSIMP_LOAD_FLAGS = PostProcessSteps.Triangulate | PostProcessSteps.GenerateSmoothNormals | PostProcessSteps.FlipUVs;
            Scene loadedAssimpScene = context.ImportFile(path, ASSIMP_LOAD_FLAGS);

            if (loadedAssimpScene == null || loadedAssimpScene.SceneFlags == SceneFlags.Incomplete)
            {
                Console.WriteLine("Scene error");
            }

            processNode(loadedAssimpScene.RootNode, loadedAssimpScene);

            return(convertAssimpToEngineFormat(meshes[0]));
        }
Пример #13
0
        /// <summary>
        /// Imports a model from the specified file. The importer sets configurations
        /// and loads the model into managed memory, releasing the unmanaged memory used by Assimp.
        /// </summary>
        /// <param name="file">Full path to the file</param>
        /// <param name="postProcessFlags">Post processing flags, if any</param>
        /// <returns>The imported scene</returns>
        /// <exception cref="AssimpException">Thrown if there was a general error in importing the model.</exception>
        /// <exception cref="System.IO.FileNotFoundException">Thrown if the file could not be located.</exception>
        /// <exception cref="System.ObjectDisposedException">Thrown if the context has already been disposed of.</exception>
        public Scene ImportFile(String file, PostProcessSteps postProcessFlags)
        {
            CheckDisposed();

            IntPtr ptr    = IntPtr.Zero;
            IntPtr fileIO = IntPtr.Zero;

            //Only do file checks if not using a custom IOSystem
            if (UsingCustomIOSystem)
            {
                fileIO = m_ioSystem.AiFileIO;
            }
            else if (string.IsNullOrEmpty(file) ||
                     !File.Exists(file))
            {
                throw new FileNotFoundException("Filename was null or could not be found", file);
            }

            PrepareImport();

            try
            {
                ptr = AssimpLibrary.Instance.ImportFile(file, PostProcessSteps.None, fileIO, m_propStore);

                if (ptr == IntPtr.Zero)
                {
                    throw new AssimpException("Error importing file: " + AssimpLibrary.Instance.GetErrorString());
                }

                TransformScene(ptr);

                if (postProcessFlags != PostProcessSteps.None)
                {
                    ptr = AssimpLibrary.Instance.ApplyPostProcessing(ptr, postProcessFlags);
                }

                return(Scene.FromUnmanagedScene(ptr));
            }
            finally
            {
                CleanupImport();

                if (ptr != IntPtr.Zero)
                {
                    AssimpLibrary.Instance.ReleaseImport(ptr);
                }
            }
        }
Пример #14
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="rootJOBJ"></param>
        public static void ExportFile(string filePath, HSD_JOBJ rootJOBJ, ModelExportSettings settings = null, Dictionary <int, string> boneLabels = null)
        {
            ModelExporter mex      = new ModelExporter();
            AssimpContext importer = new AssimpContext();

            Dictionary <string, string> extToId = new Dictionary <string, string>();

            foreach (var v in importer.GetSupportedExportFormats())
            {
                if (!extToId.ContainsKey("." + v.FileExtension))
                {
                    extToId.Add("." + v.FileExtension, v.FormatId);
                }
            }

            PostProcessSteps postProcess = PostProcessSteps.FlipWindingOrder;

            if (settings.Optimize)
            {
                postProcess |= PostProcessSteps.JoinIdenticalVertices;
            }

            if (settings.FlipUVs)
            {
                postProcess |= PostProcessSteps.FlipUVs;
            }

            settings.Directory = System.IO.Path.GetDirectoryName(filePath) + "\\";

            if (System.IO.Path.GetExtension(filePath).ToLower() == ".dae")
            {
                var sc = mex.WriteRootNode(rootJOBJ, settings, boneLabels);

                /*var scn = Scene.ToUnmanagedScene(sc);
                 * scn = AssimpLibrary.Instance.ApplyPostProcessing(scn, postProcess);
                 * var scene = Scene.FromUnmanagedScene(scn);
                 * Scene.FreeUnmanagedScene(scn);*/
                ExportCustomDAE(filePath, sc, settings);
            }
            else
            {
                importer.ExportFile(mex.WriteRootNode(rootJOBJ, settings, boneLabels), filePath, extToId[System.IO.Path.GetExtension(filePath)], postProcess);
            }

            importer.Dispose();
        }
Пример #15
0
        /// <summary>
        /// Imports a model from the stream. The importer sets configurations
        /// and loads the model into managed memory, releasing the unmanaged memory used by Assimp. It is up to the caller to dispose of the stream.
        /// </summary>
        /// <param name="stream">Stream to read from</param>
        /// <param name="postProcessFlags">Post processing flags, if any</param>
        /// <param name="formatHint">Format extension to serve as a hint to Assimp to choose which importer to use</param>
        /// <returns>The imported scene</returns>
        /// <exception cref="AssimpException">Thrown if the stream is not valid (null or write-only) or if the format hint is null or empty.</exception>
        /// <exception cref="System.ObjectDisposedException">Thrown if the context has already been disposed of.</exception>
        public Scene ImportFileFromStream(Stream stream, PostProcessSteps postProcessFlags, String formatHint)
        {
            CheckDisposed();

            if (stream == null || stream.CanRead != true)
            {
                throw new AssimpException("stream", "Can't read from the stream it's null or write-only");
            }

            if (String.IsNullOrEmpty(formatHint))
            {
                throw new AssimpException("formatHint", "Format hint is null or empty");
            }

            IntPtr ptr = IntPtr.Zero;

            PrepareImport();

            try
            {
                ptr = AssimpLibrary.Instance.ImportFileFromStream(stream, PostProcessSteps.None, formatHint, m_propStore);

                if (ptr == IntPtr.Zero)
                {
                    throw new AssimpException("Error importing file: " + AssimpLibrary.Instance.GetErrorString());
                }

                TransformScene(ptr);

                if (postProcessFlags != PostProcessSteps.None)
                {
                    ptr = AssimpLibrary.Instance.ApplyPostProcessing(ptr, postProcessFlags);
                }

                return(Scene.FromUnmanagedScene(ptr));
            }
            finally
            {
                CleanupImport();

                if (ptr != IntPtr.Zero)
                {
                    AssimpLibrary.Instance.ReleaseImport(ptr);
                }
            }
        }
Пример #16
0
        private PostProcessSteps GetConfig()
        {
            PostProcessSteps config =
                PostProcessSteps.JoinIdenticalVertices |
                PostProcessSteps.RemoveRedundantMaterials |
                PostProcessSteps.Triangulate |
                PostProcessSteps.GenerateUVCoords |
                PostProcessSteps.FindInvalidData |
                PostProcessSteps.FindInstances |
                PostProcessSteps.ValidateDataStructure |
                PostProcessSteps.OptimizeMeshes;

            if (OptimizeLevel >= 1)
            {
                config |= PostProcessSteps.JoinIdenticalVertices;
            }

            if (OptimizeLevel >= 2)
            {
                config |= PostProcessSteps.OptimizeMeshes;
                config |= PostProcessSteps.SortByPrimitiveType;
            }

            if (OptimizeLevel >= 3)
            {
                config |= PostProcessSteps.OptimizeGraph;
            }

            if (LimitBoneWeights)
            {
                config |= PostProcessSteps.LimitBoneWeights;
            }
            if (CalculateNormal)
            {
                config |= PostProcessSteps.GenerateSmoothNormals;
            }
            if (CalculateTangent)
            {
                config |= PostProcessSteps.CalculateTangentSpace;
            }

            return(config);
        }
Пример #17
0
    void CopyFileForResources(string pathOrigin)
    {
        if (File.Exists(pathOrigin))
        {
            //string pathResources = Application.streamingAssetsPath;
            string pathResources = @"C:\git\poc-tcc\augmented-reality\Assets\MarkerBasedARExample\Resources\Gift3.fbx";

            File.Copy(pathOrigin, pathResources, true);
            PropertiesModel.NameObjectSelected = pathOrigin;
            //string url = $"file:///{pathOrigin}";

            using (AssimpContext assimp = new AssimpContext())
            {
                assimp.SetConfig(new Assimp.Configs.MeshVertexLimitConfig(60000));
                assimp.SetConfig(new Assimp.Configs.MeshTriangleLimitConfig(60000));
                assimp.SetConfig(new Assimp.Configs.RemoveDegeneratePrimitivesConfig(true));
                assimp.SetConfig(new Assimp.Configs.SortByPrimitiveTypeConfig(Assimp.PrimitiveType.Line | Assimp.PrimitiveType.Point));

                PostProcessSteps postProcessSteps = PostProcessSteps.SplitLargeMeshes |
                                                    PostProcessSteps.OptimizeGraph |
                                                    PostProcessSteps.OptimizeMeshes |
                                                    PostProcessSteps.Triangulate |
                                                    PostProcessSteps.SortByPrimitiveType |
                                                    PostProcessPreset.TargetRealTimeMaximumQuality |
                                                    PostProcessSteps.FlipWindingOrder;

                Assimp.Scene scene = assimp.ImportFile(pathOrigin, postProcessSteps);
                print("rootNode name: " + scene.RootNode.Name);

                MainNodeFBX mainNodeFBX = new MainNodeFBX();
                PropertiesModel.ImportedExternalObject = new GameObject(scene.RootNode.Name);

                ImportNode(scene.RootNode, mainNodeFBX, scene, PropertiesModel.ImportedExternalObject);

                DontDestroyOnLoad(PropertiesModel.ImportedExternalObject);
                SceneManager.LoadScene("ObjectSelectMarkerLessScene");
            }
        }
    }
Пример #18
0
        public static SimpleModel LoadFromFile(String filePath, GraphicsDevice gd, PostProcessSteps ppSteps, params PropertyConfig[] configs)
        {
            if (!File.Exists(filePath) || gd == null)
            {
                return(null);
            }

            AssimpContext importer = new AssimpContext();

            if (configs != null)
            {
                foreach (PropertyConfig config in configs)
                {
                    importer.SetConfig(config);
                }
            }

            Scene scene = importer.ImportFile(filePath, ppSteps);

            if (scene == null)
            {
                return(null);
            }

            SimpleModel model = new SimpleModel();

            model.WorldMatrix = SN.Matrix4x4.Identity;
            if (!model.CreateVertexBuffer(scene, gd, Path.GetDirectoryName(filePath)))
            {
                return(null);
            }

            model.ComputeBoundingBox(scene);
            model.AdjustModelScale();

            return(model);
        }
Пример #19
0
 /// <summary>
 /// Converts the model contained in the stream to the specified format and save it to a file.
 /// </summary>
 /// <param name="inputStream">Stream to read from</param>
 /// <param name="importFormatHint">Format extension to serve as a hint to Assimp to choose which importer to use</param>
 /// <param name="outputFilename">Output file name to export to</param>
 /// <param name="exportFormatId">Format id that specifies what format to export to</param>
 /// <param name="exportProcessSteps">Pre processing steps used for the export</param>
 /// <returns>True if the conversion was successful or not, false otherwise.</returns>
 /// <exception cref="AssimpException">Thrown if the stream is not valid (null or write-only) or if the format hint is null or empty.</exception>
 /// <exception cref="System.ObjectDisposedException">Thrown if the context has already been disposed of.</exception>
 public bool ConvertFromStreamToFile(Stream inputStream, String importFormatHint, String outputFilename, String exportFormatId, PostProcessSteps exportProcessSteps)
 {
     return(ConvertFromStreamToFile(inputStream, importFormatHint, PostProcessSteps.None, outputFilename, exportFormatId, exportProcessSteps));
 }
Пример #20
0
 /// <summary>
 /// Converts the model contained in the stream to the specified format and save it to a data blob.
 /// </summary>
 /// <param name="inputStream">Stream to read from</param>
 /// <param name="importFormatHint">Format extension to serve as a hint to Assimp to choose which importer to use</param>
 /// <param name="exportFormatId">Format id that specifies what format to export to</param>
 /// <param name="exportProcessSteps">Pre processing steps used for the export</param>
 /// <returns>Data blob containing the exported scene in a binary form</returns>
 /// <exception cref="AssimpException">Thrown if the stream is not valid (null or write-only) or if the format hint is null or empty.</exception>
 /// <exception cref="System.ObjectDisposedException">Thrown if the context has already been disposed of.</exception>
 public ExportDataBlob ConvertFromStreamToBlob(Stream inputStream, String importFormatHint, String exportFormatId, PostProcessSteps exportProcessSteps)
 {
     return(ConvertFromStreamToBlob(inputStream, importFormatHint, PostProcessSteps.None, exportFormatId, exportProcessSteps));
 }
Пример #21
0
 /// <summary>
 /// Converts the model contained in the file to the specified format and save it to a file.
 /// </summary>
 /// <param name="inputFilename">Input file name to import</param>
 /// <param name="outputFilename">Output file name to export to</param>
 /// <param name="exportFormatId">Format id that specifies what format to export to</param>
 /// <param name="exportProcessSteps">Pre processing steps used for the export</param>
 /// <returns>True if the conversion was successful or not, false otherwise.</returns>
 /// <exception cref="AssimpException">Thrown if there was a general error in importing the model.</exception>
 /// <exception cref="System.IO.FileNotFoundException">Thrown if the file could not be located.</exception>
 /// <exception cref="System.ObjectDisposedException">Thrown if the context has already been disposed of.</exception>
 public bool ConvertFromFileToFile(String inputFilename, String outputFilename, String exportFormatId, PostProcessSteps exportProcessSteps)
 {
     return(ConvertFromFileToFile(inputFilename, PostProcessSteps.None, outputFilename, exportFormatId, exportProcessSteps));
 }
Пример #22
0
 /// <summary>
 /// Converts the model contained in the file to the specified format and save it to a data blob.
 /// </summary>
 /// <param name="inputFilename">Input file name to import</param>
 /// <param name="exportFormatId">Format id that specifies what format to export to</param>
 /// <param name="exportProcessSteps">Pre processing steps used for the export</param>
 /// <returns>Data blob containing the exported scene in a binary form</returns>
 /// <exception cref="AssimpException">Thrown if there was a general error in importing the model.</exception>
 /// <exception cref="System.IO.FileNotFoundException">Thrown if the file could not be located.</exception>
 /// <exception cref="System.ObjectDisposedException">Thrown if the context has already been disposed of.</exception>
 public ExportDataBlob ConvertFromFileToBlob(String inputFilename, String exportFormatId, PostProcessSteps exportProcessSteps)
 {
     return(ConvertFromFileToBlob(inputFilename, PostProcessSteps.None, exportFormatId, exportProcessSteps));
 }
Пример #23
0
        // Load a model from file using the ASSIMP model loader and generate all resources required to render the model
        void loadModel(string filename)
        {
            // Load the model from file using ASSIMP

            // Flags for loading the mesh
            PostProcessSteps assimpFlags = PostProcessSteps.FlipWindingOrder | PostProcessSteps.Triangulate | PostProcessSteps.PreTransformVertices;

            var scene = new AssimpContext().ImportFile(filename, assimpFlags);

            // Generate vertex buffer from ASSIMP scene data
            float scale = 1.0f;
            NativeList <Vertex> vertexBuffer = new NativeList <Vertex>();

            // Iterate through all meshes in the file and extract the vertex components
            for (int m = 0; m < scene.MeshCount; m++)
            {
                for (int v = 0; v < scene.Meshes[(int)m].VertexCount; v++)
                {
                    Vertex vertex;
                    Mesh   mesh = scene.Meshes[m];

                    // Use glm make_* functions to convert ASSIMP vectors to glm vectors
                    vertex.pos    = new Vector3(mesh.Vertices[v].X, mesh.Vertices[v].Y, mesh.Vertices[v].Z) * scale;
                    vertex.normal = new Vector3(mesh.Normals[v].X, mesh.Normals[v].Y, mesh.Normals[v].Z);
                    // Texture coordinates and colors may have multiple channels, we only use the first [0] one
                    vertex.uv = new Vector2(mesh.TextureCoordinateChannels[0][v].X, mesh.TextureCoordinateChannels[0][v].Y);
                    // Mesh may not have vertex colors
                    if (mesh.HasVertexColors(0))
                    {
                        vertex.color = new Vector3(mesh.VertexColorChannels[0][v].R, mesh.VertexColorChannels[0][v].G, mesh.VertexColorChannels[0][v].B);
                    }
                    else
                    {
                        vertex.color = new Vector3(1f);
                    }

                    // Vulkan uses a right-handed NDC (contrary to OpenGL), so simply flip Y-Axis
                    vertex.pos.Y *= -1.0f;

                    vertexBuffer.Add(vertex);
                }
            }
            ulong vertexBufferSize = (ulong)(vertexBuffer.Count * sizeof(Vertex));

            // Generate index buffer from ASSIMP scene data
            NativeList <uint> indexBuffer = new NativeList <uint>();

            for (int m = 0; m < scene.MeshCount; m++)
            {
                uint indexBase = indexBuffer.Count;
                for (int f = 0; f < scene.Meshes[m].FaceCount; f++)
                {
                    // We assume that all faces are triangulated
                    for (int i = 0; i < 3; i++)
                    {
                        indexBuffer.Add((uint)scene.Meshes[m].Faces[f].Indices[i] + indexBase);
                    }
                }
            }
            ulong indexBufferSize = (ulong)(indexBuffer.Count * sizeof(uint));

            model_indices_count = (int)indexBuffer.Count;

            // Static mesh should always be Device local

            bool useStaging = true;

            if (useStaging)
            {
                VkBuffer       vertexStaging_buffer;
                VkDeviceMemory vertexStaging_memory;
                VkBuffer       indexStaging_buffer;
                VkDeviceMemory indexStaging_memory;

                // Create staging buffers
                // Vertex data
                Util.CheckResult(vulkanDevice.createBuffer(
                                     VkBufferUsageFlags.TransferSrc,
                                     VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent,
                                     vertexBufferSize,
                                     &vertexStaging_buffer,
                                     &vertexStaging_memory,
                                     vertexBuffer.Data.ToPointer()));
                // Index data
                Util.CheckResult(vulkanDevice.createBuffer(
                                     VkBufferUsageFlags.TransferSrc,
                                     VkMemoryPropertyFlags.HostVisible | VkMemoryPropertyFlags.HostCoherent,
                                     indexBufferSize,
                                     &indexStaging_buffer,
                                     &indexStaging_memory,
                                     indexBuffer.Data.ToPointer()));

                // Create Device local buffers
                // Vertex buffer
                Util.CheckResult(vulkanDevice.createBuffer(
                                     VkBufferUsageFlags.VertexBuffer | VkBufferUsageFlags.TransferDst,
                                     VkMemoryPropertyFlags.DeviceLocal,
                                     vertexBufferSize,
                                     out model_vertices_buffer,
                                     out model_vertices_memory));
                // Index buffer
                Util.CheckResult(vulkanDevice.createBuffer(
                                     VkBufferUsageFlags.IndexBuffer | VkBufferUsageFlags.TransferDst,
                                     VkMemoryPropertyFlags.DeviceLocal,
                                     indexBufferSize,
                                     out model_indices_buffer,
                                     out model_indices_memory));

                // Copy from staging buffers
                VkCommandBuffer copyCmd = createCommandBuffer(VkCommandBufferLevel.Primary, true);

                VkBufferCopy copyRegion = new VkBufferCopy();

                copyRegion.size = vertexBufferSize;

                vkCmdCopyBuffer(
                    copyCmd,
                    vertexStaging_buffer,
                    model_vertices_buffer,
                    1,
                    &copyRegion);

                copyRegion.size = indexBufferSize;

                vkCmdCopyBuffer(
                    copyCmd,
                    indexStaging_buffer,
                    model_indices_buffer,
                    1,
                    &copyRegion);

                flushCommandBuffer(copyCmd, queue, true);


                vkDestroyBuffer(device, vertexStaging_buffer, null);

                vkFreeMemory(device, vertexStaging_memory, null);

                vkDestroyBuffer(device, indexStaging_buffer, null);

                vkFreeMemory(device, indexStaging_memory, null);
            }
            else
            {
                // Vertex buffer
                Util.CheckResult(vulkanDevice.createBuffer(
                                     VkBufferUsageFlags.VertexBuffer,
                                     VkMemoryPropertyFlags.HostVisible,
                                     vertexBufferSize,
                                     out model_vertices_buffer,
                                     out model_vertices_memory,
                                     vertexBuffer.Data.ToPointer()));
                // Index buffer
                Util.CheckResult(vulkanDevice.createBuffer(
                                     VkBufferUsageFlags.IndexBuffer,
                                     VkMemoryPropertyFlags.HostVisible,
                                     indexBufferSize,
                                     out model_indices_buffer,
                                     out model_indices_memory,
                                     indexBuffer.Data.ToPointer()));
            }
        }
Пример #24
0
        /// <summary>
        /// Imports a model from the specified file. The importer sets configurations
        /// and loads the model into managed memory, releasing the unmanaged memory used by Assimp.
        /// </summary>
        /// <param name="file">Full path to the file</param>
        /// <param name="postProcessFlags">Post processing flags, if any</param>
        /// <returns>The imported scene</returns>
        /// <exception cref="AssimpException">Thrown if there was a general error in importing the model.</exception>
        /// <exception cref="System.IO.FileNotFoundException">Thrown if the file could not be located.</exception>
        /// <exception cref="System.ObjectDisposedException">Thrown if the context has already been disposed of.</exception>
        public Scene ImportFile(String file, PostProcessSteps postProcessFlags) {
            CheckDisposed();

            IntPtr ptr = IntPtr.Zero;
            IntPtr fileIO = IntPtr.Zero;

            //Only do file checks if not using a custom IOSystem
            if(UsingCustomIOSystem) {
                fileIO = m_ioSystem.AiFileIO;
            } else if(String.IsNullOrEmpty(file) || !File.Exists(file)) {
                throw new FileNotFoundException("Filename was null or could not be found", file);
            }

            PrepareImport();

            try {
                ptr = AssimpLibrary.Instance.ImportFile(file, PostProcessSteps.None, fileIO, m_propStore);

                if(ptr == IntPtr.Zero)
                    throw new AssimpException("Error importing file: " + AssimpLibrary.Instance.GetErrorString());

                TransformScene(ptr);

                if(postProcessFlags != PostProcessSteps.None)
                    ptr = AssimpLibrary.Instance.ApplyPostProcessing(ptr, postProcessFlags);

                return Scene.FromUnmanagedScene(ptr);
            } finally {
                CleanupImport();

                if(ptr != IntPtr.Zero) {
                    AssimpLibrary.Instance.ReleaseImport(ptr);
                }
            }
        }
Пример #25
0
        /// <summary>
        /// Converts the model contained in the stream to the specified format and save it to a data blob.
        /// </summary>
        /// <param name="inputStream">Stream to read from</param>
        /// <param name="importFormatHint">Format extension to serve as a hint to Assimp to choose which importer to use</param>
        /// <param name="importProcessSteps">Post processing steps used for import</param>
        /// <param name="exportFormatId">Format id that specifies what format to export to</param>
        /// <param name="exportProcessSteps">Pre processing steps used for the export</param>
        /// <returns>Data blob containing the exported scene in a binary form</returns>
        /// <exception cref="AssimpException">Thrown if the stream is not valid (null or write-only) or if the format hint is null or empty.</exception>
        /// <exception cref="System.ObjectDisposedException">Thrown if the context has already been disposed of.</exception>
        public ExportDataBlob ConvertFromStreamToBlob(Stream inputStream, String importFormatHint, PostProcessSteps importProcessSteps, String exportFormatId, PostProcessSteps exportProcessSteps) {
            CheckDisposed();

            if(inputStream == null || inputStream.CanRead != true)
                throw new AssimpException("stream", "Can't read from the stream it's null or write-only");

            if(String.IsNullOrEmpty(importFormatHint))
                throw new AssimpException("formatHint", "Format hint is null or empty");

            IntPtr ptr = IntPtr.Zero;
            PrepareImport();

            try {
                ptr = AssimpLibrary.Instance.ImportFileFromStream(inputStream, importProcessSteps, importFormatHint, m_propStore);

                if(ptr == IntPtr.Zero)
                    throw new AssimpException("Error importing file: " + AssimpLibrary.Instance.GetErrorString());

                TransformScene(ptr);

                if(importProcessSteps != PostProcessSteps.None)
                    ptr = AssimpLibrary.Instance.ApplyPostProcessing(ptr, importProcessSteps);

                return AssimpLibrary.Instance.ExportSceneToBlob(ptr, exportFormatId, exportProcessSteps);
            } finally {
                CleanupImport();

                if(ptr != IntPtr.Zero)
                    AssimpLibrary.Instance.ReleaseImport(ptr);
            }
        }
Пример #26
0
        /// <summary>
        /// Imports a scene from a stream. This uses the "aiImportFileFromMemory" function. The stream can be from anyplace,
        /// not just a memory stream. It is up to the caller to dispose of the stream.
        /// </summary>
        /// <param name="stream">Stream containing the scene data</param>
        /// <param name="flags">Post processing flags</param>
        /// <param name="formatHint">A hint to Assimp to decide which importer to use to process the data</param>
        /// <param name="propStore">Property store containing the config name-values, may be null.</param>
        /// <returns></returns>
        public static IntPtr ImportFileFromStream(Stream stream, PostProcessSteps flags, String formatHint, IntPtr propStore)
        {
            byte[] buffer = MemoryHelper.ReadStreamFully(stream, 0);

            return aiImportFileFromMemoryWithProperties(buffer, (uint) buffer.Length, (uint) flags, formatHint, propStore);
        }
Пример #27
0
        public static LoadedModels <RealtimeMaterial> LoadRealtimeModelsFromFile(string baseDirectory, string localPath, PostProcessSteps flags = DefaultPostProcessSteps)
        {
            string filePath = Path.Combine(baseDirectory, localPath);

            string[] directoryStructure = localPath.Split('/');
            string   modelDir           = directoryStructure[0];

            AssimpContext assimpContext = new AssimpContext();

            Assimp.Scene pScene = assimpContext.ImportFile(filePath, flags);

            //TODO: Identify meshcount for each vertex type. Have to preprocess
            int meshCount = pScene.MeshCount;

            var loadedMeshCounts = pScene.GetHenzaiMeshCounts();
            int meshCountP       = loadedMeshCounts.meshCountP;
            int meshCountPC      = loadedMeshCounts.meshCountPC;
            int meshCountPN      = loadedMeshCounts.meshCountPN;
            int meshCountPT      = loadedMeshCounts.meshCountPT;
            int meshCountPNT     = loadedMeshCounts.meshCountPNT;
            int meshCountPNTTB   = loadedMeshCounts.meshCountPNTTB;

            Mesh <VertexPosition>[]              meshesP   = new Mesh <VertexPosition> [meshCountP];
            Mesh <VertexPositionColor>[]         meshesPC  = new Mesh <VertexPositionColor> [meshCountPC];
            Mesh <VertexPositionNormal>[]        meshesPN  = new Mesh <VertexPositionNormal> [meshCountPN];
            Mesh <VertexPositionTexture>[]       meshesPT  = new Mesh <VertexPositionTexture> [meshCountPT];
            Mesh <VertexPositionNormalTexture>[] meshesPNT = new Mesh <VertexPositionNormalTexture> [meshCountPNT];
            Mesh <VertexPositionNormalTextureTangentBitangent>[] meshesPNTTB = new Mesh <VertexPositionNormalTextureTangentBitangent> [meshCountPNTTB];

            RealtimeMaterial[] materialsP     = new RealtimeMaterial[meshCountP];
            RealtimeMaterial[] materialsPC    = new RealtimeMaterial[meshCountPC];
            RealtimeMaterial[] materialsPN    = new RealtimeMaterial[meshCountPN];
            RealtimeMaterial[] materialsPT    = new RealtimeMaterial[meshCountPT];
            RealtimeMaterial[] materialsPNT   = new RealtimeMaterial[meshCountPNT];
            RealtimeMaterial[] materialsPNTTB = new RealtimeMaterial[meshCountPNTTB];

            ushort[][] meshIndiciesP     = new ushort[meshCountP][];
            ushort[][] meshIndiciesPC    = new ushort[meshCountPC][];
            ushort[][] meshIndiciesPN    = new ushort[meshCountPN][];
            ushort[][] meshIndiciesPT    = new ushort[meshCountPT][];
            ushort[][] meshIndiciesPNT   = new ushort[meshCountPNT][];
            ushort[][] meshIndiciesPNTTB = new ushort[meshCountPNTTB][];

            int meshIndiciesP_Counter     = 0;
            int meshIndiciesPC_Counter    = 0;
            int meshIndiciesPN_Counter    = 0;
            int meshIndiciesPT_Counter    = 0;
            int meshIndiciesPNT_Counter   = 0;
            int meshIndiciesPNTTB_Counter = 0;

            var loadedModels = new LoadedModels <RealtimeMaterial>();

            VertexPosition[]              meshDefinitionP   = new VertexPosition[0];
            VertexPositionColor[]         meshDefinitionPC  = new VertexPositionColor[0];
            VertexPositionNormal[]        meshDefinitionPN  = new VertexPositionNormal[0];
            VertexPositionTexture[]       meshDefinitionPT  = new VertexPositionTexture[0];
            VertexPositionNormalTexture[] meshDefinitionPNT = new VertexPositionNormalTexture[0];
            VertexPositionNormalTextureTangentBitangent[] meshDefinitionPNTTB = new VertexPositionNormalTextureTangentBitangent[0];

            for (int i = 0; i < meshCount; i++)
            {
                var aiMesh      = pScene.Meshes[i];
                var vertexCount = aiMesh.VertexCount;
                if (vertexCount == 0)
                {
                    Console.Error.WriteLine("Mesh has no verticies");
                    continue;
                }

                Assimp.Material aiMaterial = pScene.Materials[aiMesh.MaterialIndex];
                Core.Materials.RealtimeMaterial material = aiMaterial.ToRealtimeMaterial();
                VertexRuntimeTypes henzaiVertexType      = aiMaterial.ToHenzaiVertexType();
                switch (henzaiVertexType)
                {
                case VertexRuntimeTypes.VertexPosition:
                    meshDefinitionP = new VertexPosition[vertexCount];
                    break;

                case VertexRuntimeTypes.VertexPositionColor:
                    meshDefinitionPC = new VertexPositionColor[vertexCount];
                    break;

                case VertexRuntimeTypes.VertexPositionTexture:
                    meshDefinitionPT = new VertexPositionTexture[vertexCount];
                    break;

                case VertexRuntimeTypes.VertexPositionNormalTexture:
                    meshDefinitionPNT = new VertexPositionNormalTexture[vertexCount];
                    break;

                case VertexRuntimeTypes.VertexPositionNormal:
                    meshDefinitionPN = new VertexPositionNormal[vertexCount];
                    break;

                case VertexRuntimeTypes.VertexPositionNormalTextureTangentBitangent:
                    meshDefinitionPNTTB = new VertexPositionNormalTextureTangentBitangent[vertexCount];
                    break;

                default:
                    throw new NotImplementedException($"{henzaiVertexType.ToString("g")} not implemented");
                }

                for (int j = 0; j < vertexCount; j++)
                {
                    byte[] bytes = GenerateVertexBytesArrayFromAssimp(henzaiVertexType, aiMesh, j);

                    switch (henzaiVertexType)
                    {
                    case VertexRuntimeTypes.VertexPosition:
                        meshDefinitionP[j] = ByteMarshal.ByteArrayToStructure <VertexPosition>(bytes);
                        break;

                    case VertexRuntimeTypes.VertexPositionColor:
                        meshDefinitionPC[j] = ByteMarshal.ByteArrayToStructure <VertexPositionColor>(bytes);
                        break;

                    case VertexRuntimeTypes.VertexPositionTexture:
                        meshDefinitionPT[j] = ByteMarshal.ByteArrayToStructure <VertexPositionTexture>(bytes);
                        break;

                    case VertexRuntimeTypes.VertexPositionNormalTexture:
                        meshDefinitionPNT[j] = ByteMarshal.ByteArrayToStructure <VertexPositionNormalTexture>(bytes);
                        break;

                    case VertexRuntimeTypes.VertexPositionNormal:
                        meshDefinitionPN[j] = ByteMarshal.ByteArrayToStructure <VertexPositionNormal>(bytes);
                        break;

                    case VertexRuntimeTypes.VertexPositionNormalTextureTangentBitangent:
                        meshDefinitionPNTTB[j] = ByteMarshal.ByteArrayToStructure <VertexPositionNormalTextureTangentBitangent>(bytes);
                        break;

                    default:
                        throw new NotImplementedException($"{henzaiVertexType.ToString("g")} not implemented");
                    }
                }

                var faceCount = aiMesh.FaceCount;
                switch (henzaiVertexType)
                {
                case VertexRuntimeTypes.VertexPosition:
                    materialsP[meshIndiciesP_Counter]    = material;
                    meshIndiciesP[meshIndiciesP_Counter] = new ushort[3 * faceCount];

                    for (int j = 0; j < faceCount; j++)
                    {
                        var face = aiMesh.Faces[j];

                        if (face.IndexCount != 3)
                        {
                            Console.Error.WriteLine("Loading Assimp: Face index count != 3!");
                            continue;
                        }

                        meshIndiciesP[meshIndiciesP_Counter][3 * j + 0] = face.Indices[0].ToUnsignedShort();
                        meshIndiciesP[meshIndiciesP_Counter][3 * j + 1] = face.Indices[1].ToUnsignedShort();
                        meshIndiciesP[meshIndiciesP_Counter][3 * j + 2] = face.Indices[2].ToUnsignedShort();
                    }
                    meshesP[meshIndiciesP_Counter] = new Mesh <VertexPosition>(meshDefinitionP, meshIndiciesP[meshIndiciesP_Counter]);
                    meshIndiciesP_Counter++;
                    break;

                case VertexRuntimeTypes.VertexPositionColor:
                    materialsPC[meshIndiciesPC_Counter]    = material;
                    meshIndiciesPC[meshIndiciesPC_Counter] = new ushort[3 * faceCount];

                    for (int j = 0; j < faceCount; j++)
                    {
                        var face = aiMesh.Faces[j];

                        if (face.IndexCount != 3)
                        {
                            Console.Error.WriteLine("Loading Assimp: Face index count != 3!");
                            continue;
                        }

                        meshIndiciesPC[meshIndiciesPC_Counter][3 * j + 0] = face.Indices[0].ToUnsignedShort();
                        meshIndiciesPC[meshIndiciesPC_Counter][3 * j + 1] = face.Indices[1].ToUnsignedShort();
                        meshIndiciesPC[meshIndiciesPC_Counter][3 * j + 2] = face.Indices[2].ToUnsignedShort();
                    }
                    meshesPC[meshIndiciesPC_Counter] = new Mesh <VertexPositionColor>(meshDefinitionPC, meshIndiciesPC[meshIndiciesPC_Counter]);
                    meshIndiciesPC_Counter++;
                    break;

                case VertexRuntimeTypes.VertexPositionTexture:
                    materialsPT[meshIndiciesPT_Counter]    = material;
                    meshIndiciesPT[meshIndiciesPT_Counter] = new ushort[3 * faceCount];

                    for (int j = 0; j < faceCount; j++)
                    {
                        var face = aiMesh.Faces[j];

                        if (face.IndexCount != 3)
                        {
                            Console.Error.WriteLine("Loading Assimp: Face index count != 3!");
                            continue;
                        }

                        meshIndiciesPT[meshIndiciesPT_Counter][3 * j + 0] = face.Indices[0].ToUnsignedShort();
                        meshIndiciesPT[meshIndiciesPT_Counter][3 * j + 1] = face.Indices[1].ToUnsignedShort();
                        meshIndiciesPT[meshIndiciesPT_Counter][3 * j + 2] = face.Indices[2].ToUnsignedShort();
                    }
                    meshesPT[meshIndiciesPT_Counter] = new Mesh <VertexPositionTexture>(meshDefinitionPT, meshIndiciesPT[meshIndiciesPT_Counter]);
                    meshIndiciesPT_Counter++;
                    break;

                case VertexRuntimeTypes.VertexPositionNormalTexture:
                    materialsPNT[meshIndiciesPNT_Counter]    = material;
                    meshIndiciesPNT[meshIndiciesPNT_Counter] = new ushort[3 * faceCount];

                    for (int j = 0; j < faceCount; j++)
                    {
                        var face = aiMesh.Faces[j];

                        if (face.IndexCount != 3)
                        {
                            Console.Error.WriteLine("Loading Assimp: Face index count != 3!");
                            continue;
                        }

                        meshIndiciesPNT[meshIndiciesPNT_Counter][3 * j + 0] = face.Indices[0].ToUnsignedShort();
                        meshIndiciesPNT[meshIndiciesPNT_Counter][3 * j + 1] = face.Indices[1].ToUnsignedShort();
                        meshIndiciesPNT[meshIndiciesPNT_Counter][3 * j + 2] = face.Indices[2].ToUnsignedShort();
                    }
                    meshesPNT[meshIndiciesPNT_Counter] = new Mesh <VertexPositionNormalTexture>(meshDefinitionPNT, meshIndiciesPNT[meshIndiciesPNT_Counter]);
                    meshIndiciesPNT_Counter++;
                    break;

                case VertexRuntimeTypes.VertexPositionNormal:
                    materialsPN[meshIndiciesPN_Counter]    = material;
                    meshIndiciesPN[meshIndiciesPN_Counter] = new ushort[3 * faceCount];

                    for (int j = 0; j < faceCount; j++)
                    {
                        var face = aiMesh.Faces[j];

                        if (face.IndexCount != 3)
                        {
                            Console.Error.WriteLine("Loading Assimp: Face index count != 3!");
                            continue;
                        }

                        meshIndiciesPN[meshIndiciesPN_Counter][3 * j + 0] = face.Indices[0].ToUnsignedShort();
                        meshIndiciesPN[meshIndiciesPN_Counter][3 * j + 1] = face.Indices[1].ToUnsignedShort();
                        meshIndiciesPN[meshIndiciesPN_Counter][3 * j + 2] = face.Indices[2].ToUnsignedShort();
                    }
                    meshesPN[meshIndiciesPN_Counter] = new Mesh <VertexPositionNormal>(meshDefinitionPN, meshIndiciesPN[meshIndiciesPN_Counter]);
                    meshIndiciesPN_Counter++;
                    break;

                case VertexRuntimeTypes.VertexPositionNormalTextureTangentBitangent:
                    materialsPNTTB[meshIndiciesPNTTB_Counter]    = material;
                    meshIndiciesPNTTB[meshIndiciesPNTTB_Counter] = new ushort[3 * faceCount];

                    for (int j = 0; j < faceCount; j++)
                    {
                        var face = aiMesh.Faces[j];

                        if (face.IndexCount != 3)
                        {
                            Console.Error.WriteLine("Loading Assimp: Face index count != 3!");
                            continue;
                        }

                        meshIndiciesPNTTB[meshIndiciesPNTTB_Counter][3 * j + 0] = face.Indices[0].ToUnsignedShort();
                        meshIndiciesPNTTB[meshIndiciesPNTTB_Counter][3 * j + 1] = face.Indices[1].ToUnsignedShort();
                        meshIndiciesPNTTB[meshIndiciesPNTTB_Counter][3 * j + 2] = face.Indices[2].ToUnsignedShort();
                    }
                    meshesPNTTB[meshIndiciesPNTTB_Counter] = new Mesh <VertexPositionNormalTextureTangentBitangent>(meshDefinitionPNTTB, meshIndiciesPNTTB[meshIndiciesPNTTB_Counter]);
                    meshIndiciesPNTTB_Counter++;
                    break;

                default:
                    throw new NotImplementedException($"{henzaiVertexType.ToString("g")} not implemented");
                }
            }

            if (meshCountP > 0)
            {
                loadedModels.modelP = new Model <VertexPosition, RealtimeMaterial>(modelDir, meshesP, materialsP);
            }
            if (meshCountPC > 0)
            {
                loadedModels.modelPC = new Model <VertexPositionColor, RealtimeMaterial>(modelDir, meshesPC, materialsPC);
            }
            if (meshCountPN > 0)
            {
                loadedModels.modelPN = new Model <VertexPositionNormal, RealtimeMaterial>(modelDir, meshesPN, materialsPN);
            }
            if (meshCountPT > 0)
            {
                loadedModels.modelPT = new Model <VertexPositionTexture, RealtimeMaterial>(modelDir, meshesPT, materialsPT);
            }
            if (meshCountPNT > 0)
            {
                loadedModels.modelPNT = new Model <VertexPositionNormalTexture, RealtimeMaterial>(modelDir, meshesPNT, materialsPNT);
            }
            if (meshCountPNTTB > 0)
            {
                loadedModels.modelPNTTB = new Model <VertexPositionNormalTextureTangentBitangent, RealtimeMaterial>(modelDir, meshesPNTTB, materialsPNTTB);
            }

            return(loadedModels);
        }
Пример #28
0
        /// <summary>
        /// Exports the given scene to a chosen file format. Returns the exported data as a binary blob which you can embed into another data structure or file.
        /// </summary>
        /// <param name="scene">Scene to export, it is the responsibility of the caller to free this when finished.</param>
        /// <param name="formatId">Format id describing which format to export to.</param>
        /// <param name="preProcessing">Pre processing flags to operate on the scene during the export.</param>
        /// <returns>Exported binary blob, or null if there was an error.</returns>
        public static ExportDataBlob ExportSceneToBlob(IntPtr scene, String formatId, PostProcessSteps preProcessing)
        {
            if(String.IsNullOrEmpty(formatId) || scene == IntPtr.Zero)
                return null;

            IntPtr blobPtr = aiExportSceneToBlob(scene, formatId, (uint) preProcessing);

            if(blobPtr == IntPtr.Zero)
                return null;

            AiExportDataBlob blob = MemoryHelper.MarshalStructure<AiExportDataBlob>(blobPtr);
            ExportDataBlob dataBlob = new ExportDataBlob(ref blob);
            aiReleaseExportBlob(blobPtr);

            return dataBlob;
        }
Пример #29
0
        /// <summary>
        /// Importers a model from the stream. The importer sets configurations
        /// and loads the model into managed memory, releasing the unmanaged memory used by Assimp. It is up to the caller to dispose of the stream.
        /// </summary>
        /// <param name="stream">Stream to read from</param>
        /// <param name="postProcessFlags">Post processing flags, if any</param>
        /// <param name="formatHint">Format extension to serve as a hint to Assimp to choose which importer to use</param>
        /// <returns>The imported scene</returns>
        /// <exception cref="AssimpException">Thrown if the stream is not valid (null or write-only) or if the format hint is null or empty.</exception>
        /// <exception cref="System.ObjectDisposedException">Thrown if attempting to import a model if the importer has been disposed of</exception>
        public Scene ImportFileFromStream(Stream stream, PostProcessSteps postProcessFlags, String formatHint)
        {
            lock(s_sync) {
                if(m_isDisposed) {
                    throw new ObjectDisposedException("Importer has been disposed.");
                }

                if(stream == null || stream.CanRead != true) {
                    throw new AssimpException("stream", "Can't read from the stream it's null or write-only");
                }

                if(String.IsNullOrEmpty(formatHint)) {
                    throw new AssimpException("formatHint", "Format hint is null or empty");
                }

                IntPtr ptr = IntPtr.Zero;
                PrepareImport();

                try {
                    ptr = AssimpMethods.ImportFileFromStream(stream, PostProcessSteps.None, formatHint, m_propStore);

                    if(ptr == IntPtr.Zero)
                        throw new AssimpException("Error importing file: " + AssimpMethods.GetErrorString());

                    TransformScene(ptr);

                    ptr = AssimpMethods.ApplyPostProcessing(ptr, postProcessFlags);

                    return ValidateAndCreateScene(ptr);
                } finally {
                    CleanupImport();

                    if(ptr != IntPtr.Zero) {
                        AssimpMethods.ReleaseImport(ptr);
                    }
                }
            }
        }
Пример #30
0
        /// <summary>
        /// Imports a model from the stream. The importer sets configurations
        /// and loads the model into managed memory, releasing the unmanaged memory used by Assimp. It is up to the caller to dispose of the stream.
        /// </summary>
        /// <param name="stream">Stream to read from</param>
        /// <param name="postProcessFlags">Post processing flags, if any</param>
        /// <param name="formatHint">Format extension to serve as a hint to Assimp to choose which importer to use</param>
        /// <returns>The imported scene</returns>
        /// <exception cref="AssimpException">Thrown if the stream is not valid (null or write-only) or if the format hint is null or empty.</exception>
        /// <exception cref="System.ObjectDisposedException">Thrown if the context has already been disposed of.</exception>
        public Scene ImportFileFromStream(Stream stream, PostProcessSteps postProcessFlags, String formatHint) {
            CheckDisposed();

            if(stream == null || stream.CanRead != true)
                throw new AssimpException("stream", "Can't read from the stream it's null or write-only");

            if(String.IsNullOrEmpty(formatHint))
                throw new AssimpException("formatHint", "Format hint is null or empty");

            IntPtr ptr = IntPtr.Zero;
            PrepareImport();

            try {
                ptr = AssimpLibrary.Instance.ImportFileFromStream(stream, PostProcessSteps.None, formatHint, m_propStore);

                if(ptr == IntPtr.Zero)
                    throw new AssimpException("Error importing file: " + AssimpLibrary.Instance.GetErrorString());

                TransformScene(ptr);

                if(postProcessFlags != PostProcessSteps.None)
                    ptr = AssimpLibrary.Instance.ApplyPostProcessing(ptr, postProcessFlags);

                return Scene.FromUnmanagedScene(ptr);
            } finally {
                CleanupImport();

                if(ptr != IntPtr.Zero) {
                    AssimpLibrary.Instance.ReleaseImport(ptr);
                }
            }
        }
Пример #31
0
        public static RWSection[] CreateBSPFromAssimp(string fileName, bool flipUVs, bool ignoreMeshColors)
        {
            PostProcessSteps pps =
                PostProcessSteps.Debone | PostProcessSteps.FindInstances |
                PostProcessSteps.FindInvalidData | PostProcessSteps.OptimizeGraph |
                PostProcessSteps.OptimizeMeshes | PostProcessSteps.Triangulate |
                PostProcessSteps.PreTransformVertices;

            Scene scene = new AssimpContext().ImportFile(fileName, pps);

            int vertexCount   = scene.Meshes.Sum(m => m.VertexCount);
            int triangleCount = scene.Meshes.Sum(m => m.FaceCount);

            if (vertexCount > 65535 || triangleCount > 65536)
            {
                throw new ArgumentException("Model has too many vertices or triangles. Please import a simpler model.");
            }

            List <Vertex3> vertices                  = new List <Vertex3>(vertexCount);
            List <RenderWareFile.Color> vColors      = new List <RenderWareFile.Color>(vertexCount);
            List <Vertex2> textCoords                = new List <Vertex2>(vertexCount);
            List <RenderWareFile.Triangle> triangles = new List <RenderWareFile.Triangle>(triangleCount);

            int totalVertices = 0;

            foreach (var m in scene.Meshes)
            {
                foreach (Vector3D v in m.Vertices)
                {
                    vertices.Add(new Vertex3(v.X, v.Y, v.Z));
                }

                if (m.HasTextureCoords(0))
                {
                    foreach (Vector3D v in m.TextureCoordinateChannels[0])
                    {
                        textCoords.Add(new Vertex2(v.X, flipUVs ? -v.Y : v.Y));
                    }
                }
                else
                {
                    for (int i = 0; i < m.VertexCount; i++)
                    {
                        textCoords.Add(new Vertex2());
                    }
                }

                if (m.HasVertexColors(0))
                {
                    foreach (Color4D c in m.VertexColorChannels[0])
                    {
                        vColors.Add(new RenderWareFile.Color(
                                        (byte)(c.R * 255),
                                        (byte)(c.G * 255),
                                        (byte)(c.B * 255),
                                        (byte)(c.A * 255)));
                    }
                }
                else
                {
                    for (int i = 0; i < m.VertexCount; i++)
                    {
                        vColors.Add(new RenderWareFile.Color(255, 255, 255, 255));
                    }
                }

                foreach (var t in m.Faces)
                {
                    triangles.Add(new RenderWareFile.Triangle()
                    {
                        vertex1       = (ushort)(t.Indices[0] + totalVertices),
                        vertex2       = (ushort)(t.Indices[1] + totalVertices),
                        vertex3       = (ushort)(t.Indices[2] + totalVertices),
                        materialIndex = (ushort)m.MaterialIndex
                    });
                }

                totalVertices += m.VertexCount;
            }

            if (vertices.Count != textCoords.Count || vertices.Count != vColors.Count)
            {
                throw new ArgumentException("Internal error: texture coordinate or vertex color count is different from vertex count.");
            }

            triangles = triangles.OrderBy(t => t.materialIndex).ToList();

            Vertex3 Max = new Vertex3(vertices[0].X, vertices[0].Y, vertices[0].Z);
            Vertex3 Min = new Vertex3(vertices[0].X, vertices[0].Y, vertices[0].Z);

            foreach (Vertex3 i in vertices)
            {
                if (i.X > Max.X)
                {
                    Max.X = i.X;
                }
                if (i.Y > Max.Y)
                {
                    Max.Y = i.Y;
                }
                if (i.Z > Max.Z)
                {
                    Max.Z = i.Z;
                }
                if (i.X < Min.X)
                {
                    Min.X = i.X;
                }
                if (i.Y < Min.Y)
                {
                    Min.Y = i.Y;
                }
                if (i.Z < Min.Z)
                {
                    Min.Z = i.Z;
                }
            }

            Max = new Vertex3(MaximumBoundary, MaximumBoundary, MaximumBoundary);
            Min = new Vertex3(-MaximumBoundary, -MaximumBoundary, -MaximumBoundary);

            BinMesh[] binMeshes = new BinMesh[scene.MaterialCount];

            Material_0007[] materials = new Material_0007[scene.MaterialCount];

            for (int i = 0; i < scene.MaterialCount; i++)
            {
                List <int> indices = new List <int>(triangles.Count);
                foreach (RenderWareFile.Triangle f in triangles)
                {
                    if (f.materialIndex == i)
                    {
                        indices.Add(f.vertex1);
                        indices.Add(f.vertex2);
                        indices.Add(f.vertex3);
                    }
                }

                binMeshes[i] = new BinMesh()
                {
                    materialIndex = i,
                    indexCount    = indices.Count(),
                    vertexIndices = indices.ToArray()
                };

                materials[i] = new Material_0007()
                {
                    materialStruct = new MaterialStruct_0001()
                    {
                        unusedFlags = 0,
                        color       = ignoreMeshColors ?
                                      new RenderWareFile.Color(255, 255, 255, 255) :
                                      new RenderWareFile.Color(
                            (byte)(scene.Materials[i].ColorDiffuse.R / 255),
                            (byte)(scene.Materials[i].ColorDiffuse.G / 255),
                            (byte)(scene.Materials[i].ColorDiffuse.B / 255),
                            (byte)(scene.Materials[i].ColorDiffuse.A / 255)),
                        unusedInt2 = 0x2DF53E84,
                        isTextured = scene.Materials[i].HasTextureDiffuse ? 1 : 0,
                        ambient    = ignoreMeshColors ? 1f : scene.Materials[i].ColorAmbient.A,
                        specular   = ignoreMeshColors ? 1f : scene.Materials[i].ColorSpecular.A,
                        diffuse    = ignoreMeshColors ? 1f : scene.Materials[i].ColorDiffuse.A
                    },
                    texture           = scene.Materials[i].HasTextureDiffuse ? RWTextureFromAssimpMaterial(scene.Materials[i].TextureDiffuse) : null,
                    materialExtension = new Extension_0003()
                    {
                        extensionSectionList = new List <RWSection>()
                    },
                };
            }

            WorldFlags worldFlags = WorldFlags.HasOneSetOfTextCoords | WorldFlags.HasVertexColors | WorldFlags.WorldSectorsOverlap | (WorldFlags)0x00010000;

            World_000B world = new World_000B()
            {
                worldStruct = new WorldStruct_0001()
                {
                    rootIsWorldSector = 1,
                    inverseOrigin     = new Vertex3(-0f, -0f, -0f),
                    numTriangles      = (uint)triangleCount,
                    numVertices       = (uint)vertexCount,
                    numPlaneSectors   = 0,
                    numAtomicSectors  = 1,
                    colSectorSize     = 0,
                    worldFlags        = worldFlags,
                    boxMaximum        = Max,
                    boxMinimum        = Min,
                },

                materialList = new MaterialList_0008()
                {
                    materialListStruct = new MaterialListStruct_0001()
                    {
                        materialCount = scene.MaterialCount
                    },
                    materialList = materials
                },

                firstWorldChunk = new AtomicSector_0009()
                {
                    atomicSectorStruct = new AtomicSectorStruct_0001()
                    {
                        matListWindowBase = 0,
                        numTriangles      = triangleCount,
                        numVertices       = vertexCount,
                        boxMaximum        = Max,
                        boxMinimum        = Min,
                        collSectorPresent = 0x2F50D984,
                        unused            = 0,
                        vertexArray       = vertices.ToArray(),
                        colorArray        = vColors.ToArray(),
                        uvArray           = textCoords.ToArray(),
                        triangleArray     = triangles.ToArray()
                    },
                    atomicSectorExtension = new Extension_0003()
                    {
                        extensionSectionList = new List <RWSection>()
                        {
                            new BinMeshPLG_050E()
                            {
                                binMeshHeaderFlags = BinMeshHeaderFlags.TriangleList,
                                numMeshes          = binMeshes.Count(),
                                totalIndexCount    = binMeshes.Sum(b => b.indexCount),
                                binMeshList        = binMeshes
                            },
                            new CollisionPLG_011D_Scooby()
                            {
                                splits = new Split_Scooby[0],
                                startIndex_amountOfTriangles = new short[][] { new short[] { 0, (short)triangles.Count } },
                                triangles = TriangleRange(triangles.Count)
                            }
                        }
                    }
                },

                worldExtension = new Extension_0003()
            };

            return(new RWSection[] { world });
        }
Пример #32
0
        /// <summary>
        /// Converts the model contained in the stream to the specified format and save it to a data blob.
        /// </summary>
        /// <param name="inputStream">Stream to read from</param>
        /// <param name="importFormatHint">Format extension to serve as a hint to Assimp to choose which importer to use</param>
        /// <param name="importProcessSteps">Post processing steps used for import</param>
        /// <param name="exportFormatId">Format id that specifies what format to export to</param>
        /// <param name="exportProcessSteps">Pre processing steps used for the export</param>
        /// <returns>Data blob containing the exported scene in a binary form</returns>
        /// <exception cref="AssimpException">Thrown if the stream is not valid (null or write-only) or if the format hint is null or empty.</exception>
        /// <exception cref="System.ObjectDisposedException">Thrown if the context has already been disposed of.</exception>
        public ExportDataBlob ConvertFromStreamToBlob(Stream inputStream, String importFormatHint, PostProcessSteps importProcessSteps, String exportFormatId, PostProcessSteps exportProcessSteps)
        {
            CheckDisposed();

            if (inputStream == null || inputStream.CanRead != true)
            {
                throw new AssimpException("stream", "Can't read from the stream it's null or write-only");
            }

            if (String.IsNullOrEmpty(importFormatHint))
            {
                throw new AssimpException("formatHint", "Format hint is null or empty");
            }

            IntPtr ptr = IntPtr.Zero;

            PrepareImport();

            try
            {
                ptr = AssimpLibrary.Instance.ImportFileFromStream(inputStream, importProcessSteps, importFormatHint, m_propStore);

                if (ptr == IntPtr.Zero)
                {
                    throw new AssimpException("Error importing file: " + AssimpLibrary.Instance.GetErrorString());
                }

                TransformScene(ptr);

                if (importProcessSteps != PostProcessSteps.None)
                {
                    ptr = AssimpLibrary.Instance.ApplyPostProcessing(ptr, importProcessSteps);
                }

                return(AssimpLibrary.Instance.ExportSceneToBlob(ptr, exportFormatId, exportProcessSteps));
            }
            finally
            {
                CleanupImport();

                if (ptr != IntPtr.Zero)
                {
                    AssimpLibrary.Instance.ReleaseImport(ptr);
                }
            }
        }
Пример #33
0
        /// <summary>
        /// Importers a model from the specified file. The importer sets configurations
        /// and loads the model into managed memory, releasing the unmanaged memory used by Assimp.
        /// </summary>
        /// <param name="file">Full path to the file</param>
        /// <param name="postProcessFlags">Post processing flags, if any</param>
        /// <returns>The imported scene</returns>
        /// <exception cref="AssimpException">Thrown if there was a general error in importing the model.</exception>
        /// <exception cref="System.IO.FileNotFoundException">Thrown if the file could not be located.</exception>
        /// <exception cref="System.ObjectDisposedException">Thrown if attempting to import a model if the importer has been disposed of</exception>
        public Scene ImportFile(String file, PostProcessSteps postProcessFlags)
        {
            lock(s_sync) {
                if(m_isDisposed) {
                    throw new ObjectDisposedException("Importer has been disposed.");
                }
                if(String.IsNullOrEmpty(file) || !File.Exists(file)) {
                    throw new FileNotFoundException("Filename was null or could not be found", file);
                }

                IntPtr ptr = IntPtr.Zero;
                PrepareImport();
                try {
                    ptr = AssimpMethods.ImportFile(file, PostProcessSteps.None, m_propStore);

                    if(ptr == IntPtr.Zero)
                        throw new AssimpException("Error importing file: " + AssimpMethods.GetErrorString());

                    TransformScene(ptr);

                    ptr = AssimpMethods.ApplyPostProcessing(ptr, postProcessFlags);

                    return ValidateAndCreateScene(ptr);
                } finally {
                    CleanupImport();

                    if(ptr != IntPtr.Zero) {
                        AssimpMethods.ReleaseImport(ptr);
                    }
                }
            }
        }
Пример #34
0
 /// <summary>
 /// Applies a post-processing step on an already imported scene.
 /// </summary>
 /// <param name="scene">Pointer to the unmanaged scene data structure.</param>
 /// <param name="flags">Post processing steps to run.</param>
 /// <returns>Pointer to the unmanaged scene data structure.</returns>
 public static IntPtr ApplyPostProcessing(IntPtr scene, PostProcessSteps flags)
 {
     return aiApplyPostProcessing(scene, (uint) flags);
 }
Пример #35
0
        /// <summary>
        /// Converts the model contained in the stream to the specified format and save it to a file.
        /// </summary>
        /// <param name="inputStream">Stream to read from</param>
        /// <param name="importFormatHint">Format extension to serve as a hint to Assimp to choose which importer to use</param>
        /// <param name="importProcessSteps">Post processing steps used for import</param>
        /// <param name="outputFilename">Output file name to export to</param>
        /// <param name="exportFormatId">Format id that specifies what format to export to</param>
        /// <param name="exportProcessSteps">Pre processing steps used for the export</param>
        /// <exception cref="AssimpException">Thrown if the stream is not valid (null or write-only) or if the format hint is null or empty.</exception>
        /// <exception cref="System.ObjectDisposedException">Thrown if attempting to import a model if the importer has been disposed of</exception>
        public void ConvertFromStreamToFile(Stream inputStream, String importFormatHint, PostProcessSteps importProcessSteps, String outputFilename, String exportFormatId, PostProcessSteps exportProcessSteps)
        {
            lock(s_sync) {
                if(m_isDisposed) {
                    throw new ObjectDisposedException("Importer has been disposed.");
                }

                if(inputStream == null || inputStream.CanRead != true) {
                    throw new AssimpException("stream", "Can't read from the stream it's null or write-only");
                }

                if(String.IsNullOrEmpty(importFormatHint)) {
                    throw new AssimpException("formatHint", "Format hint is null or empty");
                }

                IntPtr ptr = IntPtr.Zero;
                PrepareImport();

                try {
                    ptr = AssimpMethods.ImportFileFromStream(inputStream, importProcessSteps, importFormatHint, m_propStore);

                    if(ptr == IntPtr.Zero)
                        throw new AssimpException("Error importing file: " + AssimpMethods.GetErrorString());

                    TransformScene(ptr);
                    ptr = AssimpMethods.ApplyPostProcessing(ptr, importProcessSteps);

                    ValidateScene(ptr);

                    AssimpMethods.ExportScene(ptr, exportFormatId, outputFilename, exportProcessSteps);
                } finally {
                    CleanupImport();

                    if(ptr != IntPtr.Zero)
                        AssimpMethods.ReleaseImport(ptr);
                }
            }
        }
Пример #36
0
 /// <summary>
 /// Imports a file.
 /// </summary>
 /// <param name="file">Valid filename</param>
 /// <param name="flags">Post process flags specifying what steps are to be run after the import.</param>
 /// <param name="propStore">Property store containing config name-values, may be null.</param>
 /// <returns>Pointer to the unmanaged data structure.</returns>
 public static IntPtr ImportFile(String file, PostProcessSteps flags, IntPtr propStore)
 {
     return aiImportFileExWithProperties(file, (uint) flags, IntPtr.Zero, propStore);
 }
Пример #37
0
        /// <summary>
        /// Converts the model contained in the file to the specified format and save it to a file.
        /// </summary>
        /// <param name="inputFilename">Input file name to import</param>
        /// <param name="importProcessSteps">Post processing steps used for the import</param>
        /// <param name="outputFilename">Output file name to export to</param>
        /// <param name="exportFormatId">Format id that specifies what format to export to</param>
        /// <param name="exportProcessSteps">Pre processing steps used for the export</param>
        ///<exception cref="AssimpException">Thrown if there was a general error in importing the model.</exception>
        /// <exception cref="System.IO.FileNotFoundException">Thrown if the file could not be located.</exception>
        /// <exception cref="System.ObjectDisposedException">Thrown if attempting to import a model if the importer has been disposed of</exception>
        public void ConvertFromFileToFile(String inputFilename, PostProcessSteps importProcessSteps, String outputFilename, String exportFormatId, PostProcessSteps exportProcessSteps)
        {
            lock(s_sync) {
                if(m_isDisposed) {
                    throw new ObjectDisposedException("Importer has been disposed.");
                }

                if(String.IsNullOrEmpty(inputFilename) || !File.Exists(inputFilename)) {
                    throw new FileNotFoundException("Filename was null or could not be found", inputFilename);
                }

                IntPtr ptr = IntPtr.Zero;
                PrepareImport();

                try {
                    ptr = AssimpMethods.ImportFile(inputFilename, PostProcessSteps.None, m_propStore);

                    if(ptr == IntPtr.Zero)
                        throw new AssimpException("Error importing file: " + AssimpMethods.GetErrorString());

                    TransformScene(ptr);
                    ptr = AssimpMethods.ApplyPostProcessing(ptr, importProcessSteps);

                    ValidateScene(ptr);

                    AssimpMethods.ExportScene(ptr, exportFormatId, outputFilename, exportProcessSteps);
                } finally {
                    CleanupImport();

                    if(ptr != IntPtr.Zero)
                        AssimpMethods.ReleaseImport(ptr);
                }
            }
        }
Пример #38
0
        /// <summary>
        /// Exports a scene to the specified format and writes it to a data blob.
        /// </summary>
        /// <param name="scene">Scene containing the model to export.</param>
        /// <param name="exportFormatId">FormatID representing the format to export to.</param>
        /// <param name="preProcessing">Preprocessing flags to apply to the model before it is exported.</param>
        /// <returns>The resulting data blob, or null if the export failed.</returns>
        /// <exception cref="ArgumentNullException">Thrown if the scene is null.</exception>
        /// <exception cref="System.ObjectDisposedException">Thrown if the context has already been disposed of.</exception>
        public ExportDataBlob ExportToBlob(Scene scene, String exportFormatId, PostProcessSteps preProcessing) {
            CheckDisposed();

            IntPtr fileIO = IntPtr.Zero;
            IntPtr scenePtr = IntPtr.Zero;

            if(scene == null)
                throw new ArgumentNullException("scene", "Scene must exist.");

            try {
                scenePtr = Scene.ToUnmanagedScene(scene);

                return AssimpLibrary.Instance.ExportSceneToBlob(scenePtr, exportFormatId, preProcessing);
            } finally {
                if(scenePtr != IntPtr.Zero)
                    Scene.FreeUnmanagedScene(scenePtr);
            }
        }
Пример #39
0
        /// <summary>
        /// Exports a scene to the specified format and writes it to a file.
        /// </summary>
        /// <param name="scene">Scene containing the model to export.</param>
        /// <param name="fileName">Path to the file.</param>
        /// <param name="exportFormatId">FormatID representing the format to export to.</param>
        /// <param name="preProcessing">Preprocessing flags to apply to the model before it is exported.</param>
        /// <returns>True if the scene was exported successfully, false otherwise.</returns>
        /// <exception cref="ArgumentNullException">Thrown if the scene is null.</exception>
        /// <exception cref="System.ObjectDisposedException">Thrown if the context has already been disposed of.</exception>
        public bool ExportFile(Scene scene, String fileName, String exportFormatId, PostProcessSteps preProcessing) {
            CheckDisposed();

            IntPtr fileIO = IntPtr.Zero;
            IntPtr scenePtr = IntPtr.Zero;

            if(scene == null)
                throw new ArgumentNullException("scene", "Scene must exist.");

            try {
                scenePtr = Scene.ToUnmanagedScene(scene);

                ReturnCode status = AssimpLibrary.Instance.ExportScene(scenePtr, exportFormatId, fileName, fileIO, preProcessing);

                return status == ReturnCode.Success;
            } finally {
                if(scenePtr != IntPtr.Zero)
                    Scene.FreeUnmanagedScene(scenePtr);
            }
        }
Пример #40
0
        private void Init(
            GraphicsDevice gd,
            ResourceFactory factory,
            Stream stream,
            string extension,
            VertexElementSemantic[] elementSemantics,
            ModelCreateInfo?createInfo,
            PostProcessSteps flags = DefaultPostProcessSteps)
        {
            // Load file
            AssimpContext assimpContext = new AssimpContext();
            Scene         pScene        = assimpContext.ImportFileFromStream(stream, DefaultPostProcessSteps, extension);

            parts.Clear();
            parts.Count = (uint)pScene.Meshes.Count;

            Vector3 scale   = new Vector3(1.0f);
            Vector2 uvscale = new Vector2(1.0f);
            Vector3 center  = new Vector3(0.0f);

            if (createInfo != null)
            {
                scale   = createInfo.Value.Scale;
                uvscale = createInfo.Value.UVScale;
                center  = createInfo.Value.Center;
            }

            RawList <float> vertices = new RawList <float>();
            RawList <uint>  indices  = new RawList <uint>();

            VertexCount = 0;
            IndexCount  = 0;

            // Load meshes
            for (int i = 0; i < pScene.Meshes.Count; i++)
            {
                var paiMesh = pScene.Meshes[i];

                parts[i]            = new ModelPart();
                parts[i].vertexBase = VertexCount;
                parts[i].indexBase  = IndexCount;

                VertexCount += (uint)paiMesh.VertexCount;

                var pColor = pScene.Materials[paiMesh.MaterialIndex].ColorDiffuse;

                Vector3D Zero3D = new Vector3D(0.0f, 0.0f, 0.0f);

                for (int j = 0; j < paiMesh.VertexCount; j++)
                {
                    Vector3D pPos       = paiMesh.Vertices[j];
                    Vector3D pNormal    = paiMesh.Normals[j];
                    Vector3D pTexCoord  = paiMesh.HasTextureCoords(0) ? paiMesh.TextureCoordinateChannels[0][j] : Zero3D;
                    Vector3D pTangent   = paiMesh.HasTangentBasis ? paiMesh.Tangents[j] : Zero3D;
                    Vector3D pBiTangent = paiMesh.HasTangentBasis ? paiMesh.BiTangents[j] : Zero3D;

                    foreach (VertexElementSemantic component in elementSemantics)
                    {
                        switch (component)
                        {
                        case VertexElementSemantic.Position:
                            vertices.Add(pPos.X * scale.X + center.X);
                            vertices.Add(-pPos.Y * scale.Y + center.Y);
                            vertices.Add(pPos.Z * scale.Z + center.Z);
                            break;

                        case VertexElementSemantic.Normal:
                            vertices.Add(pNormal.X);
                            vertices.Add(-pNormal.Y);
                            vertices.Add(pNormal.Z);
                            break;

                        case VertexElementSemantic.TextureCoordinate:
                            vertices.Add(pTexCoord.X * uvscale.X);
                            vertices.Add(pTexCoord.Y * uvscale.Y);
                            break;

                        case VertexElementSemantic.Color:
                            vertices.Add(pColor.R);
                            vertices.Add(pColor.G);
                            vertices.Add(pColor.B);
                            break;

                        default: throw new System.NotImplementedException();
                        }
                        ;
                    }

                    dim.Max.X = Math.Max(pPos.X, dim.Max.X);
                    dim.Max.Y = Math.Max(pPos.Y, dim.Max.Y);
                    dim.Max.Z = Math.Max(pPos.Z, dim.Max.Z);

                    dim.Min.X = Math.Min(pPos.X, dim.Min.X);
                    dim.Min.Y = Math.Min(pPos.Y, dim.Min.Y);
                    dim.Min.Z = Math.Min(pPos.Z, dim.Min.Z);
                }

                dim.Size = dim.Max - dim.Min;

                parts[i].vertexCount = (uint)paiMesh.VertexCount;

                uint indexBase = indices.Count;
                for (uint j = 0; j < paiMesh.FaceCount; j++)
                {
                    Face Face = paiMesh.Faces[(int)j];
                    if (Face.IndexCount != 3)
                    {
                        continue;
                    }
                    indices.Add(indexBase + (uint)Face.Indices[0]);
                    indices.Add(indexBase + (uint)Face.Indices[1]);
                    indices.Add(indexBase + (uint)Face.Indices[2]);
                    parts[i].indexCount += 3;
                    IndexCount          += 3;
                }
            }


            uint vBufferSize = (vertices.Count) * sizeof(float);
            uint iBufferSize = (indices.Count) * sizeof(uint);

            VertexBuffer = factory.CreateBuffer(new BufferDescription(vBufferSize, BufferUsage.VertexBuffer));
            IndexBuffer  = factory.CreateBuffer(new BufferDescription(iBufferSize, BufferUsage.IndexBuffer));

            gd.UpdateBuffer(VertexBuffer, 0, ref vertices[0], vBufferSize);
            gd.UpdateBuffer(IndexBuffer, 0, ref indices[0], iBufferSize);
        }
Пример #41
0
 /// <summary>
 /// Converts the model contained in the file to the specified format and save it to a file.
 /// </summary>
 /// <param name="inputFilename">Input file name to import</param>
 /// <param name="outputFilename">Output file name to export to</param>
 /// <param name="exportFormatId">Format id that specifies what format to export to</param>
 /// <param name="exportProcessSteps">Pre processing steps used for the export</param>
 /// <returns>True if the conversion was successful or not, false otherwise.</returns>
 /// <exception cref="AssimpException">Thrown if there was a general error in importing the model.</exception>
 /// <exception cref="System.IO.FileNotFoundException">Thrown if the file could not be located.</exception>
 /// <exception cref="System.ObjectDisposedException">Thrown if the context has already been disposed of.</exception>
 public bool ConvertFromFileToFile(String inputFilename, String outputFilename, String exportFormatId, PostProcessSteps exportProcessSteps) {
     return ConvertFromFileToFile(inputFilename, PostProcessSteps.None, outputFilename, exportFormatId, exportProcessSteps);
 }
Пример #42
0
        public static RWSection CreateDFFFromAssimp(string fileName, bool flipUVs, bool ignoreMeshColors)
        {
            PostProcessSteps pps =
                PostProcessSteps.Debone |
                PostProcessSteps.FindInstances |
                PostProcessSteps.FindInvalidData |
                PostProcessSteps.GenerateNormals |
                PostProcessSteps.JoinIdenticalVertices |
                PostProcessSteps.OptimizeGraph |
                PostProcessSteps.OptimizeMeshes |
                PostProcessSteps.PreTransformVertices |
                PostProcessSteps.Triangulate |
                (flipUVs ? PostProcessSteps.FlipUVs : 0);

            Scene scene = new AssimpContext().ImportFile(fileName, pps);

            int vertexCount   = scene.Meshes.Sum(m => m.VertexCount);
            int triangleCount = scene.Meshes.Sum(m => m.FaceCount);

            if (vertexCount > 65535 || triangleCount > 65536)
            {
                throw new ArgumentException("Model has too many vertices or triangles. Please import a simpler model.");
            }

            var materials = new List <Material_0007>(scene.MaterialCount);

            bool atomicNeedsMaterialEffects = false;

            foreach (var m in scene.Materials)
            {
                materials.Add(new Material_0007()
                {
                    materialStruct = new MaterialStruct_0001()
                    {
                        unusedFlags = 0,
                        color       = ignoreMeshColors ?
                                      new RenderWareFile.Color(255, 255, 255, 255) :
                                      new RenderWareFile.Color(
                            (byte)(m.ColorDiffuse.R * 255),
                            (byte)(m.ColorDiffuse.G * 255),
                            (byte)(m.ColorDiffuse.B * 255),
                            (byte)(m.ColorDiffuse.A * 255)),
                        unusedInt2 = 0x2DF53E84,
                        isTextured = m.HasTextureDiffuse ? 1 : 0,
                        ambient    = ignoreMeshColors ? 1f : m.ColorAmbient.A,
                        specular   = ignoreMeshColors ? 1f : m.ColorSpecular.A,
                        diffuse    = ignoreMeshColors ? 1f : m.ColorDiffuse.A
                    },
                    texture           = m.HasTextureDiffuse ? RWTextureFromAssimpMaterial(m.TextureDiffuse) : null,
                    materialExtension = new Extension_0003()
                    {
                        extensionSectionList = m.HasTextureReflection ? new List <RWSection>()
                        {
                            new MaterialEffectsPLG_0120()
                            {
                                isAtomicExtension = false,
                                value             = MaterialEffectType.EnvironmentMap,
                                materialEffect1   = new MaterialEffectEnvironmentMap()
                                {
                                    EnvironmentMapTexture      = RWTextureFromAssimpMaterial(m.TextureReflection),
                                    ReflectionCoefficient      = m.Reflectivity,
                                    UseFrameBufferAlphaChannel = false
                                }
                            }
                        } : new List <RWSection>()
                    },
                });

                atomicNeedsMaterialEffects |= m.HasTextureReflection;
            }

            List <Vertex3> vertices   = new List <Vertex3>();
            List <Vertex3> normals    = new List <Vertex3>();
            List <Vertex2> textCoords = new List <Vertex2>();
            List <RenderWareFile.Color>    vertexColors = new List <RenderWareFile.Color>();
            List <RenderWareFile.Triangle> triangles    = new List <RenderWareFile.Triangle>();

            foreach (var m in scene.Meshes)
            {
                int totalVertices = vertices.Count;

                foreach (Vector3D v in m.Vertices)
                {
                    vertices.Add(new Vertex3(v.X, v.Y, v.Z));
                }

                foreach (Vector3D v in m.Normals)
                {
                    normals.Add(new Vertex3(v.X, v.Y, v.Z));
                }

                if (m.HasTextureCoords(0))
                {
                    foreach (Vector3D v in m.TextureCoordinateChannels[0])
                    {
                        textCoords.Add(new Vertex2(v.X, v.Y));
                    }
                }
                else
                {
                    for (int i = 0; i < m.VertexCount; i++)
                    {
                        textCoords.Add(new Vertex2(0, 0));
                    }
                }

                if (m.HasVertexColors(0))
                {
                    foreach (Color4D c in m.VertexColorChannels[0])
                    {
                        vertexColors.Add(new RenderWareFile.Color(
                                             (byte)(c.R * 255),
                                             (byte)(c.G * 255),
                                             (byte)(c.B * 255),
                                             (byte)(c.A * 255)));
                    }
                }
                else
                {
                    for (int i = 0; i < m.VertexCount; i++)
                    {
                        vertexColors.Add(new RenderWareFile.Color(255, 255, 255, 255));
                    }
                }

                foreach (var t in m.Faces)
                {
                    if (t.IndexCount == 3)
                    {
                        triangles.Add(new RenderWareFile.Triangle()
                        {
                            vertex1       = (ushort)(t.Indices[0] + totalVertices),
                            vertex2       = (ushort)(t.Indices[1] + totalVertices),
                            vertex3       = (ushort)(t.Indices[2] + totalVertices),
                            materialIndex = (ushort)m.MaterialIndex
                        });
                    }
                }
            }

            Vector3 max = new Vector3(vertices[0].X, vertices[0].Y, vertices[0].Z);
            Vector3 min = new Vector3(vertices[0].X, vertices[0].Y, vertices[0].Z);

            foreach (Vertex3 v in vertices)
            {
                if (v.X > max.X)
                {
                    max.X = v.X;
                }
                if (v.Y > max.Y)
                {
                    max.Y = v.Y;
                }
                if (v.Z > max.Z)
                {
                    max.Z = v.Z;
                }
                if (v.X < min.X)
                {
                    min.X = v.X;
                }
                if (v.Y < min.Y)
                {
                    min.Y = v.Y;
                }
                if (v.Z < min.Z)
                {
                    min.Z = v.Z;
                }
            }

            var binMeshes = new List <BinMesh>(materials.Count);

            for (int k = 0; k < materials.Count; k++)
            {
                List <int> indices = new List <int>(triangleCount * 3);

                foreach (var t in triangles)
                {
                    if (t.materialIndex == k)
                    {
                        indices.Add(t.vertex1);
                        indices.Add(t.vertex2);
                        indices.Add(t.vertex3);
                    }
                }

                if (indices.Count > 0)
                {
                    binMeshes.Add(new BinMesh()
                    {
                        materialIndex = k,
                        indexCount    = indices.Count(),
                        vertexIndices = indices.ToArray()
                    });
                }
            }

            return(ToClump(materials.ToArray(), new BoundingSphere(max + min / 2f, (max - min).Length()),
                           vertices.ToArray(), normals.ToArray(), textCoords.ToArray(), vertexColors.ToArray(), triangles.ToArray(),
                           binMeshes.ToArray(), atomicNeedsMaterialEffects));
        }
Пример #43
0
 /// <summary>
 /// Converts the model contained in the file to the specified format and save it to a data blob.
 /// </summary>
 /// <param name="inputFilename">Input file name to import</param>
 /// <param name="exportFormatId">Format id that specifies what format to export to</param>
 /// <param name="exportProcessSteps">Pre processing steps used for the export</param>
 /// <returns>Data blob containing the exported scene in a binary form</returns>
 /// <exception cref="AssimpException">Thrown if there was a general error in importing the model.</exception>
 /// <exception cref="System.IO.FileNotFoundException">Thrown if the file could not be located.</exception>
 /// <exception cref="System.ObjectDisposedException">Thrown if the context has already been disposed of.</exception>
 public ExportDataBlob ConvertFromFileToBlob(String inputFilename, String exportFormatId, PostProcessSteps exportProcessSteps) {
     return ConvertFromFileToBlob(inputFilename, PostProcessSteps.None, exportFormatId, exportProcessSteps);
 }
Пример #44
0
        private void ConvertMeshButton_Click(object sender, EventArgs e)
        {
            if (SelectedMeshFile.Length > 0)
            {
                // Prompt user to save mesh to a file
                if (SaveFileDialog.ShowDialog() == DialogResult.OK)
                {
                    string resultFile = SaveFileDialog.FileName;

                    FileMode mode;
                    if (File.Exists(resultFile))
                    {
                        mode = FileMode.Truncate;
                    }
                    else
                    {
                        mode = FileMode.Create;
                    }

                    BinaryWriter fileOut = new BinaryWriter(File.Open(resultFile, mode));

                    // Load the mesh with Assimp.NET and convert to proprietary format
                    AssimpContext importer = new AssimpContext();
                    importer.SetConfig(new NormalSmoothingAngleConfig(66.0F));
                    importer.SetConfig(new RemoveDegeneratePrimitivesConfig(true));

                    PostProcessSteps post =
                        PostProcessSteps.CalculateTangentSpace |
                        PostProcessSteps.Triangulate |
                        PostProcessSteps.ImproveCacheLocality |
                        PostProcessSteps.OptimizeMeshes |
                        PostProcessSteps.OptimizeGraph |
                        PostProcessSteps.FlipWindingOrder;
                    Scene mesh = importer.ImportFile(SelectedMeshFile, post);

                    if (mesh.HasMeshes)
                    {
                        Mesh m = mesh.Meshes[0];
                        fileOut.Write((uint)m.VertexCount);
                        for (int i = 0; i < m.VertexCount; ++i)
                        {
                            // Vertex pos
                            fileOut.Write(m.Vertices[i].X);
                            fileOut.Write(m.Vertices[i].Y);
                            fileOut.Write(m.Vertices[i].Z);

                            // Texture coordinates
                            fileOut.Write(m.TextureCoordinateChannels[0][i].X);
                            fileOut.Write(m.TextureCoordinateChannels[0][i].Y);

                            // Normals
                            fileOut.Write(m.Normals[i].X);
                            fileOut.Write(m.Normals[i].Y);
                            fileOut.Write(m.Normals[i].Z);

                            // Tangents
                            fileOut.Write(m.Tangents[i].X);
                            fileOut.Write(m.Tangents[i].Y);
                            fileOut.Write(m.Tangents[i].Z);
                        }

                        fileOut.Write((uint)m.GetUnsignedIndices().Length);
                        for (int i = 0; i < m.GetUnsignedIndices().Length; ++i)
                        {
                            fileOut.Write((uint)m.GetUnsignedIndices()[i]);
                        }

                        fileOut.Close();
                    }
                }
            }
        }
Пример #45
0
        /// <summary>
        /// Converts the model contained in the file to the specified format and save it to a data blob.
        /// </summary>
        /// <param name="inputFilename">Input file name to import</param>
        /// <param name="importProcessSteps">Post processing steps used for the import</param>
        /// <param name="exportFormatId">Format id that specifies what format to export to</param>
        /// <param name="exportProcessSteps">Pre processing steps used for the export</param>
        /// <returns>Data blob containing the exported scene in a binary form</returns>
        /// <exception cref="AssimpException">Thrown if there was a general error in importing the model.</exception>
        /// <exception cref="System.IO.FileNotFoundException">Thrown if the file could not be located.</exception>
        /// <exception cref="System.ObjectDisposedException">Thrown if the context has already been disposed of.</exception>
        public ExportDataBlob ConvertFromFileToBlob(String inputFilename, PostProcessSteps importProcessSteps, String exportFormatId, PostProcessSteps exportProcessSteps) {
            CheckDisposed();

            IntPtr ptr = IntPtr.Zero;
            IntPtr fileIO = IntPtr.Zero;

            //Only do file checks if not using a custom IOSystem
            if(UsingCustomIOSystem) {
                fileIO = m_ioSystem.AiFileIO;
            } else if(String.IsNullOrEmpty(inputFilename) || !File.Exists(inputFilename)) {
                throw new FileNotFoundException("Filename was null or could not be found", inputFilename);
            }

            PrepareImport();

            try {
                ptr = AssimpLibrary.Instance.ImportFile(inputFilename, PostProcessSteps.None, fileIO, m_propStore);

                if(ptr == IntPtr.Zero)
                    throw new AssimpException("Error importing file: " + AssimpLibrary.Instance.GetErrorString());

                TransformScene(ptr);

                if(importProcessSteps != PostProcessSteps.None)
                    ptr = AssimpLibrary.Instance.ApplyPostProcessing(ptr, importProcessSteps);

                return AssimpLibrary.Instance.ExportSceneToBlob(ptr, exportFormatId, exportProcessSteps);
            } finally {
                CleanupImport();

                if(ptr != IntPtr.Zero)
                    AssimpLibrary.Instance.ReleaseImport(ptr);
            }
        }
Пример #46
0
        public static Model <T, RealtimeMaterial> LoadFromFileWithRealtimeMaterial <T>(string baseDirectory, string localPath, VertexRuntimeTypes vertexType, PostProcessSteps flags = DefaultPostProcessSteps) where T : struct, VertexLocateable
        {
            if (!Verifier.VerifyVertexStruct <T>(vertexType))
            {
                throw new ArgumentException($"Vertex Type Mismatch AssimpLoader");
            }

            string filePath = Path.Combine(baseDirectory, localPath);

            string[] directoryStructure = localPath.Split('/');
            string   modelDir           = directoryStructure[0];

            AssimpContext assimpContext = new AssimpContext();

            Assimp.Scene pScene = assimpContext.ImportFile(filePath, flags);

            int meshCount = pScene.MeshCount;

            Mesh <T>[]         meshes       = new Mesh <T> [meshCount];
            RealtimeMaterial[] materials    = new RealtimeMaterial[meshCount];
            ushort[][]         meshIndicies = new ushort[meshCount][];

            for (int i = 0; i < meshCount; i++)
            {
                var aiMesh      = pScene.Meshes[i];
                var vertexCount = aiMesh.VertexCount;
                if (vertexCount == 0)
                {
                    continue;
                }

                Assimp.Material aiMaterial = pScene.Materials[aiMesh.MaterialIndex];
                var             material   = aiMaterial.ToRealtimeMaterial();

                T[] meshDefinition = new T[vertexCount];

                for (int j = 0; j < vertexCount; j++)
                {
                    byte[] bytes = GenerateVertexBytesArrayFromAssimp(vertexType, aiMesh, j);
                    meshDefinition[j] = ByteMarshal.ByteArrayToStructure <T>(bytes);
                }

                materials[i] = material;
                var faceCount = aiMesh.FaceCount;
                meshIndicies[i] = new ushort[3 * faceCount];

                for (int j = 0; j < faceCount; j++)
                {
                    var face = aiMesh.Faces[j];

                    if (face.IndexCount != 3)
                    {
                        Console.Error.WriteLine("Loading Assimp: Face index count != 3!");
                        continue;
                    }

                    meshIndicies[i][3 * j + 0] = face.Indices[0].ToUnsignedShort();
                    meshIndicies[i][3 * j + 1] = face.Indices[1].ToUnsignedShort();
                    meshIndicies[i][3 * j + 2] = face.Indices[2].ToUnsignedShort();
                }
                meshes[i] = new Mesh <T>(meshDefinition, meshIndicies[i]);
            }

            return(new Model <T, RealtimeMaterial>(modelDir, meshes, materials));
        }
Пример #47
0
 /// <summary>
 /// Converts the model contained in the stream to the specified format and save it to a file.
 /// </summary>
 /// <param name="inputStream">Stream to read from</param>
 /// <param name="importFormatHint">Format extension to serve as a hint to Assimp to choose which importer to use</param>
 /// <param name="outputFilename">Output file name to export to</param>
 /// <param name="exportFormatId">Format id that specifies what format to export to</param>
 /// <param name="exportProcessSteps">Pre processing steps used for the export</param>
 /// <returns>True if the conversion was successful or not, false otherwise.</returns>
 /// <exception cref="AssimpException">Thrown if the stream is not valid (null or write-only) or if the format hint is null or empty.</exception>
 /// <exception cref="System.ObjectDisposedException">Thrown if the context has already been disposed of.</exception>
 public bool ConvertFromStreamToFile(Stream inputStream, String importFormatHint, String outputFilename, String exportFormatId, PostProcessSteps exportProcessSteps) {
     return ConvertFromStreamToFile(inputStream, importFormatHint, PostProcessSteps.None, outputFilename, exportFormatId, exportProcessSteps);
 }
Пример #48
0
 /// <summary>
 /// Converts the model contained in the stream to the specified format and save it to a data blob.
 /// </summary>
 /// <param name="inputStream">Stream to read from</param>
 /// <param name="importFormatHint">Format extension to serve as a hint to Assimp to choose which importer to use</param>
 /// <param name="exportFormatId">Format id that specifies what format to export to</param>
 /// <param name="exportProcessSteps">Pre processing steps used for the export</param>
 /// <returns>Data blob containing the exported scene in a binary form</returns>
 /// <exception cref="AssimpException">Thrown if the stream is not valid (null or write-only) or if the format hint is null or empty.</exception>
 /// <exception cref="System.ObjectDisposedException">Thrown if the context has already been disposed of.</exception>
 public ExportDataBlob ConvertFromStreamToBlob(Stream inputStream, String importFormatHint, String exportFormatId, PostProcessSteps exportProcessSteps) {
     return ConvertFromStreamToBlob(inputStream, importFormatHint, PostProcessSteps.None, exportFormatId, exportProcessSteps);
 }
Пример #49
0
        /// <summary>
        /// Exports the given scene to a chosen file format and writes the result file(s) to disk.
        /// </summary>
        /// <param name="scene">The scene to export, which needs to be freed by the caller. The scene is expected to conform to Assimp's Importer output format. In short,
        /// this means the model data should use a right handed coordinate system, face winding should be counter clockwise, and the UV coordinate origin assumed to be upper left. If the input is different, specify the pre processing flags appropiately.</param>
        /// <param name="formatId">Format id describing which format to export to.</param>
        /// <param name="fileName">Output filename to write to</param>
        /// <param name="preProcessing">Pre processing flags - accepts any post processing step flag. In reality only a small subset are actually supported, e.g. to ensure the input
        /// conforms to the standard Assimp output format. Some may be redundant, such as triangulation, which some exporters may have to enforce due to the export format.</param>
        /// <returns>Return code specifying if the operation was a success.</returns>
        public static ReturnCode ExportScene(IntPtr scene, String formatId, String fileName, PostProcessSteps preProcessing)
        {
            if(String.IsNullOrEmpty(formatId) || scene == IntPtr.Zero)
                return ReturnCode.Failure;

            return aiExportScene(scene, formatId, fileName, (uint) preProcessing);
        }