-1

I am trying to generate a noise texture with the LibNoise library using perlin and some fractal to create 6 layers that i can add together in one image.

I have problems that i can't seem to fix: (3 problems that show in the debug log.)

1) The image it generates is just white. and with reason, a number of 23170.49 was printed :/

2) All the other prints are NaN, which should not happen... (over 65535 of that in the log)

3) I have an error:

IndexOutOfRangeException: Array index is out of range. HeightController.getTerrainData (Vector2 position) (at Assets/Scripts/TerrainGenerator/HeightController.cs:28) TerrainMesh.Start () (at Assets/Scripts/TerrainGenerator/TerrainMesh.cs:21)

But that error should not even occur, as it is in the bounds, so can't see why it tells me that...

Here are the codes i use,

1) HeightController

using UnityEngine;
using System.Collections;

public class HeightController : MonoBehaviour
{
    public static int layers = 6;
    public static float[] layersOpacity = {0.5f, 0.3f, 0.2f, 0.15f, 0.1f, 0.05f};

    private static int layerSize = 256;
    //private static int terrainSize = 2048;    //build heightmap here?

    private static int amplitude = 128; //divided by 2
    private static int frequency = 4;       //multiplied by 2       = obtaining a smaller height, but faster frequence.

    //when you want to generate a terrain, just get the
    //data array containing the stuffs to build a heightmap out of it.
    //this here does the calculation of layers with opacity etc.
    public static float[,] getTerrainData(Vector2 position) //the vector2 takes the SQUARES offset of terrains, 0,1 | 22,13 (the terraid ID)
    {
        float[,] finalLayersData = new float[layerSize,layerSize];
        for (int i = 0; i < layers; ++i)                //the entire array will be set an opacity then adds to the final.
        {
            float[,] currentLayerData = Calculate(position);    //there should be a less laggy way here?

            //multiplies each data with it's respective opacity.
            for (int a = 0; a < layerSize; ++a)
                for (int b = 0; b < layerSize; ++a)
                    currentLayerData[a,b] *= layersOpacity[i];

            //adds to the final data array
            for (int a = 0; a < layerSize; ++a)
                for (int b = 0; b < layerSize; ++a)
                    finalLayersData[a,b] += currentLayerData[a,b];
        }
        return finalLayersData;
    }

    private static float[,] Calculate(Vector2 position)
    {
        float[,] data = new float[layerSize,layerSize];
        int offsetX = (int)position.x*layerSize;
        int offsetY = (int)position.y*layerSize;

        Perlin perlin = new Perlin();

        //the 1/4 then 1/16 then 1/32 etc.
        FractalNoise fractal = new FractalNoise((1f/4f), frequency, amplitude, perlin);
        for (var y = 0; y < layerSize; y++)
        {
            for (var x = 0; x < layerSize; x++)
            {
                float result = fractal.HybridMultifractal(x + offsetX, y + offsetY, layerSize);
                data[x, y] = result;
                print(result);
            }
        }
        return data;
    }
}

2) TerrainMesh

using UnityEngine;
using System.Collections;

public class TerrainMesh : MonoBehaviour
{
    public static Transform[] TextureList = new Transform[64];
    //public static long seed = 34;
    public int Size = 256;

    public Mesh mesh;
    public MeshFilter meshFilter;
    public MeshCollider meshCollider;
    public Material material;
    public float[,] data;

    public Texture2D fun;

    public void Start()
    {
        fun = new Texture2D(256, 256);
        data = HeightController.getTerrainData(new Vector2(0, 0));

        for (int x = 0; x < Size; ++x)
            for (int y = 0; y < Size; ++y)
                fun.SetPixel(x, y, new Color(data[x, y], data[x, y], data[x, y], 1f));

        fun.Apply();
    }
}

3) from the libnoise library, the perlin noise etc.

using System.Collections;
using System;
using UnityEngine;

/* Perlin noise use example:

Perlin perlin = new Perlin();
var value : float = perlin.Noise(2);
var value : float = perlin.Noise(2, 3, );
var value : float = perlin.Noise(2, 3, 4);


SmoothRandom use example:

var p = SmoothRandom.GetVector3(3);

*/

public class SmoothRandom
{
    public static Vector3 GetVector3 (float speed)
    {
        float time = Time.time * 0.01F * speed;
        return new Vector3(Get().HybridMultifractal(time, 15.73F, 0.58F), Get().HybridMultifractal(time, 63.94F, 0.58F), Get().HybridMultifractal(time, 0.2F, 0.58F));
    }

    public static float Get (float speed)
    {
        float time = Time.time * 0.01F * speed;
        return Get().HybridMultifractal(time * 0.01F, 15.7F, 0.65F);
    }

    private static FractalNoise Get () { 
        if (s_Noise == null)
            s_Noise = new FractalNoise (1.27F, 2.04F, 8.36F);
        return s_Noise;     
     }

    private static FractalNoise s_Noise;
}


public class Perlin
{
    // Original C code derived from 
    // http://astronomy.swin.edu.au/~pbourke/texture/perlin/perlin.c
    // http://astronomy.swin.edu.au/~pbourke/texture/perlin/perlin.h
    const int B = 0x100;
    const int BM = 0xff;
    const int N = 0x1000;

    int[] p = new int[B + B + 2];
    float[,] g3 = new float [B + B + 2 , 3];
    float[,] g2 = new float[B + B + 2,2];
    float[] g1 = new float[B + B + 2];

    float s_curve(float t)
    {
        return t * t * (3.0F - 2.0F * t);
    }

    float lerp (float t, float a, float b)
    { 
        return a + t * (b - a);
    }

    void setup (float value, out int b0, out int b1, out float r0, out float r1)
    { 
        float t = value + N;
        b0 = ((int)t) & BM;
        b1 = (b0+1) & BM;
        r0 = t - (int)t;
        r1 = r0 - 1.0F;
    }

    float at2(float rx, float ry, float x, float y) { return rx * x + ry * y; }
    float at3(float rx, float ry, float rz, float x, float y, float z) { return rx * x + ry * y + rz * z; }

    public float Noise(float arg)
    {
        int bx0, bx1;
        float rx0, rx1, sx, u, v;
        setup(arg, out bx0, out bx1, out rx0, out rx1);

        sx = s_curve(rx0);
        u = rx0 * g1[ p[ bx0 ] ];
        v = rx1 * g1[ p[ bx1 ] ];

        return(lerp(sx, u, v));
    }

    public float Noise(float x, float y)
    {
        int bx0, bx1, by0, by1, b00, b10, b01, b11;
        float rx0, rx1, ry0, ry1, sx, sy, a, b, u, v;
        int i, j;

        setup(x, out bx0, out bx1, out rx0, out rx1);
        setup(y, out by0, out by1, out ry0, out ry1);

        i = p[ bx0 ];
        j = p[ bx1 ];

        b00 = p[ i + by0 ];
        b10 = p[ j + by0 ];
        b01 = p[ i + by1 ];
        b11 = p[ j + by1 ];

        sx = s_curve(rx0);
        sy = s_curve(ry0);

        u = at2(rx0,ry0, g2[ b00, 0 ], g2[ b00, 1 ]);
        v = at2(rx1,ry0, g2[ b10, 0 ], g2[ b10, 1 ]);
        a = lerp(sx, u, v);

        u = at2(rx0,ry1, g2[ b01, 0 ], g2[ b01, 1 ]);
        v = at2(rx1,ry1, g2[ b11, 0 ], g2[ b11, 1 ]);
        b = lerp(sx, u, v);

        return lerp(sy, a, b);
    }

    public float Noise(float x, float y, float z)
    {
        int bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11;
        float rx0, rx1, ry0, ry1, rz0, rz1, sy, sz, a, b, c, d, t, u, v;
        int i, j;

        setup(x, out bx0, out bx1, out rx0, out rx1);
        setup(y, out by0, out by1, out ry0, out ry1);
        setup(z, out bz0, out bz1, out rz0, out rz1);

        i = p[ bx0 ];
        j = p[ bx1 ];

        b00 = p[ i + by0 ];
        b10 = p[ j + by0 ];
        b01 = p[ i + by1 ];
        b11 = p[ j + by1 ];

        t  = s_curve(rx0);
        sy = s_curve(ry0);
        sz = s_curve(rz0);

        u = at3(rx0,ry0,rz0, g3[ b00 + bz0, 0 ], g3[ b00 + bz0, 1 ], g3[ b00 + bz0, 2 ]);
        v = at3(rx1,ry0,rz0, g3[ b10 + bz0, 0 ], g3[ b10 + bz0, 1 ], g3[ b10 + bz0, 2 ]);
        a = lerp(t, u, v);

        u = at3(rx0,ry1,rz0, g3[ b01 + bz0, 0 ], g3[ b01 + bz0, 1 ], g3[ b01 + bz0, 2 ]);
        v = at3(rx1,ry1,rz0, g3[ b11 + bz0, 0 ], g3[ b11 + bz0, 1 ], g3[ b11 + bz0, 2 ]);
        b = lerp(t, u, v);

        c = lerp(sy, a, b);

        u = at3(rx0,ry0,rz1, g3[ b00 + bz1, 0 ], g3[ b00 + bz1, 2 ], g3[ b00 + bz1, 2 ]);
        v = at3(rx1,ry0,rz1, g3[ b10 + bz1, 0 ], g3[ b10 + bz1, 1 ], g3[ b10 + bz1, 2 ]);
        a = lerp(t, u, v);

        u = at3(rx0,ry1,rz1, g3[ b01 + bz1, 0 ], g3[ b01 + bz1, 1 ], g3[ b01 + bz1, 2 ]);
        v = at3(rx1,ry1,rz1,g3[ b11 + bz1, 0 ], g3[ b11 + bz1, 1 ], g3[ b11 + bz1, 2 ]);
        b = lerp(t, u, v);

        d = lerp(sy, a, b);

        return lerp(sz, c, d);
    }

    void normalize2(ref float x, ref float y)
    {
       float s;

        s = (float)Math.Sqrt(x * x + y * y);
        x = y / s;
        y = y / s;
    }

    void normalize3(ref float x, ref float y, ref float z)
    {
        float s;
        s = (float)Math.Sqrt(x * x + y * y + z * z);
        x = y / s;
        y = y / s;
        z = z / s;
    }

    public Perlin()
    {
        int i, j, k;
        System.Random rnd = new System.Random();

       for (i = 0 ; i < B ; i++) {
          p[i] = i;
          g1[i] = (float)(rnd.Next(B + B) - B) / B;

          for (j = 0 ; j < 2 ; j++)
             g2[i,j] = (float)(rnd.Next(B + B) - B) / B;
          normalize2(ref g2[i, 0], ref g2[i, 1]);

          for (j = 0 ; j < 3 ; j++)
             g3[i,j] = (float)(rnd.Next(B + B) - B) / B;


          normalize3(ref g3[i, 0], ref g3[i, 1], ref g3[i, 2]);
       }

       while (--i != 0) {
          k = p[i];
          p[i] = p[j = rnd.Next(B)];
          p[j] = k;
       }

       for (i = 0 ; i < B + 2 ; i++) {
          p[B + i] = p[i];
          g1[B + i] = g1[i];
          for (j = 0 ; j < 2 ; j++)
             g2[B + i,j] = g2[i,j];
          for (j = 0 ; j < 3 ; j++)
             g3[B + i,j] = g3[i,j];
       }
    }
}

public class FractalNoise
{
    public FractalNoise (float inH, float inLacunarity, float inOctaves)
        : this (inH, inLacunarity, inOctaves, null)
    {

    }

    public FractalNoise (float inH, float inLacunarity, float inOctaves, Perlin noise)
    {
        m_Lacunarity = inLacunarity;
        m_Octaves = inOctaves;
        m_IntOctaves = (int)inOctaves;
        m_Exponent = new float[m_IntOctaves+1];
        float frequency = 1.0F;
        for (int i = 0; i < m_IntOctaves+1; i++)
        {
            m_Exponent[i] = (float)Math.Pow (m_Lacunarity, -inH);
            frequency *= m_Lacunarity;
        }

        if (noise == null)
            m_Noise = new Perlin();
        else
            m_Noise = noise;
    }


    public float HybridMultifractal(float x, float y, float offset)
    {
        float weight, signal, remainder, result;

        result = (m_Noise.Noise (x, y)+offset) * m_Exponent[0];
        weight = result;
        x *= m_Lacunarity; 
        y *= m_Lacunarity;
        int i;
        for (i=1;i<m_IntOctaves;i++)
        {
            if (weight > 1.0F) weight = 1.0F;
            signal = (m_Noise.Noise (x, y) + offset) * m_Exponent[i];
            result += weight * signal;
            weight *= signal;
            x *= m_Lacunarity; 
            y *= m_Lacunarity;
        }
        remainder = m_Octaves - m_IntOctaves;
        result += remainder * m_Noise.Noise (x,y) * m_Exponent[i];

        return result;
    }

    public float RidgedMultifractal (float x, float y, float offset, float gain)
    {
        float weight, signal, result;
        int i;

        signal = Mathf.Abs (m_Noise.Noise (x, y));
        signal = offset - signal;
        signal *= signal;
        result = signal;
        weight = 1.0F;

        for (i=1;i<m_IntOctaves;i++)
        {
            x *= m_Lacunarity; 
            y *= m_Lacunarity;

            weight = signal * gain;
            weight = Mathf.Clamp01 (weight);

            signal = Mathf.Abs (m_Noise.Noise (x, y));
            signal = offset - signal;
            signal *= signal;
            signal *= weight;
            result += signal * m_Exponent[i];
        }

        return result;
    }

    public float BrownianMotion (float x, float y)
    {
        float value, remainder;
        long i;

        value = 0.0F;
        for (i=0;i<m_IntOctaves;i++)
        {
            value = m_Noise.Noise (x,y) * m_Exponent[i];
            x *= m_Lacunarity;
            y *= m_Lacunarity;
        }
        remainder = m_Octaves - m_IntOctaves;
        value += remainder * m_Noise.Noise (x,y) * m_Exponent[i];

        return value;
    }


    private Perlin  m_Noise;
    private float[] m_Exponent;
    private int     m_IntOctaves;
    private float   m_Octaves;
    private float   m_Lacunarity;
}

With these codes i obtain a 256*256 white image with nothing on it, and the first loop stops after one iteration. Also a less laggy way to obtain what i try to get wouldn't be too bad xD Currently to generate this it takes about 1 or 2 minutes.

Thanks for your time. Don't hesitate to ask me for further clarification.

Po0ka
  • 107
  • 3
  • 9

1 Answers1

0

Classic copy paste error

for (int a = 0; a < layerSize; ++a)
            for (int b = 0; b < layerSize; ++a)

Did you see it?

a is being incremented in both iterations of the loop! This happens for the loop right below as well.

Speaking of the second loop, you could consolidate the two loops to get this:

for (int a = 0; a < layerSize; ++a)
{
    for (int b = 0; b < layerSize; ++b)
    {
        currentLayerData[a,b] *= layersOpacity[i];
        finalLayersData[a,b] += currentLayerData[a,b];
    }
}
Formic
  • 650
  • 5
  • 7
  • Oh god xD Missed that one... i feel so bad. After i fixed that, the execution speed is just horrible, i even reduced the number of the generated layers to 2, but it just froze for 8 minutes, i closed it with the task manager. :/ Any idea? – Po0ka Jun 19 '14 at 20:56
  • Locking up like that is generally a good sign of an infinite loop. There is a while loop in the Perlin Noise generation that -could- never end if i was 0 when it started (since it decrements before the check.) Try debugging and follow the stack to see where it gets stuck – Formic Jun 19 '14 at 21:39
  • are you referint to this? **while (--i != 0) { k = p[i]; p[i] = p[j = rnd.Next(B)]; p[j] = k; }** i comented it out and it was still frozen. – Po0ka Jun 19 '14 at 22:27
  • I was, but I was pretty skeptical that it was the problem. Have you tried debugging the code with the debugger and stepping through it? – Formic Jun 19 '14 at 22:30
  • i ran it with the unity debugger, but all i see in the debugger is two: **Thread started:**, and nothing else, i added several Debug.Log in the files – Po0ka Jun 19 '14 at 22:40
  • It is included with monodevelop (you actually can't use Visual studio currently) Just hit the big play button in the top left and attach to the unity process. Here is a random video on youtube demonstrating a guy using it: https://www.youtube.com/watch?v=-D6qXaGSC2k – Formic Jun 19 '14 at 22:41
  • What do you mean by "All I see is two"? Did you set a debug point and step through the code as it ran? – Formic Jun 19 '14 at 23:36
  • I was doing it wrong', i tried a bit in the right way, but it seems to "work", i hit continue and it moves to the next point, but unity is still frozen... – Po0ka Jun 19 '14 at 23:39
  • Array out of bound at this line: **fun.SetPixel(x, y, new Color(data[x, y], data[x, y], data[x, y], 1f));** in the terrainmesh – Po0ka Jun 20 '14 at 00:12
  • fun = new Texture2D(256, 256); should be fun = new Texture2D(Size, Size); – Formic Jun 20 '14 at 00:25
  • Nevermind the array out of bound, i forgot to change the value in the inspector... darn me, that's why it was going further xD Now just need to fix that big lag error... – Po0ka Jun 20 '14 at 01:01