/// <summary> /// Sets the decoration for a specific cell /// </summary> /// <param name="cell">The cell to set for</param> /// <param name="cellMappedData">The cell's mapped data</param> /// <param name="mesh">The decoration mesh</param> private void SetCellDecoration(Cell cell, CellMappedData cellMappedData, string decoration) { if (cellMappedData.Decoration.Key == decoration) { return; } // Free old decoration if (cellMappedData.Decoration.Key != null) { this.decorations[cellMappedData.Decoration.Key].FreeIndex(cellMappedData.Decoration.Value); } // Set new decoration if (decoration != null && decoration.Length > 0) { var index = this.decorations[decoration].GetFreeIndex(); cellMappedData.Decoration = new KeyValuePair <string, int>(decoration, index); this.decorations[decoration].SetPosition(index, new Vector3(TopographyHelper.HexToWorld(cell.Coordinates), (float)cell.Elevation)); } else { cellMappedData.Decoration = new KeyValuePair <string, int>(null, 0); } }
/// <summary> /// Generates terrain meshes, cell and biome data from a scene. Can be put in a task. /// </summary> /// <param name="scene">The scene to generate from</param> /// <returns>Results</returns> private MeshGenerationResult GenerateMeshesFromScene(Scene scene) { // Results var renderableMeshes = new List <RenderableMesh>(); var rawMeshes = new List <Mesh>(); var cellData = new Dictionary <Cell, CellMappedData>(); // Stopwatch used for performance logging Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); // Create world meshes var hexCombiner = new MeshCombiner(); int range = scene.WorldMap.Radius; for (int p = -range; p <= range; p++) { for (int q = -range; q <= range; q++) { var cell = scene.WorldMap.GetCell(p, q); // Due to the hexagonal shape we might be out of bounds if (cell == null) { continue; } var worldPoint = TopographyHelper.HexToWorld(new Point(p, q)); var position = new Vector3(worldPoint, (float)cell.Elevation); var color = GetCellColor(cell); Mesh mesh = biomeMappedData[cell.Biome.Name].HexMesh; // Ensure sea is actually level if (cell.IsWater && cell.Elevation < scene.Settings.SeaLevel) { position.Z = scene.Settings.SeaLevel; } // Add it to the combiner, using the cell's location as a tag so we can later // get the vertexes of this hex inside the larger mesh int meshIndex = hexCombiner.Add(new MeshInstance { mesh = mesh, matrix = Matrix.CreateTranslation(position), tag = new Point(p, q), color = color, useColor = true, }); // Register partial cell mapped data to be used later var cellMappedData = new CellMappedData { MeshIndex = meshIndex }; cellData[cell] = cellMappedData; } } // Combine meshes var meshList = hexCombiner.GetCombinedMeshes(); for (int i = 0; i < meshList.Count; i++) { var renderable = new RenderableMesh(orbis.GraphicsDevice, meshList[i]); renderableMeshes.Add(renderable); } // Finish cell mapped data foreach (var cell in cellData) { var mesh = meshList[cell.Value.MeshIndex]; cell.Value.VertexIndexes = mesh.TagIndexMap[cell.Key.Coordinates]; } stopwatch.Stop(); Debug.WriteLine("Generated " + renderableMeshes.Count + " meshes in " + stopwatch.ElapsedMilliseconds + " ms"); return(new MeshGenerationResult { cellData = cellData, rawMeshes = rawMeshes, renderableMeshes = renderableMeshes }); }