Пример #1
0
        /// <summary>
        /// Calculates the height of the specified midpoint against its Von Neumann neighborhood.
        /// </summary>
        /// <param name="t">Playground.</param>
        /// <param name="M">Midpoint in question.</param>
        /// <param name="SS">Section step.</param>
        /// <returns>Transformed midpoint.</returns>
        private static double GetMidpointHeight(Terrain t, HeightPoint M, int SS)
        {
            //   T
            // L M R
            //   B

            HeightPoint L, R, T, B;
            int         size;

            // No error checking here bacuse it is called from an inner loop.

            size = t.Size.Width;
            L    = M + (HeightPoint.LeftVector * SS / 2);
            R    = M + (HeightPoint.RightVector * SS / 2);
            T    = M + (HeightPoint.TopVector * SS / 2);
            B    = M + (HeightPoint.BottomVector * SS / 2);

            if (L.X < 0)
            {
                L.X = size - 1;
            }
            if (R.X >= size)
            {
                R.X = 0;
            }
            if (T.Y < 0)
            {
                T.Y = size - 1;
            }
            if (B.Y >= size)
            {
                B.Y = 0;
            }

            L.Height = t[L.X, L.Y];
            R.Height = t[R.X, R.Y];
            T.Height = t[T.X, T.Y];
            B.Height = t[B.X, B.Y];

            M = HeightPoint.Midpoint(L, R, T, B);
            return(M.Height);
        }
Пример #2
0
            /// <summary>
            /// Strict, iterative implementation of the Diamond-Square terrain generation algorithm.
            /// Terrain must be a square with edges in the form of 2^I + 1, where I is the number of required iteraions.
            /// </summary>
            /// <param name="t">Terrain to use.</param>
            /// <param name="H">Jag parameter.</param>
            public static void DiamondSquare_Strict(Terrain t, [AttributeDouble("Jag Parameter", 1.0, 0.0, 10.0, 2, 0.1)] double H)
            {
                // A  e  B     e:AB f:AC g:BD h:CD
                // f  M  g     M:AD
                // C  h  D

                VerifyNotNull(t, "t");
                VerifyValidDouble(H, "H");
                if (t.Size.Width != t.Size.Height)
                {
                    throw new ArgumentException("Terrain height and width must be equal.", "t");
                }
                if (Math.Log(t.Size.Width - 1, 2) != (int)Math.Log(t.Size.Width - 1, 2))
                {
                    throw new ArgumentException("Terrain size must be in the form of 2^I + 1.", "t");
                }

                HeightPoint A, B, C, D;
                HeightPoint M, e, f, g, h;
                int         size;
                int         SP, I, SC, SS, Sx, Sy;
                double      R, r;
                Random      rg;

                // Get terrain size, initialize RNG and randomize the four terrain corners.
                size                  = t.Size.Width;
                rg                    = new Random();
                r                     = 0; // GetRandom(rg, 1);
                t[0, 0]               = r;
                t[size - 1, 0]        = r;
                t[0, size - 1]        = r;
                t[size - 1, size - 1] = r;

                #region REPORT INIT
                if (t.PBW != null)
                {
                    t.PBW.Report("Diamond Square (Strict)", (int)((2.0 / 3.0) * (double)(size * size - 2 * size)));
                    if (t.PBW.CancellationPending)
                    {
                        return;
                    }
                }
                #endregion
                SP = (int)Math.Log(size - 1, 2);
                for (I = 0; I < SP; I++)
                {
                    SS = (int)Math.Pow(2, SP - I);
                    SC = (int)Math.Pow(2, I);
                    R  = Math.Pow(2, (-H * I));

                    // Diamond step
                    for (Sx = 0; Sx < SC; Sx++)
                    {
                        for (Sy = 0; Sy < SC; Sy++)
                        {
                            #region REPORT
                            if (t.PBW != null)
                            {
                                t.PBW.Report();
                                if (t.PBW.CancellationPending)
                                {
                                    return;
                                }
                            }
                            #endregion
                            // Find the four corners and thier heights.
                            A        = new HeightPoint(SS * Sx, SS * Sy);
                            B        = new HeightPoint(SS * (Sx + 1), SS * Sy);
                            C        = new HeightPoint(SS * Sx, SS * (Sy + 1));
                            D        = new HeightPoint(SS * (Sx + 1), SS * (Sy + 1));
                            A.Height = t[A.X, A.Y];
                            B.Height = t[B.X, B.Y];
                            C.Height = t[C.X, C.Y];
                            D.Height = t[D.X, D.Y];

                            // Find the center and calculate its height.
                            M        = A % D;
                            r        = GetRandom(rg, R);
                            M.Height = (A.Height + B.Height + C.Height + D.Height) / 4 + r;

                            // Store the results.
                            t[M.X, M.Y] = M.Height;
                        }
                    }

                    // Square step
                    for (Sx = 0; Sx < SC; Sx++)
                    {
                        for (Sy = 0; Sy < SC; Sy++)
                        {
                            #region REPORT
                            if (t.PBW != null)
                            {
                                t.PBW.Report();
                                if (t.PBW.CancellationPending)
                                {
                                    return;
                                }
                            }
                            #endregion
                            // Find the four corners and their heights.
                            A = new HeightPoint(SS * Sx, SS * Sy);
                            B = new HeightPoint(SS * (Sx + 1), SS * Sy);
                            C = new HeightPoint(SS * Sx, SS * (Sy + 1));
                            D = new HeightPoint(SS * (Sx + 1), SS * (Sy + 1));

                            // For each midpoint, find its coordinates, calculate height and store the result.
                            e           = A % B;
                            e.Height    = GetMidpointHeight(t, e, SS);
                            t[e.X, e.Y] = e.Height;

                            f           = A % C;
                            f.Height    = GetMidpointHeight(t, f, SS);
                            t[f.X, f.Y] = f.Height;

                            if (Sx == (SC - 1))
                            {
                                g           = B % D;
                                g.Height    = GetMidpointHeight(t, g, SS);
                                t[g.X, g.Y] = g.Height;
                            }

                            if (Sy == (SC - 1))
                            {
                                h           = C % D;
                                h.Height    = GetMidpointHeight(t, h, SS);
                                t[h.X, h.Y] = h.Height;
                            }
                        }
                    }
                }
                t.Normalize();
            }