private void GenerateHeightmap() { if (this.heightmapGenerated) { return; } MainForm.ProgressStart("Processing heightmap ..."); using (MagickImage offsetmap = zoneConfiguration.GetOffsetMap()) { using (MagickImage terrainmap = zoneConfiguration.GetTerrainMap()) { m_heightmap = new MagickImage(Color.Black, offsetmap.Width, offsetmap.Height); using (IPixelCollection heightmapPixels = m_heightmap.GetPixels()) { IPixelCollection terrainPixels = terrainmap.GetPixels(); IPixelCollection offsetPixels = offsetmap.GetPixels(); for (int x = 0; x < offsetmap.Width; x++) { for (int y = 0; y < offsetmap.Height; y++) { ushort terrainPixelValue = (ushort)(terrainPixels[x, y].GetChannel(0) / 256); ushort offsetPixelValue = (ushort)(offsetPixels[x, y].GetChannel(0) / 256); ushort heightmapPixelValue = (ushort)(terrainPixelValue * m_terrainfactor + offsetPixelValue * m_offsetfactor); heightmapPixels.SetPixel(x, y, new ushort[] { heightmapPixelValue, heightmapPixelValue, heightmapPixelValue }); } int percent = 100 * x / offsetmap.Width; MainForm.ProgressUpdate(percent); } //heightmapPixels.Write(); } MainForm.ProgressStartMarquee("Merging ..."); m_heightmap.Quality = 100; m_heightmap.Write(m_heightmapFile.FullName); // Scale to target size m_heightmapScaled = new MagickImage(m_heightmap); m_heightmapScaled.Resize(zoneConfiguration.TargetMapSize, zoneConfiguration.TargetMapSize); } } this.heightmapGenerated = true; MainForm.ProgressReset(); }
public MapWater(ZoneConfiguration zoneConfiguration) { MainForm.ProgressStartMarquee("Loading water configurations ..."); this.zoneConfiguration = zoneConfiguration; bool riversFound = true; int riverIndex = 0; while (riversFound) { string riverIndexString = "river" + ((riverIndex < 10) ? "0" + riverIndex : riverIndex.ToString()); // Check if there is a section string riverCheck = DataWrapper.GetDatFileProperty(zoneConfiguration.SectorDatStreamReader, riverIndexString, "name"); if (string.IsNullOrEmpty(riverCheck)) { riversFound = false; continue; } WaterConfiguration waterConf = new WaterConfiguration(riverCheck); waterConf.Texture = DataWrapper.GetDatFileProperty(zoneConfiguration.SectorDatStreamReader, riverIndexString, "texture"); waterConf.Multitexture = DataWrapper.GetDatFileProperty(zoneConfiguration.SectorDatStreamReader, riverIndexString, "multitexture"); waterConf.Flow = DataWrapper.GetDatFileProperty(zoneConfiguration.SectorDatStreamReader, riverIndexString, "flow"); waterConf.Height = Convert.ToInt32(DataWrapper.GetDatFileProperty(zoneConfiguration.SectorDatStreamReader, riverIndexString, "height")); waterConf.Bankpoints = Convert.ToInt32(DataWrapper.GetDatFileProperty(zoneConfiguration.SectorDatStreamReader, riverIndexString, "bankpoints")); waterConf.Extend_PosX = DataWrapper.GetDatFileProperty(zoneConfiguration.SectorDatStreamReader, riverIndexString, "Extend_PosX"); waterConf.Extend_PosY = DataWrapper.GetDatFileProperty(zoneConfiguration.SectorDatStreamReader, riverIndexString, "Extend_PosY"); waterConf.Extend_NegX = DataWrapper.GetDatFileProperty(zoneConfiguration.SectorDatStreamReader, riverIndexString, "Extend_NegX"); waterConf.Extend_NegY = DataWrapper.GetDatFileProperty(zoneConfiguration.SectorDatStreamReader, riverIndexString, "Extend_NegY"); waterConf.Tesselation = DataWrapper.GetDatFileProperty(zoneConfiguration.SectorDatStreamReader, riverIndexString, "Tesselation"); waterConf.Type = DataWrapper.GetDatFileProperty(zoneConfiguration.SectorDatStreamReader, riverIndexString, "type"); // Adjust some river heights if (zoneConfiguration.ZoneId == "168" || zoneConfiguration.ZoneId == "171" || zoneConfiguration.ZoneId == "178") { waterConf.Height += 30; } // Ignore some definitions if (zoneConfiguration.ZoneId == "163" && riverIndexString == "river14") { riverIndex++; continue; } string color = DataWrapper.GetDatFileProperty(zoneConfiguration.SectorDatStreamReader, riverIndexString, "color"); string baseColor = DataWrapper.GetDatFileProperty(zoneConfiguration.SectorDatStreamReader, riverIndexString, "base_color"); if (color.Length >= 6) { waterConf.Color = ColorTranslator.FromWin32(Convert.ToInt32((string.IsNullOrEmpty(baseColor)) ? color : baseColor)); } for (int i = 0; i < waterConf.Bankpoints; i++) { string coordinatesIndexString = (i < 10) ? "0" + i : i.ToString(); string left = DataWrapper.GetDatFileProperty(zoneConfiguration.SectorDatStreamReader, riverIndexString, "left" + coordinatesIndexString); string right = DataWrapper.GetDatFileProperty(zoneConfiguration.SectorDatStreamReader, riverIndexString, "right" + coordinatesIndexString); if (string.IsNullOrEmpty(left) || string.IsNullOrEmpty(right)) { continue; } string[] leftArr = left.Split(','); string[] rightArr = right.Split(','); PointD leftPoint = new PointD((Convert.ToInt32(leftArr[0]) >= 0) ? Convert.ToInt32(leftArr[0]) : 0, (Convert.ToInt32(leftArr[1]) >= 0) ? Convert.ToInt32(leftArr[1]) : 0); waterConf.LeftCoordinates.Add(leftPoint); PointD rightPoint = new PointD((Convert.ToInt32(rightArr[0]) >= 0) ? Convert.ToInt32(rightArr[0]) : 0, (Convert.ToInt32(rightArr[1]) >= 0) ? Convert.ToInt32(rightArr[1]) : 0); waterConf.RightCoordinates.Add(rightPoint); } this.m_waterAreas.Add(waterConf); riverIndex++; } MainForm.ProgressReset(); }
public void Draw(MagickImage map) { MainForm.ProgressStart("Rendering water ..."); using (IPixelCollection heightmapPixels = zoneConfiguration.Heightmap.HeightmapScaled.GetPixels()) { using (MagickImage water = new MagickImage(MagickColors.Transparent, zoneConfiguration.TargetMapSize, zoneConfiguration.TargetMapSize)) { int progressCounter = 0; foreach (WaterConfiguration river in m_waterAreas) { MainForm.Log(river.Name + "...", MainForm.LogLevel.notice); MagickColor fillColor; if (m_useClientColors) { fillColor = river.Color; } else { fillColor = m_waterColor; } //water.FillColor = fillColor; // Get the river coordinates and scale them to the targets size List <PointD> riverCoordinates = river.GetCoordinates().Select(c => new PointD(c.X * zoneConfiguration.MapScale, c.Y * zoneConfiguration.MapScale)).ToList(); // Texture using (MagickImage texture = new MagickImage((river.Type.ToLower() == "lava") ? GetLavaTexture() : GetWateryTexture())) { using (MagickImage pattern = new MagickImage(fillColor, texture.Width, texture.Height)) { texture.Composite(pattern, 0, 0, CompositeOperator.DstIn); texture.Composite(pattern, 0, 0, CompositeOperator.ColorDodge); water.Settings.FillPattern = texture; DrawablePolygon poly = new DrawablePolygon(riverCoordinates); water.Draw(poly); } } // get the min/max and just process them int minX = Convert.ToInt32(riverCoordinates.Min(m => m.X)) - 10; int maxX = Convert.ToInt32(riverCoordinates.Max(m => m.X)) + 10; int minY = Convert.ToInt32(riverCoordinates.Min(m => m.Y)) - 10; int maxY = Convert.ToInt32(riverCoordinates.Max(m => m.Y)) + 10; using (IPixelCollection riverPixelCollection = water.GetPixels()) { for (int x = minX; x < maxX; x++) { if (x < 0) { continue; } if (x >= zoneConfiguration.TargetMapSize) { continue; } for (int y = minY; y < maxY; y++) { if (y < 0) { continue; } if (y >= zoneConfiguration.TargetMapSize) { continue; } ushort pixelHeight = heightmapPixels.GetPixel(x, y).GetChannel(0); if (pixelHeight > river.Height) { Pixel newPixel = new Pixel(x, y, new ushort[] { 0, 0, 0, ushort.MinValue }); riverPixelCollection.SetPixel(newPixel); } } } } if (debug) { DebugRiver(progressCounter, river, riverCoordinates); } int percent = 100 * progressCounter / m_waterAreas.Count(); MainForm.ProgressUpdate(percent); progressCounter++; } MainForm.ProgressStartMarquee("Merging..."); if (WaterTransparency != 0) { water.Alpha(AlphaOption.Set); double divideValue = 100.0 / (100.0 - WaterTransparency); water.Evaluate(Channels.Alpha, EvaluateOperator.Divide, divideValue); } water.Blur(); map.Composite(water, 0, 0, CompositeOperator.SrcOver); } } MainForm.ProgressReset(); }
public void Draw(MagickImage map) { MainForm.ProgressStart("Drawing lightmap ..."); // Get the heightmap MagickImage heightmap = zoneConfiguration.Heightmap.Heightmap; using (MagickImage lightmap = new MagickImage(Color.Transparent, 256, 256)) { using (IPixelCollection heightmapPixels = heightmap.GetPixels()) { using (IPixelCollection lightmapPixels = lightmap.GetPixels()) { // z-component of surface normals double nz = 512d / zScale; double nz_2 = nz * nz; double nzlz = nz * lightVector[2]; int y1 = 0, y2 = 0; for (int y = 0; y < lightmap.Height; y++) { if (y == 0) { y1 = 0; } else { y1 = y - 1; } if (y == 255) { y2 = 255; } else { y2 = y + 1; } int x1 = 0, x2 = 0; for (int x = 0; x < lightmap.Width; x++) { if (x == 0) { x1 = 0; } else { x1 = x - 1; } if (x == 255) { x2 = 255; } else { x2 = x + 1; } double l = heightmapPixels.GetPixel(x1, y).GetChannel(0); double r = heightmapPixels.GetPixel(x2, y).GetChannel(0); double u = heightmapPixels.GetPixel(x, y1).GetChannel(0); double d = heightmapPixels.GetPixel(x, y2).GetChannel(0); double nx = l - r; double ny = u - d; double m_normal = Math.Sqrt(nx * nx + ny * ny + nz_2); double ndotl = (nx * lightVector[0] + ny * lightVector[1] + nzlz) / m_normal; double pixelValue = lightBase - ndotl * lightScale * 256d; ushort pixelValueDiff = 0; ushort alphaValue = ushort.MaxValue; if (pixelValue < 0) { pixelValueDiff = 0; alphaValue = (ushort)pixelValue; } else { pixelValueDiff = (ushort)pixelValue; } // ColorDodge map // white lightens areas where black does nothing // alpha darkens areas lightmapPixels.SetPixel(x, y, new ushort[] { pixelValueDiff, pixelValueDiff, pixelValueDiff, alphaValue }); } int percent = 100 * y / lightmap.Height; MainForm.ProgressUpdate(percent); } } } MainForm.ProgressStartMarquee("Merging..."); lightmap.Blur(0.0, 0.5); lightmap.VirtualPixelMethod = VirtualPixelMethod.Transparent; lightmap.FilterType = FilterType.Gaussian; lightmap.Resize(zoneConfiguration.TargetMapSize, zoneConfiguration.TargetMapSize); // Apply the bumpmap using ColorDodge map.Composite(lightmap, 0, 0, CompositeOperator.ColorDodge); MainForm.ProgressReset(); } }
public void Start() { if (m_fixtures.Count == 0) { return; } MainForm.ProgressStartMarquee("Sorting fixtures ...."); // Create paths out of the rivers Dictionary <WaterConfiguration, System.Drawing.Drawing2D.GraphicsPath> riverPaths = new Dictionary <WaterConfiguration, System.Drawing.Drawing2D.GraphicsPath>(); foreach (WaterConfiguration rConf in rivers) { System.Drawing.Drawing2D.GraphicsPath riverPath = new System.Drawing.Drawing2D.GraphicsPath(); System.Drawing.PointF[] points = rConf.GetCoordinates().Select(c => new System.Drawing.PointF(Convert.ToSingle(c.X * zoneConfiguration.MapScale), Convert.ToSingle(c.Y * zoneConfiguration.MapScale))).ToArray(); riverPath.AddPolygon(points); riverPaths.Add(rConf, riverPath); } foreach (DrawableFixture model in m_fixtures) { // ignote the model if there are no polygons if (model.ProcessedPolygons.Count() == 0) { continue; } // UI options if (!DrawTrees && (model.IsTree || model.IsTreeCluster)) { continue; } if (!DrawFixtures && !(model.IsTree || model.IsTreeCluster)) { continue; } if (!DrawTreesAsImages && (model.IsTree || model.IsTreeCluster)) { model.RendererConf = FixtureRendererConfigurations.GetRendererById("TreeShaded"); } double modelCenterX = zoneConfiguration.ZoneCoordinateToMapCoordinate(model.FixtureRow.X); double modelCenterY = zoneConfiguration.ZoneCoordinateToMapCoordinate(model.FixtureRow.Y); // Check if on river or not int riverHeight = 0; foreach (KeyValuePair <WaterConfiguration, System.Drawing.Drawing2D.GraphicsPath> river in riverPaths) { if (river.Value.IsVisible(Convert.ToSingle(modelCenterX), Convert.ToSingle(modelCenterY))) { riverHeight = river.Key.Height; break; } } if (riverHeight == 0 || (riverHeight != 0 && model.FixtureRow.Z > riverHeight)) { m_fixturesAboveWater.Add(model); } else { m_fixturesUnderWater.Add(model); } } m_fixturesAboveWater = m_fixturesAboveWater.OrderBy(f => f.CanvasZ).ToList(); m_fixturesUnderWater = m_fixturesUnderWater.OrderBy(f => f.CanvasZ).ToList(); // Dispose all paths riverPaths.Select(d => d.Value).ToList().ForEach(r => r.Dispose()); MainForm.ProgressReset(); }
private void Draw(MagickImage map, List <DrawableFixture> fixtures) { MainForm.ProgressStart(string.Format("Drawing fixtures ({0}) ...", fixtures.Count)); Stopwatch timer = Stopwatch.StartNew(); using (MagickImage modelsOverlay = new MagickImage(MagickColors.Transparent, zoneConfiguration.TargetMapSize, zoneConfiguration.TargetMapSize)) { using (MagickImage treeOverlay = new MagickImage(MagickColors.Transparent, zoneConfiguration.TargetMapSize, zoneConfiguration.TargetMapSize)) { int processCounter = 0; foreach (DrawableFixture fixture in fixtures) { // Debug single models //if (fixture.FixtureRow.NifId != 408) //{ // continue; //} switch (fixture.RendererConf.Renderer) { case FixtureRenderererType.Shaded: DrawShaded((fixture.IsTree || fixture.IsTreeCluster) ? treeOverlay : modelsOverlay, fixture); break; case FixtureRenderererType.Flat: DrawFlat((fixture.IsTree || fixture.IsTreeCluster) ? treeOverlay : modelsOverlay, fixture); break; case FixtureRenderererType.Image: //DrawShaded((fixture.IsTree || fixture.IsTreeCluster) ? treeOverlay : modelsOverlay, fixture); DrawImage((fixture.IsTree || fixture.IsTreeCluster) ? treeOverlay : modelsOverlay, fixture); break; } int percent = 100 * processCounter / fixtures.Count(); MainForm.ProgressUpdate(percent); processCounter++; } MainForm.ProgressStartMarquee("Merging ..."); FixtureRendererConfiguration2 treeImagesRConf = FixtureRendererConfigurations.GetRendererById("TreeImage"); if (treeImagesRConf.HasShadow) { CastShadow( treeOverlay, treeImagesRConf.ShadowOffsetX, treeImagesRConf.ShadowOffsetY, treeImagesRConf.ShadowSize, new Percentage(100 - treeImagesRConf.ShadowTransparency), treeImagesRConf.ShadowColor, false ); } if (treeImagesRConf.Transparency != 0) { treeOverlay.Alpha(AlphaOption.Set); double divideValue = 100.0 / (100.0 - TreeTransparency); treeOverlay.Evaluate(Channels.Alpha, EvaluateOperator.Divide, divideValue); } map.Composite(modelsOverlay, 0, 0, CompositeOperator.SrcOver); map.Composite(treeOverlay, 0, 0, CompositeOperator.SrcOver); } } timer.Stop(); MainForm.Log(string.Format("Finished in {0} seconds.", timer.Elapsed.TotalSeconds), MainForm.LogLevel.success); MainForm.ProgressReset(); }
private void DebugMaps() { MainForm.Log("Drawing debug bound images ...", MainForm.LogLevel.warning); MainForm.ProgressStartMarquee("Debug bound images ..."); DirectoryInfo debugDir = new DirectoryInfo(string.Format("{0}\\debug\\bound\\{1}", System.Windows.Forms.Application.StartupPath, zoneConfiguration.ZoneId)); if (!debugDir.Exists) { debugDir.Create(); } debugDir.GetFiles().ToList().ForEach(f => f.Delete()); int boundIndex = 0; foreach (List <PointF> allCoords in m_bounds) { using (MagickImage bound = new MagickImage(MagickColors.Transparent, zoneConfiguration.TargetMapSize, zoneConfiguration.TargetMapSize)) { List <PointD> coords = allCoords.Select(c => new PointD(zoneConfiguration.ZoneCoordinateToMapCoordinate(c.X), zoneConfiguration.ZoneCoordinateToMapCoordinate(c.Y))).ToList(); DrawablePolygon poly = new DrawablePolygon(coords); bound.Settings.FillColor = new MagickColor(0, 0, 0, 256 * 128); bound.Draw(poly); // Print Text for (int i = 0; i < coords.Count; i++) { double x, y; if (coords[i].X > zoneConfiguration.TargetMapSize / 2) { x = coords[i].X - 15; } else { x = coords[i].X + 1; } if (coords[i].Y < zoneConfiguration.TargetMapSize / 2) { y = coords[i].Y + 15; } else { y = coords[i].Y - 1; } bound.Settings.FontPointsize = 10.0; bound.Settings.FillColor = Color.Black; DrawableText text = new DrawableText(x, y, string.Format("{0} ({1}/{2})", i, zoneConfiguration.MapCoordinateToZoneCoordinate(coords[i].X), zoneConfiguration.MapCoordinateToZoneCoordinate(coords[i].Y))); bound.Draw(text); using (IPixelCollection pixels = bound.GetPixels()) { int x2, y2; if (coords[i].X == zoneConfiguration.TargetMapSize) { x2 = zoneConfiguration.TargetMapSize - 1; } else { x2 = (int)coords[i].X; } if (coords[i].Y == zoneConfiguration.TargetMapSize) { y2 = zoneConfiguration.TargetMapSize - 1; } else { y2 = (int)coords[i].Y; } pixels.SetPixel(x2, y2, new ushort[] { 0, 0, 65535, 0 }); } } //bound.Quality = 100; bound.Write(string.Format("{0}\\bound_{1}.png", debugDir.FullName, boundIndex)); boundIndex++; } } MainForm.ProgressReset(); }
/// <summary> /// Draw the bounds onto map /// </summary> /// <param name="map"></param> public void Draw(MagickImage map) { if (m_bounds.Count == 0) { return; } MainForm.ProgressStart("Drawing zone bounds ..."); // Sort the polygons List <List <PointD> > polygons = new List <List <PointD> >(); List <List <PointD> > negatedPolygons = new List <List <PointD> >(); foreach (List <PointF> polygon in m_bounds) { bool isClockwise = Tools.PolygonHasClockwiseOrder(polygon); var polygonConverted = polygon.Select(c => new PointD(zoneConfiguration.ZoneCoordinateToMapCoordinate(c.X), zoneConfiguration.ZoneCoordinateToMapCoordinate(c.Y))).ToList(); // polygons in clockwise order needs to be negated if (isClockwise) { negatedPolygons.Add(polygonConverted); } else { polygons.Add(polygonConverted); } } MagickColor backgroundColor = MagickColors.Transparent; if (polygons.Count == 0) { // There are no normal polygons, we need to fill the hole zone and substract negatedPolygons backgroundColor = m_boundsColor; } using (MagickImage boundMap = new MagickImage(backgroundColor, zoneConfiguration.TargetMapSize, zoneConfiguration.TargetMapSize)) { int progressCounter = 0; boundMap.Alpha(AlphaOption.Set); boundMap.Settings.FillColor = m_boundsColor; foreach (List <PointD> coords in polygons) { DrawablePolygon poly = new DrawablePolygon(coords); boundMap.Draw(poly); progressCounter++; int percent = 100 * progressCounter / m_bounds.Count(); MainForm.ProgressUpdate(percent); } if (negatedPolygons.Count > 0) { using (MagickImage negatedBoundMap = new MagickImage(Color.Transparent, zoneConfiguration.TargetMapSize, zoneConfiguration.TargetMapSize)) { negatedBoundMap.Settings.FillColor = m_boundsColor; foreach (List <PointD> coords in negatedPolygons) { DrawablePolygon poly = new DrawablePolygon(coords); negatedBoundMap.Draw(poly); progressCounter++; int percent = 100 * progressCounter / m_bounds.Count(); MainForm.ProgressUpdate(percent); } boundMap.Composite(negatedBoundMap, 0, 0, CompositeOperator.DstOut); } } MainForm.ProgressStartMarquee("Merging ..."); if (ExcludeFromMap) { map.Composite(boundMap, 0, 0, CompositeOperator.DstOut); } else { if (m_transparency != 0) { boundMap.Alpha(AlphaOption.Set); double divideValue = 100.0 / (100.0 - m_transparency); boundMap.Evaluate(Channels.Alpha, EvaluateOperator.Divide, divideValue); } map.Composite(boundMap, 0, 0, CompositeOperator.SrcOver); } } if (debug) { DebugMaps(); } MainForm.ProgressReset(); }
public MagickImage Draw() { MainForm.ProgressStart("Rendering background ..."); // Check which terrain file is used string texMpk = string.Format("{0}\\tex{1}.mpk", this.textureZoneDataDirectory, this.textureZoneId); string lodMpk = string.Format("{0}\\lod{1}.mpk", this.textureZoneDataDirectory, this.textureZoneId); // Get the tile dimension double tileWidth = 512.0; string tileTemplate = ""; MPAK mpak = new MPAK(); if (File.Exists(texMpk)) { mpak.Load(texMpk); if (mpak.Files.Where(f => f.Name.ToLower() == "tex00-00.dds").Count() > 0) { tileTemplate += "tex0{0}-0{1}.dds"; tileWidth = 512.0; } } if (string.IsNullOrEmpty(tileTemplate)) { mpak.Load(lodMpk); if (mpak.Files.Where(f => f.Name.ToLower() == "lod00-00.dds").Count() > 0) { tileTemplate += "lod0{0}-0{1}.dds"; tileWidth = 256.0; } } if (string.IsNullOrEmpty(tileTemplate)) { MainForm.Log(string.Format("Zone {0}: No background textures found!", zoneConfiguration.ZoneId), MainForm.LogLevel.error); return(null); } // original size double orginalWidth = tileWidth * 8; double resizeFactor = (double)zoneConfiguration.TargetMapSize / (double)orginalWidth; // 0 - 1 MagickImage map = new MagickImage(Color.Transparent, zoneConfiguration.TargetMapSize, zoneConfiguration.TargetMapSize); int lastWidth = 0; int x = 0; for (int col = 0; col <= 7; col++) { int y = 0; for (int row = 0; row <= 7; row++) { string filename = string.Format(tileTemplate, col, row); using (MagickImage mapTile = new MagickImage(mpak.GetFile(filename).Data)) { int newSize = Convert.ToInt32(mapTile.Width * resizeFactor); mapTile.Resize(newSize, newSize); map.Composite(mapTile, x, y, CompositeOperator.SrcOver); // Calculate new y y += mapTile.Height; lastWidth = mapTile.Height; } } x += lastWidth; int percent = 100 * col / 8; MainForm.ProgressUpdate(percent); } MainForm.ProgressStartMarquee("Merging ..."); // Remove rounding fails map.Trim(); // Flip if set if (this.flipX) { map.Flop(); } if (this.flipY) { map.Flip(); } // Sharpen (tested a lot, seems to be the best values) map.Sharpen(4, 3); MainForm.ProgressReset(); return(map); }