Lua Perlin Noise Gen给人奇怪的木匠

时间:2019-03-12 14:51:19

标签: javascript lua porting p5.js perlin-noise

所以我正在为使用lua api的factorio制作一个mod。我需要Perlin噪声发生器,因此我使用网站上的指南进行了编码:https://flafla2.github.io/2014/08/09/perlinnoise.html 我首先用javascript编码,因为我比较擅长js。工作正常。但是当我将其移植到lua时,它会生成这些奇怪的块和线。

黑色表示低值,而白色表示高值

我花了最后5个小时来浏览代码,但没有任何反应。请帮忙。

下面是lua中的代码。我在每个磁贴处都叫pn.p2D(x,y)。由于我已经多次测试,因此正确输入了x和y。 LuaRandomGenerator是一个随机数生成器,它给出随机数。

--note: pn.ran_gen is a LuaRandomGenerator which should be created
--      when pn was init


--local vals


--local functions

local sudoR = function(seed,rs,rm,gs,rg)
    seed = seed%rs
    rg.re_seed(seed+gs)
    return rg(rm-1)
end

local lerp = function(v0,v1,t)
    return v0+t*(v1-v0)
end

local fade = function(t)
    return t*t*t*(t*(6*t-15)+10) -- 6t^5-15t^4+10t^3
end

local inc = function(num,rm)
    return (num+1)%rm
end

local grad = function(hash,x,y,z)
    local case = hash%16
        if (case==0 ) then return x+y
    elseif (case==1 ) then return -x+y
    elseif (case==2 ) then return x-y
    elseif (case==3 ) then return -x-y
    elseif (case==4 ) then return x+z
    elseif (case==5 ) then return -x+z
    elseif (case==6 ) then return x-z
    elseif (case==7 ) then return -x-z
    elseif (case==8 ) then return y+z
    elseif (case==9 ) then return -y+z
    elseif (case==10) then return y-z
    elseif (case==11) then return -y-z
    elseif (case==12) then return y+x
    elseif (case==13) then return -y+z
    elseif (case==14) then return y-x
    elseif (case==15) then return -y-z
    else error("How val%16 end up being larger then 15? I guess val is not int.")
    end
end

local perlin_noise = function(x,y,z,rs,rm,gs,rg)
    --game.players[1].print(x)
    local xi = math.floor(x) % rs
    local yi = math.floor(y) % rs
    local zi = math.floor(z) % rs
    local xf = x - math.floor(x)
    local yf = y - math.floor(y)
    local zf = z - math.floor(z)

    local xg = fade(xf)
    local yg = fade(yf)
    local zg = fade(zf)

    --hashing
    local aaa = sudoR(sudoR(sudoR(    xi    ,rs,rm,gs,rg)+    yi    ,rs,rm,gs,rg)+    zi    ,rs,rm,gs,rg)
    local aba = sudoR(sudoR(sudoR(    xi    ,rs,rm,gs,rg)+inc(yi,rm),rs,rm,gs,rg)+    zi    ,rs,rm,gs,rg)
    local aab = sudoR(sudoR(sudoR(    xi    ,rs,rm,gs,rg)+    yi    ,rs,rm,gs,rg)+inc(zi,rm),rs,rm,gs,rg)
    local abb = sudoR(sudoR(sudoR(    xi    ,rs,rm,gs,rg)+inc(yi,rm),rs,rm,gs,rg)+inc(zi,rm),rs,rm,gs,rg)
    local baa = sudoR(sudoR(sudoR(inc(xi,rm),rs,rm,gs,rg)+    yi    ,rs,rm,gs,rg)+    zi    ,rs,rm,gs,rg)
    local bba = sudoR(sudoR(sudoR(inc(xi,rm),rs,rm,gs,rg)+inc(yi,rm),rs,rm,gs,rg)+    zi    ,rs,rm,gs,rg)
    local bab = sudoR(sudoR(sudoR(inc(xi,rm),rs,rm,gs,rg)+    yi    ,rs,rm,gs,rg)+inc(zi,rm),rs,rm,gs,rg)
    local bbb = sudoR(sudoR(sudoR(inc(xi,rm),rs,rm,gs,rg)+inc(yi,rm),rs,rm,gs,rg)+inc(zi,rm),rs,rm,gs,rg)

    --gen result
    local x1 = lerp(grad (aaa, xf  , yf  , zf),
                    grad (baa, xf-1, yf  , zf),
                    xg)
    local x2 = lerp(grad (aba, xf  , yf-1, zf),
                    grad (bba, xf-1, yf-1, zf),
                    xg)
    local y1 = lerp(x1, x2, yg)
          x1 = lerp(grad (aab, xf  , yf  , zf-1),
                    grad (bab, xf-1, yf  , zf-1),
                    xg)
          x2 = lerp(grad (abb, xf  , yf-1, zf-1),
                    grad (bbb, xf-1, yf-1, zf-1),
                    xg)
    local y2 = lerp(x1, x2, yg)
    local z1 = lerp(y1, y2, zg)

    return (z1+1)/2
end

local octave_perlin = function(x,y,z,octaves,persistence,rs,rm,gs,rg)

    local total = 0
    local fre = 1
    local amp = 1
    local maxValue = 0
    for i=1, octaves do
        total = total+perlin_noise(x*fre,y*fre,z*fre,rs,rm,gs,rg)*amp
        maxValue = maxValue+amp
        amp = amp*persistence
        fre = fre*2
    end

    return total/maxValue
end

--useable functions/vals
local pn = {}

pn.ran_max = 256
pn.ran_size = 256
pn.default_z = 4
pn.seed = 0--nil
pn.octaves = 8
pn.persistence = 0.5
pn.scale = 64
pn.ran_gen = nil

pn.init = function()
    --pn.ran_max = settings
    --pn.seed = game.default_map_gen_settings.seed
    pn.ran_gen = game.create_random_generator()
end

pn.p3D = function(x,y,z)
    return fade(octave_perlin(x/pn.scale,y/pn.scale,z/pn.scale,pn.octaves,pn.persistence,pn.ran_size,pn.ran_max,pn.seed,pn.ran_gen))
end

pn.p2D = function(x,y)
    return pn.p3D(x,y,pn.default_z)
end

pn.simple3D = function(x,y,z)
    return fade(perlin_noise(x/pn.scale,y/pn.scale,z/pn.scale,pn.ran_size,pn.ran_max,pn.seed,pn.ran_gen))
end

pn.simple2D = function(x,y)
    return pn.simple3D(x,y,pn.default_z)
end

return pn

下一个代码块是使用p5.js在javascript中工作的代码块。您可以将其复制到https://editor.p5js.org/中以查看弹出结果。

grid = [];
    w = 2;
    g = 400/w-1;
    ran = [];
    ran_num = 256;
    ran_seed = 51;
    p = [];
    psize = 64;
    
    function setup() {
    	noStroke();
        createCanvas(400, 400);
    	randomSeed(ran_seed);
    	perlin_setup();
    	pDetails = 8; //int
    	pDetailsWeight = 0.5; //between 0 and 0.5
    	
    	for (x=0;x<g;x++) {
    		
    		grid[x] = [];
    		
    		for (y=0;y<g;y++) {
    			//grid[x][y] = perlin_noise(x/16,y/16,0)*256;
    			grid[x][y] = fade(octave_perlin(x/psize,y/psize,0,pDetails,pDetailsWeight))*256;
    		}
    	}
    }
    
    function inc(num) {
    	num++;
    	num = num%ran_num;
    	return num;
    }
    
    function fade(t) {
    	return t*t*t*(t*(6*t-15)+10); //6t^5-15t^4+10t^3
    }
    
    function grad(hash,x,y,z) {
    	switch(hash%16) {
        case 0: return  x + y;
        case 1: return -x + y;
        case 2: return  x - y;
        case 3: return -x - y;
        case 4: return  x + z;
        case 5: return -x + z;
        case 6: return  x - z;
        case 7: return -x - z;
        case 8: return  y + z;
      	case 9: return -y + z;
        case 10: return  y - z;
        case 11: return -y - z;
        case 12: return  y + x;
        case 13: return -y + z;
        case 14: return  y - x;
        case 15: return -y - z;
      	default: return 0; // never happens
    	}
    	
    }
    
    function perlin_setup() {
    	
    	for (i=0;i<ran_num;i++) {
    		ran[i] = floor(random(256));
    		p[i] = ran[i];
    		p[i+ran_num] = ran[i];
    	}
    	
    }
    
    function perlin_noise(x,y,z) {
    	xi = floor(x)%ran_num;
    	yi = floor(y)%ran_num;
    	zi = floor(z)%ran_num;
    	xf = x-floor(x);
    	yf = y-floor(y);
    	zf = z-floor(z);
    	
    	u = fade(xf);
    	v = fade(yf);
    	h = fade(zf);
    	
    	//console.log("  "+h);
    	
    	//hashing
        aaa = p[p[p[    xi ]+    yi ]+    zi ];
        aba = p[p[p[    xi ]+inc(yi)]+    zi ];
        aab = p[p[p[    xi ]+    yi ]+inc(zi)];
        abb = p[p[p[    xi ]+inc(yi)]+inc(zi)];
        baa = p[p[p[inc(xi)]+    yi ]+    zi ];
        bba = p[p[p[inc(xi)]+inc(yi)]+    zi ];
        bab = p[p[p[inc(xi)]+    yi ]+inc(zi)];
        bbb = p[p[p[inc(xi)]+inc(yi)]+inc(zi)];
        
    	//gen result
        x1 = lerp(grad (aaa, xf  , yf  , zf),
                  grad (baa, xf-1, yf  , zf),
                  u);
        x2 = lerp(grad (aba, xf  , yf-1, zf),
                  grad (bba, xf-1, yf-1, zf),
                  u);
        y1 = lerp(x1, x2, v);
    
        x1 = lerp(grad (aab, xf  , yf  , zf-1),
                  grad (bab, xf-1, yf  , zf-1),
                  u);
        x2 = lerp(grad (abb, xf  , yf-1, zf-1),
                  grad (bbb, xf-1, yf-1, zf-1),
                  u);
        y2 = lerp(x1, x2, v);
    	
        z1 = lerp(y1, y2, h);
    	
    	return (z1+1)/2;
    }
    
    function octave_perlin(x,y,z,octaves,persistence) {
    	
    	total = 0;
    	fre = 1;
    	amp = 1;
    	maxValue = 0;
    	for(i=0;i<octaves;i++) {
    		total += perlin_noise(x*fre,y*fre,z*fre)*amp;
    		
    		maxValue += amp;
    		
    		amp *= persistence;
    		fre *= 2;
    	}
    	
    	return total/maxValue;
    }
    
    function draw() {
      background(220);
    	for (x=0;x<g;x++) {
    		for (y=0;y<g;y++) {
    				fill(0,0,255);
    			if (x==0) {
    				fill(255, 125, 0);
    			} else if (y==0) {
    				fill(0,255,255);
    			} else {
    				fill(grid[x][y]);
    			}
    			rect(x*w+w/2, y*w+w/2, w, w);
    			
    		}
    	}
    	noLoop();
    }
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.3/p5.js"></script>

0 个答案:

没有答案