2012-06-24 8 views
0

Я создал функцию шума Perlin. Моя проблема заключается в том, когда я генерирую карту местности из-за шума, который он заканчивает блочным, ничего подобного облачным изображениям, которые я видел. Мне любопытно, что я делаю неправильно (если вообще). вот мой код:Perlin Noise issue

main.cpp

#include "PerlinNoise.h" 
#include <stdio.h> 
#include <SDL/SDL.h> 

void DrawPixel(SDL_Surface *screen, int x, int y, Uint8 R, Uint8 G, Uint8 B); 
SDL_Surface *Render_Noise(int w, int h, int r, int g, int b); 
PerlinNoise noiseGen(2,.5,25); 

int main(int argc, char **argv) 
{ 
    SDL_Init(SDL_INIT_EVERYTHING); 
    SDL_Surface *screen = SDL_SetVideoMode(500,500,32,SDL_SWSURFACE); 
    SDL_Surface *noise = Render_Noise(500,500,255,255,255); 

    SDL_SaveBMP(noise, "noise.bmp"); 

    bool quit = false; 

    while(!quit) 
    { 
     SDL_Event e; 

     SDL_WaitEvent(&e); 

     switch(e.type) 
     { 
     case SDL_QUIT: 
      quit = true; 
     } 

     SDL_BlitSurface(noise,NULL,screen,NULL); 
     SDL_Flip(screen); 
     SDL_Delay(2000); 
    } 

    SDL_FreeSurface(noise); 
    SDL_Quit(); 

    return 0; 
} 

void DrawPixel(SDL_Surface *screen, int x, int y, Uint8 R, Uint8 G, Uint8 B) 
{ 
    Uint32 color = SDL_MapRGB(screen->format, R, G, B); 

    if(SDL_MUSTLOCK(screen)) 
    { 
     if(SDL_LockSurface(screen) < 0) 
     { 
      return; 
     } 
    } 

    switch(screen->format->BytesPerPixel) 
    { 
    case 1: 
     { 
     Uint8 *bufp; 

     bufp = (Uint8 *)screen->pixels + y*screen->pitch + x; 
     *bufp = color; 
     } 
     break; 

    case 2: 
     { 
     Uint16 *bufp; 
     bufp = (Uint16 *)screen->pixels + y*screen->pitch/2 + x; 
     *bufp = color; 
     } 
     break; 

    case 3: 
     { 
     Uint8 *bufp; 

     bufp = (Uint8 *)screen->pixels + y*screen->pitch + x; 
     *(bufp+screen->format->Rshift/8) = R; 
     *(bufp+screen->format->Bshift/8) = B; 
     *(bufp+screen->format->Gshift/8) = G; 
     } 
     break; 

    case 4: 
     { 
     Uint32 *bufp; 

     bufp = (Uint32 *)screen->pixels + y*screen->pitch/4 + x; 
     *bufp = color; 
     } 
     break; 
    } 

    if(SDL_MUSTLOCK(screen)) 
    { 
     SDL_UnlockSurface(screen); 
    } 
    SDL_UpdateRect(screen, x, y, 1, 1); 
} 

SDL_Surface *Render_Noise(int w, int h, int r, int g, int b) 
{ 
    SDL_Surface *ret = SDL_CreateRGBSurface(SDL_SWSURFACE,w,h,32,0,0,0,0);   //create an empty image 

    for(int y = 0; y < h; y++) 
    { 
     for(int x = 0; x < w; x++) 
     { 
      double getnoise = 0; 
      for(int a = 0; a < noiseGen.n; a++) 
      { 
       getnoise += noiseGen.generateNoise(x,y); 
       noiseGen.z = rand() % 100; 
      } 

      getnoise/noiseGen.n; 

      int color = (int)((getnoise * 128.0) + 128.0);  //convert noise to 0-256 value 

      if (color > 255) 
       color = 255; 
      if (color < 0) 
       color = 0; 

      DrawPixel(ret, x, y, (int)((r/255.0) * (double)color), (int)((g/255.0) * (double)color), (int)((b/255.0) * (double)color)); 
     } 
    } 
    return ret; 
} 

perlinnoise.cpp

#include "PerlinNoise.h" 

PerlinNoise::PerlinNoise(int octaves, double persistence, int zoom) 
{ 
    p = persistence; 
    n = octaves - 1; 
    z = zoom; 
} 

PerlinNoise::~PerlinNoise() 
{ 

} 

///<summary>Gets a random number using x and y as seeds </summary> 
///<param name = x> A double value </param> 
///<param name = y> A double value </param> 
///<returns> A random number between -1.0 and 1.0 </returns> 
inline double PerlinNoise::noise(double x, double y) 
{ 
    int n = x + y * 57; 
    n = (n << 13)^n; 

    return (1.0 - ((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff)/1073741824.0); 
} 

///<summary> Smooths out noise values </summary> 
///<param name = x> a double value </param> 
///<param name = y> a double value </param> 
///<returns> a smoothed value between -1.0 and 1.0 </returns> 
double PerlinNoise::smoothNoise(double x, double y) 
{ 
    double corners = (noise(x+1, y+1) + noise(x+1,y-1) + noise(x-1,y+1) + noise(x-1,y-1))/16; 
    double sides = (noise(x,y+1) + noise(x,y-1) + noise(x+1,y) + noise(x-1,y))/8; 
    double center = noise(x,y)/4; 

    return corners + sides + center; 
} 

///<summary> Cosine Interpolation </summary> 
///<param name = a> The low value to be interpolated </param> 
///<param name = b> The high value to be interpolated </param> 
///<param name = x> A value between -1.0 and 1.0 </param> 
///<returns> Interpolated value between a and b </returns> 
double PerlinNoise::cosineInterpolation(double a, double b, double x) 
{ 
    double ft = x * 3.1415927; 
    double f = (1.0 - cos(ft)) * .5; 

    return a * (1.0 - f) + b * f; 
} 

///<summary> Gets smoothed noise values and interpolates them </summary> 
///<param name = x> a double value </param> 
///<param name = y> a double value </param> 
///<returns> a value between -1 and 1 that's been smoothed and interpolated </returns> 
double PerlinNoise::interpolatedNoise(double x, double y) 
{ 
    double integer_x = (int)x; 
    double fractional_x = x - integer_x; 

    double integer_y = (int)y; 
    double fractional_y = y - integer_y; 

    double v1 = smoothNoise(integer_x, integer_y); 
    double v2 = smoothNoise(integer_x + 1, integer_y); 
    double v3 = smoothNoise(integer_x, integer_y + 1); 
    double v4 = smoothNoise(integer_x + 1, integer_y + 1); 

    double inter1 = cosineInterpolation(v1, v2, fractional_x); 
    double inter2 = cosineInterpolation(v3, v4, fractional_x); 

    return cosineInterpolation(inter1, inter2, fractional_y); 
} 

double PerlinNoise::generateNoise(double x, double y) 
{ 
    double total = 0; 

    for(int i = 0; i < n; i++) 
    { 
     frequency = pow(2.0,i); 
     amplitude = pow(p,i); 

     total = total + interpolatedNoise(x * frequency/z, y * frequency/z) * amplitude; 
    } 

    return total; 
} 
+2

Проводка изображения вашего выхода была бы очень полезно. – Pubby

+0

Учитывая, что ваш код не компилируется (листинг является неполным), довольно сложно предоставить любые полезные комментарии. Тем не менее, блочные выходы предполагают слишком мало октав шума, а жесткие выходы предполагают, что нужна какая-то фильтрация. Свяжите некоторые результаты, пожалуйста. – Rook

+0

[здесь] (http://imgur.com/zfyTU), что я получаю. Для компиляции вам понадобится заголовок SDL и [this] (http://pastie.org/4144014). Я выбрал два наиболее важных файла для загрузки, поскольку переполнение стека позволит мне только 2 – Zacharias3960

ответ

0

Найдено проблема, моя настойчивость была намного ниже, чем это должно быть, что повысит I Получено облачное изображение Я ожидал