示例#1
0
文件: Noise.cs 项目: rivony/synthesis
    public static float[,] GenerateNoiseMap(int mapWidth, int mapHeight, int seed, float scale,
                                            int octavesNumber, float persistance, float lacunarity,
                                            Float2 offset, NormalizedMode normalizeMode)
    {
        float[,] noiseMap = new float[mapWidth, mapHeight];

        float amplitude   = 1;
        float frequency   = 1;
        float noiseHeight = 0;

        float sampleX;
        float sampleY;

        float halfWidth  = mapWidth / 2f;
        float halfHeight = mapHeight / 2f;

        float perlinValue;

        //divide by zero handler
        if (scale <= 0)
        {
            scale = 0.0001f;
        }

        System.Random prng          = new System.Random(seed); //pseudo-random number generator (prng)
        Float2[]      octaveOffsets = new Float2[octavesNumber];

        float maxPossibleHeight = 0;

        for (int i = 0; i < octavesNumber; i++)
        {
            //we don't want to give Mathf.PerlinNoise a coordinate that's too hight,
            //otherwise it's just keep returning the same value over and over again
            //range(-100000, 100000) works pretty well
            float offsetX = prng.Next(-100000, 100000) + offset.x;
            float offsetY = prng.Next(-100000, 100000) - offset.y;             //substraction to inverse the orientation of the generation on the y axis
            octaveOffsets[i] = new Float2(offsetX, offsetY);

            maxPossibleHeight += amplitude;            //we found the max possible height value here (end of the for loop)
            amplitude         *= persistance;
        }

        float maxLocalNoiseHeight = float.MinValue;
        float minLocalNoiseHeight = float.MaxValue;

        for (int y = 0; y < mapHeight; y++)
        {
            for (int x = 0; x < mapWidth; x++)
            {
                amplitude   = 1;
                frequency   = 1;
                noiseHeight = 0;

                for (int i = 0; i < octavesNumber; i++)
                {
                    //take the frequency into account:
                    //the higher the frequency the further the sample points will be
                    //the height value will change more rapidly
                    sampleX = (x - halfWidth + octaveOffsets[i].x) / scale * frequency;
                    sampleY = (y - halfHeight + octaveOffsets[i].y) / scale * frequency;

                    perlinValue = Mathf.PerlinNoise(sampleX, sampleY);     // give value between 0 and 1
                    perlinValue = perlinValue * 2 - 1;                     //to get negative values so that the noiseHeight could decrease
                    //Perlin value of each octaves
                    noiseHeight += perlinValue * amplitude;

                    amplitude *= persistance;                    // 0 < persistance < 1: decreases the octave
                    frequency *= lacunarity;                     // the frequency increases each octave: lacunarity > 1
                }

                //to know the min/max noiseHeight
                if (noiseHeight > maxLocalNoiseHeight)
                {
                    maxLocalNoiseHeight = noiseHeight;
                }
                else if (noiseHeight < minLocalNoiseHeight)
                {
                    minLocalNoiseHeight = noiseHeight;
                }

                //to apply the noiseHeight to the noiseMap
                noiseMap[x, y] = noiseHeight;
            }
        }

        //"normalization" of the noiseMap so that the values get back to range(0,1),
        //need to keep track the lowest and the highest values
                #warning (Rivo) need to optimise this

        if (normalizeMode == NormalizedMode.Local)
        {
            for (int y = 0; y < mapHeight; y++)
            {
                for (int x = 0; x < mapWidth; x++)
                {
                    noiseMap [x, y] = Mathf.InverseLerp(minLocalNoiseHeight, maxLocalNoiseHeight, noiseMap [x, y]);
                    //produces the interpolant value of noiseMap [x, y] within the range(minNoiseHeight, maxNoiseHeight)
                    //if the values is exceding the max it is set to 1
                    //if it is exceding the min it is set to 0
                }
            }
        }
        else
        {
            float normalizedHeight;
            //float divisor;
            for (int y = 0; y < mapHeight; y++)
            {
                for (int x = 0; x < mapWidth; x++)
                {
                    //divisor = 2f;
                    //divisor *= maxPossibleHeight;
                    //as the heightMap will never reach the max possible height, the map will render too flatly
                    //need of estimation: division by 1.5 or 1.75
                    //divisor /= 1.75f;
                    normalizedHeight = (noiseMap [x, y] + 1) / maxPossibleHeight;                     // inverse of the op done (cf perlinValue = perlinValue * 2 - 1; //to get negative values so that the noiseHeight could decrease)

                    noiseMap[x, y] = Mathf.Clamp(normalizedHeight, 0, int.MaxValue);                  //assuming that the height can exceed one
                }
            }
        }
        return(noiseMap);
    }
    public static float[, ] GeneratedNoiseMap(int mapWidth, int mapHeight, float scale, int seed, int octaves, float persistance, float lacunarity, Vector2 offset, NormalizedMode normalizedMode)
    {
        float[, ] noiseMap = new float[mapWidth, mapHeight];

        System.Random prng           = new System.Random(seed);
        Vector2[]     octavesOffsets = new Vector2[octaves];

        float halfWidht  = mapWidth / 2f;
        float halfHeight = mapHeight / 2f;

        float maxPossibleHeight = 0f;
        float amplitude         = 1;
        float frequency         = 1;

        for (int i = 0; i < octaves; i++)
        {
            float offsetX = prng.Next(-100000, 100000) + offset.x;
            float offsetY = prng.Next(-100000, 100000) - offset.y;
            octavesOffsets[i] = new Vector2(offsetX, offsetY);

            maxPossibleHeight += amplitude;
            amplitude         *= persistance;
        }
        if (scale <= 0)
        {
            scale = 0.0001f;
        }

        float maxLocalNoiseHeight = float.MinValue;
        float minNoiseHeight      = float.MaxValue;

        for (int y = 0; y < mapHeight; y++)
        {
            for (int x = 0; x < mapWidth; x++)
            {
                amplitude = 1;
                frequency = 1;
                float noiseHeight = 0;
                for (int i = 0; i < octaves; i++)
                {
                    float sampleX = (x - halfWidht + octavesOffsets[i].x) / scale * frequency;
                    float sampleY = (y - halfHeight + octavesOffsets[i].y) / scale * frequency;

                    float perlinVale = Mathf.PerlinNoise(sampleX, sampleY) * 2 - 1;
                    noiseHeight += perlinVale * amplitude;

                    amplitude *= persistance;
                    frequency *= lacunarity;
                }

                if (maxLocalNoiseHeight < noiseHeight)
                {
                    maxLocalNoiseHeight = noiseHeight;
                    // Debug.Log("Max value changed to: "+maxNoiseHeight);
                }
                else if (minNoiseHeight > noiseHeight)
                {
                    minNoiseHeight = noiseHeight;
                    // Debug.Log("Min value changed to: " + maxNoiseHeight);
                }

                noiseMap[x, y] = noiseHeight;
            }
        }

        for (int y = 0; y < mapHeight; y++)
        {
            for (int x = 0; x < mapWidth; x++)
            {
                if (normalizedMode == NormalizedMode.Local)
                {
                    noiseMap[x, y] = Mathf.InverseLerp(minNoiseHeight, maxLocalNoiseHeight, noiseMap[x, y]);
                }
                else
                {
                    float normalizedHeight = (noiseMap[x, y] + 1) / (2f * maxPossibleHeight / 2f);
                    noiseMap[x, y] = Mathf.Clamp(normalizedHeight, 0, int.MaxValue);
                }
            }
        }
        return(noiseMap);
    }
示例#3
0
        /// <summary>
        /// GenerateNoiseMap by some random math
        /// </summary>
        /// <param name="mapWidth">the map's width by pixels</param>
        /// <param name="mapHeight">the map's height by pixels</param>
        /// <param name="seed"> randmom seed </param>
        /// <param name="scale">the scale of the NoiseMap</param>
        /// <param name="octaves">the stack for the Noise may. we add all stack of the NoiseMap together make more detail for the NoiseMap</param>
        /// <param name="persistance">Change the amplitude for each stack,if the first stack's possible max Height is 1. then the next stack possible height will be persistance, the thrid statck persistance*persistance, the total possible max Height will be 1 +  persistance + persistance * persistance</param>
        /// <param name="lacunarity">Change the frequency for each stack</param>
        /// <param name="offset"></param>
        /// <param name="normalizedMode"></param>
        /// <returns></returns>
        public static float[,] GenerateNoiseMap(int mapWidth, int mapHeight, int seed, float scale, int octaves, float persistance, float lacunarity, Vector2 offset, NormalizedMode normalizedMode)
        {
            float[,] noiseMap = new float[mapWidth, mapHeight];

            if (scale == 0)
            {
                scale = 0.0001f;
            }

            System.Random prng              = new System.Random(seed);
            Vector2[]     octaveOffsets     = new Vector2[octaves]; // because now octaves represent the total of the Vector2, so It should be a passitive int or z
            float         maxPossibleHeight = 0;
            float         amplitude         = 1;                    //up down value
            float         frequency         = 1;                    //

            for (int j = 0; j < octaves; ++j)
            {
                float offsetX = prng.Next(-100000, 100000) + offset.x;
                float offsetY = prng.Next(-100000, 100000) - offset.y;
                octaveOffsets[j]   = new Vector2(offsetX, offsetY);
                maxPossibleHeight += amplitude;
                amplitude         *= persistance;
            }

            float maxLocalNoiseHeight = float.MinValue;
            float minLocalNoiseHeight = float.MaxValue;

            float halfWidth  = mapWidth / 2f;
            float halfHeight = mapHeight / 2f;

            for (int y = 0; y < mapHeight; ++y)
            {
                for (int x = 0; x < mapWidth; ++x)
                {
                    amplitude = 1; //up down value
                    frequency = 1; //
                    float noiseHeight = 0;

                    // x - halfWidth and y - halfHeight means move the origin point to the center of the map when we scale the map
                    // when we scale we move to the origiin to the center, then we zoom in or zoom out.
                    for (int i = 0; i < octaves; ++i)
                    {
                        float sampleX = (x - halfWidth + octaveOffsets[i].x) / scale * frequency * 1.000003f; //just wanna make sure sampleX and sampleY not intger all the time.
                        float sampleY = (y - halfHeight + octaveOffsets[i].y) / scale * frequency * 1.000003f;
                        //the perlinValue is the greyscale values represent values from 0..1
                        float perlinValue = Mathf.PerlinNoise(sampleX, sampleY) * 2 - 1;  // now the value become [-1,1]
                                                                                          //Debug.Log(perlinValue);

                        //octaves 1, main outline. octaves 2,boulders. octaves 3 small rocks.
                        noiseHeight += perlinValue * amplitude; // here those three stack overleped.
                                                                // the first noiseHeight will be perlinValue, the second noisHeight will be (noiseHeight + noiseHeight * persistance)...(noiseHeight + noiseHeight * persistance^2);
                        amplitude *= persistance;               //a1 =p^0; a2 = p^1; a3 = p^2; change the undown amplitude value of each stack
                        frequency *= lacunarity;                //f1 = l^0; f2 = l^1; f3 = l^2; change the frequency for each stack.
                    }

                    // When an set numbers is not increase order, or decrease order.
                    // and we wanta get the min and max....we can use this mothed.
                    //   Max)------------------------->
                    //           noiseHeight
                    //<------------------------(Min
                    if (noiseHeight > maxLocalNoiseHeight)
                    {
                        maxLocalNoiseHeight = noiseHeight;
                    }
                    if (noiseHeight < minLocalNoiseHeight)
                    {
                        minLocalNoiseHeight = noiseHeight;
                    }
                    noiseMap[x, y] = noiseHeight;
                }
            }

            for (int y = 0; y < mapHeight; ++y)
            {
                for (int x = 0; x < mapWidth; ++x)
                {
                    //if noiseMap[x,y] = minNoiseHeight, then return 0; if...... return 1;
                    //before the range of noiseMap[x,y] is [minNoiseHeight,MaxNoiseHeight].
                    //now we covert the range to [0,1] based on the origin noiseMap[x,y]
                    if (normalizedMode == NormalizedMode.Local)
                    {
                        noiseMap[x, y] = Mathf.InverseLerp(minLocalNoiseHeight, maxLocalNoiseHeight, noiseMap[x, y]);
                    }
                    else
                    {
                        float normalizeHeight = (noiseMap[x, y] + 1) / (maxPossibleHeight);
                        noiseMap[x, y] = Mathf.Clamp(normalizeHeight, 0, int.MaxValue);
                    }
                }
            }
            return(noiseMap);
        }