| 1 | using System; | 
 
 
 
 
 | 2 | using System.Collections.Generic; | 
 
 
 
 
 | 3 | using System.IO; | 
 
 
 
 
 | 4 | using Oni.Imaging; | 
 
 
 
 
 | 5 | using Oni.Motoko; | 
 
 
 
 
 | 6 |  | 
 
 
 
 
 | 7 | namespace Oni.Akira | 
 
 
 
 
 | 8 | { | 
 
 
 
 
 | 9 | internal class AkiraDatReader | 
 
 
 
 
 | 10 | { | 
 
 
 
 
 | 11 | #region Private data | 
 
 
 
 
 | 12 | private InstanceDescriptor akev; | 
 
 
 
 
 | 13 | private InstanceDescriptor agdb; | 
 
 
 
 
 | 14 | private InstanceDescriptor pnta; | 
 
 
 
 
 | 15 | private InstanceDescriptor plea; | 
 
 
 
 
 | 16 | private InstanceDescriptor txca; | 
 
 
 
 
 | 17 | private InstanceDescriptor agqg; | 
 
 
 
 
 | 18 | private InstanceDescriptor agqc; | 
 
 
 
 
 | 19 | private InstanceDescriptor agqr; | 
 
 
 
 
 | 20 | private InstanceDescriptor txma; | 
 
 
 
 
 | 21 | private InstanceDescriptor akva; | 
 
 
 
 
 | 22 | private InstanceDescriptor akba; | 
 
 
 
 
 | 23 | private InstanceDescriptor idxa1; | 
 
 
 
 
 | 24 | private InstanceDescriptor idxa2; | 
 
 
 
 
 | 25 | private InstanceDescriptor akbp; | 
 
 
 
 
 | 26 | private InstanceDescriptor akaa; | 
 
 
 
 
 | 27 |  | 
 
 
 
 
 | 28 | private PolygonMesh mesh; | 
 
 
 
 
 | 29 | private Plane[] planes; | 
 
 
 
 
 | 30 | private Polygon[] polygons; | 
 
 
 
 
 | 31 | #endregion | 
 
 
 
 
 | 32 |  | 
 
 
 
 
 | 33 | #region private class DatRoom | 
 
 
 
 
 | 34 |  | 
 
 
 
 
 | 35 | private class DatRoom | 
 
 
 
 
 | 36 | { | 
 
 
 
 
 | 37 | public readonly int BspRootIndex; | 
 
 
 
 
 | 38 | public readonly int SideListStart; | 
 
 
 
 
 | 39 | public readonly int SideListEnd; | 
 
 
 
 
 | 40 | public readonly int ChildIndex; | 
 
 
 
 
 | 41 | public readonly int SiblingIndex; | 
 
 
 
 
 | 42 | public readonly int XTiles; | 
 
 
 
 
 | 43 | public readonly int ZTiles; | 
 
 
 
 
 | 44 | public readonly BoundingBox BoundingBox; | 
 
 
 
 
 | 45 | public readonly float TileSize; | 
 
 
 
 
 | 46 | public readonly int XOrigin; | 
 
 
 
 
 | 47 | public readonly int ZOrigin; | 
 
 
 
 
 | 48 | public readonly RoomFlags Flags; | 
 
 
 
 
 | 49 | public readonly Plane Floor; | 
 
 
 
 
 | 50 | public readonly float Height; | 
 
 
 
 
 | 51 | public readonly byte[] CompressedGridData; | 
 
 
 
 
 | 52 |  | 
 
 
 
 
 | 53 | public DatRoom(InstanceDescriptor descriptor, BinaryReader reader) | 
 
 
 
 
 | 54 | { | 
 
 
 
 
 | 55 | BspRootIndex = reader.ReadInt32(); | 
 
 
 
 
 | 56 | reader.Skip(4); | 
 
 
 
 
 | 57 | SideListStart = reader.ReadInt32(); | 
 
 
 
 
 | 58 | SideListEnd = reader.ReadInt32(); | 
 
 
 
 
 | 59 | ChildIndex = reader.ReadInt32(); | 
 
 
 
 
 | 60 | SiblingIndex = reader.ReadInt32(); | 
 
 
 
 
 | 61 | reader.Skip(4); | 
 
 
 
 
 | 62 | XTiles = reader.ReadInt32(); | 
 
 
 
 
 | 63 | ZTiles = reader.ReadInt32(); | 
 
 
 
 
 | 64 | int ofsGridData = reader.ReadInt32(); | 
 
 
 
 
 | 65 | int lenGridData = reader.ReadInt32(); | 
 
 
 
 
 | 66 | TileSize = reader.ReadSingle(); | 
 
 
 
 
 | 67 | BoundingBox = reader.ReadBoundingBox(); | 
 
 
 
 
 | 68 | XOrigin = reader.ReadInt16(); | 
 
 
 
 
 | 69 | ZOrigin = reader.ReadInt16(); | 
 
 
 
 
 | 70 | reader.Skip(16); | 
 
 
 
 
 | 71 | Flags = (RoomFlags)reader.ReadInt32(); | 
 
 
 
 
 | 72 | Floor = reader.ReadPlane(); | 
 
 
 
 
 | 73 | Height = reader.ReadSingle(); | 
 
 
 
 
 | 74 |  | 
 
 
 
 
 | 75 | if (ofsGridData != 0 && lenGridData != 0) | 
 
 
 
 
 | 76 | { | 
 
 
 
 
 | 77 | using (BinaryReader rawReader = descriptor.GetRawReader(ofsGridData)) | 
 
 
 
 
 | 78 | CompressedGridData = rawReader.ReadBytes(lenGridData); | 
 
 
 
 
 | 79 | } | 
 
 
 
 
 | 80 | } | 
 
 
 
 
 | 81 | } | 
 
 
 
 
 | 82 |  | 
 
 
 
 
 | 83 | #endregion | 
 
 
 
 
 | 84 | #region private class DatRoomBspNode | 
 
 
 
 
 | 85 |  | 
 
 
 
 
 | 86 | private class DatRoomBspNode | 
 
 
 
 
 | 87 | { | 
 
 
 
 
 | 88 | public readonly int PlaneIndex; | 
 
 
 
 
 | 89 | public readonly int FrontChildIndex; | 
 
 
 
 
 | 90 | public readonly int BackChildIndex; | 
 
 
 
 
 | 91 |  | 
 
 
 
 
 | 92 | public DatRoomBspNode(BinaryReader reader) | 
 
 
 
 
 | 93 | { | 
 
 
 
 
 | 94 | PlaneIndex = reader.ReadInt32(); | 
 
 
 
 
 | 95 | BackChildIndex = reader.ReadInt32(); | 
 
 
 
 
 | 96 | FrontChildIndex = reader.ReadInt32(); | 
 
 
 
 
 | 97 | } | 
 
 
 
 
 | 98 | } | 
 
 
 
 
 | 99 |  | 
 
 
 
 
 | 100 | #endregion | 
 
 
 
 
 | 101 | #region private class DatRoomSide | 
 
 
 
 
 | 102 |  | 
 
 
 
 
 | 103 | private class DatRoomSide | 
 
 
 
 
 | 104 | { | 
 
 
 
 
 | 105 | public readonly int SideListStart; | 
 
 
 
 
 | 106 | public readonly int SideListEnd; | 
 
 
 
 
 | 107 |  | 
 
 
 
 
 | 108 | public DatRoomSide(BinaryReader reader) | 
 
 
 
 
 | 109 | { | 
 
 
 
 
 | 110 | reader.Skip(4); | 
 
 
 
 
 | 111 | SideListStart = reader.ReadInt32(); | 
 
 
 
 
 | 112 | SideListEnd = reader.ReadInt32(); | 
 
 
 
 
 | 113 | reader.Skip(16); | 
 
 
 
 
 | 114 | } | 
 
 
 
 
 | 115 | } | 
 
 
 
 
 | 116 |  | 
 
 
 
 
 | 117 | #endregion | 
 
 
 
 
 | 118 | #region private class DatRoomAdjacency | 
 
 
 
 
 | 119 |  | 
 
 
 
 
 | 120 | private class DatRoomAdjacency | 
 
 
 
 
 | 121 | { | 
 
 
 
 
 | 122 | public readonly int RoomIndex; | 
 
 
 
 
 | 123 | public readonly int QuadIndex; | 
 
 
 
 
 | 124 |  | 
 
 
 
 
 | 125 | public DatRoomAdjacency(BinaryReader reader) | 
 
 
 
 
 | 126 | { | 
 
 
 
 
 | 127 | RoomIndex = reader.ReadInt32(); | 
 
 
 
 
 | 128 | QuadIndex = reader.ReadInt32(); | 
 
 
 
 
 | 129 | reader.Skip(4); | 
 
 
 
 
 | 130 | } | 
 
 
 
 
 | 131 | } | 
 
 
 
 
 | 132 |  | 
 
 
 
 
 | 133 | #endregion | 
 
 
 
 
 | 134 |  | 
 
 
 
 
 | 135 | public static PolygonMesh Read(InstanceDescriptor akev) | 
 
 
 
 
 | 136 | { | 
 
 
 
 
 | 137 | var reader = new AkiraDatReader | 
 
 
 
 
 | 138 | { | 
 
 
 
 
 | 139 | akev = akev, | 
 
 
 
 
 | 140 | mesh = new PolygonMesh(new MaterialLibrary()) | 
 
 
 
 
 | 141 | }; | 
 
 
 
 
 | 142 |  | 
 
 
 
 
 | 143 | reader.Read(); | 
 
 
 
 
 | 144 | return reader.mesh; | 
 
 
 
 
 | 145 | } | 
 
 
 
 
 | 146 |  | 
 
 
 
 
 | 147 | private void Read() | 
 
 
 
 
 | 148 | { | 
 
 
 
 
 | 149 | using (var reader = akev.OpenRead()) | 
 
 
 
 
 | 150 | { | 
 
 
 
 
 | 151 | pnta = reader.ReadInstance(); | 
 
 
 
 
 | 152 | plea = reader.ReadInstance(); | 
 
 
 
 
 | 153 | txca = reader.ReadInstance(); | 
 
 
 
 
 | 154 | agqg = reader.ReadInstance(); | 
 
 
 
 
 | 155 | agqr = reader.ReadInstance(); | 
 
 
 
 
 | 156 | agqc = reader.ReadInstance(); | 
 
 
 
 
 | 157 | agdb = reader.ReadInstance(); | 
 
 
 
 
 | 158 | txma = reader.ReadInstance(); | 
 
 
 
 
 | 159 | akva = reader.ReadInstance(); | 
 
 
 
 
 | 160 | akba = reader.ReadInstance(); | 
 
 
 
 
 | 161 | idxa1 = reader.ReadInstance(); | 
 
 
 
 
 | 162 | idxa2 = reader.ReadInstance(); | 
 
 
 
 
 | 163 | akbp = reader.ReadInstance(); | 
 
 
 
 
 | 164 | reader.Skip(8); | 
 
 
 
 
 | 165 | akaa = reader.ReadInstance(); | 
 
 
 
 
 | 166 | } | 
 
 
 
 
 | 167 |  | 
 
 
 
 
 | 168 | ReadGeometry(); | 
 
 
 
 
 | 169 | ReadDebugInfo(); | 
 
 
 
 
 | 170 | ReadMaterials(); | 
 
 
 
 
 | 171 | ReadScriptIndices(); | 
 
 
 
 
 | 172 | ReadRooms(); | 
 
 
 
 
 | 173 | } | 
 
 
 
 
 | 174 |  | 
 
 
 
 
 | 175 | private void ReadGeometry() | 
 
 
 
 
 | 176 | { | 
 
 
 
 
 | 177 | int[] planeIndices; | 
 
 
 
 
 | 178 |  | 
 
 
 
 
 | 179 | using (var reader = pnta.OpenRead(52)) | 
 
 
 
 
 | 180 | mesh.Points.AddRange(reader.ReadVector3VarArray()); | 
 
 
 
 
 | 181 |  | 
 
 
 
 
 | 182 | using (var reader = txca.OpenRead(20)) | 
 
 
 
 
 | 183 | mesh.TexCoords.AddRange(reader.ReadVector2VarArray()); | 
 
 
 
 
 | 184 |  | 
 
 
 
 
 | 185 | using (var reader = plea.OpenRead(20)) | 
 
 
 
 
 | 186 | planes = reader.ReadPlaneVarArray(); | 
 
 
 
 
 | 187 |  | 
 
 
 
 
 | 188 | using (var reader = agqc.OpenRead(20)) | 
 
 
 
 
 | 189 | { | 
 
 
 
 
 | 190 | planeIndices = new int[reader.ReadInt32()]; | 
 
 
 
 
 | 191 |  | 
 
 
 
 
 | 192 | for (int i = 0; i < planeIndices.Length; i++) | 
 
 
 
 
 | 193 | { | 
 
 
 
 
 | 194 | planeIndices[i] = reader.ReadInt32(); | 
 
 
 
 
 | 195 |  | 
 
 
 
 
 | 196 | // | 
 
 
 
 
 | 197 | // Ignore bounding boxes, we don't need them | 
 
 
 
 
 | 198 | // | 
 
 
 
 
 | 199 |  | 
 
 
 
 
 | 200 | reader.Skip(24); | 
 
 
 
 
 | 201 | } | 
 
 
 
 
 | 202 | } | 
 
 
 
 
 | 203 |  | 
 
 
 
 
 | 204 | using (var reader = agqg.OpenRead(20)) | 
 
 
 
 
 | 205 | { | 
 
 
 
 
 | 206 | polygons = new Polygon[reader.ReadInt32()]; | 
 
 
 
 
 | 207 |  | 
 
 
 
 
 | 208 | for (int i = 0; i < polygons.Length; i++) | 
 
 
 
 
 | 209 | { | 
 
 
 
 
 | 210 | var pointIndices = reader.ReadInt32Array(4); | 
 
 
 
 
 | 211 | var texCoordIndices = reader.ReadInt32Array(4); | 
 
 
 
 
 | 212 | var colors = reader.ReadColorArray(4); | 
 
 
 
 
 | 213 | var flags = (GunkFlags)reader.ReadInt32(); | 
 
 
 
 
 | 214 | int objectId = reader.ReadInt32(); | 
 
 
 
 
 | 215 |  | 
 
 
 
 
 | 216 | if ((flags & GunkFlags.Triangle) != 0) | 
 
 
 
 
 | 217 | { | 
 
 
 
 
 | 218 | Array.Resize(ref pointIndices, 3); | 
 
 
 
 
 | 219 | Array.Resize(ref texCoordIndices, 3); | 
 
 
 
 
 | 220 | Array.Resize(ref colors, 3); | 
 
 
 
 
 | 221 |  | 
 
 
 
 
 | 222 | flags &= ~GunkFlags.Triangle; | 
 
 
 
 
 | 223 | } | 
 
 
 
 
 | 224 |  | 
 
 
 
 
 | 225 | var polygon = new Polygon(mesh, pointIndices, PlaneFromIndex(planeIndices[i])) | 
 
 
 
 
 | 226 | { | 
 
 
 
 
 | 227 | Flags = flags & ~GunkFlags.Transparent, | 
 
 
 
 
 | 228 | TexCoordIndices = texCoordIndices, | 
 
 
 
 
 | 229 | Colors = colors | 
 
 
 
 
 | 230 | }; | 
 
 
 
 
 | 231 |  | 
 
 
 
 
 | 232 | if (objectId == -1) | 
 
 
 
 
 | 233 | { | 
 
 
 
 
 | 234 | polygon.ObjectType = -1; | 
 
 
 
 
 | 235 | polygon.ObjectId = -1; | 
 
 
 
 
 | 236 | } | 
 
 
 
 
 | 237 | else | 
 
 
 
 
 | 238 | { | 
 
 
 
 
 | 239 | polygon.ObjectType = (objectId >> 24) & 0xff; | 
 
 
 
 
 | 240 | polygon.ObjectId = objectId & 0xffffff; | 
 
 
 
 
 | 241 | } | 
 
 
 
 
 | 242 |  | 
 
 
 
 
 | 243 | polygons[i] = polygon; | 
 
 
 
 
 | 244 | } | 
 
 
 
 
 | 245 | } | 
 
 
 
 
 | 246 |  | 
 
 
 
 
 | 247 | foreach (var polygon in polygons) | 
 
 
 
 
 | 248 | { | 
 
 
 
 
 | 249 | if ((polygon.Flags & (GunkFlags.Ghost | GunkFlags.StairsUp | GunkFlags.StairsDown)) != 0) | 
 
 
 
 
 | 250 | mesh.Ghosts.Add(polygon); | 
 
 
 
 
 | 251 | else | 
 
 
 
 
 | 252 | mesh.Polygons.Add(polygon); | 
 
 
 
 
 | 253 | } | 
 
 
 
 
 | 254 | } | 
 
 
 
 
 | 255 |  | 
 
 
 
 
 | 256 | private Plane PlaneFromIndex(int index) | 
 
 
 
 
 | 257 | { | 
 
 
 
 
 | 258 | var plane = planes[index & int.MaxValue]; | 
 
 
 
 
 | 259 |  | 
 
 
 
 
 | 260 | if (index < 0) | 
 
 
 
 
 | 261 | { | 
 
 
 
 
 | 262 | plane.Normal = -plane.Normal; | 
 
 
 
 
 | 263 | plane.D = -plane.D; | 
 
 
 
 
 | 264 | } | 
 
 
 
 
 | 265 |  | 
 
 
 
 
 | 266 | return plane; | 
 
 
 
 
 | 267 | } | 
 
 
 
 
 | 268 |  | 
 
 
 
 
 | 269 | private void ReadMaterials() | 
 
 
 
 
 | 270 | { | 
 
 
 
 
 | 271 | // | 
 
 
 
 
 | 272 | // Read material list from TXMA | 
 
 
 
 
 | 273 | // | 
 
 
 
 
 | 274 |  | 
 
 
 
 
 | 275 | Material[] materials; | 
 
 
 
 
 | 276 |  | 
 
 
 
 
 | 277 | using (var reader = txma.OpenRead(20)) | 
 
 
 
 
 | 278 | { | 
 
 
 
 
 | 279 | materials = new Material[reader.ReadInt32()]; | 
 
 
 
 
 | 280 |  | 
 
 
 
 
 | 281 | for (int i = 0; i < materials.Length; i++) | 
 
 
 
 
 | 282 | { | 
 
 
 
 
 | 283 | var texture = reader.ReadInstance(); | 
 
 
 
 
 | 284 |  | 
 
 
 
 
 | 285 | if (texture == null) | 
 
 
 
 
 | 286 | continue; | 
 
 
 
 
 | 287 |  | 
 
 
 
 
 | 288 | var material = mesh.Materials.GetMaterial(Utils.CleanupTextureName(texture.Name)); | 
 
 
 
 
 | 289 | material.Image = TextureDatReader.Read(texture).Surfaces[0]; | 
 
 
 
 
 | 290 |  | 
 
 
 
 
 | 291 | if (material.Image.HasAlpha) | 
 
 
 
 
 | 292 | material.Flags |= GunkFlags.Transparent; | 
 
 
 
 
 | 293 |  | 
 
 
 
 
 | 294 | materials[i] = material; | 
 
 
 
 
 | 295 | } | 
 
 
 
 
 | 296 | } | 
 
 
 
 
 | 297 |  | 
 
 
 
 
 | 298 | // | 
 
 
 
 
 | 299 | // Assign materials to polygons based on AGQR | 
 
 
 
 
 | 300 | // | 
 
 
 
 
 | 301 |  | 
 
 
 
 
 | 302 | using (var reader = agqr.OpenRead(20)) | 
 
 
 
 
 | 303 | { | 
 
 
 
 
 | 304 | int count = reader.ReadInt32(); | 
 
 
 
 
 | 305 |  | 
 
 
 
 
 | 306 | for (int i = 0; i < count; i++) | 
 
 
 
 
 | 307 | polygons[i].Material = materials[reader.ReadInt32() & 0xffff]; | 
 
 
 
 
 | 308 | } | 
 
 
 
 
 | 309 |  | 
 
 
 
 
 | 310 | // | 
 
 
 
 
 | 311 | // Assign special materials: danger, stairs etc. | 
 
 
 
 
 | 312 | // | 
 
 
 
 
 | 313 |  | 
 
 
 
 
 | 314 | foreach (var polygon in polygons) | 
 
 
 
 
 | 315 | { | 
 
 
 
 
 | 316 | var marker = mesh.Materials.Markers.GetMarker(polygon); | 
 
 
 
 
 | 317 |  | 
 
 
 
 
 | 318 | if (marker != null) | 
 
 
 
 
 | 319 | polygon.Material = marker; | 
 
 
 
 
 | 320 | } | 
 
 
 
 
 | 321 | } | 
 
 
 
 
 | 322 |  | 
 
 
 
 
 | 323 | private void ReadScriptIndices() | 
 
 
 
 
 | 324 | { | 
 
 
 
 
 | 325 | if (idxa1 == null || idxa2 == null) | 
 
 
 
 
 | 326 | return; | 
 
 
 
 
 | 327 |  | 
 
 
 
 
 | 328 | int[] scriptQuadIndices; | 
 
 
 
 
 | 329 | int[] scriptIds; | 
 
 
 
 
 | 330 |  | 
 
 
 
 
 | 331 | using (var reader = idxa1.OpenRead(20)) | 
 
 
 
 
 | 332 | scriptQuadIndices = reader.ReadInt32VarArray(); | 
 
 
 
 
 | 333 |  | 
 
 
 
 
 | 334 | using (var reader = idxa2.OpenRead(20)) | 
 
 
 
 
 | 335 | scriptIds = reader.ReadInt32VarArray(); | 
 
 
 
 
 | 336 |  | 
 
 
 
 
 | 337 | for (int i = 0; i < scriptQuadIndices.Length; i++) | 
 
 
 
 
 | 338 | polygons[scriptQuadIndices[i]].ScriptId = scriptIds[i]; | 
 
 
 
 
 | 339 | } | 
 
 
 
 
 | 340 |  | 
 
 
 
 
 | 341 | private void ReadDebugInfo() | 
 
 
 
 
 | 342 | { | 
 
 
 
 
 | 343 | if (agdb == null) | 
 
 
 
 
 | 344 | { | 
 
 
 
 
 | 345 | var debugFileName = "AGDB" + akev.Name + ".oni"; | 
 
 
 
 
 | 346 | var debugFilePath = Path.Combine(Path.GetDirectoryName(akev.File.FilePath), debugFileName); | 
 
 
 
 
 | 347 |  | 
 
 
 
 
 | 348 | if (!File.Exists(debugFilePath)) | 
 
 
 
 
 | 349 | return; | 
 
 
 
 
 | 350 |  | 
 
 
 
 
 | 351 | Console.WriteLine(debugFilePath); | 
 
 
 
 
 | 352 |  | 
 
 
 
 
 | 353 | var debugFile = akev.File.FileManager.OpenFile(debugFilePath); | 
 
 
 
 
 | 354 |  | 
 
 
 
 
 | 355 | if (debugFile == null) | 
 
 
 
 
 | 356 | return; | 
 
 
 
 
 | 357 |  | 
 
 
 
 
 | 358 | agdb = debugFile.Descriptors[0]; | 
 
 
 
 
 | 359 | } | 
 
 
 
 
 | 360 |  | 
 
 
 
 
 | 361 | if (agdb == null || agdb.Template.Tag != TemplateTag.AGDB) | 
 
 
 
 
 | 362 | return; | 
 
 
 
 
 | 363 |  | 
 
 
 
 
 | 364 | using (var reader = agdb.OpenRead(20)) | 
 
 
 
 
 | 365 | { | 
 
 
 
 
 | 366 | int count = reader.ReadInt32(); | 
 
 
 
 
 | 367 |  | 
 
 
 
 
 | 368 | var fileNames = new Dictionary<int, string>(); | 
 
 
 
 
 | 369 | var objectNames = new Dictionary<int, string>(); | 
 
 
 
 
 | 370 |  | 
 
 
 
 
 | 371 | for (int i = 0; i < count; i++) | 
 
 
 
 
 | 372 | { | 
 
 
 
 
 | 373 | int objectNameOffset = reader.ReadInt32(); | 
 
 
 
 
 | 374 | string objectName; | 
 
 
 
 
 | 375 |  | 
 
 
 
 
 | 376 | if (!objectNames.TryGetValue(objectNameOffset, out objectName)) | 
 
 
 
 
 | 377 | { | 
 
 
 
 
 | 378 | using (var rawReader = agdb.GetRawReader(objectNameOffset)) | 
 
 
 
 
 | 379 | objectName = rawReader.ReadString(256); | 
 
 
 
 
 | 380 |  | 
 
 
 
 
 | 381 | objectName = objectName.Replace('.', '_'); | 
 
 
 
 
 | 382 | objectNames.Add(objectNameOffset, objectName); | 
 
 
 
 
 | 383 | } | 
 
 
 
 
 | 384 |  | 
 
 
 
 
 | 385 | int fileNameOffset = reader.ReadInt32(); | 
 
 
 
 
 | 386 | string fileName; | 
 
 
 
 
 | 387 |  | 
 
 
 
 
 | 388 | if (!fileNames.TryGetValue(fileNameOffset, out fileName)) | 
 
 
 
 
 | 389 | { | 
 
 
 
 
 | 390 | using (var rawReader = agdb.GetRawReader(fileNameOffset)) | 
 
 
 
 
 | 391 | fileName = rawReader.ReadString(256); | 
 
 
 
 
 | 392 |  | 
 
 
 
 
 | 393 | fileName = Path.GetFileNameWithoutExtension(fileName); | 
 
 
 
 
 | 394 | fileNames.Add(fileNameOffset, fileName); | 
 
 
 
 
 | 395 | } | 
 
 
 
 
 | 396 |  | 
 
 
 
 
 | 397 | if (!string.IsNullOrEmpty(objectName)) | 
 
 
 
 
 | 398 | mesh.HasDebugInfo = true; | 
 
 
 
 
 | 399 |  | 
 
 
 
 
 | 400 | polygons[i].ObjectName = objectName; | 
 
 
 
 
 | 401 | polygons[i].FileName = fileName; | 
 
 
 
 
 | 402 | } | 
 
 
 
 
 | 403 | } | 
 
 
 
 
 | 404 | } | 
 
 
 
 
 | 405 |  | 
 
 
 
 
 | 406 | private void ReadRooms() | 
 
 
 
 
 | 407 | { | 
 
 
 
 
 | 408 | DatRoomBspNode[] bspTrees; | 
 
 
 
 
 | 409 | DatRoomSide[] roomSides; | 
 
 
 
 
 | 410 | DatRoomAdjacency[] roomAdjacencies; | 
 
 
 
 
 | 411 | DatRoom[] roomsData; | 
 
 
 
 
 | 412 |  | 
 
 
 
 
 | 413 | using (var reader = akbp.OpenRead(22)) | 
 
 
 
 
 | 414 | { | 
 
 
 
 
 | 415 | bspTrees = new DatRoomBspNode[reader.ReadUInt16()]; | 
 
 
 
 
 | 416 |  | 
 
 
 
 
 | 417 | for (int i = 0; i < bspTrees.Length; i++) | 
 
 
 
 
 | 418 | bspTrees[i] = new DatRoomBspNode(reader); | 
 
 
 
 
 | 419 | } | 
 
 
 
 
 | 420 |  | 
 
 
 
 
 | 421 | using (var reader = akba.OpenRead(20)) | 
 
 
 
 
 | 422 | { | 
 
 
 
 
 | 423 | roomSides = new DatRoomSide[reader.ReadInt32()]; | 
 
 
 
 
 | 424 |  | 
 
 
 
 
 | 425 | for (int i = 0; i < roomSides.Length; i++) | 
 
 
 
 
 | 426 | roomSides[i] = new DatRoomSide(reader); | 
 
 
 
 
 | 427 | } | 
 
 
 
 
 | 428 |  | 
 
 
 
 
 | 429 | using (var reader = akaa.OpenRead(20)) | 
 
 
 
 
 | 430 | { | 
 
 
 
 
 | 431 | roomAdjacencies = new DatRoomAdjacency[reader.ReadInt32()]; | 
 
 
 
 
 | 432 |  | 
 
 
 
 
 | 433 | for (int i = 0; i < roomAdjacencies.Length; i++) | 
 
 
 
 
 | 434 | roomAdjacencies[i] = new DatRoomAdjacency(reader); | 
 
 
 
 
 | 435 | } | 
 
 
 
 
 | 436 |  | 
 
 
 
 
 | 437 | using (var reader = akva.OpenRead(20)) | 
 
 
 
 
 | 438 | { | 
 
 
 
 
 | 439 | roomsData = new DatRoom[reader.ReadInt32()]; | 
 
 
 
 
 | 440 |  | 
 
 
 
 
 | 441 | for (int i = 0; i < roomsData.Length; i++) | 
 
 
 
 
 | 442 | roomsData[i] = new DatRoom(akva, reader); | 
 
 
 
 
 | 443 | } | 
 
 
 
 
 | 444 |  | 
 
 
 
 
 | 445 | var rooms = new Room[roomsData.Length]; | 
 
 
 
 
 | 446 |  | 
 
 
 
 
 | 447 | for (int i = 0; i < roomsData.Length; i++) | 
 
 
 
 
 | 448 | { | 
 
 
 
 
 | 449 | var data = roomsData[i]; | 
 
 
 
 
 | 450 |  | 
 
 
 
 
 | 451 | var room = new Room | 
 
 
 
 
 | 452 | { | 
 
 
 
 
 | 453 | BspTree = BspNodeDataToBspNode(bspTrees, data.BspRootIndex), | 
 
 
 
 
 | 454 | BoundingBox = data.BoundingBox | 
 
 
 
 
 | 455 | }; | 
 
 
 
 
 | 456 |  | 
 
 
 
 
 | 457 | if ((data.Flags & RoomFlags.Stairs) != 0) | 
 
 
 
 
 | 458 | { | 
 
 
 
 
 | 459 | room.FloorPlane = data.Floor; | 
 
 
 
 
 | 460 | room.Height = data.Height; | 
 
 
 
 
 | 461 | } | 
 
 
 
 
 | 462 | else | 
 
 
 
 
 | 463 | { | 
 
 
 
 
 | 464 | room.FloorPlane = new Plane(Vector3.Up, -data.BoundingBox.Min.Y); | 
 
 
 
 
 | 465 | room.Height = data.BoundingBox.Max.Y - data.BoundingBox.Min.Y; | 
 
 
 
 
 | 466 | } | 
 
 
 
 
 | 467 |  | 
 
 
 
 
 | 468 | room.Grid = RoomGrid.FromCompressedData(data.XTiles, data.ZTiles, data.CompressedGridData); | 
 
 
 
 
 | 469 | rooms[i] = room; | 
 
 
 
 
 | 470 | } | 
 
 
 
 
 | 471 |  | 
 
 
 
 
 | 472 | for (int i = 0; i < roomsData.Length; i++) | 
 
 
 
 
 | 473 | { | 
 
 
 
 
 | 474 | var data = roomsData[i]; | 
 
 
 
 
 | 475 | var room = rooms[i]; | 
 
 
 
 
 | 476 |  | 
 
 
 
 
 | 477 | //if (data.SiblingIndex != -1) | 
 
 
 
 
 | 478 | //    room.Sibling = rooms[data.SiblingIndex]; | 
 
 
 
 
 | 479 |  | 
 
 
 
 
 | 480 | //if (data.ChildIndex != -1) | 
 
 
 
 
 | 481 | //    room.Child = rooms[data.ChildIndex]; | 
 
 
 
 
 | 482 |  | 
 
 
 
 
 | 483 | for (int j = data.SideListStart; j < data.SideListEnd; j++) | 
 
 
 
 
 | 484 | { | 
 
 
 
 
 | 485 | var sideData = roomSides[j]; | 
 
 
 
 
 | 486 |  | 
 
 
 
 
 | 487 | for (int k = sideData.SideListStart; k < sideData.SideListEnd; k++) | 
 
 
 
 
 | 488 | { | 
 
 
 
 
 | 489 | var adjData = roomAdjacencies[k]; | 
 
 
 
 
 | 490 | var adjacentRoom = rooms[adjData.RoomIndex]; | 
 
 
 
 
 | 491 | var ghost = polygons[adjData.QuadIndex]; | 
 
 
 
 
 | 492 |  | 
 
 
 
 
 | 493 | room.Ajacencies.Add(new RoomAdjacency(adjacentRoom, ghost)); | 
 
 
 
 
 | 494 | } | 
 
 
 
 
 | 495 | } | 
 
 
 
 
 | 496 | } | 
 
 
 
 
 | 497 |  | 
 
 
 
 
 | 498 | mesh.Rooms.AddRange(rooms); | 
 
 
 
 
 | 499 | } | 
 
 
 
 
 | 500 |  | 
 
 
 
 
 | 501 | private RoomBspNode BspNodeDataToBspNode(DatRoomBspNode[] data, int index) | 
 
 
 
 
 | 502 | { | 
 
 
 
 
 | 503 | var nodeData = data[index]; | 
 
 
 
 
 | 504 | RoomBspNode front = null, back = null; | 
 
 
 
 
 | 505 |  | 
 
 
 
 
 | 506 | if (nodeData.BackChildIndex != -1) | 
 
 
 
 
 | 507 | back = BspNodeDataToBspNode(data, nodeData.BackChildIndex); | 
 
 
 
 
 | 508 |  | 
 
 
 
 
 | 509 | if (nodeData.FrontChildIndex != -1) | 
 
 
 
 
 | 510 | front = BspNodeDataToBspNode(data, nodeData.FrontChildIndex); | 
 
 
 
 
 | 511 |  | 
 
 
 
 
 | 512 | return new RoomBspNode(PlaneFromIndex(nodeData.PlaneIndex), back, front); | 
 
 
 
 
 | 513 | } | 
 
 
 
 
 | 514 | } | 
 
 
 
 
 | 515 | } |