Gamestudio Links
Zorro Links
Newest Posts
Data from CSV not parsed correctly
by EternallyCurious. 04/18/24 10:45
StartWeek not working as it should
by Zheka. 04/18/24 10:11
folder management functions
by VoroneTZ. 04/17/24 06:52
lookback setting performance issue
by 7th_zorro. 04/16/24 03:08
zorro 64bit command line support
by 7th_zorro. 04/15/24 09:36
Zorro FIX plugin - Experimental
by flink. 04/14/24 07:48
Zorro FIX plugin - Experimental
by flink. 04/14/24 07:46
AUM Magazine
Latest Screens
The Bible Game
A psychological thriller game
SHADOW (2014)
DEAD TASTE
Who's Online Now
2 registered members (ozgur, TipmyPip), 722 guests, and 0 spiders.
Key: Admin, Global Mod, Mod
Newest Members
EternallyCurious, howardR, 11honza11, ccorrea, sakolin
19047 Registered Users
Previous Thread
Next Thread
Print Thread
Rate Thread
Perlin Noise Heightmap Generator #433965
12/09/13 16:16
12/09/13 16:16
Joined: Aug 2002
Posts: 3,258
Mainz
oliver2s Offline OP
Expert
oliver2s  Offline OP
Expert

Joined: Aug 2002
Posts: 3,258
Mainz
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:

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);
	}
}


Re: Perlin Noise Heightmap Generator [Re: oliver2s] #433975
12/09/13 22:11
12/09/13 22:11
Joined: Mar 2011
Posts: 3,150
Budapest
sivan Offline
Expert
sivan  Offline
Expert

Joined: Mar 2011
Posts: 3,150
Budapest
thanks! I'll test it tomorrow together with your other corresponding contribution.


Free world editor for 3D Gamestudio: MapBuilder Editor
Re: Perlin Noise Heightmap Generator [Re: sivan] #453181
07/10/15 14:41
07/10/15 14:41
Joined: Sep 2003
Posts: 6,861
Kiel (Germany)
Superku Offline
Senior Expert
Superku  Offline
Senior Expert

Joined: Sep 2003
Posts: 6,861
Kiel (Germany)
Thanks!


"Falls das Resultat nicht einfach nur dermassen gut aussieht, sollten Sie nochmal von vorn anfangen..." - Manual

Check out my new game: Pogostuck: Rage With Your Friends

Moderated by  HeelX, Lukas, rayp, Rei_Ayanami, Superku, Tobias, TWO, VeT 

Gamestudio download | chip programmers | Zorro platform | shop | Data Protection Policy

oP group Germany GmbH | Birkenstr. 25-27 | 63549 Ronneburg / Germany | info (at) opgroup.de

Powered by UBB.threads™ PHP Forum Software 7.7.1