/**************************************************************************/ 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); }