/// <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); } }
/// <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); } }
/// <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); }