Question

Iv'e been working on a perlin script but have been having problems with creating simple pseudo random values.

I need to be able to create a seed value from an xy coordinate but x+y has obvious problems with recurring values. Also they go into negative space so x^y doesn't work.

Sorry if this has been already answered somewhere else but either I didn't understand or couldn't find it.

Was it helpful?

Solution

You need to better define the problem to get an optimal answer.

If your x and y values are relatively small, you could place them into the high and low portions of an integer (is the seed in your language an integer), e.g. for a 32-bit platform:

int seed = x << 16 + y;

If the seed value is not allowed to be negative (I didn't fully understand what you meant by "negative space" in your question, whether you were referring to geography or the seed value), you can take the absolute value of the seed.

If you meant that the coordinates can have negative values, your best course of action depends on whether you want the same seed for a coordinate and for it's inverse.

OTHER TIPS

Do you want to assing a repetible random number to each x,y pair ?

Using a linear or in general function combination of the x,y as a seed will give artifacts in the distribution (at least if you don't use a very complex function). Try with this, I've the same problem ant it worked for me

//seeded random for JS - integer
function irnd2()
{
    a=1664525;
    c=1013904223;
    m=4294967296;
    rnd2.r=(rnd2.r*a+c)%m;
    return rnd2.r;
}

//seeded random for JS - double [0,1]
function rnd2()
{
    a=1664525;
    c=1013904223;
    m=4294967296;
    rnd2.r=(rnd2.r*a+c)%m;
    return rnd2.r/m;
}


rnd2.r=192837463;

//seed function
function seed2(s)
{
    s=s>0?s:-s;
    rnd2.r=192837463^s;
}

//my smart seed from 2 integer
function myseed(x,y)
{
seed2(x);//x is integer
var sx=irnd2();//sx is integer
seed2(y);//y is integer
var sy=irnd2();//sy is integer
seed2(sx^sy);//using binary xor you won't lose information 
}

In order to use it :

myseed(x,y);
irnd2();

In this manner you can obtain a good uncorrelated random sequence.

I use it in JS but it should work also in other languages supposing the argument of seed and the returned value of rnd is an integer.

Take the absolute value of both x and y first; then x^y will work fine. One of the easiest ways to create a pseudo-random source is with time. You might try multiplying x^y by the current system time; this method has an extremely low chance of generating recurring seed values.

If you know the range of values you have, you could simply cast x and y as strings padded with zeroes, append the two strings, then run the resulting string through a hash function.

In C#, adapted and improved from alexroat's answer. Just set Random.seed = MyUtils.GetSeedXY(x, y) and you're good to go.

public static class MyUtils
{
    static int seed2(int _s)
    {
        var s = 192837463 ^ System.Math.Abs(_s);
        var a = 1664525;
        var c = 1013904223;
        var m = 4294967296;
        return (int) ((s * a + c) % m);
    }

    public static int GetSeedXY(int x, int y)
    {
        int sx = seed2(x * 1947);
        int sy = seed2(y * 2904);
        return seed2(sx ^ sy);
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top