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