public SUR(byte[] data) { HardpointSections = new List <HardpointSection>(); int pos = 0; VersionString = Utilities.GetString(data, ref pos, 4); VersionNumber = Utilities.GetFloat(data, ref pos); if (VersionNumber != 2.0f || VersionString != "vers") { throw new FormatException(); } MeshId = Utilities.GetDWord(data, ref pos); SurfaceType = Utilities.GetDWord(data, ref pos); SurfaceSection ss = new SurfaceSection(); while (pos < data.Length) { string nextType = Utilities.GetString(data, ref pos, 4); if (nextType == "hpid") { HardpointSection hps = new HardpointSection(); hps.MeshIdCount = Utilities.GetDWord(data, ref pos); hps.MeshIds = new uint[hps.MeshIdCount]; for (int a = 0; a < hps.MeshIdCount; a++) { hps.MeshIds[a] = Utilities.GetDWord(data, ref pos); } HardpointSections.Add(hps); } else if (nextType == "!fxd") { FixedFlag = nextType; } else if (nextType == "exts") { ss.BoundingBox = new SharpDX.Vector3[2]; for (int a = 0; a < 2; a++) { ss.BoundingBox[a] = new SharpDX.Vector3( Utilities.GetFloat(data, ref pos), Utilities.GetFloat(data, ref pos), Utilities.GetFloat(data, ref pos)); } } else if (nextType == "surf") { uint unk = Utilities.GetDWord(data, ref pos); ss.Center = new SharpDX.Vector3( Utilities.GetFloat(data, ref pos), Utilities.GetFloat(data, ref pos), Utilities.GetFloat(data, ref pos)); ss.Inertia = new SharpDX.Vector3( Utilities.GetFloat(data, ref pos), Utilities.GetFloat(data, ref pos), Utilities.GetFloat(data, ref pos)); ss.Radius = Utilities.GetFloat(data, ref pos); ss.Scale = data[pos++]; ss.Size = Utilities.GetDWord(data, ref pos) & 0x00FFFFFF; pos--; ss.BitsSectionOffset = Utilities.GetDWord(data, ref pos); // padding pos += 3 * sizeof(uint); int maxPos = data.Length; while (pos < maxPos) { TriangleGroup tgh = new TriangleGroup(); tgh.VertexOffset = Utilities.GetDWord(data, ref pos); tgh.MeshId = Utilities.GetDWord(data, ref pos); tgh.Type = data[pos++]; tgh.RefVertexCount = Utilities.GetDWord(data, ref pos) & 0x00FFFFFF; pos--; tgh.TriangleCount = Utilities.GetShort(data, ref pos); tgh.Triangles = new Triangle[tgh.TriangleCount]; maxPos = pos + (int)tgh.VertexOffset; for (int a = 0; a < tgh.TriangleCount; a++) { Triangle t = new Triangle(); byte[] tempData = new byte[20]; Array.Copy(data, pos, tempData, 0, 20); BitArray br = new BitArray(tempData); int bitpos = 0; bitpos += 13; t.TriangleNumber = (ushort)Advance(br, 12, ref bitpos); t.TriangleOpp = (ushort)Advance(br, 12, ref bitpos); bitpos += 7; t.Flag = (byte)Advance(br, 1, ref bitpos); t.Indices = new Index[3]; for (int b = 0; b < 3; b++) { Index i = new Index(); i.VertexId = (ushort)Advance(br, sizeof(ushort) * 8, ref bitpos); i.Offset = (short)Advance(br, 15, ref bitpos); i.Flag = (byte)Advance(br, 1, ref bitpos); t.Indices[b] = i; } tgh.Triangles[a] = t; PrintBits(br); pos += 20; } } } else { throw new FormatException(); } } }
/// <summary> /// WARNING THIS IS NOT FINISHED AND IS DEFINITELY BROKEN /// </summary> /// <param name="filePath"></param> public SurFile(string filePath) { this.FilePath = filePath; byte[] data; using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { data = new byte[fs.Length]; fs.Read(data, 0, (int)fs.Length); fs.Close(); } int pos = 0; VersionString = Utilities.GetString(data, ref pos, 4); VersionNumber = Utilities.GetFloat(data, ref pos); if (VersionNumber != 2.0f || VersionString != "vers") { throw new FormatException(); } while (pos < data.Length) { Mesh m = new Mesh(); m.HardpointSections = new List <HardpointSection>(); m.SurfaceSections = new List <SurfaceSection>(); m.MeshId = Utilities.GetDWord(data, ref pos); uint blockCount = Utilities.GetDWord(data, ref pos); while (blockCount-- > 0) { string nextType = Utilities.GetString(data, ref pos, 4); if (nextType == "hpid") { HardpointSection hps = new HardpointSection(); hps.MeshIdCount = Utilities.GetDWord(data, ref pos); hps.MeshIds = new uint[hps.MeshIdCount]; for (int a = 0; a < hps.MeshIdCount; a++) { hps.MeshIds[a] = Utilities.GetDWord(data, ref pos); } m.HardpointSections.Add(hps); } else if (nextType == "!fxd") { FixedFlag = nextType; } else if (nextType == "exts") { m.BoundingBox = new SharpDX.Vector3[2]; for (int a = 0; a < 2; a++) { m.BoundingBox[a] = new SharpDX.Vector3( Utilities.GetFloat(data, ref pos), Utilities.GetFloat(data, ref pos), Utilities.GetFloat(data, ref pos)); } } else if (nextType == "surf") { SurfaceSection ss = new SurfaceSection(); uint size = Utilities.GetDWord(data, ref pos); uint header_pos = (uint)pos; ss.Center = new SharpDX.Vector3( Utilities.GetFloat(data, ref pos), Utilities.GetFloat(data, ref pos), Utilities.GetFloat(data, ref pos)); ss.Inertia = new SharpDX.Vector3( Utilities.GetFloat(data, ref pos), Utilities.GetFloat(data, ref pos), Utilities.GetFloat(data, ref pos)); ss.Radius = Utilities.GetFloat(data, ref pos); ss.Scale = data[pos] / 250.0f; ss.Size = Utilities.GetDWord(data, ref pos) >> 8; ss.BitsSectionOffset = Utilities.GetDWord(data, ref pos); ss.TriangleGroups = new List <TriangleGroup>(); ss.Vertices = new List <Vertex>(); uint bits_beg = header_pos + ss.BitsSectionOffset; uint bits_end = header_pos + ss.Size; // padding pos += 3 * sizeof(uint); int vertBufStart = data.Length; while (pos < vertBufStart) { TriangleGroup tgh = new TriangleGroup(); int group_pos = pos; tgh.VertexOffset = Utilities.GetDWord(data, ref pos); tgh.MeshId = Utilities.GetDWord(data, ref pos); tgh.Type = data[pos]; tgh.RefVertexCount = Utilities.GetDWord(data, ref pos) >> 8; tgh.TriangleCount = Utilities.GetShort(data, ref pos); pos += 2; tgh.Triangles = new Triangle[tgh.TriangleCount]; vertBufStart = group_pos + (int)tgh.VertexOffset; for (int a = 0; a < tgh.TriangleCount; a++) { Triangle t = new Triangle(); byte[] tempData = new byte[(12 + 12 + 7 + 1 + 3 * (16 + 15 + 1)) / 8]; Array.Copy(data, pos, tempData, 0, tempData.Length); pos += tempData.Length; BitArray br = new BitArray(tempData); int bitpos = 0; t.TriangleNumber = (ushort)Advance(br, 12, ref bitpos); t.TriangleOpp = (ushort)Advance(br, 12, ref bitpos); bitpos += 7; t.Flag = (byte)Advance(br, 1, ref bitpos); t.Indices = new Index[3]; for (int b = 0; b < 3; b++) { Index i = new Index(); i.VertexId = (ushort)Advance(br, sizeof(ushort) * 8, ref bitpos); i.Offset = (short)Advance(br, 15, ref bitpos); i.Flag = (byte)Advance(br, 1, ref bitpos); t.Indices[b] = i; } tgh.Triangles[a] = t; } ss.TriangleGroups.Add(tgh); } // Vertices while (pos < bits_beg) { Vertex vertex = new Vertex(); vertex.X = Utilities.GetFloat(data, ref pos); vertex.Y = Utilities.GetFloat(data, ref pos); vertex.Z = Utilities.GetFloat(data, ref pos); vertex.MeshId = Utilities.GetDWord(data, ref pos); ss.Vertices.Add(vertex); } m.SurfaceSections.Add(ss); pos = (int)bits_end; } else { throw new FormatException(); } } Meshes.Add(m); } }