public byte[] Serialize(Section section, CompressionBounds boundingBox, out Resource[] resources) { MemoryStream stream = new MemoryStream(); BinaryWriter bw = new BinaryWriter(stream); List<Resource> resourceList = new List<Resource>(); byte[] fourCC = Encoding.UTF8.GetBytes("crsr"); bw.Write(Encoding.UTF8.GetBytes("hklb"), 0, 4); stream.Seek(4, SeekOrigin.Current); bw.Write(Groups.Length); //stream.Seek(4, SeekOrigin.Current); //bw.Write(1); stream.Seek(8, SeekOrigin.Current); stream.Seek(20, SeekOrigin.Current); bw.Write(Indices.Length); stream.Seek(20, SeekOrigin.Current); bw.Write(3); stream.Seek(40, SeekOrigin.Current); bw.Write(1); stream.Seek(8, SeekOrigin.Current); bw.Write(fourCC, 0, 4); resourceList.Add(new Resource(ResourceType.MeshInformation, ResourceSubType.MeshInformationData, (int)(stream.Position - 120), 72)); for (int i = 0; i < Groups.Length; i++) { Groups[i].Serialize(stream, boundingBox); } //bw.Write(fourCC, 0, 4); //resourceList.Add(new Resource(ResourceType.UnknownStruct8, ResourceSubType.UnknownStruct8, (int)(stream.Position - 120), 8)); //bw.Write(0x00000000); bw.Write((ushort)0xFFFF); bw.Write((short)0x0000); bw.Write(fourCC, 0, 4); resourceList.Add(new Resource(ResourceType.TriangleStrip, ResourceSubType.IndiceStripData, (int)(stream.Position - 120), Indices.Length * 2)); foreach (short i in Indices) bw.Write(i); stream.Pad(4); bw.Write(fourCC, 0, 4); resourceList.Add(new Resource(ResourceType.Unknown, ResourceSubType.UnknownData, (int)(stream.Position - 120), 96)); bw.Write((byte)0x02); bw.Write((byte)0x06); bw.Write((byte)0x00); bw.Write((byte)0x00); bw.Write(new byte[28]); bw.Write((byte)0x19); bw.Write((byte)0x04); bw.Write((byte)0x00); bw.Write((byte)0x00); bw.Write(new byte[28]); bw.Write((byte)0x1B); bw.Write((byte)0x0C); bw.Write((byte)0x00); bw.Write((byte)0x00); bw.Write(new byte[28]); bw.Write(fourCC, 0, 4); resourceList.Add(new Resource(ResourceType.Vertex, ResourceSubType.VertexData, (int)(stream.Position - 120), _Vertices.Length * 6)); foreach (Vector3 v in _Vertices) { bw.Write(CompressionBounds.Compress(v.X, boundingBox.X)); bw.Write(CompressionBounds.Compress(v.Y, boundingBox.Y)); bw.Write(CompressionBounds.Compress(v.Z, boundingBox.Z)); } bw.Write(Padding.GetBytes(stream.Position, 4)); bw.Write(fourCC, 0, 4); resourceList.Add(new Resource(ResourceType.Vertex, ResourceSubType.UVData, (int)(stream.Position - 120), _Vertices.Length * 4)); foreach (Vector2 t in Texcoords) { bw.Write(CompressionBounds.Compress(t.X, boundingBox.X)); bw.Write(CompressionBounds.Compress(t.Y, boundingBox.Y)); } bw.Write(Padding.GetBytes(stream.Position, 4)); bw.Write(fourCC, 0, 4); resourceList.Add(new Resource(ResourceType.Vertex, ResourceSubType.VectorData, (int)(stream.Position - 120), Normals.Length * 4 * 3)); for (int i = 0; i < Normals.Length; i++) { bw.Write(CompressVector(Normals[i])); bw.Write(CompressVector(Tangents[i])); bw.Write(CompressVector(Bitangents[i])); } bw.Write(Padding.GetBytes(stream.Position, 4)); bw.Write(fourCC, 0, 4); resourceList.Add(new Resource(ResourceType.BoneMap, ResourceSubType.BoneData, (int)(stream.Position - 120), BoneMap.Length)); if (BoneMap.Length == 0) { foreach (byte b in BoneMap) bw.Write(b); bw.Write(Padding.GetBytes(stream.Position, 4)); } else { bw.Write(0); } bw.Write(Encoding.UTF8.GetBytes("fklb"), 0, 4); int rawLength = (int)stream.Position; stream.Seek(4, SeekOrigin.Begin); bw.Write(rawLength - 116); resources = resourceList.ToArray(); return stream.ToArray(); }
public Mesh(Stream stream, Resource[] resources, Section section, CompressionBounds boundingBox) { int StartOffset = (int)stream.Position; BinaryReader br = new BinaryReader(stream); stream.Position = 4; Size = br.ReadInt32(); foreach (Resource r in resources) { stream.Position = StartOffset + 120 + r.RawDataOffset; int Count=0; switch (r.MainRawDataType) { case ResourceType.BoneMap: BoneMap = br.ReadBytes(r.RawDataSize); break; case ResourceType.MeshInformation: Groups = new Group[r.RawDataSize / 72]; for (int i = 0; i < Groups.Length; i++) { stream.Position = StartOffset + 120 + r.RawDataOffset + (i * 72); Groups[i] = new Group(br.ReadBytes(Group.Size)); } break; case ResourceType.Vertex: switch (r.SubRawDataType) { #region Vertices case ResourceSubType.VertexData: byte[] Bytes = br.ReadBytes(r.RawDataSize); int Index = 0; int Stride; switch (section.VertexType) { case VertexType.Rigid: Stride = 0;//xyz break; case VertexType.RigidBoned: Stride = 2;//xyz break; case VertexType.Skinned: Stride = 6;//xyz break; default: throw new Exception(); } if ((section.CompressionFlags & Compression.Position) != Compression.Position) { int VertexSize = 12 + Stride; int VertexCount = Bytes.Length / VertexSize; Index = 0; _Vertices = new Vector3[VertexCount]; for (int i = 0; i < VertexCount; i++) { float x = BitConverter.ToSingle(Bytes, Index + 0); float y = BitConverter.ToSingle(Bytes, Index + 4); float z = BitConverter.ToSingle(Bytes, Index + 8); _Vertices[i] = new Vector3(x, y, z); Index += VertexSize; } } else { int VertexSize = 6 + Stride; int VertexCount = Bytes.Length / VertexSize; Index = 0; _Vertices = new Vector3[VertexCount]; for (int i = 0; i < VertexCount; i++) { _Vertices[i] = new Vector3(CompressionBounds.Decompress(BitConverter.ToInt16(Bytes, Index + 0), boundingBox.X), CompressionBounds.Decompress(BitConverter.ToInt16(Bytes, Index + 2), boundingBox.Y), CompressionBounds.Decompress(BitConverter.ToInt16(Bytes, Index + 4), boundingBox.Z)); Index += VertexSize; } } break; #endregion #region Texcoords case ResourceSubType.UVData: Index = 0; Bytes = br.ReadBytes(r.RawDataSize); if ((section.CompressionFlags & Compression.Texcoord) == Compression.Texcoord) { int TexcoordSize = 4; Count = Bytes.Length / TexcoordSize; Texcoords = new Vector2[Count]; for (int i = 0; i < Count; i++) { Texcoords[i] = new Vector2(CompressionBounds.Decompress(BitConverter.ToInt16(Bytes, Index + 0), boundingBox.U), CompressionBounds.Decompress(BitConverter.ToInt16(Bytes, Index + 2), boundingBox.V)); Index += TexcoordSize; } } else { int TexcoordSize = 8; Count = Bytes.Length / TexcoordSize; Texcoords = new Vector2[Count]; for (int i = 0; i < Count; i++) { float u = BitConverter.ToSingle(Bytes, Index); float v = BitConverter.ToSingle(Bytes, Index + 4); Texcoords[i] = new Vector2(u, v); Index += TexcoordSize; } } break; #endregion #region Normals, Tangents, and Bitangents case ResourceSubType.VectorData: int[] Ints = new int[r.RawDataSize / 4]; for (int i = 0; i < Ints.Length; i++) Ints[i] = br.ReadInt32(); Normals = new Vector3[Ints.Length / 3]; Tangents = new Vector3[Ints.Length / 3]; Bitangents = new Vector3[Ints.Length / 3]; int[] normInts = new int[Ints.Length / 3]; for (int i = 0; i < normInts.Length; i++) { normInts[i] = Ints[i * 3]; } int normalsCount = 0; int tangentsCount = 0; int bitangentsCount = 0; for (int i = 0; i < Ints.Length; i++) { int CompressedData = Ints[i]; int x10 = (CompressedData & 0x000007FF); if ((x10 & 0x00000400) == 0x00000400) { x10 = -((~x10) & 0x000007FF); if (x10 == 0) x10 = -1; } int y11 = (CompressedData >> 11) & 0x000007FF; if ((y11 & 0x00000400) == 0x00000400) { y11 = -((~y11) & 0x000007FF); if (y11 == 0) y11 = -1; } int z11 = (CompressedData >> 22) & 0x000003FF; if ((z11 & 0x00000200) == 0x00000200) { z11 = -((~z11) & 0x000003FF); if (z11 == 0) z11 = -1; } float x, y, z; x = (x10 / (float)0x000003ff); y = (y11 / (float)0x000003FF); z = (z11 / (float)0x000001FF); int o = 0; switch (i % 3) { case 0: Normals[normalsCount] = new Vector3(x, y, z); normalsCount++; break; case 1: Tangents[tangentsCount] = new Vector3(x, y, z); tangentsCount++; break; case 2: Bitangents[bitangentsCount] = new Vector3(x, y, z); bitangentsCount++; break; } } //Normals = GenerateNormals(Vertices, Indices); break; #endregion } break; #region Triangle Strip Indices case ResourceType.TriangleStrip: Count = r.RawDataSize / 2; Indices = new short[Count]; for (int x = 0; x < Count; x++) { Indices[x] = br.ReadInt16(); } break; #endregion } } Vertices = new Vertex[_Vertices.Length]; for (int i = 0; i < Vertices.Length; i++) { Vertices[i] = new Vertex(){ Position = _Vertices[i].ToXnaVector3(), Color = Microsoft.Xna.Framework.Graphics.Color.Gray, Normal = Normals[i].ToXnaVector3(), Tangent = Tangents[i].ToXnaVector3(), Bitangent = Bitangents[i].ToXnaVector3(), /*Texcoord = Texcoords[i] */ }; } }
public Section(Tag tag, CompressionInfo boundingBox) { BinaryReader br = new BinaryReader(tag.TagStream); int StartOffset = (int)tag.TagStream.Position; buffer = br.ReadBytes(Size); tag.TagStream.Position = StartOffset; VertexType = (VertexType)br.ReadInt32(); VertexCount = br.ReadInt16(); TriangleCount = br.ReadInt16(); tag.TagStream.Position = StartOffset + 26; CompressionFlags = (Compression)br.ReadInt32(); tag.TagStream.Position = StartOffset + 56; RawOffset = br.ReadInt32(); RawSize = br.ReadInt32(); br.ReadInt32(); RawDataSize = br.ReadInt32(); tag.TagStream.Position = StartOffset + 72; int Count = br.ReadInt32(); if (Count > 0) { int Offset = br.ReadInt32(); Resources = new Resource[Count]; for (int i = 0; i < Count; i++) { tag.TagStream.Position = Offset + (i * Resource.Size); Resources[i] = new Resource(tag.TagStream); } } if (Globals.IsExternalResource(RawOffset)) { return; } tag.ResourceStream.Position = tag.ResourceInformation[RawOffset].Address; mesh = new Mesh(tag.ResourceStream, Resources, this, boundingBox); Microsoft.Xna.Framework.Vector3[] points = new Microsoft.Xna.Framework.Vector3[mesh.Vertices.Length]; for (int i = 0; i < points.Length; i++) points[i] = mesh.Vertices[i].Position; BoundingBox = Microsoft.Xna.Framework.BoundingBox.CreateFromPoints(points); }