2016-07-06 112 views
2

我試圖找出辦法有用於固定的規模:鑽石廣場算法固定大小

https://en.wikipedia.org/wiki/Diamond-square_algorithm

我看到算法要求的2(+1)大小的力量陣列。

我遇到的問題是,我想有不管決議產生相同的高度圖。所以如果我有一個512的分辨率,它看起來與分辨率256相同,但是隻有更少的細節。我只是無法弄清楚如何做到這一點。

我的初始想法是總是創建在某一尺寸如高度圖1024和下采樣到我想要的水庫。問題是我希望較高的分辨率相當高(比如說4096),並且這會嚴重降低較低分辨率下的性能,因爲我們必須以最高分辨率運行算法。

目前該算法是在JavaScript這裏是一個片段:

function Advanced() { 
    var adv = {}, 
    res, max, heightmap, roughness; 

    adv.heightmap = function() { 
     // heightmap has one extra pixel this is ot remove it. 
     var hm = create2DArray(res-1, res-1); 
     for(var x = 0;x< res-1;x++) { 
      for(var y = 0;y< res-1;y++) { 
       hm[x][y] = heightmap[x][y]; 
      } 
     } 
     return hm; 
    } 

    adv.get = function(x,y) { 
     if (x < 0 || x > max || y < 0 || y > max) return -1; 
     return heightmap[x][y]; 
    } 

    adv.set = function(x,y,val) { 
     if(val < 0) { 
      val = 0; 
     } 

     heightmap[x][y] = val; 

    } 

    adv.divide = function(size) { 
     var x, y, half = size/2; 
     var scale = roughness * size; 
     if (half < 1) return; 

     for (y = half; y < max; y += size) { 
      for (x = half; x < max; x += size) { 
       adv.square(x, y, half, Math.random() * scale * 2 - scale); 
      } 
     } 
     for (y = 0; y <= max; y += half) { 
      for (x = (y + half) % size; x <= max; x += size) { 
       adv.diamond(x, y, half, Math.random() * scale * 2 - scale); 
      } 
     } 
     adv.divide(size/2); 
    } 

    adv.average = function(values) { 
     var valid = values.filter(function(val) { 
      return val !== -1; 
     }); 
     var total = valid.reduce(function(sum, val) { 
      return sum + val; 
     }, 0); 
     return total/valid.length; 
    } 

    adv.square = function(x, y, size, offset) { 
     var ave = adv.average([ 
      adv.get(x - size, y - size), // upper left 
      adv.get(x + size, y - size), // upper right 
      adv.get(x + size, y + size), // lower right 
      adv.get(x - size, y + size) // lower left 
     ]); 
     adv.set(x, y, ave + offset); 
    } 

    adv.diamond = function(x, y, size, offset) { 

     var ave = adv.average([ 
      adv.get(x, y - size), // top 
      adv.get(x + size, y), // right 
      adv.get(x, y + size), // bottom 
      adv.get(x - size, y) // left 
     ]); 

     adv.set(x, y, Math.abs(ave + offset)); 
    } 

    adv.generate = function(properties, resolution) { 
     Math.seedrandom(properties.seed); 

     res = resolution + 1; 
     max = res - 1; 
     heightmap = create2DArray(res, res); 

     roughness = properties.roughness; 

     adv.set(0, 0, max); 
     adv.set(max, 0, max/2); 
     adv.set(max, max, 0); 
     adv.set(0, max, max/2); 

     adv.divide(max); 
    } 

    function create2DArray(d1, d2) { 
     var x = new Array(d1), 
     i = 0, 
     j = 0; 

     for (i = 0; i < d1; i += 1) { 
      x[i] = new Array(d2); 
     } 

     for (i=0; i < d1; i += 1) { 
      for (j = 0; j < d2; j += 1) { 
       x[i][j] = 0; 
      } 
     } 

     return x; 
    } 

    return adv; 
} 

有誰這樣做過?

+0

貌似沒有再笑! – Dave3of5

回答

0

不太清楚,如果我理解你的問題還沒有,但如果我可以,我會提供進一步的澄清。

你描述你想要在一個大小爲512使用與256的分辨率的菱形方高度圖而無需縮放了的情況下。我將通過一個使用2x2高度圖的例子來說明4x4的「大小」。

鑽石方高度圖是真是一組頂點,而不是磚或正方形的,所以有大小2×2的高度圖真如所示的一組3×3的頂點:

enter image description here

你可以要麼使用拐角的高度來渲染它,要麼通過取四個周圍點的平均值,將它變成一個2×2的正方形集合 - 實際上,這只是沒有位移步驟的算法的「平方」步驟。

enter image description here

因此,在這種情況下,左上方的 「高度」 是的平均值(0,0),(0,1),(1,1)和(1, 0)分。

如果你想在更高的分辨率得出這樣的,你可能分裂每平方米成較小的一套4個格的基礎上,它是每一個點的接近程度調整的平均水平。

enter image description here

所以現在左上角最方形的價值將是其周圍的4個子點或相對於周圍的點的位置的樣本的樣本。但實際上,這只是再次應用鑽石平方算法而沒有任何位移(無粗糙),因此您可以再次應用該算法並進行更大尺寸。

你說要去你不妨去將太多的處理器來處理,所以你可能想要去與較小尺寸此抽樣方法的大小。一種有效的方法是將高度圖渲染爲紋理和樣本以及所需的位置。

0

正確實施鑽石&方算法具有相同的第一N步驟,無論地圖分辨率,因此唯一需要確保相同的外觀是使用了僞隨機生成一些特定的種子。

爲了使這項工作,你需要:

  1. 組種子
  2. 分配陣列,並設置基地隨機性幅度
  3. 鑽石
  4. 廣場
  5. 基數較低的隨機性幅度
  6. # 3直到最低分辨率命中

如果不是正確地降低隨機性的大小,那麼較低的遞歸/迭代層可以覆蓋上層結果的形狀,從而使其不起作用。

這裏看到我這樣做只是增加了種子:

看行:

r=(r*220)>>8; if (r<2) r=2; 

r是基礎隨機性幅度。你降低它的方式將決定結果的形狀,因爲你可以看到我沒有將它除以2,而是乘以220/256,所以更低的分辨率有更大的顛簸,這符合我的需要。

現在,如果你想使用非2^x+1分辨率,然後選擇更接近更大的分辨率,然後縮小,以使他們也爲他們工作。縮小應仔細做,以保留它們的前幾個遞歸/迭代步驟的主要網格點或使用雙立方體...

如果你有興趣看看更多最新的發電機基於連接的一種: