2013-04-16 4 views
0

제목에 Perlin Noise를 사용하여 Heightmap Generator를 만들고 있습니다. >http://freespace.virgin.net/hugo.elias/models/m_perlin.htmPerlin을 사용하는 Heightmap Generation 노이즈가 검은 비트 맵을 반환합니다.

및 C# 코드에 설정 -

이 사이트에서 의사 코드를 사용했습니다. 지금까지 모든 변수 유형 할당을 수행했으며 코드는 출력을 제공합니다. 불행히도 내 출력은 다음과 같습니다. ->enter image description here

오른쪽에서 볼 수 있듯이 오른쪽과 아래쪽 가장자리는 검은 색에서 흰색으로 약간 그라데이션이 있지만 나머지 모든 것은 검은 색입니다.

여기 내 C# 소스입니다 - 누구에게의를 원하는 경우>

private void button1_Click(object sender, EventArgs e) { 
     persistence = float.Parse(textBox4.Text); 
     NumberOfOctaves = Int32.Parse(textBox5.Text); 

     int width = Int32.Parse(textBox1.Text); 
     int height = Int32.Parse(textBox2.Text); 
     float zoom = float.Parse(textBox3.Text); 

     generate(width, height, zoom); 
    } 

    public float Noise(int x, int y) { 
     long n = x + (y * 57); 
     n = (long)Math.Pow((n << 13), n); 
     return (float)(1.0 - ((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff)/1073741824.0); 
    } 

    public float SmoothNoise(float x, float y) { 
     float corners = (Noise((int) (x-1), (int) (y-1)) + Noise((int) (x+1), (int) (y-1)) + Noise((int) (x-1), (int) (y+1)) + Noise((int) (x+1), (int) (y+1)))/16; 
     float sides = (Noise((int) (x-1), (int) y) + Noise((int) (x+1), (int) y) + Noise((int) x, (int) (y-1)) + Noise((int) x, (int) (y+1)))/8 ; 
     float center = Noise((int)x, (int)y)/4; 
     return corners + sides + center; 
    } 

    public float CosineInterpolate(float a, float b, float x) { 
     double ft = x * 3.1415927; 
     double f = (1 - Math.Cos(ft)) * 0.5; 

     return (float)((a * (1 - f)) + (b * f)); 
    } 

    public float InterpolatedNoise(float x, float y) { 
     // MessageBox.Show(x.ToString()); 
     int intX = (int)x; 
     float fractX = x - intX; 

     int intY = (int) y; 
     float fractY = y - intY; 

     float v1 = SmoothNoise(intX,  intY); 
     float v2 = SmoothNoise(intX + 1, intY); 
     float v3 = SmoothNoise(intX,  intY + 1); 
     float v4 = SmoothNoise(intX + 1, intY + 1); 

     float i1 = CosineInterpolate(v1 , v2 , fractX); 
     float i2 = CosineInterpolate(v3 , v4 , fractX); 

     // MessageBox.Show(intX + "\n" + intY + "\n" + fractX + "\n" + fractY + "\n" + v1 + "\n" + v2 + "\n" + v3 + "\n" + v4 + "\n" + i1 + "\n" + i2 + "\n" + CosineInterpolate(i1, i2, fractY)); 

     return CosineInterpolate(i1 , i2 , fractY); 
    } 

    public float PerlinNoise2D(float x, float y) { 
     float total = 0; 
     float p = persistence; 
     int n = NumberOfOctaves; 

     for(int i = 0; i < n; i++) { 
      int frequency = (int)Math.Pow(2, i); 
      // MessageBox.Show(Math.Pow(2, i).ToString()); 
      float amplitude = (int)Math.Pow(p, i); 
      total = total + InterpolatedNoise(x * frequency, y * frequency) * amplitude; 
     } 
     return total; 
    } 

    private void generate(int sizeX, int sizeY, float zoom) { 
     int zoomX = (int)(sizeX * zoom); 
     int zoomY = (int)(sizeY * zoom); 

     float max = int.MinValue; 
     float min = int.MaxValue; 

     float[,] nmap = new float[zoomX,zoomY]; 

     Bitmap heightMap = new Bitmap(zoomX,zoomY); 

     for (int x=0; x<zoomX; x++) { 
      for (int y=0; y<zoomY; y++) { 
       // MessageBox.Show(PerlinNoise2D(x/zoom, y/zoom).ToString()); 

       nmap[x,y] = PerlinNoise2D(x/zoom,y/zoom); 
       max = (max < nmap[x,y]) ? nmap[x,y] : max; 
       min = (min > nmap[x,y]) ? nmap[x,y] : min; 
      } 
     } 

     max = max-min; 

     for (int x=0; x<zoomX;x++) { 
      for (int y=0; y<zoomY;y++) { 
       int calc = (int) ((nmap[x,y] - min)/max); 
       heightMap.SetPixel(x,y,Color.FromArgb(calc,calc,calc)); 
      } 
     } 

     pictureBox1.Image = heightMap; 
    } 

도 내가 우편의 비주얼 스튜디오 솔루션을 업로드 할 수 있습니다.

지금까지 Noise() 함수가 잘못되었음을 알았습니다. 왜냐하면 -0,281을 반환하기 때문에 ... 가장 많은 시간입니다. -1.0에서 1.0 사이의 부동 소수점 숫자를 반환해야합니다. 다른 무작위 기능으로 시도했지만 출력은 매번 똑같습니다.

당신이 나를 도울 수 있기를 바랍니다. 그리고 anny 제안을 위해 thx.

+0

나는 0x7fffffff를 의미한다고 생각합니다. 즉, C#의 내장 Random 클래스를 대신 사용해보십시오. – redtuna

+0

또한 0x7fffffff로 시도했지만 그 결과는 같습니다. 알다시피, 거의 모든 프로그래밍 언어에서 모든 무작위 클래스의 모든 빌드는 최대 값과 최소값에서 100 % 무작위가 아닙니다 ... min & max 사이의 값은 generatet 많은 oftener 다음 min & 맥스 ... – Ace

+0

에이스, 그건 이상한 일입니다 - 당신이 그것을 확인할 수 있었습니까? 물론 확정적 함수는 100 % 무작위가 될 수는 없지만 의사 난수 함수가 손상 되었다면 자체적으로 교체하기 전에 먼저 내장 함수를 시도하는 것이 합리적입니다. – redtuna

답변

2

코드에서 두 가지 문제점을 발견했습니다.

먼저 x32 작업 인 동안 원래 소스 코드 의 전원 함수로 ^ 심볼을 잘못 해석했습니다. 그래서 라인

n = (long)Math.Pow((n << 13), n); 

n = (long)((n << 13)^n); 

둘째이어야한다 노이즈 값에서 컬러 픽셀을 만들 때, 당신의 잡음이 범위 0..1이며, 색상 값이 범위를 0..255에 있어야합니다, 그래서 라인

int calc = (int) ((nmap[x,y] - min)/max); 

은이어야한다

int calc = (int) (((nmap[x,y] - min)/max) * 255); 

전체 작동 (콘솔) 샘플 : http://ideone.com/RGVf8J

관련 문제