public static void ExportModelToDirectory(Model model, string directory, ExportOptions exportOptions) { switch (exportOptions.ExportFormatInfo.ExportFormat) { case ExportFormats.Obj: exportModelAsOBJToDirectory(model, directory, exportOptions); break; //case ModelExportFormats.STL: // exportModelAsSTLToDirectory(model, directory, formatOptions.Options); // break; } }
public static Mesh LoadFromStream(Model model, Stream stream) { BinaryReader binaryReader = new BinaryReader(stream); uint bytesPerVertex = 0; uint vertexStreamCount = 0; Mesh mesh = new Mesh(model); mesh.MaterialIndex = binaryReader.ReadUInt32(); mesh.Unknown1 = binaryReader.ReadUInt32(); mesh.Unknown2 = binaryReader.ReadUInt32(); mesh.Unknown3 = binaryReader.ReadUInt32(); vertexStreamCount = binaryReader.ReadUInt32(); mesh.IndexSize = binaryReader.ReadUInt32(); mesh.IndexCount = binaryReader.ReadUInt32(); mesh.VertexCount = binaryReader.ReadUInt32(); mesh.VertexStreams = new VertexStream[(int)vertexStreamCount]; // read vertex streams for (int j = 0; j < vertexStreamCount; ++j) { bytesPerVertex = binaryReader.ReadUInt32(); byte[] buffer = binaryReader.ReadBytes((int)mesh.VertexCount * (int)bytesPerVertex); VertexStream vertexStream = new VertexStream((int)bytesPerVertex, buffer); if (vertexStream != null) { mesh.VertexStreams[j] = vertexStream; } } // read indices mesh.IndexData = binaryReader.ReadBytes((int)mesh.IndexCount * (int)mesh.IndexSize); uint materialDefinitionHash = model.Materials[(int)mesh.MaterialIndex].MaterialDefinitionHash; MaterialDefinition materialDefinition = null; MaterialDefinitionLibrary.Instance.MaterialDefinitions.TryGetValue(materialDefinitionHash, out materialDefinition); string effectName = materialDefinition.DrawStyles[0].Effect; return mesh; }
private Mesh(Model model) { this.Model = model; }
private static void exportModelAsOBJToDirectory(Model model, string directory, ExportOptions options) { //TODO: Figure out what to do with non-version 4 models. if (model != null && model.Version != 4) { return; } NumberFormatInfo format = new NumberFormatInfo(); format.NumberDecimalSeparator = "."; if (options.Package) { try { DirectoryInfo directoryInfo = Directory.CreateDirectory(directory + @"\" + Path.GetFileNameWithoutExtension(model.Name)); directory = directoryInfo.FullName; } catch (Exception) { } } if (options.Textures) { ImageImporter imageImporter = new ImageImporter(); ImageExporter imageExporter = new ImageExporter(); foreach(String textureString in model.TextureStrings) { MemoryStream textureMemoryStream = AssetManager.Instance.CreateAssetMemoryStreamByName(textureString); if(textureMemoryStream == null) continue; Image textureImage = imageImporter.LoadImageFromStream(textureMemoryStream); if(textureImage == null) continue; imageExporter.SaveImage(textureImage, options.TextureFormat.ImageType, directory + @"\" + Path.GetFileNameWithoutExtension(textureString) + @"." + options.TextureFormat.Extension); } } String path = directory + @"\" + Path.GetFileNameWithoutExtension(model.Name) + ".obj"; FileStream fileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Write); StreamWriter streamWriter = new StreamWriter(fileStream); for (Int32 i = 0; i < model.Meshes.Length; ++i) { Mesh mesh = model.Meshes[i]; MaterialDefinition materialDefinition = MaterialDefinitionManager.Instance.MaterialDefinitions[model.Materials[(Int32)mesh.MaterialIndex].MaterialDefinitionHash]; VertexLayout vertexLayout = MaterialDefinitionManager.Instance.VertexLayouts[materialDefinition.DrawStyles[0].VertexLayoutNameHash]; //position VertexLayout.Entry.DataTypes positionDataType; Int32 positionOffset; Int32 positionStreamIndex; vertexLayout.GetEntryInfoFromDataUsageAndUsageIndex(VertexLayout.Entry.DataUsages.Position, 0, out positionDataType, out positionStreamIndex, out positionOffset); Mesh.VertexStream positionStream = mesh.VertexStreams[positionStreamIndex]; for (Int32 j = 0; j < mesh.VertexCount; ++j) { Vector3 position = readVector3(options, positionOffset, positionStream, j); position.X *= options.Scale.X; position.Y *= options.Scale.Y; position.Z *= options.Scale.Z; streamWriter.WriteLine("v " + position.X.ToString(format) + " " + position.Y.ToString(format) + " " + position.Z.ToString(format)); } //texture coordinates if (options.TextureCoordinates) { VertexLayout.Entry.DataTypes texCoord0DataType; Int32 texCoord0Offset = 0; Int32 texCoord0StreamIndex = 0; Boolean texCoord0Present = vertexLayout.GetEntryInfoFromDataUsageAndUsageIndex(VertexLayout.Entry.DataUsages.Texcoord, 0, out texCoord0DataType, out texCoord0StreamIndex, out texCoord0Offset); if (texCoord0Present) { Mesh.VertexStream texCoord0Stream = mesh.VertexStreams[texCoord0StreamIndex]; for (Int32 j = 0; j < mesh.VertexCount; ++j) { Vector2 texCoord; switch (texCoord0DataType) { case VertexLayout.Entry.DataTypes.Float2: texCoord.X = BitConverter.ToSingle(texCoord0Stream.Data, (j * texCoord0Stream.BytesPerVertex) + 0); texCoord.Y = 1.0f - BitConverter.ToSingle(texCoord0Stream.Data, (j * texCoord0Stream.BytesPerVertex) + 4); break; case VertexLayout.Entry.DataTypes.float16_2: texCoord.X = Half.FromBytes(texCoord0Stream.Data, (j * texCoord0Stream.BytesPerVertex) + texCoord0Offset + 0).ToSingle(); texCoord.Y = 1.0f - Half.FromBytes(texCoord0Stream.Data, (j * texCoord0Stream.BytesPerVertex) + texCoord0Offset + 2).ToSingle(); break; default: texCoord.X = 0; texCoord.Y = 0; break; } streamWriter.WriteLine("vt " + texCoord.X.ToString(format) + " " + texCoord.Y.ToString(format)); } } } } //faces UInt32 vertexCount = 0; for (Int32 i = 0; i < model.Meshes.Length; ++i) { Mesh mesh = model.Meshes[i]; streamWriter.WriteLine("g Mesh" + i); for (Int32 j = 0; j < mesh.IndexCount; j += 3) { UInt32 index0, index1, index2; switch (mesh.IndexSize) { case 2: index0 = vertexCount + BitConverter.ToUInt16(mesh.IndexData, (j * 2) + 0) + 1; index1 = vertexCount + BitConverter.ToUInt16(mesh.IndexData, (j * 2) + 2) + 1; index2 = vertexCount + BitConverter.ToUInt16(mesh.IndexData, (j * 2) + 4) + 1; break; case 4: index0 = vertexCount + BitConverter.ToUInt32(mesh.IndexData, (j * 4) + 0) + 1; index1 = vertexCount + BitConverter.ToUInt32(mesh.IndexData, (j * 4) + 4) + 1; index2 = vertexCount + BitConverter.ToUInt32(mesh.IndexData, (j * 4) + 8) + 1; break; default: index0 = 0; index1 = 0; index2 = 0; break; } if (options.Normals && options.TextureCoordinates) { streamWriter.WriteLine("f " + index2 + "/" + index2 + "/" + index2 + " " + index1 + "/" + index1 + "/" + index1 + " " + index0 + "/" + index0 + "/" + index0); } else if (options.Normals) { streamWriter.WriteLine("f " + index2 + "//" + index2 + " " + index1 + "//" + index1 + " " + index0 + "//" + index0); } else if (options.TextureCoordinates) { streamWriter.WriteLine("f " + index2 + "/" + index2 + " " + index1 + "/" + index1 + " " + index0 + "/" + index0); } else { streamWriter.WriteLine("f " + index2 + " " + index1 + " " + index0); } } vertexCount += (UInt32)mesh.VertexCount; } streamWriter.Close(); }
private static void exportModelAsSTLToDirectory(Model model, string directory, ExportOptions options) { //NumberFormatInfo format = new NumberFormatInfo(); //format.NumberDecimalSeparator = "."; //String path = directory + @"\" + Path.GetFileNameWithoutExtension(model.Name) + ".stl"; //FileStream fileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Write); //StreamWriter streamWriter = new StreamWriter(fileStream); //for (Int32 i = 0; i < model.Meshes.Length; ++i) //{ // Mesh mesh = model.Meshes[i]; // for (Int32 j = 0; j < mesh.Indices.Length; j += 3) // { // Vector3 normal = Vector3.Zero; // normal += mesh.Vertices[mesh.Indices[j + 0]].Normal; // normal += mesh.Vertices[mesh.Indices[j + 1]].Normal; // normal += mesh.Vertices[mesh.Indices[j + 2]].Normal; // normal.Normalize(); // streamWriter.WriteLine("facet normal " + normal.X.ToString("E", format) + " " + normal.Y.ToString("E", format) + " " + normal.Z.ToString("E", format)); // streamWriter.WriteLine("outer loop"); // for (Int32 k = 0; k < 3; ++k) // { // Vector3 vertex = mesh.Vertices[mesh.Indices[j + k]].Position; // streamWriter.WriteLine("vertex " + vertex.X.ToString("E", format) + " " + vertex.Y.ToString("E", format) + " " + vertex.Z.ToString("E", format)); // } // streamWriter.WriteLine("endloop"); // streamWriter.WriteLine("endfacet"); // } //} //streamWriter.Close(); }
public ModelInstance(Model model) { this.Model = model; }
public static Model LoadFromStream(string name, Stream stream) { BinaryReader binaryReader = new BinaryReader(stream); //header byte[] magic = binaryReader.ReadBytes(4); if (magic[0] != 'D' || magic[1] != 'M' || magic[2] != 'O' || magic[3] != 'D') { return null; } Model model = new Model(); model.Version = binaryReader.ReadUInt32(); if (model.Version != 4) return null; uint modelHeaderOffset = binaryReader.ReadUInt32(); model.Name = name; //textures & materials model.TextureStrings = new List<string>(); model.Materials = new List<Material>(); Dma.Dma.LoadFromStream(binaryReader.BaseStream, model.TextureStrings, model.Materials); //bounding box Vector3 min = new Vector3(); min.X = binaryReader.ReadSingle(); min.Y = binaryReader.ReadSingle(); min.Z = binaryReader.ReadSingle(); model.Min = min; Vector3 max = new Vector3(); max.X = binaryReader.ReadSingle(); max.Y = binaryReader.ReadSingle(); max.Z = binaryReader.ReadSingle(); model.Max = max; //meshes uint meshCount = binaryReader.ReadUInt32(); model.Meshes = new Mesh[meshCount]; for (int i = 0; i < meshCount; ++i) { Mesh mesh = Mesh.LoadFromStream(model, binaryReader.BaseStream); if (mesh != null) model.Meshes[i] = mesh; } //bone maps uint boneMapCount = binaryReader.ReadUInt32(); model.BoneMaps = new BoneMap[boneMapCount]; for (int i = 0; i < boneMapCount; ++i) { BoneMap boneMap = BoneMap.LoadFromStream(binaryReader.BaseStream); model.BoneMaps[i] = boneMap; } //bone map entries uint boneMapEntryCount = binaryReader.ReadUInt32(); BoneMapEntry[] boneMapEntries = new BoneMapEntry[boneMapEntryCount]; for (int i = 0; i < boneMapEntryCount; ++i) { BoneMapEntry boneMapEntry = BoneMapEntry.LoadFromStream(binaryReader.BaseStream); boneMapEntries[i] = boneMapEntry; } for (int i = 0; i < model.BoneMaps.Length; ++i) { uint end = 0; if (model.BoneMaps[i].BoneCount > 0) { for (int j = 0; j < model.BoneMaps[i].BoneCount; ++j) { if (boneMapEntries[j].GlobalIndex + model.BoneMaps[i].Delta > end) { end = boneMapEntries[j].GlobalIndex + model.BoneMaps[i].Delta; } } } model.BoneMaps[i].BoneEnd = end; } uint boneCount = binaryReader.ReadUInt32(); model.Bones = new Matrix4[boneCount]; model.BonesMins = new Vector3[boneCount]; model.BonesMaxs = new Vector3[boneCount]; model.BoneHashes = new uint[boneCount]; if (boneCount > 0) { for (int i = 0; i < boneCount; ++i) { Matrix4 boneMatrix = Matrix4.Identity; boneMatrix.M11 = binaryReader.ReadSingle(); boneMatrix.M12 = binaryReader.ReadSingle(); boneMatrix.M13 = binaryReader.ReadSingle(); boneMatrix.M21 = binaryReader.ReadSingle(); boneMatrix.M22 = binaryReader.ReadSingle(); boneMatrix.M23 = binaryReader.ReadSingle(); boneMatrix.M31 = binaryReader.ReadSingle(); boneMatrix.M32 = binaryReader.ReadSingle(); boneMatrix.M33 = binaryReader.ReadSingle(); boneMatrix.M41 = binaryReader.ReadSingle(); boneMatrix.M42 = binaryReader.ReadSingle(); boneMatrix.M43 = binaryReader.ReadSingle(); boneMatrix.Invert(); model.Bones[i] = boneMatrix; } //bones bounding box for(int i = 0; i < boneCount; ++i) { Vector3 boneMin = new Vector3(); boneMin.X = binaryReader.ReadSingle(); boneMin.Y = binaryReader.ReadSingle(); boneMin.Z = binaryReader.ReadSingle(); model.BonesMins[i] = boneMin; Vector3 boneMax = new Vector3(); boneMax.X = binaryReader.ReadSingle(); boneMax.Y = binaryReader.ReadSingle(); boneMax.Z = binaryReader.ReadSingle(); model.BonesMaxs[i] = boneMax; } //bone hashes for (int i = 0; i < boneCount; ++i) model.BoneHashes[i] = binaryReader.ReadUInt32(); } return model; }
public static Model LoadFromStream(String name, Stream stream) { BinaryReader binaryReader = new BinaryReader(stream); //header byte[] magic = binaryReader.ReadBytes(4); if (magic[0] != 'D' || magic[1] != 'M' || magic[2] != 'O' || magic[3] != 'D') { return null; } Model model = new Model(); model.Version = binaryReader.ReadUInt32(); if (model.Version != 4) { return null; } UInt32 modelHeaderOffset = binaryReader.ReadUInt32(); model.Name = name; //materials model.TextureStrings = new List<String>(); model.Materials = new List<Material>(); Dma.Dma.LoadFromStream(binaryReader.BaseStream, model.TextureStrings, model.Materials); //bounding box model.min.X = binaryReader.ReadSingle(); model.min.Y = binaryReader.ReadSingle(); model.min.Z = binaryReader.ReadSingle(); model.max.X = binaryReader.ReadSingle(); model.max.Y = binaryReader.ReadSingle(); model.max.Z = binaryReader.ReadSingle(); //meshes UInt32 meshCount = binaryReader.ReadUInt32(); model.Meshes = new Mesh[meshCount]; for (Int32 i = 0; i < meshCount; ++i) { Mesh mesh = Mesh.LoadFromStream(binaryReader.BaseStream, model.Materials); if (mesh != null) { model.Meshes[i] = mesh; } } //bone maps UInt32 boneMapCount = binaryReader.ReadUInt32(); model.BoneMaps = new BoneMap[boneMapCount]; for (Int32 i = 0; i < boneMapCount; ++i) { BoneMap boneMap = BoneMap.LoadFromStream(binaryReader.BaseStream); if (boneMap != null) { model.BoneMaps[i] = boneMap; } } //bone map entries UInt32 boneMapEntryCount = binaryReader.ReadUInt32(); BoneMapEntry[] boneMapEntries = new BoneMapEntry[boneMapEntryCount]; for (Int32 i = 0; i < boneMapEntryCount; ++i) { BoneMapEntry boneMapEntry = BoneMapEntry.LoadFromStream(binaryReader.BaseStream); boneMapEntries[i] = boneMapEntry; } return model; }
public ModelInstance(Model model) { Model = model; }
public void ExportModelToDirectoryWithExportOptions(Model model, string directory, ModelExportOptions exportOptions) { if (model == null || directory == null || exportOptions == null ) return; NumberFormatInfo numberFormatInfo = new NumberFormatInfo(); numberFormatInfo.NumberDecimalSeparator = "."; if (exportOptions.Package) { try { DirectoryInfo directoryInfo = Directory.CreateDirectory(directory + @"\" + Path.GetFileNameWithoutExtension(model.Name)); directory = directoryInfo.FullName; } catch (Exception) { } } if (exportOptions.Textures) { ImageImporter imageImporter = new ImageImporter(); ImageExporter imageExporter = new ImageExporter(); foreach(string textureString in model.TextureStrings) { MemoryStream textureMemoryStream = AssetManager.Instance.CreateAssetMemoryStreamByName(textureString); if(textureMemoryStream == null) continue; Image textureImage = imageImporter.LoadImageFromStream(textureMemoryStream); if(textureImage == null) continue; imageExporter.SaveImage(textureImage, exportOptions.TextureFormat.ImageType, directory + @"\" + Path.GetFileNameWithoutExtension(textureString) + @"." + exportOptions.TextureFormat.Extension); } } string path = string.Format(@"{0}\{1}.{2}", directory, Path.GetFileNameWithoutExtension(model.Name), Extension); FileStream fileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Write); StreamWriter streamWriter = new StreamWriter(fileStream); for (int i = 0; i < model.Meshes.Length; ++i) { Mesh mesh = model.Meshes[i]; //positions List<Vector3> positions; if (mesh.GetPositions(out positions, 0)) { foreach (Vector3 position in positions) { Vector3 scaledPosition = Vector3.Multiply(position, exportOptions.Scale); streamWriter.WriteLine("v {0} {1} {2}", scaledPosition.X.ToString(numberFormatInfo), scaledPosition.Y.ToString(numberFormatInfo), scaledPosition.Z.ToString(numberFormatInfo)); } } //texture coordinates if (exportOptions.TextureCoordinates) { Vector2[] texCoords; if (mesh.GetTexCoords(out texCoords, 0)) { foreach (Vector2 texcoord in texCoords) streamWriter.WriteLine("vt {0} {1}", texcoord.X.ToString(numberFormatInfo), (-texcoord.Y).ToString(numberFormatInfo)); } } //normals if (exportOptions.Normals) { Vector3[] normals; if (mesh.GetNormals(out normals, 0)) { foreach (Vector3 normal in normals) streamWriter.WriteLine("vn {0} {1} {2}", normal.X.ToString(numberFormatInfo), normal.Y.ToString(numberFormatInfo), normal.Z.ToString(numberFormatInfo)); } } } //faces uint vertexCount = 0; for (int i = 0; i < model.Meshes.Length; ++i) { Mesh mesh = model.Meshes[i]; streamWriter.WriteLine("g Mesh{0}", i); uint[] indices; mesh.GetIndices(out indices); for (int j = 0; j < mesh.IndexCount; j += 3) { uint index0 = indices[j + 0]; uint index1 = indices[j + 1]; uint index2 = indices[j + 2]; if (exportOptions.TextureCoordinates && exportOptions.Normals) { streamWriter.WriteLine("f {0}/{0}/{0} {1}/{1}/{1} {2}/{2}/{2}", index2, index1, index0); } else if (exportOptions.Normals) { streamWriter.WriteLine("f {0}//{0} {1}//{1} {2}//{2}", index2, index1, index0); } else if (exportOptions.TextureCoordinates) { streamWriter.WriteLine("f {0}/{0} {1}/{1} {2}/{2}", index2, index1, index0); } else { streamWriter.WriteLine("f {0} {1} {2}", index2, index1, index0); } } vertexCount += (uint)mesh.VertexCount; } streamWriter.Close(); }