I'm bumping this thread because after a 3-week "research" about WoW geometry and navmesh-related stuff, this tool is the only one I found that works just fine with 5.4.7 (build 17956). Despite the gitHub version being quite old, you can still parse and view the tiles of the game. I just want to point out the issues that I ran into and the fixes:
1 - I checked-out the latest github version and it wasn't even running. Then I noticed that CrystalMPQ has a method to automatically find the WoW installation, which wasn't working for me. So I checked-out the latest modified CrystalMPQ version (https://github.com/Bananenbrot/crystalmpq) and modified the file WoWInstallation.cs to make it return the path of my WoW installation.
2 - After compiling, I grabbed the DLLs and put them in trunk\Dependencies of BananaMPQ. I then ran the project and it finally loaded everything just fine.
3 - I read this thread (http://www.ownedcore.com/forums/worl...ng-issues.html ([NavMesh][MPQ] Geometry parsing issues)) where Bananenbrot reported 2 issues. The first one was just a mistake, nothing to worry about. The second one required some corrections in the code, which were posted by Bananenbrot in the thread, but it took me a while to make everything compile just fine. So I'm posting here the new MapChunk.cs file that corrects the issues with "holes":
Code:
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System;
using BananaMpq.Layer.Chunks;
using BananaMpq.Visualization;
using SharpDX;
namespace BananaMpq.Layer.AdtRelated
{
public class MapChunk : Chunk, IChunkCollector
{
public const float ChunkWidth = Adt.AdtWidth / 16.0f;
public const int TilesPerChunk = 8;
public const float TileSize = ChunkWidth / TilesPerChunk;
public float[,] HeightMap { get; private set; }
public uint Flags { get; private set; }
public byte[] Holes { get; private set; }
public int X { get; private set; }
public int Y { get; private set; }
private BoundingBox _bounds;
public BoundingBox Bounds
{
get { return _bounds; }
}
public ChunkLiquid Liquid { get; set; }
public int[] WmoReferences { get; private set; }
public int[] DoodadReferences { get; private set; }
internal unsafe MapChunk(ChunkHeader* header)
: base(header)
{
header->ValidateMagic("MCNK");
var cur = (byte*)header + sizeof(ChunkHeader);
ParseMcnkHeader(cur);
Chunks = ChunkCollector.CreateChunks(cur + sizeof(McnkHeader), cur + header->Size, CreateChunks);
}
public bool HasHole(int col, int row)
{
return ((Holes[row] >> col) & 1) == 1;
}
private static byte[] TransformToHighRes(ushort holes)
{
var ret = new byte[8];
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
int holeIdxL = (i / 2) * 4 + (j / 2);
if (((holes >> holeIdxL) & 1) == 1)
ret[i] |= (byte)(1 << j);
}
}
return ret;
}
private unsafe void ParseMcnkHeader(byte* cur)
{
//var mcnk = (McnkHeader*)cur;
McnkHeader* mcnk = (McnkHeader*)cur;
_bounds = new BoundingBox(
mcnk->Position + new Vector3(-ChunkWidth, -ChunkWidth, 0.0f),
mcnk->Position
);
//Holes = mcnk->Holes;
Flags = (uint)mcnk->Flags;
Holes = mcnk->Flags.HasFlag(McnkHeaderFlags.HighResHoleMap) ? mcnk->HighResHoles : TransformToHighRes(mcnk->Holes);
X = mcnk->X;
Y = mcnk->Y;
}
private unsafe Chunk CreateChunks(ChunkHeader* header)
{
switch (header->Magic)
{
case "MCVT":
var mcvt = new McvtChunk(header);
HeightMap = mcvt.HeightMap;
_bounds.Maximum.Z += HeightMap.Cast<float>().Max();
return mcvt;
case "MCRD":
var mcrd = new OffsetChunk(header);
DoodadReferences = mcrd.Offsets;
return mcrd;
case "MCRW":
var mcrw = new OffsetChunk(header);
WmoReferences = mcrw.Offsets;
return mcrw;
default:
return new Chunk(header);
}
}
internal unsafe void ParseOptionalData(ChunkHeader* header)
{
header->ValidateMagic("MCNK");
var cur = (byte*)header + sizeof(ChunkHeader);
Chunks = Chunks.Concat(ChunkCollector.CreateChunks(cur, cur + header->Size, CreateChunks));
}
#region Implementation of IChunkCollector
public IEnumerable<Chunk> Chunks { get; private set; }
#endregion
#pragma warning disable 169, 649
[Flags]
public enum McnkHeaderFlags : uint
{
HighResHoleMap = 0x10000
}
public struct McnkHeader
{
public McnkHeaderFlags Flags;
public int X;
public int Y;
int nLayers;
int nDoodadRefs;
uint offMcvt; // 0x14
uint offMcnr; // 0x18
int offMcly;
int offMcrf;
int offMcal;
int sizeAlpha;
int offMcsh;
int sizeShadow;
int areaId;
int nMapObjRefs;
public ushort Holes;
ushort HolesAlign;
unsafe fixed short lowQualityTexturingMap[8];
int predTex;
int noEffectDoodad;
int offMcse;
int nSoundEmitters;
int offMclq;
int sizeLiquid;
public Vector3 Position;
int offMccv;
unsafe fixed int pad[2];
public byte[] HighResHoles { get { return BitConverter.GetBytes(offMcvt + ((ulong)offMcnr << 32)); } } // 0x14
}
#pragma warning restore 169, 649
public override IEnumerable<PropertyInfo> VisualizableProperties
{
get
{
var type = typeof(MapChunk);
return base.VisualizableProperties.Concat(new[]
{
type.GetProperty("Bounds"),
type.GetProperty("X"),
type.GetProperty("Y"),
type.GetProperty("Flags"),
type.GetProperty("Holes"),
type.GetProperty("HeightMap"),
type.GetProperty("DoodadReferences"),
type.GetProperty("WmoReferences"),
});
}
}
}
}
4 - After doing this, I recompiled all the projects, including the Dumper. And yeah, the issue was perfectly fixed:
5 - To open MOP tiles, add this to the function MapToFolder(WowContinent continent) in MpqFilePath.cs:
Code:
case WowContinent.Pandaria:
return "HawaiiMainLand";
Bananen probably has an updated version of his parser/viewer, but I don't know if he plans to commit it to his Github or not. It seems that this tool currently ignores _obj1.adt's and I honestly have no idea if it will end up missing certain WMO's or Doodads.
Other than that, I just want to thank the developer for his amazing work and for leaving the source opened. I read WoWDev, checked-out wowmapper's (outdated and doesn't seem to support MOP) and meshReader's code, but I was still struggling with all these crazy chunks. Now, with this working version, I guess I can try once again to understand how all the information is parsed. Thanks
PS: C++ boy here... maybe that's why it took me so long to get everything working >.<