/**************************************************************************/ public bool loadVMap(uint mapID, uint tileX, uint tileY, MeshData meshData) { bool result = vmapManager.LoadSingleMap(mapID, "vmaps", tileX, tileY); bool retval = false; do { if (!result) { break; } Dictionary <uint, StaticMapTree> instanceTrees; vmapManager.GetInstanceMapTree(out instanceTrees); if (instanceTrees[mapID] == null) { break; } ModelInstance[] models = null; uint count; instanceTrees[mapID].GetModelInstances(out models, out count); if (models == null) { break; } for (uint i = 0; i < count; ++i) { ModelInstance instance = models[i]; if (instance == null) { continue; } // model instances exist in tree even though there are instances of that model in this tile WorldModel worldModel = instance.GetWorldModel(); if (worldModel == null) { continue; } // now we have a model to add to the meshdata retval = true; List <GroupModel> groupModels; worldModel.getGroupModels(out groupModels); // all M2s need to have triangle indices reversed bool isM2 = (instance.flags & ModelFlags.M2) != 0; // transform data float scale = instance.iScale; Matrix3 rotation = Matrix3.fromEulerAnglesXYZ(MathF.PI * instance.iRot.Z / -180.0f, MathF.PI * instance.iRot.X / -180.0f, MathF.PI * instance.iRot.Y / -180.0f); Vector3 position = instance.iPos; position.X -= 32 * SharedConst.GRID_SIZE; position.Y -= 32 * SharedConst.GRID_SIZE; foreach (var it in groupModels) { List <Vector3> tempVertices; List <Vector3> transformedVertices = new List <Vector3>(); List <MeshTriangle> tempTriangles; WmoLiquid liquid = null; it.GetMeshData(out tempVertices, out tempTriangles, out liquid); // first handle collision mesh transform(tempVertices.ToArray(), transformedVertices, scale, rotation, position); int offset = meshData.solidVerts.Count / 3; copyVertices(transformedVertices.ToArray(), meshData.solidVerts); copyIndices(tempTriangles, meshData.solidTris, offset, isM2); // now handle liquid data if (liquid != null && liquid.iFlags != null) { List <Vector3> liqVerts = new List <Vector3>(); List <uint> liqTris = new List <uint>(); uint tilesX, tilesY, vertsX, vertsY; Vector3 corner; liquid.GetPosInfo(out tilesX, out tilesY, out corner); vertsX = tilesX + 1; vertsY = tilesY + 1; byte[] flags = liquid.iFlags; float[] data = liquid.iHeight; NavArea type = NavArea.Empty; // convert liquid type to NavTerrain var liquidTypeRecord = liquidTypeStorage.LookupByKey(liquid.GetLiquidType()); uint liquidFlags = (uint)(liquidTypeRecord != null ? (1 << liquidTypeRecord.SoundBank) : 0); if ((liquidFlags & (uint)(LiquidTypeMask.Water | LiquidTypeMask.Ocean)) != 0) { type = NavArea.Water; } else if ((liquidFlags & (uint)(LiquidTypeMask.Magma | LiquidTypeMask.Slime)) != 0) { type = NavArea.MagmaSlime; } // indexing is weird... // after a lot of trial and error, this is what works: // vertex = y*vertsX+x // tile = x*tilesY+y // flag = y*tilesY+x Vector3 vert; for (uint x = 0; x < vertsX; ++x) { for (uint y = 0; y < vertsY; ++y) { vert = new Vector3(corner.X + x * SharedConst.GRID_PART_SIZE, corner.Y + y * SharedConst.GRID_PART_SIZE, data[y * vertsX + x]); vert = vert * rotation * scale + position; vert.X *= -1.0f; vert.Y *= -1.0f; liqVerts.Add(vert); } } uint idx1, idx2, idx3, idx4; uint square; for (uint x = 0; x < tilesX; ++x) { for (uint y = 0; y < tilesY; ++y) { if ((flags[x + y * tilesX] & 0x0f) != 0x0f) { square = x * tilesY + y; idx1 = square + x; idx2 = square + 1 + x; idx3 = square + tilesY + 1 + 1 + x; idx4 = square + tilesY + 1 + x; // top triangle liqTris.Add(idx3); liqTris.Add(idx2); liqTris.Add(idx1); // bottom triangle liqTris.Add(idx4); liqTris.Add(idx3); liqTris.Add(idx1); } } } int liqOffset = meshData.liquidVerts.Count / 3; for (int x = 0; x < liqVerts.Count; ++x) { meshData.liquidVerts.Add(liqVerts[x].Y); meshData.liquidVerts.Add(liqVerts[x].Z); meshData.liquidVerts.Add(liqVerts[x].X); } for (int x = 0; x < liqTris.Count / 3; ++x) { meshData.liquidTris.Add((int)(liqTris[x * 3 + 1] + liqOffset)); meshData.liquidTris.Add((int)(liqTris[x * 3 + 2] + liqOffset)); meshData.liquidTris.Add((int)(liqTris[x * 3] + liqOffset)); meshData.liquidType.Add((byte)type); } } } } }while (false); vmapManager.UnloadSingleMap(mapID, tileX, tileY); return(retval); }
public bool Read(BinaryReader reader) { mogpflags = reader.ReadUInt32(); GroupWMOID = reader.ReadUInt32(); Vector3 vec1 = reader.Read <Vector3>(); Vector3 vec2 = reader.Read <Vector3>(); bounds = new AxisAlignedBox(vec1, vec2); liquidflags = reader.ReadUInt32(); string blockId = reader.ReadStringFromChars(4); if (blockId != "GRP ") { Console.WriteLine($"Error: {blockId} != GRP "); return(false); } int blocksize = reader.ReadInt32(); uint branches = reader.ReadUInt32(); for (uint b = 0; b < branches; ++b) { // indexes for each branch (not used yet) uint indexes = reader.ReadUInt32(); } // ---- indexes blockId = reader.ReadStringFromChars(4); if (blockId != "INDX") { Console.WriteLine($"Error: {blockId} != INDX"); return(false); } blocksize = reader.ReadInt32(); uint nindexes = reader.ReadUInt32(); if (nindexes > 0) { ushort[] indexarray = new ushort[nindexes]; for (var i = 0; i < nindexes; ++i) { indexarray[i] = reader.ReadUInt16(); } for (uint i = 0; i < nindexes; i += 3) { triangles.Add(new MeshTriangle(indexarray[i], indexarray[i + 1], indexarray[i + 2])); } } // ---- vectors blockId = reader.ReadStringFromChars(4); if (blockId != "VERT") { Console.WriteLine($"Error: {blockId} != VERT"); return(false); } blocksize = reader.ReadInt32(); uint nvectors = reader.ReadUInt32(); if (nvectors > 0) { float[] vectorarray = new float[nvectors * 3]; for (var i = 0; i < nvectors * 3; ++i) { vectorarray[i] = reader.ReadSingle(); } vertexArray = new List <Vector3>(); for (uint i = 0; i < nvectors; ++i) { vertexArray.Add(new Vector3(vectorarray[3 * i], vectorarray[3 * i + 1], vectorarray[3 * i + 2])); } } // ----- liquid liquid = null; if (Convert.ToBoolean(liquidflags & 3)) { blockId = reader.ReadStringFromChars(4); if (blockId != "LIQU") { Console.WriteLine($"Error: {blockId} != LIQU"); return(false); } blocksize = reader.ReadInt32(); uint liquidType = reader.ReadUInt32(); if (Convert.ToBoolean(liquidflags & 1)) { WMOLiquidHeader hlq = reader.Read <WMOLiquidHeader>(); liquid = new WmoLiquid((uint)hlq.xtiles, (uint)hlq.ytiles, new Vector3(hlq.pos_x, hlq.pos_y, hlq.pos_z), liquidType); int size = hlq.xverts * hlq.yverts; liquid.iHeight = new float[size]; for (var i = 0; i < size; ++i) { liquid.iHeight[i] = reader.ReadSingle(); } size = hlq.xtiles * hlq.ytiles; liquid.iFlags = new byte[size]; for (var i = 0; i < size; ++i) { liquid.iFlags[i] = reader.ReadByte(); } } else { liquid = new WmoLiquid(0, 0, Vector3.Zero, liquidType); liquid.iHeight[0] = bounds.Hi.Z; } } return(true); }