public void AddArea(XPoint2 pos, int size, float coherence, Func <XPoint2, bool> validityCheck) { List <XPoint2> stack = new List <XPoint2>(); stack.Add(pos); int at = 0; int loopAt = stack.Count; Map[pos.X, pos.Y] = new Node() { Weight = 100000 }; List <XPoint2> tmp = new List <XPoint2>(); activeArea = new XRectangle(pos.X, pos.Y, 1, 1); while (size > 0) { float maxV = float.MinValue; for (int i = 0; i < stack.Count; ++i) { var p = stack[i]; var node = Map[p.X, p.Y]; Debug.Assert(node.Weight > 0, "Weight < 0 means the tile is already accepted!"); float weight = node.Weight + (1 + node.Extra); if (weight > maxV) { maxV = weight; at = i; } } var pnt = stack[at]; { --size; stack.RemoveAt(at--); --loopAt; float val = Map[pnt.X, pnt.Y].Weight; Debug.Assert(val > 0, "Tile must have a positive weight to start with!"); Map[pnt.X, pnt.Y].Weight = -1; activeArea = activeArea.ExpandToInclude(pnt); const float NoiseScale = 30; /*if (coherence < 1) { * float noise = (SimplexNoise.simplex_noise_3octaves(pnt.X / NoiseScale, 0, pnt.Y / NoiseScale) / 2 - 0.5f); * val *= 1 + (noise - 0.5f) * (1 - coherence) / 0.5f; * }*/ tmp.Clear(); for (int p = 0; p < propogOffs.Length; ++p) { XPoint2 pnt2 = pnt + propogOffs[p]; if (pnt2.X >= 0 && pnt2.Y >= 0 && pnt2.X < Map.GetLength(0) && pnt2.Y < Map.GetLength(1)) { if (!validityCheck(pnt2)) { continue; } if (Map[pnt2.X, pnt2.Y].Weight < 0) { continue; } tmp.Add(pnt2); } } for (int t = 0; t < tmp.Count; ++t) { var pnt2 = tmp[t]; XPoint2 delta = pnt2 - pnt; float noise = (SimplexNoise.simplex_noise_3octaves(pnt2.X / NoiseScale, (delta.X + delta.Y * 2) * 5, pnt2.Y / NoiseScale) / 2 - 0.5f); float tVal = val - (float)Math.Sqrt(delta.X * delta.X + delta.Y * delta.Y); //tVal *= 1 + (noise - 0.5f) * (1 - coherence) / 0.3f; Map[pnt2.X, pnt2.Y].Weight = Math.Max(Map[pnt2.X, pnt2.Y].Weight, tVal); Map[pnt2.X, pnt2.Y].Extra = Math.Max( Map[pnt2.X, pnt2.Y].Extra, (noise - 0.0f) * (1 - coherence) / 0.5f * 50 ); if (!stack.Contains(pnt2)) { stack.Add(pnt2); } } /*} else { * stack.RemoveAt(at--); * --loopAt;*/ } if (stack.Count == 0) { break; } /*at += 1; * while (at >= loopAt) { * at -= loopAt; * loopAt = stack.Count; * }*/ } }
public void AddArea(XPoint2 pos, int size, XReal coherence, Func <XPoint2, bool> validityCheck) { int origSize = size; List <XPoint2> stack = new List <XPoint2>(); stack.Add(pos); int at = 0; for (int x = 0; x < Map.GetLength(0); ++x) { for (int y = 0; y < Map.GetLength(1); ++y) { Map[x, y].Weight = int.MaxValue; Map[x, y].Extra = 0; } } Debug.Assert(pos.X >= 0 && pos.Y >= 0 && pos.X < Map.GetLength(0) && pos.Y < Map.GetLength(1), "Out of bounds"); Map[pos.X, pos.Y] = new Node() { Weight = 70 }; activeArea = new XRectangle(pos.X, pos.Y, 1, 1); while (size > 0 && stack.Count > 0) { float minV = float.MaxValue; for (int i = 0; i < stack.Count; ++i) { var p = stack[i]; var node = Map[p.X, p.Y]; float weight = Math.Abs(node.Weight) + node.Extra; if (weight < minV) { minV = weight; at = i; } } var pnt = stack[at]; --size; stack.RemoveAt(at--); int val = Map[pnt.X, pnt.Y].Weight; activeArea = activeArea.ExpandToInclude(pnt); const float NoiseScale = 30; for (int p = 0; p < propogOffs.Length; ++p) { XPoint2 pnt2 = pnt + propogOffs[p]; if (pnt2.X >= 0 && pnt2.Y >= 0 && pnt2.X < Map.GetLength(0) && pnt2.Y < Map.GetLength(1)) { if (!validityCheck(pnt2)) { continue; } if (Map[pnt2.X, pnt2.Y].Weight <= val + propogCost[p]) { continue; } int extraW = 0; for (int p2 = 0; p2 < propogOffs.Length; ++p2) { XPoint2 delta = propogOffs[p2]; float noise = (SimplexNoise.simplex_noise_3octaves(pnt2.X / NoiseScale, (delta.X + delta.Y * 2) * 5, pnt2.Y / NoiseScale) / 2 - 0.5f); extraW = Math.Max( extraW, (int)(20 * 70 * (noise - 0.0f) * (1 - coherence) / 0.5f) );//origSize / 46 } if (!stack.Contains(pnt2)) { if (Map[pnt2.X, pnt2.Y].IsPositive) { size++; } stack.Add(pnt2); } Map[pnt2.X, pnt2.Y].Weight = val + propogCost[p] * Math.Sign(val); if (extraW > Map[pnt2.X, pnt2.Y].Extra) { Map[pnt2.X, pnt2.Y].Extra = extraW; } } } } for (int s = 0; s < stack.Count; ++s) { var pnt = stack[s]; Map[pnt.X, pnt.Y].Weight = int.MinValue; } }