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;
                 * }*/
            }
        }
Ejemplo n.º 2
0
        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;
            }
        }