public void LoadWad(string fileName) { BaseName = Path.GetFileNameWithoutExtension(fileName); BasePath = Path.GetDirectoryName(fileName); FileName = fileName; logger.Info("Reading wad file: " + fileName); // Initialize stream using (BinaryReaderEx reader = new BinaryReaderEx(new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))) { // Read wad version Version = reader.ReadInt32(); if (Version != 129 && Version != 130) { logger.Error("Wad version " + Version + " is not supported!"); throw new InvalidDataException(); } // Read textures uint numTextures = reader.ReadUInt32(); logger.Info("Wad object textures: " + numTextures); for (int i = 0; i < numTextures; i++) { wad_object_texture text; reader.ReadBlock(out text); Textures.Add(text); } uint numTextureBytes = reader.ReadUInt32(); logger.Info("Wad texture data size: " + numTextureBytes); TexturePages = reader.ReadBytes((int)numTextureBytes); NumTexturePages = (int)(numTextureBytes / 196608); // Read meshes uint numMeshPointers = reader.ReadUInt32(); logger.Info("Wad mesh pointers: " + numMeshPointers); for (int i = 0; i < numMeshPointers; i++) { Pointers.Add(reader.ReadUInt32()); RealPointers.Add(0); } uint numMeshWords = reader.ReadUInt32(); uint bytesToRead = numMeshWords * 2; uint bytesRead = 0; logger.Info("Wad mesh data size: " + bytesToRead); while (bytesRead < bytesToRead) { var startOfMesh = (uint)reader.BaseStream.Position; wad_mesh mesh = new wad_mesh(); mesh.Polygons = new List <wad_polygon>(); mesh.Vertices = new List <wad_vertex>(); mesh.Normals = new List <wad_vertex>(); mesh.Shades = new List <short>(); mesh.SphereX = reader.ReadInt16(); mesh.SphereY = reader.ReadInt16(); mesh.SphereZ = reader.ReadInt16(); mesh.Radius = reader.ReadUInt16(); mesh.Unknown = reader.ReadUInt16(); var numVertices = reader.ReadUInt16(); mesh.NumVertices = numVertices; var xMin = Int32.MaxValue; var yMin = Int32.MaxValue; var zMin = Int32.MaxValue; var xMax = Int32.MinValue; var yMax = Int32.MinValue; var zMax = Int32.MinValue; for (var i = 0; i < numVertices; i++) { var v = new wad_vertex(); v.X = reader.ReadInt16(); v.Y = reader.ReadInt16(); v.Z = reader.ReadInt16(); if (v.X < xMin) { xMin = v.X; } if (-v.Y < yMin) { yMin = -v.Y; } if (v.Z < zMin) { zMin = v.Z; } if (v.X > xMax) { xMax = v.X; } if (-v.Y > yMax) { yMax = -v.Y; } if (v.Z > zMax) { zMax = v.Z; } mesh.Vertices.Add(v); } mesh.Minimum = new Vector3(xMin, yMin, zMin); mesh.Maximum = new Vector3(xMax, yMax, zMax); short numNormals = reader.ReadInt16(); mesh.NumNormals = numNormals; if (numNormals > 0) { for (var i = 0; i < numNormals; i++) { var n = new wad_vertex(); n.X = reader.ReadInt16(); n.Y = reader.ReadInt16(); n.Z = reader.ReadInt16(); mesh.Normals.Add(n); } } else { for (var i = 0; i < -numNormals; i++) { mesh.Shades.Add(reader.ReadInt16()); } } ushort numPolygons = reader.ReadUInt16(); mesh.NumPolygons = numPolygons; ushort numQuads = 0; for (var i = 0; i < numPolygons; i++) { var poly = new wad_polygon(); poly.Shape = reader.ReadUInt16(); poly.V1 = reader.ReadUInt16(); poly.V2 = reader.ReadUInt16(); poly.V3 = reader.ReadUInt16(); if (poly.Shape == 9) { poly.V4 = reader.ReadUInt16(); } poly.Texture = reader.ReadUInt16(); poly.Attributes = reader.ReadByte(); poly.Unknown = reader.ReadByte(); if (poly.Shape == 9) { numQuads++; } mesh.Polygons.Add(poly); } if (numQuads % 2 != 0) { reader.ReadInt16(); } var endPosition = (uint)reader.BaseStream.Position; bytesRead += endPosition - startOfMesh; Meshes.Add(mesh); // Update the real pointers for (int k = 0; k < Pointers.Count; k++) { if (Pointers[k] == bytesRead) { RealPointers[k] = (uint)Meshes.Count; } } } var numAnimations = reader.ReadUInt32(); logger.Info("Wad animations: " + numAnimations); for (var i = 0; i < numAnimations; i++) { var anim = new wad_animation(); anim.KeyFrameOffset = reader.ReadUInt32(); anim.FrameDuration = reader.ReadByte(); anim.KeyFrameSize = reader.ReadByte(); anim.StateId = reader.ReadUInt16(); anim.Speed = reader.ReadInt32(); anim.Accel = reader.ReadInt32(); anim.SpeedLateral = reader.ReadInt32(); anim.AccelLateral = reader.ReadInt32(); anim.FrameStart = reader.ReadUInt16(); anim.FrameEnd = reader.ReadUInt16(); anim.NextAnimation = reader.ReadUInt16(); anim.NextFrame = reader.ReadUInt16(); anim.NumStateChanges = reader.ReadUInt16(); anim.ChangesIndex = reader.ReadUInt16(); anim.NumCommands = reader.ReadUInt16(); anim.CommandOffset = reader.ReadUInt16(); Animations.Add(anim); } var numChanges = reader.ReadUInt32(); logger.Info("Wad animation state changes: " + numChanges); for (var i = 0; i < numChanges; i++) { var change = new wad_state_change(); change.StateId = reader.ReadUInt16(); change.NumDispatches = reader.ReadUInt16(); change.DispatchesIndex = reader.ReadUInt16(); Changes.Add(change); } var numDispatches = reader.ReadUInt32(); logger.Info("Wad animation dispatches: " + numDispatches); for (var i = 0; i < numDispatches; i++) { var anim = new wad_anim_dispatch(); anim.Low = reader.ReadInt16(); anim.High = reader.ReadInt16(); anim.NextAnimation = reader.ReadInt16(); anim.NextFrame = reader.ReadInt16(); Dispatches.Add(anim); } var numCommands = reader.ReadUInt32(); logger.Info("Wad animation commands: " + numCommands); for (var i = 0; i < numCommands; i++) { Commands.Add(reader.ReadInt16()); } var numLinks = reader.ReadUInt32(); logger.Info("Wad animation links: " + numLinks); for (var i = 0; i < numLinks; i++) { Links.Add(reader.ReadInt32()); } var numFrames = reader.ReadUInt32(); logger.Info("Wad animation frames: " + numFrames); for (int i = 0; i < numFrames; i++) { KeyFrames.Add(reader.ReadInt16()); } var numMoveables = reader.ReadUInt32(); logger.Info("Wad objects (moveables): " + numMoveables); for (var i = 0; i < numMoveables; i++) { var moveable = new wad_moveable(); moveable.ObjectID = reader.ReadUInt32(); moveable.NumPointers = reader.ReadUInt16(); moveable.PointerIndex = reader.ReadUInt16(); moveable.LinksIndex = reader.ReadUInt32(); moveable.KeyFrameOffset = reader.ReadUInt32(); moveable.AnimationIndex = reader.ReadInt16(); Moveables.Add(moveable); } var numStaticMeshes = reader.ReadUInt32(); logger.Info("Wad static meshes: " + numStaticMeshes); for (var i = 0; i < numStaticMeshes; i++) { var staticMesh = new wad_static_mesh(); staticMesh.ObjectId = reader.ReadUInt32(); staticMesh.PointersIndex = reader.ReadUInt16(); staticMesh.VisibilityX1 = reader.ReadInt16(); staticMesh.VisibilityX2 = reader.ReadInt16(); staticMesh.VisibilityY1 = reader.ReadInt16(); staticMesh.VisibilityY2 = reader.ReadInt16(); staticMesh.VisibilityZ1 = reader.ReadInt16(); staticMesh.VisibilityZ2 = reader.ReadInt16(); staticMesh.CollisionX1 = reader.ReadInt16(); staticMesh.CollisionX2 = reader.ReadInt16(); staticMesh.CollisionY1 = reader.ReadInt16(); staticMesh.CollisionY2 = reader.ReadInt16(); staticMesh.CollisionZ1 = reader.ReadInt16(); staticMesh.CollisionZ2 = reader.ReadInt16(); staticMesh.Flags = reader.ReadUInt16(); Statics.Add(staticMesh); } reader.Close(); logger.Info("Wad loaded successfully."); } // Read sprites logger.Info("Reading sprites (swd file) associated with wad."); using (var readerSprites = new BinaryReaderEx(new FileStream(BasePath + Path.DirectorySeparatorChar + BaseName + ".swd", FileMode.Open, FileAccess.Read, FileShare.Read))) { // Version readerSprites.ReadUInt32(); var numSpritesTextures = readerSprites.ReadUInt32(); logger.Info("Sprites: " + numSpritesTextures); //Sprite texture array for (var i = 0; i < numSpritesTextures; i++) { var buffer = readerSprites.ReadBytes(16); var spriteTexture = new wad_sprite_texture { Tile = buffer[2], X = buffer[0], Y = buffer[1], Width = buffer[5], Height = buffer[7], LeftSide = buffer[0], TopSide = buffer[1], RightSide = (short)(buffer[0] + buffer[5] + 1), BottomSide = (short)(buffer[1] + buffer[7] + 1) }; SpriteTextures.Add(spriteTexture); } // Sprites size var spriteDataSize = readerSprites.ReadInt32(); SpriteData = readerSprites.ReadBytes(spriteDataSize); var numSequences = readerSprites.ReadUInt32(); logger.Info("Sprite sequences: " + numSequences); // Sprite sequences for (var i = 0; i < numSequences; i++) { var sequence = new wad_sprite_sequence(); sequence.ObjectID = readerSprites.ReadInt32(); sequence.NegativeLength = readerSprites.ReadInt16(); sequence.Offset = readerSprites.ReadInt16(); SpriteSequences.Add(sequence); } } // Read WAS using (var reader = new StreamReader(File.OpenRead(BasePath + Path.DirectorySeparatorChar + BaseName + ".was"))) { while (!reader.EndOfStream) { LegacyNames.Add(reader.ReadLine().Split(':')[0].Replace(" ", "").Replace("EXTRA0", "EXTRA")); } } }
private static WadMesh ConvertTr4MeshToWadMesh(Wad2 wad, Tr4Wad oldWad, Dictionary <int, WadTexture> textures, wad_mesh oldMesh, int objectID) { WadMesh mesh = new WadMesh(); var meshIndex = oldWad.Meshes.IndexOf(oldMesh); mesh.Name = "Mesh-" + objectID + "-" + meshIndex; // Create the bounding sphere mesh.BoundingSphere = new BoundingSphere(new Vector3(oldMesh.SphereX, -oldMesh.SphereY, oldMesh.SphereZ), oldMesh.Radius); // Add positions foreach (var oldVertex in oldMesh.Vertices) { mesh.VerticesPositions.Add(new Vector3(oldVertex.X, -oldVertex.Y, oldVertex.Z)); } // Add normals foreach (var oldNormal in oldMesh.Normals) { mesh.VerticesNormals.Add(new Vector3(oldNormal.X, -oldNormal.Y, oldNormal.Z)); } // Add shades foreach (var oldShade in oldMesh.Shades) { mesh.VerticesShades.Add(oldShade); } // Add polygons foreach (var oldPoly in oldMesh.Polygons) { WadPolygon poly = new WadPolygon(); poly.Shape = oldPoly.Shape == 8 ? WadPolygonShape.Triangle : WadPolygonShape.Quad; // Polygon indices poly.Index0 = oldPoly.V1; poly.Index1 = oldPoly.V2; poly.Index2 = oldPoly.V3; if (poly.Shape == WadPolygonShape.Quad) { poly.Index3 = oldPoly.V4; } // Polygon special effects poly.ShineStrength = (byte)((oldPoly.Attributes & 0x7c) >> 2); // Add the texture poly.Texture = CalculateTr4UVCoordinates(wad, oldWad, oldPoly, textures); mesh.Polys.Add(poly); } mesh.BoundingBox = new BoundingBox(oldMesh.Minimum, oldMesh.Maximum); // Usually only for static meshes if (mesh.VerticesNormals.Count == 0) { mesh.CalculateNormals(); } return(mesh); }