public void SaveMapMeshes(Structs.WISMDA WISMDA) { Structs.XBC1[] MapInfoDatas = WISMDA.FilesBySearch("bina_basefix.temp_wi"); Structs.MXMD[] MapMXMDs = new Structs.MXMD[MapInfoDatas.Length]; Structs.MapInfo[] MapInfos = new Structs.MapInfo[MapInfoDatas.Length]; for (int i = 0; i < MapInfoDatas.Length; i++) { MapInfos[i] = ft.ReadMapInfo(MapInfoDatas[i].Data, new BinaryReader(MapInfoDatas[i].Data), false); for (int j = 0; j < MapInfos[i].MeshFileLookup.Length; j++) { if (i != 0) { MapInfos[i].MeshFileLookup[j] += (short)(MapInfos[i - 1].MeshFileLookup.Max() + 1); } } MapMXMDs[i] = new Structs.MXMD { Version = 0xFF }; MapMXMDs[i].Materials = MapInfos[i].Materials; MapMXMDs[i].ModelStruct.MeshesCount = MapInfos[i].MeshTableDataCount; MapMXMDs[i].ModelStruct.Meshes = new Structs.MXMDMeshes[MapInfos[i].MeshTables.Length]; for (int j = 0; j < MapInfos[i].MeshTables.Length; j++) { MapMXMDs[i].ModelStruct.Meshes[j].TableCount = MapInfos[i].MeshTables[j].MeshCount; MapMXMDs[i].ModelStruct.Meshes[j].Descriptors = MapInfos[i].MeshTables[j].Descriptors; } } if (App.ShowInfo) { foreach (Structs.MapInfo map in MapInfos) { App.PushLog("MapInfo:" + Structs.ReflectToString(map, 1, 180)); } } Structs.XBC1[] MapMeshDatas = WISMDA.FilesBySearch("basemap/poli//"); Structs.Mesh[] MapMeshes = new Structs.Mesh[MapMeshDatas.Length]; for (int i = 0; i < MapMeshes.Length; i++) { MemoryStream model = MapMeshDatas[i].Data; MapMeshes[i] = ft.ReadMesh(model, new BinaryReader(model)); } for (int i = 0; i < MapInfos.Length; i++) { switch (App.ExportFormat) { case Structs.ExportFormat.XNALara: ft.ModelToASCII(MapMeshes, MapMXMDs[i], new Structs.SKEL { Unknown1 = Int32.MaxValue }, MapInfos[i]); break; case Structs.ExportFormat.glTF: ft.ModelToGLTF(MapMeshes, MapMXMDs[i], new Structs.SKEL { Unknown1 = Int32.MaxValue }, MapInfos[i]); break; } } }
public void SaveMapProps(Structs.WISMDA WISMDA) { Structs.XBC1[] MapInfoDatas = WISMDA.FilesBySearch("seamwork/inst/out"); Structs.XBC1[] MapMeshDatas = WISMDA.FilesBySearch("seamwork/inst/mdl"); Structs.XBC1[] MapPosDatas = WISMDA.FilesBySearch("seamwork/inst/pos"); Structs.Mesh[] MapMeshes = new Structs.Mesh[MapMeshDatas.Length]; List <Structs.MXMD> MapMXMDs = new List <Structs.MXMD>(); Structs.SeamworkPropPosition[] MapPositions = new Structs.SeamworkPropPosition[MapPosDatas.Length]; Structs.MapInfo[] MapInfos = new Structs.MapInfo[MapInfoDatas.Length]; Dictionary <Structs.MXMD, Structs.MapInfo> MXMDToMapInfo = new Dictionary <Structs.MXMD, Structs.MapInfo>(); int MapPositionsIndex = 0; for (int i = 0; i < MapPosDatas.Length; i++) { MapPositions[i] = ft.ReadPropPositions(MapPosDatas[i].Data, new BinaryReader(MapPosDatas[i].Data)); } for (int i = 0; i < MapInfoDatas.Length; i++) { MapInfos[i] = ft.ReadMapInfo(MapInfoDatas[i].Data, new BinaryReader(MapInfoDatas[i].Data), true); for (int j = 0; j < MapMeshDatas.Length; j++) { if (MapMeshes[j].VertexTableOffset == 0) { MapMeshes[j] = ft.ReadMesh(MapMeshDatas[j].Data, new BinaryReader(MapMeshDatas[j].Data)); } } if (MapInfos[i].PropPosTableCount == 1 && MapInfos[i].PropPositions[0].PropID != 0) { MapInfos[i].PropPositions.AddRange(MapPositions[MapPositionsIndex].Positions); MapInfos[i].PropPosTableCount = MapInfos[i].PropPositions.Count; MapPositionsIndex++; } //base things off prop position table //the table has the prop ids I need //duplicate ids mean duplicate meshes //get the highest LOD available //scrub through the propid table and only take unique values, dictionary this by index //take the dictionary and get the same indexes out of meshtables //loop through each prop position and build the MXMD based off those + artificial prop table //keep in mind structs are just memory values so I can duplicate things easily Dictionary <int, int> UniqueIDIndex = new Dictionary <int, int>(); for (int j = 0; j < MapInfos[i].PropIDs.Count; j++) { if (!UniqueIDIndex.ContainsKey(MapInfos[i].PropIDs[j])) { UniqueIDIndex.Add(MapInfos[i].PropIDs[j], j); } } Structs.MapInfoMeshTable[] MeshTables = new Structs.MapInfoMeshTable[UniqueIDIndex.Count]; int[] MeshLookup = new int[UniqueIDIndex.Count]; for (int j = 0; j < UniqueIDIndex.Count; j++) { MeshTables[j] = MapInfos[i].MeshTables[UniqueIDIndex.Values.ElementAt(j)]; MeshLookup[j] = MapInfos[i].PropFileLookup[UniqueIDIndex.Values.ElementAt(j)]; } MapInfos[i].PropFileLookup = MeshLookup; for (int j = 0; j < (MapInfos[i].PropPosTableCount / App.PropSplitCount) + 1; j++) { int MeshCount = j + 1 == (MapInfos[i].PropPosTableCount / App.PropSplitCount) + 1 ? MapInfos[i].PropPosTableCount % App.PropSplitCount : App.PropSplitCount; Structs.MXMD FakeMXMD = new Structs.MXMD { Version = 0xFF }; FakeMXMD.Materials = MapInfos[i].Materials; FakeMXMD.ModelStruct.MeshesCount = MeshCount; FakeMXMD.ModelStruct.Meshes = new Structs.MXMDMeshes[MeshCount]; for (int k = 0; k < MeshCount; k++) { Structs.MapInfoPropPosition PropPosition = MapInfos[i].PropPositions[k + (j * App.PropSplitCount)]; FakeMXMD.ModelStruct.Meshes[k].Unknown1 = k + (j * App.PropSplitCount); FakeMXMD.ModelStruct.Meshes[k].TableCount = MeshTables[PropPosition.PropID].MeshCount; FakeMXMD.ModelStruct.Meshes[k].Descriptors = MeshTables[PropPosition.PropID].Descriptors; } MapMXMDs.Add(FakeMXMD); MXMDToMapInfo.Add(FakeMXMD, MapInfos[i]); } } if (App.ShowInfo) { foreach (Structs.MapInfo map in MapInfos) { App.PushLog("PropInfo:" + Structs.ReflectToString(map, 1, 180)); } } for (int i = 0; i < MXMDToMapInfo.Count; i++) { switch (App.ExportFormat) { case Structs.ExportFormat.XNALara: ft.ModelToASCII(MapMeshes, MXMDToMapInfo.Keys.ElementAt(i), new Structs.SKEL { Unknown1 = Int32.MaxValue }, MXMDToMapInfo.Values.ElementAt(i), $"props{i}x{MXMDToMapInfo.Keys.ElementAt(i).ModelStruct.MeshesCount}"); break; case Structs.ExportFormat.glTF: ft.ModelToGLTF(MapMeshes, MXMDToMapInfo.Keys.ElementAt(i), new Structs.SKEL { Unknown1 = Int32.MaxValue }, MXMDToMapInfo.Values.ElementAt(i), $"props{i}x{MXMDToMapInfo.Keys.ElementAt(i).ModelStruct.MeshesCount}"); break; } } }
public void ExtractModels() { App.PushLog($"Reading {App.CurFileNameNoExt}..."); //wismt FileStream fsWISMT = new FileStream(App.CurFilePathAndName + ".wismt", FileMode.Open, FileAccess.Read); BinaryReader brWISMT = new BinaryReader(fsWISMT); Structs.MSRD MSRD = ft.ReadMSRD(fsWISMT, brWISMT); if (App.ExportAnims) { if (File.Exists(App.CurFilePathAndName + ".mot")) { foreach (string file in Directory.GetFiles(App.CurFilePath, $"{App.CurFileNameNoExt}*.mot")) { FileStream fsMOT = new FileStream(file, FileMode.Open, FileAccess.Read); BinaryReader brMOT = new BinaryReader(fsMOT); Structs.SAR1 SAR1 = ft.ReadSAR1(fsMOT, brMOT, @"\Animations\", App.ExportAnims); brMOT.Dispose(); fsMOT.Dispose(); } } else { App.PushLog("No .mot file exists, continuing..."); } } //start mesh file if (MSRD.TOC.Length > 0) { if (App.ExportFormat != Structs.ExportFormat.None && !Directory.Exists(App.CurOutputPath)) { Directory.CreateDirectory(App.CurOutputPath); } if (App.ExportTextures) { ft.ReadTextures(MSRD, $@"{App.CurOutputPath}\Textures"); } BinaryReader brCurFile = new BinaryReader(MSRD.TOC[0].Data); //start new file Structs.Mesh Mesh = ft.ReadMesh(MSRD.TOC[0].Data, brCurFile); Structs.MXMD MXMD = new Structs.MXMD { Version = Int32.MaxValue }; if (File.Exists(App.CurFilePathAndName + ".wimdo")) { FileStream fsWIMDO = new FileStream(App.CurFilePathAndName + ".wimdo", FileMode.Open, FileAccess.Read); BinaryReader brWIMDO = new BinaryReader(fsWIMDO); MXMD = ft.ReadMXMD(fsWIMDO, brWIMDO); } Structs.SAR1 SAR1 = new Structs.SAR1 { Version = Int32.MaxValue }; Structs.SKEL SKEL = new Structs.SKEL { Unknown1 = Int32.MaxValue }; if (File.Exists(App.CurFilePathAndName + ".arc")) { FileStream fsARC = new FileStream(App.CurFilePathAndName + ".arc", FileMode.Open, FileAccess.Read); BinaryReader brARC = new BinaryReader(fsARC); SAR1 = ft.ReadSAR1(fsARC, brARC, @"\RawFiles\", App.ExportFormat == Structs.ExportFormat.RawFiles); BinaryReader brSKEL = new BinaryReader(SAR1.ItemBySearch(".skl").Data); SKEL = ft.ReadSKEL(brSKEL.BaseStream, brSKEL); } if (App.ShowInfo) { App.PushLog(MSRD.ToString()); App.PushLog(Mesh.ToString()); App.PushLog(MXMD.ToString()); } switch (App.ExportFormat) { case Structs.ExportFormat.XNALara: ft.ModelToASCII(new Structs.Mesh[] { Mesh }, MXMD, SKEL, new Structs.MapInfo { Unknown1 = Int32.MaxValue }); break; case Structs.ExportFormat.glTF: ft.ModelToGLTF(new Structs.Mesh[] { Mesh }, MXMD, SKEL, new Structs.MapInfo { Unknown1 = Int32.MaxValue }); break; } App.PushLog($"Finished {App.CurFileNameNoExt}!"); } else { App.PushLog($"No files found in {App.CurFilePathAndName}.wismt?"); } brWISMT.Dispose(); fsWISMT.Dispose(); }