Пример #1
0
        /// <summary>
        /// Imports a model from the given file.
        /// </summary>
        /// <param name="sourceFile">The source file to be loaded.</param>
        /// <param name="importOptions">Some configuration for the importer.</param>
        public ImportedModelContainer ImportModel(ResourceLink sourceFile, ImportOptions importOptions)
        {
            // Get import options
            ACImportOptions acImportOptions = importOptions as ACImportOptions;

            if (acImportOptions == null)
            {
                throw new SeeingSharpException("Invalid import options for ACImporter!");
            }

            ImportedModelContainer result = new ImportedModelContainer(acImportOptions);

            // Get needed resource key
            NamedOrGenericKey resGeometry = GraphicsCore.GetNextGenericResourceKey();

            // Load and fill result object
            ObjectType objType = ACFileLoader.ImportObjectType(sourceFile);

            result.ImportedResources.Add(new ImportedResourceInfo(
                                             resGeometry,
                                             () => new GeometryResource(objType)));
            result.Objects.Add(new GenericObject(resGeometry));

            return(result);
        }
Пример #2
0
        /// <summary>
        /// Reads the model in ASCII format from the specified stream.
        /// </summary>
        private ImportedModelContainer TryReadAscii(Stream stream, StlImportOptions importOptions)
        {
            using (var reader = new StreamReader(stream, ENCODING, false, 128, true))
            {
                VertexStructure newStructure = new VertexStructure();
                while (!reader.EndOfStream)
                {
                    var line = reader.ReadLine();
                    if (line == null)
                    {
                        continue;
                    }

                    line = line.Trim();
                    if (line.Length == 0 || line.StartsWith("\0") || line.StartsWith("#") || line.StartsWith("!") ||
                        line.StartsWith("$"))
                    {
                        continue;
                    }

                    string id, values;
                    ParseLine(line, out id, out values);
                    switch (id)
                    {
                    // Header.. not needed here
                    case "solid":
                        break;

                    // Geometry data
                    case "facet":
                        this.ReadFacet(reader, values, newStructure, importOptions);
                        break;

                    // End of file
                    case "endsolid":
                        break;
                    }
                }

                // Generate result container
                ImportedModelContainer result         = new ImportedModelContainer(importOptions);
                NamedOrGenericKey      geoResourceKey = result.GetResourceKey(
                    RES_KEY_GEO_CLASS, RES_KEY_GEO_NAME);
                result.ImportedResources.Add(new ImportedResourceInfo(
                                                 geoResourceKey,
                                                 () => new GeometryResource(newStructure)));
                GenericObject geoObject = new GenericObject(geoResourceKey);
                result.Objects.Add(geoObject);

                // Append an object which transform the whole coordinate system
                ScenePivotObject rootObject = result.CreateAndAddRootObject();
                result.ParentChildRelationships.Add(new Tuple <SceneObject, SceneObject>(rootObject, geoObject));

                return(result);
            }
        }
Пример #3
0
        /// <summary>
        /// Reads the model from the specified binary stream.
        /// </summary>
        private ImportedModelContainer TryReadBinary(Stream stream, StlImportOptions importOptions)
        {
            // Check length
            long length = stream.Length;

            if (length < 84)
            {
                throw new SeeingSharpException("Incomplete file (smaller that 84 bytes)");
            }

            // Read number of triangles
            uint numberTriangles = 0;

            using (var reader = new BinaryReader(stream, Encoding.GetEncoding("us-ascii"), true))
            {
                // Read header (is not needed)
                //  (solid stands for Ascii format)
                string header = ENCODING.GetString(reader.ReadBytes(80), 0, 80).Trim();
                if (header.StartsWith("solid", StringComparison.OrdinalIgnoreCase))
                {
                    return(null);
                }

                // Read and check number of triangles
                numberTriangles = ReadUInt32(reader);
                if (length - 84 != numberTriangles * 50)
                {
                    throw new SeeingSharpException("Incomplete file (smaller that expected byte count)");
                }

                // Read geometry data
                VertexStructure newStructure = new VertexStructure((int)numberTriangles * 3);
                newStructure.CreateSurface((int)numberTriangles);
                for (int loop = 0; loop < numberTriangles; loop++)
                {
                    this.ReadTriangle(reader, newStructure, importOptions);
                }

                // Generate result container
                ImportedModelContainer result         = new ImportedModelContainer(importOptions);
                NamedOrGenericKey      geoResourceKey = result.GetResourceKey(
                    RES_KEY_GEO_CLASS, RES_KEY_GEO_NAME);
                result.ImportedResources.Add(new ImportedResourceInfo(
                                                 geoResourceKey,
                                                 () => new GeometryResource(newStructure)));
                GenericObject geoObject = new GenericObject(geoResourceKey);
                result.Objects.Add(geoObject);

                // Append an object which transform the whole coordinate system
                ScenePivotObject rootObject = result.CreateAndAddRootObject();
                result.ParentChildRelationships.Add(new Tuple <SceneObject, SceneObject>(rootObject, geoObject));

                return(result);
            }
        }
Пример #4
0
        /// <summary>
        /// Imports a model from the given file.
        /// </summary>
        /// <param name="importOptions">Some configuration for the importer.</param>
        /// <param name="sourceFile">The source file to be loaded.</param>
        public ImportedModelContainer ImportModel(ResourceLink sourceFile, ImportOptions importOptions)
        {
            // Get import options
            StlImportOptions stlImportOptions = importOptions as StlImportOptions;

            if (stlImportOptions == null)
            {
                throw new SeeingSharpException("Invalid import options for StlImporter!");
            }

            ImportedModelContainer result = null;

            try
            {
                // Try to read in BINARY format first
                using (Stream inStream = sourceFile.OpenInputStream())
                {
                    result = this.TryReadBinary(inStream, stlImportOptions);
                }

                // Read in ASCII format (if binary did not work)
                if (result == null)
                {
                    using (Stream inStream = sourceFile.OpenInputStream())
                    {
                        result = this.TryReadAscii(inStream, stlImportOptions);
                    }
                }
            }
            catch (Exception ex)
            {
                throw new SeeingSharpException($"Unable to read Stl file {sourceFile}: {ex.Message}!", ex);
            }

            // Handle empty result (unknown format error)
            if (result == null)
            {
                throw new SeeingSharpException($"Unable to read Stl file {sourceFile}: Unrecognized format error!");
            }

            return(result);
        }
Пример #5
0
        /// <summary>
        /// Imports a model from the given file.
        /// </summary>
        /// <param name="sourceFile">The source file to be loaded.</param>
        /// <param name="importOptions">Some configuration for the importer.</param>
        public ImportedModelContainer ImportModel(ResourceLink sourceFile, ImportOptions importOptions)
        {
            // Get import options
            ObjImportOptions objImportOptions = importOptions as ObjImportOptions;

            if (objImportOptions == null)
            {
                throw new SeeingSharpException("Invalid import options for ACImporter!");
            }

            ImportedModelContainer result = new ImportedModelContainer(objImportOptions);

            // Read object file
            ObjFileReader objFileReader = new ObjFileReader(sourceFile, result, objImportOptions);

            objFileReader.Read();
            objFileReader.GenerateObjects();

            return(result);
        }
Пример #6
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ObjFileReader"/> class.
        /// </summary>
        /// <param name="resource">The resource to be loaded.</param>
        /// <param name="targetContainer">The target ModelContainer into which to put the generated objects and resources.</param>
        /// <param name="importOptions">Current import settings.</param>
        public ObjFileReader(ResourceLink resource, ImportedModelContainer targetContainer, ObjImportOptions importOptions)
        {
            resource.EnsureNotNull(nameof(resource));
            targetContainer.EnsureNotNull(nameof(targetContainer));
            importOptions.EnsureNotNull(nameof(importOptions));

            m_resource        = resource;
            m_targetContainer = targetContainer;
            m_importOptions   = importOptions;

            m_rawVertices           = new List <Vector3>(1024);
            m_rawNormals            = new List <Vector3>(1014);
            m_rawTextureCoordinates = new List <Vector2>(1024);
            m_targetVertexStructure = new VertexStructure();

            // Apply transform matrix in case of a different coordinate system (switched coordinate axes)
            Matrix4x4 coordSpaceTransformMatrix = importOptions.GetTransformMatrixForCoordinateSystem();

            if (coordSpaceTransformMatrix != Matrix4x4.Identity)
            {
                m_targetVertexStructure.EnableBuildTimeTransform(coordSpaceTransformMatrix);
            }
        }
Пример #7
0
        /// <summary>
        /// Imports the texture node where the xml reader is currently located.
        /// </summary>
        private void ImportObject(XmlReader inStreamXml, ImportedModelContainer container, SceneObject parentObject, XglImportOptions xglImportOptions)
        {
            Vector3 upVector       = Vector3.UnitY;
            Vector3 forwardVector  = Vector3.UnitZ;
            Vector3 positionVector = Vector3.UnitX;
            string  meshID         = string.Empty;

            // Define a action which finally create the new object
            //  (may be called on two locations here.. so this action was defined
            SceneSpacialObject newObject            = null;
            Action             actionFinalizeObject = () =>
            {
                if (newObject != null)
                {
                    return;
                }

                if (string.IsNullOrEmpty(meshID))
                {
                    // Generate a Pivot on which other objects are orientated
                    newObject = new ScenePivotObject();
                }
                else
                {
                    // Generate an instance of a 3d mesh
                    newObject = new GenericObject(
                        container.GetResourceKey(RES_CLASS_MESH, meshID));
                }
                newObject.Position           = positionVector;
                newObject.TransformationType = SpacialTransformationType.TranslationDirection;
                newObject.RotationForward    = forwardVector;
                newObject.RotationUp         = upVector;
                container.Objects.Add(newObject);

                // Add dependency (parent => child)
                if (parentObject != null)
                {
                    container.ParentChildRelationships.Add(Tuple.Create <SceneObject, SceneObject>(
                                                               parentObject, newObject));
                }
            };

            // Read xml contents
            while (inStreamXml.Read())
            {
                // Ending condition
                if ((inStreamXml.NodeType == XmlNodeType.EndElement) &&
                    (inStreamXml.Name == NODE_NAME_OBJECT))
                {
                    break;
                }

                // Continue condition
                if (inStreamXml.NodeType != XmlNodeType.Element)
                {
                    continue;
                }

                switch (inStreamXml.Name)
                {
                case NODE_NAME_OBJECT:
                    actionFinalizeObject();
                    ImportObject(inStreamXml, container, newObject, xglImportOptions);
                    break;

                case NODE_NAME_TRANS_FORWARD:
                    inStreamXml.Read();
                    forwardVector = inStreamXml.ReadContentAsVector3();
                    break;

                case NODE_NAME_TRANS_UP:
                    inStreamXml.Read();
                    upVector = inStreamXml.ReadContentAsVector3();
                    break;

                case NODE_NAME_TRANS_POSITION:
                    inStreamXml.Read();
                    positionVector = inStreamXml.ReadContentAsVector3() * xglImportOptions.ResizeFactor;
                    break;

                case NODE_NAME_MESHREF:
                    inStreamXml.Read();
                    meshID = inStreamXml.ReadContentAsString();
                    break;

                case NODE_NAME_TRANSFORM:
                    break;

                default:
                    break;
                }
            }

            // finalize object here
            actionFinalizeObject();
        }
Пример #8
0
        /// <summary>
        /// Imports the mode node where the xml reader is currently located.
        /// </summary>
        /// <param name="inStreamXml">The xml reader object.</param>
        /// <param name="container">The container where to import to.</param>
        /// <param name="xglImportOptions">Current import options.</param>
        private Tuple <int, MaterialProperties> ImportMaterial(XmlReader inStreamXml, ImportedModelContainer container, XglImportOptions xglImportOptions)
        {
            int resultID = Int32.Parse(inStreamXml.GetAttribute("ID"));
            MaterialProperties result = new MaterialProperties();

            while (inStreamXml.Read())
            {
                // Ending condition
                if ((inStreamXml.NodeType == XmlNodeType.EndElement) &&
                    (inStreamXml.Name == NODE_NAME_MAT))
                {
                    break;
                }

                // Continue condition
                if (inStreamXml.NodeType != XmlNodeType.Element)
                {
                    continue;
                }

                switch (inStreamXml.Name)
                {
                case NODE_NAME_MAT_DIFFUSE:
                    if (result == null)
                    {
                        continue;
                    }
                    inStreamXml.Read();
                    result.DiffuseColor = new Color4(inStreamXml.ReadContentAsVector3(), 1f);
                    break;

                case NODE_NAME_MAT_AMB:
                    if (result == null)
                    {
                        continue;
                    }
                    inStreamXml.Read();
                    result.AmbientColor = new Color4(inStreamXml.ReadContentAsVector3(), 1f);
                    break;

                case NODE_NAME_MAT_EMISS:
                    if (result == null)
                    {
                        continue;
                    }
                    inStreamXml.Read();
                    result.EmissiveColor = new Color4(inStreamXml.ReadContentAsVector3(), 1f);
                    break;

                case NODE_NAME_MAT_SPEC:
                    if (result == null)
                    {
                        continue;
                    }
                    inStreamXml.Read();
                    result.SpecularColor = new Color4(inStreamXml.ReadContentAsVector3(), 1f);
                    break;

                case NODE_NAME_MAT_ALPHA:
                    break;

                case NODE_NAME_MAT_SHINE:
                    if (result == null)
                    {
                        continue;
                    }
                    inStreamXml.Read();
                    result.Shininess = inStreamXml.ReadContentAsFloat();
                    break;
                }
            }

            return(Tuple.Create(resultID, result));
        }
Пример #9
0
        /// <summary>
        /// Imports the texture node where the xml reader is currently located.
        /// </summary>
        /// <param name="inStreamXml">The xml reader object.</param>
        /// <param name="container">The container where to import to.</param>
        /// <param name="xglImportOptions">Current import options.</param>
        private void ImportMesh(XmlReader inStreamXml, ImportedModelContainer container, XglImportOptions xglImportOptions)
        {
            string          id = inStreamXml.GetAttribute("ID");
            VertexStructure actVertexStructure = new VertexStructure();
            int             minVertexID        = int.MaxValue;
            int             actVertexIndex     = -1;
            int             actNormalIndex     = -1;
            int             actTextureIndex    = -1;
            Vertex          actTempVertex      = Vertex.Empty;

            int[] actFaceReferences = new int[3];
            Dictionary <int, MaterialProperties> localMaterialInfos = new Dictionary <int, MaterialProperties>();

            while (inStreamXml.Read())
            {
                // Ending condition
                if ((inStreamXml.NodeType == XmlNodeType.EndElement) &&
                    (inStreamXml.Name == NODE_NAME_MESH))
                {
                    break;
                }

                // Continue condition
                if (inStreamXml.NodeType != XmlNodeType.Element)
                {
                    continue;
                }

                switch (inStreamXml.Name)
                {
                case NODE_NAME_SURFACE:
                    // If this tag is present, faces will be visible from both sides. If this flag is absent, faces will be visible from only one side as described in the <F> tag
                    break;

                case NODE_NAME_MAT:
                    // Read the next material
                    var materialAndID = ImportMaterial(inStreamXml, container, xglImportOptions);
                    localMaterialInfos[materialAndID.Item1] = materialAndID.Item2;
                    break;

                case NODE_NAME_PATCH:
                    // A patch is a group of faces
                    // We don't need to handle this one
                    break;

                case NODE_NAME_POINT:
                    // Read next point
                    if (minVertexID == int.MaxValue)
                    {
                        minVertexID = Int32.Parse(inStreamXml.GetAttribute("ID"));
                    }
                    actVertexIndex++;
                    actTempVertex       = actVertexStructure.EnsureVertexAt(actVertexIndex);
                    actTempVertex.Color = Color4.White;
                    inStreamXml.Read();
                    actTempVertex.Position = inStreamXml.ReadContentAsVector3() * xglImportOptions.ResizeFactor;
                    actVertexStructure.Vertices[actVertexIndex] = actTempVertex;
                    break;

                case NODE_NAME_NORMAL:
                    // Read next normal
                    if (minVertexID == int.MaxValue)
                    {
                        minVertexID = Int32.Parse(inStreamXml.GetAttribute("ID"));
                    }
                    actNormalIndex++;
                    actTempVertex = actVertexStructure.EnsureVertexAt(actNormalIndex);
                    inStreamXml.Read();
                    actTempVertex.Normal = inStreamXml.ReadContentAsVector3();
                    actVertexStructure.Vertices[actNormalIndex] = actTempVertex;
                    break;

                case NODE_NAME_TC:
                    // Read next texture coordinate
                    if (minVertexID == int.MaxValue)
                    {
                        minVertexID = Int32.Parse(inStreamXml.GetAttribute("ID"));
                    }
                    actTextureIndex++;
                    actTempVertex = actVertexStructure.EnsureVertexAt(actTextureIndex);
                    inStreamXml.Read();
                    actTempVertex.TexCoord = inStreamXml.ReadContentAsVector2();
                    actVertexStructure.Vertices[actTextureIndex] = actTempVertex;
                    break;

                case NODE_NAME_FACE:
                    // Read next face
                    actFaceReferences[0] = 0;
                    actFaceReferences[1] = 0;
                    actFaceReferences[2] = 0;
                    int loopFacePoint     = 0;
                    int referencedMat     = -1;
                    int referencedTexture = -1;
                    while (inStreamXml.Read())
                    {
                        // Ending condition
                        if ((inStreamXml.NodeType == XmlNodeType.EndElement) &&
                            (inStreamXml.Name == NODE_NAME_FACE))
                        {
                            break;
                        }
                        if (inStreamXml.NodeType != XmlNodeType.Element)
                        {
                            continue;
                        }

                        // Read next face index
                        if (inStreamXml.Name == NODE_NAME_FACE_MATERIAL_REF)
                        {
                            inStreamXml.Read();
                            referencedMat = inStreamXml.ReadContentAsInt();
                        }
                        else if (inStreamXml.Name == NODE_NAME_FACE_TEXTUREREF_REF)
                        {
                            inStreamXml.Read();
                            referencedTexture = inStreamXml.ReadContentAsInt();
                        }
                        else if (inStreamXml.Name == NODE_NAME_FACE_POINT_REF)
                        {
                            if (loopFacePoint >= 3)
                            {
                                throw new SeeingSharpGraphicsException("Invalid face index count!");
                            }
                            inStreamXml.Read();
                            actFaceReferences[loopFacePoint] = inStreamXml.ReadContentAsInt() - minVertexID;
                            loopFacePoint++;
                        }
                        else
                        {
                        }
                    }

                    // Get the correct material
                    MaterialProperties referencedMatObject = MaterialProperties.Empty;
                    if (referencedMat > -1)
                    {
                        localMaterialInfos.TryGetValue(referencedMat, out referencedMatObject);
                    }
                    if (referencedTexture > -1)
                    {
                        referencedMatObject            = referencedMatObject.Clone();
                        referencedMatObject.TextureKey = container.GetResourceKey(RES_CLASS_TEXTURE, referencedTexture.ToString());
                    }

                    //for (int actFaceLoc = 0; actFaceLoc < 3; actFaceLoc++)
                    //{
                    //    int actVertexIndexInner = actFaceReferences[actFaceLoc];
                    //    actTempVertex = actVertexStructure.Vertices[actVertexIndexInner];
                    //    actTempVertex.Color = referencedMatObject.DiffuseColor;
                    //    actVertexStructure.Vertices[actVertexIndexInner] = actTempVertex;
                    //}

                    // Add the triangle
                    if (loopFacePoint != 3)
                    {
                        throw new SeeingSharpGraphicsException("Invalid face index count!");
                    }
                    actVertexStructure
                    .CreateOrGetExistingSurface(referencedMatObject)
                    .AddTriangle(actFaceReferences[0], actFaceReferences[1], actFaceReferences[2]);
                    break;

                default:
                    //throw new SeeingSharpGraphicsException(string.Format(
                    //    "Unknown element {0} in xgl file!",
                    //    inStreamXml.Name));
                    break;
                }
            }

            // Add the geometry resource
            container.ImportedResources.Add(new ImportedResourceInfo(
                                                container.GetResourceKey(RES_CLASS_MESH, id),
                                                () => new GeometryResource(actVertexStructure)));
        }
Пример #10
0
        /// <summary>
        /// Imports the texture node where the xml reader is currently located.
        /// </summary>
        /// <param name="inStreamXml">The xml reader object.</param>
        /// <param name="container">The container where to import to.</param>
        private void ImportTexture(XmlReader inStreamXml, ImportedModelContainer container)
        {
            string id     = inStreamXml.GetAttribute("ID");
            int    width  = 0;
            int    height = 0;
            MemoryMappedTexture32bpp inMemoryTexture = null;

            while (inStreamXml.Read())
            {
                // Ending condition
                if ((inStreamXml.NodeType == XmlNodeType.EndElement) &&
                    (inStreamXml.Name == NODE_NAME_TEXTURE))
                {
                    break;
                }

                // Continue condition
                if (inStreamXml.NodeType != XmlNodeType.Element)
                {
                    continue;
                }

                // Read all texture data

                switch (inStreamXml.Name)
                {
                case NODE_NAME_TEXTURE_RGBA:
                    width  = Int32.Parse(inStreamXml.GetAttribute("WIDTH"));
                    height = Int32.Parse(inStreamXml.GetAttribute("HEIGHT"));
                    unsafe
                    {
                        inMemoryTexture = new MemoryMappedTexture32bpp(new Size2(width, height));
                        byte *inMemoryTextureP = (byte *)inMemoryTexture.Pointer.ToPointer();

                        int    fullSize     = width * height * 4;
                        byte[] sourceBuffer = new byte[fullSize];
                        inStreamXml.Read();
                        inStreamXml.ReadContentAsBinHex(sourceBuffer, 0, fullSize);
                        for (int loop = 0; loop < fullSize; loop += 4)
                        {
                            // Target format is BGRA (default one in Seeing#)

                            inMemoryTextureP[loop + 2] = sourceBuffer[loop];
                            inMemoryTextureP[loop + 1] = sourceBuffer[loop + 1];
                            inMemoryTextureP[loop + 0] = sourceBuffer[loop + 2];
                            inMemoryTextureP[loop + 3] = sourceBuffer[loop + 3];
                        }
                    }
                    break;

                case NODE_NAME_TEXTURE_RGB:
                    width  = Int32.Parse(inStreamXml.GetAttribute("WIDTH"));
                    height = Int32.Parse(inStreamXml.GetAttribute("HEIGHT"));
                    unsafe
                    {
                        inMemoryTexture = new MemoryMappedTexture32bpp(new Size2(width, height));
                        byte *inMemoryTextureP = (byte *)inMemoryTexture.Pointer.ToPointer();

                        int    fullSize     = width * height * 3;
                        int    loopTarget   = 0;
                        byte[] sourceBuffer = new byte[fullSize];
                        inStreamXml.Read();
                        inStreamXml.ReadContentAsBinHex(sourceBuffer, 0, fullSize);
                        for (int loop = 0; loop < fullSize; loop += 3)
                        {
                            // Target format is BGRA (default one in Seeing#)
                            inMemoryTextureP[loopTarget + 2] = sourceBuffer[loop];
                            inMemoryTextureP[loopTarget + 1] = sourceBuffer[loop + 1];
                            inMemoryTextureP[loopTarget + 0] = sourceBuffer[loop + 2];
                            inMemoryTextureP[loopTarget + 3] = 255;
                            loopTarget += 4;
                        }
                    }
                    break;

                case NODE_NAME_TEXTURE_MODULATE:
                    break;

                case NODE_NAME_TEXTURE_REPEAT:
                    break;

                default:
                    //throw new SeeingSharpGraphicsException(string.Format(
                    //    "Unknown element {0} in xgl file!",
                    //    inStreamXml.Name));
                    break;
                }
            }

            // Check values
            if (width < 0)
            {
                throw new SeeingSharpGraphicsException("Unable to read with of a texture!");
            }
            if (height < 0)
            {
                throw new SeeingSharpGraphicsException("Unable to read height of a texture!");
            }
            if (inMemoryTexture == null)
            {
                throw new SeeingSharpGraphicsException("Unable to read the contents of a texture!");
            }

            // Add the imported texture
            var resKeyTexture = container.GetResourceKey(RES_CLASS_TEXTURE, id);

            container.ImportedResources.Add(new ImportedResourceInfo(
                                                resKeyTexture,
                                                () => new StandardTextureResource(inMemoryTexture)));
            container.ImportedResources.Add(new ImportedResourceInfo(
                                                container.GetResourceKey(RES_CLASS_MATERIAL, id),
                                                () => new SimpleColoredMaterialResource(resKeyTexture)));
        }
Пример #11
0
        /// <summary>
        /// Imports a model from the given file.
        /// </summary>
        /// <param name="sourceFile">The source file to be loaded.</param>
        /// <param name="importOptions">Some configuration for the importer.</param>
        public ImportedModelContainer ImportModel(ResourceLink sourceFile, ImportOptions importOptions)
        {
            // Get import options
            XglImportOptions xglImportOptions = importOptions as XglImportOptions;

            if (xglImportOptions == null)
            {
                throw new SeeingSharpException("Invalid import options for ACImporter!");
            }

            ImportedModelContainer result = new ImportedModelContainer(importOptions);

            // Append an object which transform the whole coordinate system
            ScenePivotObject rootObject = result.CreateAndAddRootObject();

            // Load current model by walking through xml nodes
            using (Stream inStream = sourceFile.OpenInputStream())
            {
                // Handle compressed xgl files (extension zgl)
                Stream nextStream = inStream;
                if (sourceFile.FileExtension.Equals("zgl", StringComparison.OrdinalIgnoreCase))
                {
                    // Skip the first bytes in case of compression
                    //  see https://github.com/assimp/assimp/blob/master/code/XGLLoader.cpp
                    inStream.ReadByte();
                    inStream.ReadByte();
                    nextStream = new System.IO.Compression.DeflateStream(inStream, CompressionMode.Decompress);
                }

                // Read all xml data
                try
                {
                    using (XmlReader inStreamXml = XmlReader.Create(nextStream, new XmlReaderSettings()
                    {
                        CloseInput = false
                    }))
                    {
                        while (inStreamXml.Read())
                        {
                            try
                            {
                                if (inStreamXml.NodeType != XmlNodeType.Element)
                                {
                                    continue;
                                }

                                switch (inStreamXml.Name)
                                {
                                case NODE_NAME_DATA:
                                    break;

                                case NODE_NAME_BACKGROUND:
                                    break;

                                case NODE_NAME_LIGHTING:
                                    break;

                                case NODE_NAME_TEXTURE:
                                    ImportTexture(inStreamXml, result);
                                    break;

                                case NODE_NAME_MESH:
                                    ImportMesh(inStreamXml, result, xglImportOptions);
                                    break;

                                case NODE_NAME_OBJECT:
                                    ImportObject(inStreamXml, result, rootObject, xglImportOptions);
                                    break;

                                default:
                                    break;
                                }
                            }
                            catch (Exception ex)
                            {
                                // Get current line and column
                                int          currentLine   = 0;
                                int          currentColumn = 0;
                                IXmlLineInfo lineInfo      = inStreamXml as IXmlLineInfo;
                                if (lineInfo != null)
                                {
                                    currentLine   = lineInfo.LineNumber;
                                    currentColumn = lineInfo.LinePosition;
                                }

                                // Throw an exception with more detail where the error was raised originally
                                throw new SeeingSharpGraphicsException(string.Format(
                                                                           "Unable to read file {0} because of an error while reading xml at {1}",
                                                                           sourceFile,
                                                                           currentLine + ", " + currentColumn), ex);
                            }
                        }
                    }
                }
                finally
                {
                    if (inStream != nextStream)
                    {
                        nextStream.Dispose();
                    }
                }
            }

            return(result);
        }