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