public static FLVER2 Read(byte[] bytes, FlverCache cache) { BinaryReaderEx br = new BinaryReaderEx(false, bytes); FLVER2 file = new FLVER2(); file.Cache = cache; br = SFUtil.GetDecompressedBR(br, out file.Compression); file.Read(br); return(file); }
/// <summary> /// Loads a file from the specified path, automatically decompressing it if necessary. /// </summary> public static FLVER2 Read(string path, FlverCache cache) { using (FileStream stream = File.OpenRead(path)) { BinaryReaderEx br = new BinaryReaderEx(false, stream); FLVER2 file = new FLVER2(); file.Cache = cache; br = SFUtil.GetDecompressedBR(br, out file.Compression); file.Read(br); return(file); } }
internal FaceSet(BinaryReaderEx br, FLVERHeader header, FlverCache cache, int headerIndexSize, int dataOffset) { Flags = (FSFlags)br.ReadUInt32(); TriangleStrip = br.ReadBoolean(); CullBackfaces = br.ReadBoolean(); Unk06 = br.ReadByte(); Unk07 = br.ReadByte(); int indexCount = br.ReadInt32(); int indicesOffset = br.ReadInt32(); int indexSize = 0; if (header.Version > 0x20005) { br.ReadInt32(); // Indices length br.AssertInt32(0); indexSize = br.AssertInt32(0, 16, 32); br.AssertInt32(0); } if (indexSize == 0) { indexSize = headerIndexSize; } if (indexSize == 16) { //Indices = new int[indexCount]; IndicesCount = indexCount; Indices = cache.GetCachedIndices(indexCount); int i = 0; foreach (ushort index in br.GetUInt16s(dataOffset + indicesOffset, indexCount)) { Indices[i] = index; i++; } } else if (indexSize == 32) { IndicesCount = indexCount; Indices = br.GetInt32s(dataOffset + indicesOffset, indexCount); } else { throw new NotImplementedException($"Unsupported index size: {indexSize}"); } }
/// <summary> /// Reads FLVER data from a BinaryReaderEx. /// </summary> protected override void Read(BinaryReaderEx br) { if (Cache == null) { Cache = new FlverCache(); } br.BigEndian = false; Header = new FLVERHeader(); br.AssertASCII("FLVER\0"); Header.BigEndian = br.AssertASCII("L\0", "B\0") == "B\0"; br.BigEndian = Header.BigEndian; // Gundam Unicorn: 0x20005, 0x2000E // DS1: 2000C, 2000D // DS2 NT: 2000F, 20010 // DS2: 20010, 20009 (armor 9320) // SFS: 20010 // BB: 20013, 20014 // DS3: 20013, 20014 // SDT: 2001A, 20016 (test chr) Header.Version = br.AssertInt32(0x20005, 0x20009, 0x2000C, 0x2000D, 0x2000E, 0x2000F, 0x20010, 0x20013, 0x20014, 0x20016, 0x2001A); int dataOffset = br.ReadInt32(); br.ReadInt32(); // Data length int dummyCount = br.ReadInt32(); int materialCount = br.ReadInt32(); int boneCount = br.ReadInt32(); int meshCount = br.ReadInt32(); int vertexBufferCount = br.ReadInt32(); Header.BoundingBoxMin = br.ReadVector3(); Header.BoundingBoxMax = br.ReadVector3(); br.ReadInt32(); // Face count not including motion blur meshes or degenerate faces br.ReadInt32(); // Total face count int vertexIndicesSize = br.AssertByte(0, 16, 32); Header.Unicode = br.ReadBoolean(); Header.Unk4A = br.ReadBoolean(); br.AssertByte(0); Header.Unk4C = br.ReadInt32(); int faceSetCount = br.ReadInt32(); int bufferLayoutCount = br.ReadInt32(); int textureCount = br.ReadInt32(); Header.Unk5C = br.ReadByte(); Header.Unk5D = br.ReadByte(); br.AssertByte(0); br.AssertByte(0); br.AssertInt32(0); br.AssertInt32(0); Header.Unk68 = br.AssertInt32(0, 1, 2, 3, 4); br.AssertInt32(0); br.AssertInt32(0); br.AssertInt32(0); br.AssertInt32(0); br.AssertInt32(0); Dummies = new List <FLVER.Dummy>(dummyCount); for (int i = 0; i < dummyCount; i++) { Dummies.Add(new FLVER.Dummy(br, Header.Version)); } Materials = new List <Material>(materialCount); var gxListIndices = new Dictionary <int, int>(); GXLists = new List <GXList>(); for (int i = 0; i < materialCount; i++) { Materials.Add(new Material(br, Header, GXLists, gxListIndices)); } Bones = new List <FLVER.Bone>(boneCount); for (int i = 0; i < boneCount; i++) { Bones.Add(new FLVER.Bone(br, Header.Unicode)); } Meshes = new List <Mesh>(meshCount); for (int i = 0; i < meshCount; i++) { Meshes.Add(new Mesh(br, Header)); } var faceSets = new List <FaceSet>(faceSetCount); for (int i = 0; i < faceSetCount; i++) { faceSets.Add(new FaceSet(br, Header, Cache, vertexIndicesSize, dataOffset)); } var vertexBuffers = new List <VertexBuffer>(vertexBufferCount); for (int i = 0; i < vertexBufferCount; i++) { vertexBuffers.Add(new VertexBuffer(br)); } BufferLayouts = new List <BufferLayout>(bufferLayoutCount); for (int i = 0; i < bufferLayoutCount; i++) { BufferLayouts.Add(new BufferLayout(br)); } var textures = new List <Texture>(textureCount); for (int i = 0; i < textureCount; i++) { textures.Add(new Texture(br, Header)); } if (Header.Version >= 0x2001A) { SekiroUnk = new SekiroUnkStruct(br); } Dictionary <int, Texture> textureDict = SFUtil.Dictionize(textures); foreach (Material material in Materials) { material.TakeTextures(textureDict); } if (textureDict.Count != 0) { throw new NotSupportedException("Orphaned textures found."); } Dictionary <int, FaceSet> faceSetDict = SFUtil.Dictionize(faceSets); Dictionary <int, VertexBuffer> vertexBufferDict = SFUtil.Dictionize(vertexBuffers); foreach (Mesh mesh in Meshes) { mesh.TakeFaceSets(faceSetDict); mesh.TakeVertexBuffers(vertexBufferDict, BufferLayouts); mesh.ReadVertices(br, dataOffset, BufferLayouts, Header, Cache); } if (faceSetDict.Count != 0) { throw new NotSupportedException("Orphaned face sets found."); } if (vertexBufferDict.Count != 0) { throw new NotSupportedException("Orphaned vertex buffers found."); } }
internal void ReadVertices(BinaryReaderEx br, int dataOffset, List <BufferLayout> layouts, FLVERHeader header, FlverCache cache) { var layoutMembers = layouts.SelectMany(l => l); int uvCap = layoutMembers.Where(m => m.Semantic == FLVER.LayoutSemantic.UV).Count(); int tanCap = layoutMembers.Where(m => m.Semantic == FLVER.LayoutSemantic.Tangent).Count(); int colorCap = layoutMembers.Where(m => m.Semantic == FLVER.LayoutSemantic.VertexColor).Count(); VertexCount = VertexBuffers[0].VertexCount; Vertices = cache.GetCachedVertexArray(VertexCount); if (Vertices == null) { Vertices = new FLVER.Vertex[VertexCount]; for (int i = 0; i < VertexCount; i++) { Vertices[i] = new FLVER.Vertex(uvCap, tanCap, colorCap); } cache.CacheVertexArray(Vertices); } else { for (int i = 0; i < Vertices.Length; i++) { Vertices[i].UVCount = 0; Vertices[i].TangentCount = 0; } } foreach (VertexBuffer buffer in VertexBuffers) { buffer.ReadBuffer(br, layouts, Vertices, VertexCount, dataOffset, header); } }