private static int GetTr4TextureIdFromPolygon(wad_polygon polygon) { short textureId = (short)(polygon.Texture); if (polygon.Shape == 8) { textureId = (short)(polygon.Texture & 0xFFF); if ((polygon.Texture & 0x8000) != 0) { textureId = (short)(-textureId); } } else { // HACK: for taking in account sign if (textureId > 0x7FFF) { textureId = (short)(textureId - 0xFFFF); } } textureId = Math.Abs(textureId); return(textureId); }
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 TextureArea CalculateTr4UVCoordinates(Wad2 wad, Tr4Wad oldWad, wad_polygon poly, Dictionary <int, WadTexture> textures) { TextureArea textureArea = new TextureArea(); textureArea.BlendMode = (poly.Attributes & 0x01) != 0 ? BlendMode.Additive : BlendMode.Normal; textureArea.DoubleSided = false; int textureId = GetTr4TextureIdFromPolygon(poly); textureArea.Texture = textures[textureId]; // Add the UV coordinates int shape = (poly.Texture & 0x7000) >> 12; int flipped = (poly.Texture & 0x8000) >> 15; wad_object_texture texture = oldWad.Textures[textureId]; Vector2 nw = new Vector2(0, 0); Vector2 ne = new Vector2(texture.Width + 1.0f, 0); Vector2 se = new Vector2(texture.Width + 1.0f, texture.Height + 1.0f); Vector2 sw = new Vector2(0, texture.Height + 1.0f); if (poly.Shape == 9) { if (flipped == 1) { textureArea.TexCoord0 = ne; textureArea.TexCoord1 = nw; textureArea.TexCoord2 = sw; textureArea.TexCoord3 = se; } else { textureArea.TexCoord0 = nw; textureArea.TexCoord1 = ne; textureArea.TexCoord2 = se; textureArea.TexCoord3 = sw; } } else { switch (shape) { case 0: if (flipped == 1) { textureArea.TexCoord0 = ne; textureArea.TexCoord1 = nw; textureArea.TexCoord2 = se; textureArea.TexCoord3 = textureArea.TexCoord2; } else { textureArea.TexCoord0 = nw; textureArea.TexCoord1 = ne; textureArea.TexCoord2 = sw; textureArea.TexCoord3 = textureArea.TexCoord2; } break; case 2: if (flipped == 1) { textureArea.TexCoord0 = nw; textureArea.TexCoord1 = sw; textureArea.TexCoord2 = ne; textureArea.TexCoord3 = textureArea.TexCoord2; } else { textureArea.TexCoord0 = ne; textureArea.TexCoord1 = se; textureArea.TexCoord2 = nw; textureArea.TexCoord3 = textureArea.TexCoord2; } break; case 4: if (flipped == 1) { textureArea.TexCoord0 = sw; textureArea.TexCoord1 = se; textureArea.TexCoord2 = nw; textureArea.TexCoord3 = textureArea.TexCoord2; } else { textureArea.TexCoord0 = se; textureArea.TexCoord1 = sw; textureArea.TexCoord2 = ne; textureArea.TexCoord3 = textureArea.TexCoord2; } break; case 6: if (flipped == 1) { textureArea.TexCoord0 = se; textureArea.TexCoord1 = ne; textureArea.TexCoord2 = sw; textureArea.TexCoord3 = textureArea.TexCoord2; } else { textureArea.TexCoord0 = sw; textureArea.TexCoord1 = nw; textureArea.TexCoord2 = se; textureArea.TexCoord3 = textureArea.TexCoord2; } break; default: throw new NotImplementedException("Unknown texture shape " + shape + " found in the wad."); } } return(textureArea); }