2011-04-03 113 views
8

對於我正在開發的元胞自動機項目,我需要使用不同的算法和技巧隨機生成二維布爾數組。此刻,我在應用程序中只有一種隨機化 - 遍歷數組中的每個單元格並生成一個隨機雙變量,然後如果隨機數大於0.5,則將該單元格設置爲true,如果不是,則將其設置爲true假。Java中的Perlin噪聲

我想看看使用更有趣的算法,如柏林噪聲或類似的東西來產生這些布爾矩陣。如果你知道除了Perlin噪聲(Minecraft的世界一代給了我這個想法),用於地形生成或類似的噪聲發生器可能是好的。

唯一的問題是我不知道從哪裏開始(任何想法?):)

回答

9

我想到的第一件事情是一個隨機的位移分。它也用於生成地形,比Perlin Noise更容易。

package so; 

import java.util.Random; 

public class Noise { 
    /** Source of entropy */ 
    private Random rand_; 

    /** Amount of roughness */ 
    float roughness_; 

    /** Plasma fractal grid */ 
    private float[][] grid_; 


    /** Generate a noise source based upon the midpoint displacement fractal. 
    * 
    * @param rand The random number generator 
    * @param roughness a roughness parameter 
    * @param width the width of the grid 
    * @param height the height of the grid 
    */ 
    public Noise(Random rand, float roughness, int width, int height) { 
     roughness_ = roughness/width; 
     grid_ = new float[width][height]; 
     rand_ = (rand == null) ? new Random() : rand; 
    } 


    public void initialise() { 
     int xh = grid_.length - 1; 
     int yh = grid_[0].length - 1; 

     // set the corner points 
     grid_[0][0] = rand_.nextFloat() - 0.5f; 
     grid_[0][yh] = rand_.nextFloat() - 0.5f; 
     grid_[xh][0] = rand_.nextFloat() - 0.5f; 
     grid_[xh][yh] = rand_.nextFloat() - 0.5f; 

     // generate the fractal 
     generate(0, 0, xh, yh); 
    } 


    // Add a suitable amount of random displacement to a point 
    private float roughen(float v, int l, int h) { 
     return v + roughness_ * (float) (rand_.nextGaussian() * (h - l)); 
    } 


    // generate the fractal 
    private void generate(int xl, int yl, int xh, int yh) { 
     int xm = (xl + xh)/2; 
     int ym = (yl + yh)/2; 
     if ((xl == xm) && (yl == ym)) return; 

     grid_[xm][yl] = 0.5f * (grid_[xl][yl] + grid_[xh][yl]); 
     grid_[xm][yh] = 0.5f * (grid_[xl][yh] + grid_[xh][yh]); 
     grid_[xl][ym] = 0.5f * (grid_[xl][yl] + grid_[xl][yh]); 
     grid_[xh][ym] = 0.5f * (grid_[xh][yl] + grid_[xh][yh]); 

     float v = roughen(0.5f * (grid_[xm][yl] + grid_[xm][yh]), xl + yl, yh 
       + xh); 
     grid_[xm][ym] = v; 
     grid_[xm][yl] = roughen(grid_[xm][yl], xl, xh); 
     grid_[xm][yh] = roughen(grid_[xm][yh], xl, xh); 
     grid_[xl][ym] = roughen(grid_[xl][ym], yl, yh); 
     grid_[xh][ym] = roughen(grid_[xh][ym], yl, yh); 

     generate(xl, yl, xm, ym); 
     generate(xm, yl, xh, ym); 
     generate(xl, ym, xm, yh); 
     generate(xm, ym, xh, yh); 
    } 


    /** 
    * Dump out as a CSV 
    */ 
    public void printAsCSV() { 
     for(int i = 0;i < grid_.length;i++) { 
      for(int j = 0;j < grid_[0].length;j++) { 
       System.out.print(grid_[i][j]); 
       System.out.print(","); 
      } 
      System.out.println(); 
     } 
    } 


    /** 
    * Convert to a Boolean array 
    * @return the boolean array 
    */ 
    public boolean[][] toBooleans() { 
     int w = grid_.length; 
     int h = grid_[0].length; 
     boolean[][] ret = new boolean[w][h]; 
     for(int i = 0;i < w;i++) { 
      for(int j = 0;j < h;j++) { 
       ret[i][j] = grid_[i][j] < 0; 
      } 
     } 
     return ret; 
    } 


    /** For testing */ 
    public static void main(String[] args) { 
     Noise n = new Noise(null, 1.0f, 250, 250); 
     n.initialise(); 
     n.printAsCSV(); 
    } 
} 

random displacement fractal plot 1 random displacement fractal plot 2 random displacement fractal plot 3

+0

我改變(屠殺)你的來源產生噪音的情節,藍色最低,黃色最高值。圖像上似乎有不同的線條,最明顯的是在「中點」,但在較小的程度上,每個「孩子」的中點。有什麼方法可以減少或消除這些不連續性?如果有人感興趣,我可以添加更改後的來源。 – 2011-04-05 12:43:30

+2

這種分形很容易編碼,但會產生這些線條。它有一個改進,稱爲鑽石正方形分形,應該儘量減少這些文物。 – 2011-04-05 13:10:59

+0

順便說一句我認爲我的實現也存在問題。該代碼設置每邊中點的高度兩次。這會導致不連續性。如果網格初始化爲Float.NaN並且每個點只通過測試設置一次,我認爲輸出會得到改進。 – 2011-04-05 13:22:04

4

我有一些柏林噪聲的實現和其他一些噪音生成功能在我的庫代碼:

http://code.google.com/p/mikeralib/source/browse/#svn%2Ftrunk%2FMikera%2Fsrc%2Fmain%2Fjava%2Fmikera%2Fmath

歡迎瀏覽/使用(代碼是基於J3D代碼的開源GPL)。

+0

我似乎無法從您的perlin函數中獲得除了負數或正數0浮點數以外的任何內容; 'PerlinNoise perlin = new PerlinNoise(409623546); (float y = 0; y <100; y ++) System.out.println(perlin。noise1(Y)* 100000); } }' – 2011-12-20 17:44:53

+0

@TimothyGroote 嘗試此,它的工作對我來說: 雙格[] [] =新的雙[寬度] [高度]; (int x = 0; x 2012-06-13 16:06:17