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 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; } } }