private int SizeOf2MeshData(GcGame game) { bool isVtx16Bit = (SectionFlags & (uint)GcmfSectionFlags._16Bit) != 0 && !GcmfVersionDetails.Is16BitEffectiveModelIgnored(game); return(PaddingUtils.Align(Meshes.Sum(mesh => mesh.SizeOfIndexedData(isVtx16Bit)), 0x20)); }
private void RefreshBuffers() { int totalVertexCount = Meshes.Sum(x => x.VertexCount); if (totalVertexCount == 0) { _vertexArray = null; _indexArray = null; return; } // Resize vertex array if necessary if (totalVertexCount != _vertexArray?.Length) { _vertexArray = new VertexPositionColorTexture[totalVertexCount]; } // Fill vertex array int i = 0; foreach (IVisualMesh mesh in Meshes) { mesh.CopyToVertexArray(_vertexArray, i); i += mesh.VertexCount; } // Skip index array if none provided int totalIndexCount = Meshes.Sum(x => x.TriangulationIndexCount); if (totalIndexCount == 0) { _indexArray = null; return; } // Resize index buffer if necessary if (totalIndexCount != _indexArray?.Length) { _indexArray = new int[totalIndexCount]; } // Fill index array i = 0; foreach (IVisualMesh mesh in Meshes) { mesh.CopyToIndexArray(_indexArray, i); i += mesh.TriangulationIndexCount; } }
// ---- METHODS ------------------------------------------------------------------------------------------------ void IResData.Load(ResFileLoader loader) { loader.CheckSignature(_signature); if (loader.IsSwitch) { Switch.ShapeParser.Read((Switch.Core.ResFileSwitchLoader)loader, this); } else { Name = loader.LoadString(); Flags = loader.ReadEnum <ShapeFlags>(true); ushort idx = loader.ReadUInt16(); MaterialIndex = loader.ReadUInt16(); BoneIndex = loader.ReadUInt16(); VertexBufferIndex = loader.ReadUInt16(); ushort numSkinBoneIndex = loader.ReadUInt16(); VertexSkinCount = loader.ReadByte(); byte numMesh = loader.ReadByte(); byte numKeyShape = loader.ReadByte(); TargetAttribCount = loader.ReadByte(); ushort numSubMeshBoundingNodes = loader.ReadUInt16(); // Padding in engine. if (loader.ResFile.Version >= 0x04050000) { RadiusArray = loader.LoadCustom(() => loader.ReadSingles(numMesh))?.ToList(); } else { RadiusArray = loader.ReadSingles(1).ToList(); } VertexBuffer = loader.Load <VertexBuffer>(); Meshes = loader.LoadList <Mesh>(numMesh).ToList(); SkinBoneIndices = loader.LoadCustom(() => loader.ReadUInt16s(numSkinBoneIndex))?.ToList(); KeyShapes = loader.LoadDict <KeyShape>(); // TODO: At least BotW has more data following the Boundings, or that are no boundings at all. if (numSubMeshBoundingNodes == 0) { if (loader.ResFile.Version >= 0x04050000) { numSubMeshBoundingNodes = (ushort)(Meshes.Count + Meshes.Sum(x => x.SubMeshes.Count)); } else { numSubMeshBoundingNodes = (ushort)(1 + Meshes[0].SubMeshes.Count + 1); } SubMeshBoundings = loader.LoadCustom(() => loader.ReadBoundings(numSubMeshBoundingNodes))?.ToList(); } else { SubMeshBoundingNodes = loader.LoadList <BoundingNode>(numSubMeshBoundingNodes)?.ToList(); SubMeshBoundings = loader.LoadCustom(() => loader.ReadBoundings(numSubMeshBoundingNodes))?.ToList(); SubMeshBoundingIndices = loader.LoadCustom(() => loader.ReadUInt16s(numSubMeshBoundingNodes))?.ToList(); } if (SubMeshBoundingNodes == null) { SubMeshBoundingNodes = new List <BoundingNode>(); } if (SubMeshBoundings == null) { SubMeshBoundings = new List <Bounding>(); } if (SubMeshBoundingIndices == null) { SubMeshBoundingIndices = new List <ushort>(); } uint userPointer = loader.ReadUInt32(); } }
/// <summary> /// Writes FLVER data to a BinaryWriterEx. /// </summary> protected override void Write(BinaryWriterEx bw) { bw.BigEndian = Header.BigEndian; bw.WriteASCII("FLVER\0"); bw.WriteASCII(Header.BigEndian ? "B\0" : "L\0"); bw.WriteInt32(Header.Version); bw.ReserveInt32("DataOffset"); bw.ReserveInt32("DataSize"); bw.WriteInt32(Dummies.Count); bw.WriteInt32(Materials.Count); bw.WriteInt32(Bones.Count); bw.WriteInt32(Meshes.Count); bw.WriteInt32(Meshes.Sum(m => m.VertexBuffers.Count)); bw.WriteVector3(Header.BoundingBoxMin); bw.WriteVector3(Header.BoundingBoxMax); int trueFaceCount = 0; int totalFaceCount = 0; foreach (Mesh mesh in Meshes) { bool allowPrimitiveRestarts = mesh.Vertices.Length < ushort.MaxValue; foreach (FaceSet faceSet in mesh.FaceSets) { faceSet.AddFaceCounts(allowPrimitiveRestarts, ref trueFaceCount, ref totalFaceCount); } } bw.WriteInt32(trueFaceCount); bw.WriteInt32(totalFaceCount); byte vertexIndicesSize = 0; if (Header.Version < 0x20013) { vertexIndicesSize = 16; foreach (Mesh mesh in Meshes) { foreach (FaceSet fs in mesh.FaceSets) { vertexIndicesSize = (byte)Math.Max(vertexIndicesSize, fs.GetVertexIndexSize()); } } } bw.WriteByte(vertexIndicesSize); bw.WriteBoolean(Header.Unicode); bw.WriteBoolean(Header.Unk4A); bw.WriteByte(0); bw.WriteInt32(Header.Unk4C); bw.WriteInt32(Meshes.Sum(m => m.FaceSets.Count)); bw.WriteInt32(BufferLayouts.Count); bw.WriteInt32(Materials.Sum(m => m.Textures.Count)); bw.WriteByte(Header.Unk5C); bw.WriteByte(Header.Unk5D); bw.WriteByte(0); bw.WriteByte(0); bw.WriteInt32(0); bw.WriteInt32(0); bw.WriteInt32(Header.Unk68); bw.WriteInt32(0); bw.WriteInt32(0); bw.WriteInt32(0); bw.WriteInt32(0); bw.WriteInt32(0); foreach (FLVER.Dummy dummy in Dummies) { dummy.Write(bw, Header.Version); } for (int i = 0; i < Materials.Count; i++) { Materials[i].Write(bw, i); } for (int i = 0; i < Bones.Count; i++) { Bones[i].Write(bw, i); } for (int i = 0; i < Meshes.Count; i++) { Meshes[i].Write(bw, i); } int faceSetIndex = 0; foreach (Mesh mesh in Meshes) { for (int i = 0; i < mesh.FaceSets.Count; i++) { int indexSize = vertexIndicesSize; if (indexSize == 0) { indexSize = mesh.FaceSets[i].GetVertexIndexSize(); } mesh.FaceSets[i].Write(bw, Header, indexSize, faceSetIndex + i); } faceSetIndex += mesh.FaceSets.Count; } int vertexBufferIndex = 0; foreach (Mesh mesh in Meshes) { for (int i = 0; i < mesh.VertexBuffers.Count; i++) { mesh.VertexBuffers[i].Write(bw, Header, vertexBufferIndex + i, i, BufferLayouts, mesh.Vertices.Length); } vertexBufferIndex += mesh.VertexBuffers.Count; } for (int i = 0; i < BufferLayouts.Count; i++) { BufferLayouts[i].Write(bw, i); } int textureIndex = 0; for (int i = 0; i < Materials.Count; i++) { Materials[i].WriteTextures(bw, i, textureIndex); textureIndex += Materials[i].Textures.Count; } if (Header.Version >= 0x2001A) { SekiroUnk.Write(bw); } bw.Pad(0x10); for (int i = 0; i < BufferLayouts.Count; i++) { BufferLayouts[i].WriteMembers(bw, i); } bw.Pad(0x10); for (int i = 0; i < Meshes.Count; i++) { Meshes[i].WriteBoundingBox(bw, i, Header); } bw.Pad(0x10); int boneIndicesStart = (int)bw.Position; for (int i = 0; i < Meshes.Count; i++) { Meshes[i].WriteBoneIndices(bw, i, boneIndicesStart); } bw.Pad(0x10); faceSetIndex = 0; for (int i = 0; i < Meshes.Count; i++) { bw.FillInt32($"MeshFaceSetIndices{i}", (int)bw.Position); for (int j = 0; j < Meshes[i].FaceSets.Count; j++) { bw.WriteInt32(faceSetIndex + j); } faceSetIndex += Meshes[i].FaceSets.Count; } bw.Pad(0x10); vertexBufferIndex = 0; for (int i = 0; i < Meshes.Count; i++) { bw.FillInt32($"MeshVertexBufferIndices{i}", (int)bw.Position); for (int j = 0; j < Meshes[i].VertexBuffers.Count; j++) { bw.WriteInt32(vertexBufferIndex + j); } vertexBufferIndex += Meshes[i].VertexBuffers.Count; } bw.Pad(0x10); var gxOffsets = new List <int>(); foreach (GXList gxList in GXLists) { gxOffsets.Add((int)bw.Position); gxList.Write(bw, Header); } for (int i = 0; i < Materials.Count; i++) { Materials[i].FillGXOffset(bw, i, gxOffsets); } bw.Pad(0x10); textureIndex = 0; for (int i = 0; i < Materials.Count; i++) { Material material = Materials[i]; material.WriteStrings(bw, Header, i); for (int j = 0; j < material.Textures.Count; j++) { material.Textures[j].WriteStrings(bw, Header, textureIndex + j); } textureIndex += material.Textures.Count; } bw.Pad(0x10); for (int i = 0; i < Bones.Count; i++) { Bones[i].WriteStrings(bw, Header.Unicode, i); } int alignment = Header.Version <= 0x2000E ? 0x20 : 0x10; bw.Pad(alignment); if (Header.Version == 0x2000F || Header.Version == 0x20010) { bw.Pad(0x20); } int dataStart = (int)bw.Position; bw.FillInt32("DataOffset", dataStart); faceSetIndex = 0; vertexBufferIndex = 0; for (int i = 0; i < Meshes.Count; i++) { Mesh mesh = Meshes[i]; for (int j = 0; j < mesh.FaceSets.Count; j++) { int indexSize = vertexIndicesSize; if (indexSize == 0) { indexSize = mesh.FaceSets[j].GetVertexIndexSize(); } bw.Pad(alignment); mesh.FaceSets[j].WriteVertices(bw, indexSize, faceSetIndex + j, dataStart); } faceSetIndex += mesh.FaceSets.Count; foreach (FLVER.Vertex vertex in mesh.Vertices) { vertex.PrepareWrite(); } for (int j = 0; j < mesh.VertexBuffers.Count; j++) { bw.Pad(alignment); mesh.VertexBuffers[j].WriteBuffer(bw, vertexBufferIndex + j, BufferLayouts, mesh.Vertices, dataStart, Header); } foreach (FLVER.Vertex vertex in mesh.Vertices) { vertex.FinishWrite(); } vertexBufferIndex += mesh.VertexBuffers.Count; } bw.Pad(alignment); bw.FillInt32("DataSize", (int)bw.Position - dataStart); if (Header.Version == 0x2000F || Header.Version == 0x20010) { bw.Pad(0x20); } }
private int SizeOf2MeshHeaders() { return(Meshes.Sum(mesh => mesh.SizeOfHeader())); }
private int SizeOf2MeshData() { return(PaddingUtils.Align(Meshes.Sum(mesh => mesh.SizeOfIndexedData()), 0x20)); }