/// <summary> /// Creates and returns a mesh file /// </summary> /// <returns></returns> public Mesh GetMeshFile() { Mesh mesh = new Mesh { //TODO: bounding box stuff // Rigging Objects = new MeshObject[meshes.Count] }; // create mesh objects and buffers BinaryWriter vertexBuffer1 = new BinaryWriter(new MemoryStream()); BinaryWriter vertexBuffer2 = new BinaryWriter(new MemoryStream()); // there are actually 4 buffers, but only 2 seem to be used BinaryWriter indexBuffer = new BinaryWriter(new MemoryStream()); int finalBufferOffset = 0; int meshIndex = 0; Dictionary <string, int> meshGroups = new Dictionary <string, int>(); List <MeshRiggingGroup> riggingGroups = new List <MeshRiggingGroup>(); foreach (var tempmesh in meshes) { MeshObject mo = new MeshObject { Name = tempmesh.Name }; if (meshGroups.ContainsKey(mo.Name)) { meshGroups[mo.Name] += 1; } else { meshGroups.Add(mo.Name, 0); } mo.SubIndex = meshGroups[mo.Name]; mo.BoundingSphereCenter = new Formats.Vector3 { X = tempmesh.BoundingSphere.X, Y = tempmesh.BoundingSphere.Y, Z = tempmesh.BoundingSphere.Z }; mo.BoundingSphereRadius = tempmesh.BoundingSphere.W; mo.BoundingBoxMax = new Formats.Vector3 { X = tempmesh.BbMax.X, Y = tempmesh.BbMax.Y, Z = tempmesh.BbMax.Z }; mo.BoundingBoxMin = new Formats.Vector3 { X = tempmesh.BbMin.X, Y = tempmesh.BbMin.Y, Z = tempmesh.BbMin.Z }; mo.OrientedBoundingBoxCenter = new Formats.Vector3 { X = tempmesh.ObbCenter.X, Y = tempmesh.ObbCenter.Y, Z = tempmesh.ObbCenter.Z }; mo.OrientedBoundingBoxSize = new Formats.Vector3 { X = tempmesh.ObbSize.X, Y = tempmesh.ObbSize.Y, Z = tempmesh.ObbSize.Z }; mo.OrientedBoundingBoxTransform.Row1.X = tempmesh.ObbMatrix3X3[0]; mo.OrientedBoundingBoxTransform.Row1.Y = tempmesh.ObbMatrix3X3[1]; mo.OrientedBoundingBoxTransform.Row1.Z = tempmesh.ObbMatrix3X3[2]; mo.OrientedBoundingBoxTransform.Row2.X = tempmesh.ObbMatrix3X3[3]; mo.OrientedBoundingBoxTransform.Row2.Y = tempmesh.ObbMatrix3X3[4]; mo.OrientedBoundingBoxTransform.Row2.Z = tempmesh.ObbMatrix3X3[5]; mo.OrientedBoundingBoxTransform.Row3.X = tempmesh.ObbMatrix3X3[6]; mo.OrientedBoundingBoxTransform.Row3.Y = tempmesh.ObbMatrix3X3[7]; mo.OrientedBoundingBoxTransform.Row3.Z = tempmesh.ObbMatrix3X3[8]; // Create Rigging riggingGroups.Add(SsbhRiggingCompiler.CreateRiggingGroup(mo.Name, (int)mo.SubIndex, tempmesh.Influences.ToArray())); // set object mesh.Objects[meshIndex++] = mo; mo.ParentBoneName = tempmesh.ParentBone; if (tempmesh.Influences.Count > 0 && (tempmesh.ParentBone == null || tempmesh.ParentBone.Equals(""))) { mo.RiggingType = RiggingType.Regular; } int stride1 = 0; int stride2 = 0; mo.VertexOffset = (int)vertexBuffer1.BaseStream.Length; mo.VertexOffset2 = (int)vertexBuffer2.BaseStream.Length; mo.ElementOffset = (uint)indexBuffer.BaseStream.Length; // gather strides mo.Attributes = new MeshAttribute[tempmesh.VertexData.Count]; int attributeIndex = 0; foreach (var keypair in tempmesh.VertexData) { // For some reason the attribute string doesn't match the attribute's name for Tangent0. var attributeName = keypair.Key.Name; if (keypair.Key.Name == "Tangent0") { attributeName = "map1"; } MeshAttribute attr = new MeshAttribute { Name = attributeName, Index = keypair.Key.Index, BufferIndex = keypair.Key.BufferIndex, DataType = keypair.Key.DataType, BufferOffset = keypair.Key.BufferIndex == 0 ? stride1 : stride2, AttributeStrings = new MeshAttributeString[] { new MeshAttributeString() { Name = keypair.Key.Name } } }; mo.Attributes[attributeIndex++] = attr; if (keypair.Key.BufferIndex == 0) { stride1 += keypair.Key.ComponentCount * keypair.Key.DataType.GetSizeInBytes(); } else { stride2 += keypair.Key.ComponentCount * keypair.Key.DataType.GetSizeInBytes(); } } // now that strides are known... long buffer1Start = vertexBuffer1.BaseStream.Length; long buffer2Start = vertexBuffer2.BaseStream.Length; vertexBuffer1.Write(new byte[stride1 * tempmesh.VertexCount]); vertexBuffer2.Write(new byte[stride2 * tempmesh.VertexCount]); attributeIndex = 0; foreach (var keypair in tempmesh.VertexData) { var attr = mo.Attributes[attributeIndex++]; float[] data = keypair.Value; var buffer = attr.BufferIndex == 0 ? vertexBuffer1 : vertexBuffer2; int bufferOffset = (int)(attr.BufferIndex == 0 ? buffer1Start : buffer2Start); int stride = (attr.BufferIndex == 0 ? stride1 : stride2); int componentCount = keypair.Key.ComponentCount; for (int vertexIndex = 0; vertexIndex < tempmesh.VertexCount; vertexIndex++) { buffer.Seek(bufferOffset + stride * vertexIndex + attr.BufferOffset, SeekOrigin.Begin); for (int j = 0; j < componentCount; j++) { WriteType(buffer, attr.DataType, data[vertexIndex * componentCount + j]); } } // seek to end just to make sure buffer.Seek((int)buffer.BaseStream.Length, SeekOrigin.Begin); } mo.FinalBufferOffset = finalBufferOffset; finalBufferOffset += (4 + stride1) * tempmesh.VertexCount; mo.VertexCount = tempmesh.VertexCount; mo.IndexCount = tempmesh.Indices.Count; mo.Stride = stride1; mo.Stride2 = stride2; // write index buffer if (tempmesh.VertexCount > ushort.MaxValue) { mo.DrawElementType = DrawElementType.UnsignedInt; foreach (var i in tempmesh.Indices) { indexBuffer.Write(i); } } else { foreach (var i in tempmesh.Indices) { indexBuffer.Write((ushort)i); } } } mesh.PolygonIndexSize = indexBuffer.BaseStream.Length; mesh.BufferSizes = new int[] { (int)vertexBuffer1.BaseStream.Length, (int)vertexBuffer2.BaseStream.Length, 0, 0 }; mesh.PolygonBuffer = ((MemoryStream)indexBuffer.BaseStream).ToArray(); Console.WriteLine(mesh.PolygonBuffer.Length + " " + indexBuffer.BaseStream.Length); mesh.VertexBuffers = new MeshBuffer[] { new MeshBuffer { Buffer = ((MemoryStream)vertexBuffer1.BaseStream).ToArray() }, new MeshBuffer { Buffer = ((MemoryStream)vertexBuffer2.BaseStream).ToArray() }, new MeshBuffer { Buffer = new byte[0] }, new MeshBuffer { Buffer = new byte[0] } }; mesh.RiggingBuffers = riggingGroups.ToArray().OrderBy(o => o.MeshName, StringComparer.Ordinal).ToArray(); vertexBuffer1.Close(); vertexBuffer2.Close(); indexBuffer.Close(); return(mesh); }
/// <summary> /// Creates and returns a mesh file /// </summary> /// <returns></returns> public Mesh GetMeshFile() { Mesh mesh = new Mesh { //TODO: bounding box stuff // Rigging Objects = new MeshObject[meshes.Count] }; // create mesh objects and buffers BinaryWriter vertexBuffer1 = new BinaryWriter(new MemoryStream()); BinaryWriter vertexBuffer2 = new BinaryWriter(new MemoryStream()); // there are actually 4 buffers, but only 2 seem to be used BinaryWriter indexBuffer = new BinaryWriter(new MemoryStream()); int finalBufferOffset = 0; int meshIndex = 0; Dictionary <string, int> meshGroups = new Dictionary <string, int>(); List <MeshRiggingGroup> riggingGroups = new List <MeshRiggingGroup>(); foreach (var tempmesh in meshes) { MeshObject mo = new MeshObject { Name = tempmesh.Name }; if (meshGroups.ContainsKey(mo.Name)) { meshGroups[mo.Name] += 1; } else { meshGroups.Add(mo.Name, 0); } mo.SubMeshIndex = meshGroups[mo.Name]; mo.BoundingSphereX = tempmesh.BoundingSphere.X; mo.BoundingSphereY = tempmesh.BoundingSphere.Y; mo.BoundingSphereZ = tempmesh.BoundingSphere.Z; mo.BoundingSphereRadius = tempmesh.BoundingSphere.W; mo.MaxBoundingBoxX = tempmesh.BbMax.X; mo.MaxBoundingBoxY = tempmesh.BbMax.Y; mo.MaxBoundingBoxZ = tempmesh.BbMax.Z; mo.MinBoundingBoxX = tempmesh.BbMin.X; mo.MinBoundingBoxY = tempmesh.BbMin.Y; mo.MinBoundingBoxZ = tempmesh.BbMin.Z; mo.ObbCenterX = tempmesh.ObbCenter.X; mo.ObbCenterY = tempmesh.ObbCenter.Y; mo.ObbCenterZ = tempmesh.ObbCenter.Z; mo.ObbSizeX = tempmesh.ObbSize.X; mo.ObbSizeY = tempmesh.ObbSize.Y; mo.ObbSizeZ = tempmesh.ObbSize.Z; mo.M11 = tempmesh.ObbMatrix3X3[0]; mo.M12 = tempmesh.ObbMatrix3X3[1]; mo.M13 = tempmesh.ObbMatrix3X3[2]; mo.M21 = tempmesh.ObbMatrix3X3[3]; mo.M22 = tempmesh.ObbMatrix3X3[4]; mo.M23 = tempmesh.ObbMatrix3X3[5]; mo.M31 = tempmesh.ObbMatrix3X3[6]; mo.M32 = tempmesh.ObbMatrix3X3[7]; mo.M33 = tempmesh.ObbMatrix3X3[8]; // Create Rigging riggingGroups.Add(SsbhRiggingCompiler.CreateRiggingGroup(mo.Name, (int)mo.SubMeshIndex, tempmesh.Influences.ToArray())); // set object mesh.Objects[meshIndex++] = mo; mo.ParentBoneName = tempmesh.ParentBone; if (tempmesh.Influences.Count > 0 && (tempmesh.ParentBone == null || tempmesh.ParentBone.Equals(""))) { mo.HasRigging = 1; } int stride1 = 0; int stride2 = 0; mo.VertexOffset = (int)vertexBuffer1.BaseStream.Length; mo.VertexOffset2 = (int)vertexBuffer2.BaseStream.Length; mo.ElementOffset = (uint)indexBuffer.BaseStream.Length; // gather strides mo.Attributes = new MeshAttribute[tempmesh.VertexData.Count]; int attributeIndex = 0; foreach (var keypair in tempmesh.VertexData) { MeshAttribute attr = new MeshAttribute { Name = GetAttributeName(keypair.Key), Index = GetAttributeIndex(keypair.Key), BufferIndex = GetBufferIndex(keypair.Key), DataType = GetAttributeDataType(keypair.Key), BufferOffset = (GetBufferIndex(keypair.Key) == 0) ? stride1 : stride2, AttributeStrings = new MeshAttributeString[] { new MeshAttributeString() { Name = keypair.Key.ToString() } } }; mo.Attributes[attributeIndex++] = attr; if (GetBufferIndex(keypair.Key) == 0) { stride1 += GetAttributeSize(keypair.Key) * GetAttributeDataSize(keypair.Key); } else { stride2 += GetAttributeSize(keypair.Key) * GetAttributeDataSize(keypair.Key); } } // now that strides are known... long buffer1Start = vertexBuffer1.BaseStream.Length; long buffer2Start = vertexBuffer2.BaseStream.Length; vertexBuffer1.Write(new byte[stride1 * tempmesh.VertexCount]); vertexBuffer2.Write(new byte[stride2 * tempmesh.VertexCount]); attributeIndex = 0; foreach (var keypair in tempmesh.VertexData) { var attr = mo.Attributes[attributeIndex++]; float[] data = keypair.Value; var buffer = attr.BufferIndex == 0 ? vertexBuffer1 : vertexBuffer2; int bufferOffset = (int)(attr.BufferIndex == 0 ? buffer1Start : buffer2Start); int stride = (attr.BufferIndex == 0 ? stride1 : stride2); int size = GetAttributeSize(keypair.Key); for (int vertexIndex = 0; vertexIndex < tempmesh.VertexCount; vertexIndex++) { buffer.Seek(bufferOffset + stride * vertexIndex + attr.BufferOffset, SeekOrigin.Begin); for (int j = 0; j < size; j++) { WriteType(buffer, attr.DataType, data[vertexIndex * size + j]); } } // seek to end just to make sure buffer.Seek((int)buffer.BaseStream.Length, SeekOrigin.Begin); } mo.FinalBufferOffset = finalBufferOffset; finalBufferOffset += (4 + stride1) * tempmesh.VertexCount; mo.VertexCount = tempmesh.VertexCount; mo.IndexCount = tempmesh.Indices.Count; mo.Stride = stride1; mo.Stride2 = stride2; // write index buffer if (tempmesh.VertexCount > ushort.MaxValue) { mo.DrawElementType = 1; foreach (var i in tempmesh.Indices) { indexBuffer.Write(i); } } else { foreach (var i in tempmesh.Indices) { indexBuffer.Write((ushort)i); } } } mesh.PolygonIndexSize = indexBuffer.BaseStream.Length; mesh.BufferSizes = new int[] { (int)vertexBuffer1.BaseStream.Length, (int)vertexBuffer2.BaseStream.Length, 0, 0 }; mesh.PolygonBuffer = ((MemoryStream)indexBuffer.BaseStream).ToArray(); Console.WriteLine(mesh.PolygonBuffer.Length + " " + indexBuffer.BaseStream.Length); mesh.VertexBuffers = new MeshBuffer[] { new MeshBuffer { Buffer = ((MemoryStream)vertexBuffer1.BaseStream).ToArray() }, new MeshBuffer { Buffer = ((MemoryStream)vertexBuffer2.BaseStream).ToArray() }, new MeshBuffer { Buffer = new byte[0] }, new MeshBuffer { Buffer = new byte[0] } }; mesh.RiggingBuffers = riggingGroups.ToArray().OrderBy(o => o.Name, StringComparer.Ordinal).ToArray(); vertexBuffer1.Close(); vertexBuffer2.Close(); indexBuffer.Close(); return(mesh); }