function Cosine_Interpolate(var a, var b, var x)
{
double ft = x * 3.1415927;
double f = (1 - cos(ft)) * 0.5;
return a*(1-f) + b*f;
}
//Perlin Noise Heightmap Generator
char* perlin_noise_tmp_pixels=NULL;
//recommended default values:
// size_ = 512
// freq_ = 64
// height_min_ = -50
// height_max_ = 200
// iterations_ = 5
// persistence_ = 2
BMAP* perlin_noise(double size_,var freq_,var height_min_,var height_max_,var iteration_,var persistence_)
{
//create bmaps
perlin_noise_tmp_pixels=(char*)sys_malloc(iteration_ * sizeof(char) * size_*size_);
int t=1;
int i; for(i=0;i<iteration_;i++)
{
//get random height value (0-255)
int py; for(py=0;py<size_;py+=freq_/t)
{
int px; for(px=0;px<size_;px+=freq_/t)
{
perlin_noise_tmp_pixels[i*size_*size_+px*size_+py]=clamp(integer(random((height_max_+150)-(height_min_+150))+(height_min_+150))-150,0,255);
}
}
//interpolate pixels in x direction
var a=1/(freq_/t),px1=0,py1=0,px=0,py=0,j=0; while(j<(size_-(size_/(freq_/t)))*(size_/(freq_/t)))
{
var h1=perlin_noise_tmp_pixels[i*size_*size_+px*size_+py];
var h2=perlin_noise_tmp_pixels[i*size_*size_+(px+(freq_/t))*size_+py];
if(px==size_-(freq_/t)){h2=perlin_noise_tmp_pixels[i*size_*size_+0*size_+py];}
perlin_noise_tmp_pixels[i*size_*size_+(px+px1+1)*size_+py]=Cosine_Interpolate(h1,h2,a);
px1+=1;
a+=1/(freq_/t);
if(px1 > (freq_/t)-2)
{
a=1/(freq_/t);
px+=(freq_/t);
px1=0;
py1+=1;
if(py1 > (size_/(freq_/t))-1)
{
px1=0;
py1=0;
px=0;
py+=(freq_/t);
a=1/(freq_/t);
}
}
j+=1;
}
//interpolate pixels in y direction
var a=1/(freq_/t),px1=0,py1=0,px=0,py=0,j=0; while(j<(size_-(size_/(freq_/t)))*(size_))
{
var h1=perlin_noise_tmp_pixels[i*size_*size_+px*size_+py];
var h2=perlin_noise_tmp_pixels[i*size_*size_+px*size_+clamp(py+(freq_/t),0,size_-1)];
if(py==size_-(freq_/t)){h2=perlin_noise_tmp_pixels[i*size_*size_+px*size_+clamp(0,0,size_-1)];}
perlin_noise_tmp_pixels[i*size_*size_+px*size_+(py+py1+1)]=Cosine_Interpolate(h1,h2,a);
py1+=1;
a+=1/(freq_/t);
if(py1 > (freq_/t)-2)
{
a=1/(freq_/t);
py+=(freq_/t);
py1=0;
px1+=1;
if(px1 > (size_/(freq_/t))-1)
{
py1=0;
px1=0;
py=0;
px+=1;
a=1/(freq_/t);
}
}
j+=1;
}
t*=persistence_; t=clamp(t,1,freq_);
}
//create bmap
BMAP* bmp_tmp=bmap_createblack(size_,size_,24);
int i; for(i=0;i<iteration_;i++)
{
int py; for(py=0;py<size_;py++)
{
int px; for(px=0;px<size_;px++)
{
//get bmap color
VECTOR bmp_color_;
var format=bmap_lock(bmp_tmp,0);var alpha_;
var pixel=pixel_for_bmap(bmp_tmp, px, py);
pixel_to_vec(bmp_color_,alpha_,format,pixel);
bmap_unlock(bmp_tmp);
//get heightmap color
var grey=perlin_noise_tmp_pixels[((iteration_-i)-1)*size_*size_+px*size_+py];
//lerp colors
bmp_color_.x=integer(bmp_color_.x+grey)/2;
bmp_color_.y=integer(bmp_color_.y+grey)/2;
bmp_color_.z=integer(bmp_color_.z+grey)/2;
//add to heightmap
var format=bmap_lock(bmp_tmp,0);
var pixel=pixel_for_vec(bmp_color_,100,format);
pixel_to_bmap(bmp_tmp, px, py, pixel);
bmap_unlock(bmp_tmp);
}
}
}
//free pixels and bmaps
sys_free(perlin_noise_tmp_pixels);
return bmp_tmp;
}