Posted By: oliver2s
Perlin Noise Heightmap Generator - 12/09/13 16:16
Some months ago I posted my very old Perlin Noise Generator script after a user asked for it.
This script was very badly done (and slow). Today I rewrote it. Here's the new memory and speed optimized script:
Example:
This script was very badly done (and slow). Today I rewrote it. Here's the new memory and speed optimized script:
Code:
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; }
Example:
Code:
void main() { video_mode=9; wait(1); BMAP* bmp=perlin_noise(512,64,-50,200,5,2); while(1) { DEBUG_BMAP(bmp,0,1); wait(1); } }